aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvg <vgm+dev@devys.org>2020-05-10 16:20:37 +0200
committervg <vgm+dev@devys.org>2020-05-10 16:20:37 +0200
commite87270846261f0a1b6f598ed36517f4c37cc2804 (patch)
tree6638a9e89d46d8549b8434d3ebcc3d1118d86e67
parent8e4f016a05809f3e09e92fac2f5fae5d5d21aa89 (diff)
downloadkana_quest_solver-e87270846261f0a1b6f598ed36517f4c37cc2804.tar.gz
kana_quest_solver-e87270846261f0a1b6f598ed36517f4c37cc2804.tar.bz2
kana_quest_solver-e87270846261f0a1b6f598ed36517f4c37cc2804.zip
add new kana type: slimes (slim)
-rw-r--r--levels/level_5.01.yaml10
-rwxr-xr-xsolver.py61
2 files changed, 51 insertions, 20 deletions
diff --git a/levels/level_5.01.yaml b/levels/level_5.01.yaml
new file mode 100644
index 0000000..3f6bd99
--- /dev/null
+++ b/levels/level_5.01.yaml
@@ -0,0 +1,10 @@
+# kana quest grid level 5.01
+size: [3, 3]
+max_actions: 3
+target_score: 3
+grid: [
+ [slim, i ], [slim, i ], [void, null],
+ [norm, ke ], [norm, null], [norm, ni ],
+ [void, null], [norm, so ], [void, null],
+]
+# The kana 'no' need to be protected else the program convert it into False...
diff --git a/solver.py b/solver.py
index e435c8a..87273a9 100755
--- a/solver.py
+++ b/solver.py
@@ -20,8 +20,9 @@ import yaml
class Kana:
- types = ('void', 'norm', 'froz', 'rock', 'myst',
- 'ar_u', 'ar_l', 'ar_d', 'ar_r')
+ types = ('void', 'norm', 'froz', 'rock', 'myst', 'slim',
+ 'ar_u', 'ar_r', 'ar_d', 'ar_l')
+ slime_merge_types = ('norm', 'froz', 'ar_u', 'ar_r', 'ar_d', 'ar_l')
def __init__(self, type_name, kana=None):
self.type_name = type_name
@@ -33,8 +34,11 @@ class Kana:
# missing yet: 'n' and 'y...' and 'w...' are not we all vowels
if kana:
- assert kana[0] in 'kstnhmryw'
- assert kana[1] in 'aiueo'
+ if type_name == 'slim':
+ assert kana[0] in 'aiueo'
+ else:
+ assert kana[0] in 'kstnhmryw'
+ assert kana[1] in 'aiueo'
def __repr__(self):
return "%s(%s)" % (self.type_name, self.kana)
@@ -47,6 +51,8 @@ kana_void = Kana('void')
class KanaGrid:
+ actions = ('reveal', 'up', 'right', 'down', 'left')
+
def __init__(self, size, grid,
action_count=0, score=0, myst_count=0, parent=None):
@@ -98,23 +104,35 @@ class KanaGrid:
return False
def action(self, pos, action_type):
- if action_type == "reveal":
- kana = self.get_kana(pos)
+ kana = self.get_kana(pos)
+ if action_type == 'reveal':
if kana.type_name == 'myst':
new_grid = self.copy()
new_grid.action_count += 1
new_grid.set_kana(pos, Kana('norm', kana.kana))
return new_grid
- elif action_type in ("up", "right", "down", "left"):
- if action_type == "up":
- pos_dest = (pos[0], pos[1]-1)
- elif action_type == "right":
- pos_dest = (pos[0]+1, pos[1])
- elif action_type == "down":
- pos_dest = (pos[0], pos[1]+1)
- elif action_type == "left":
- pos_dest = (pos[0]-1, pos[1])
- if self.is_swappable(pos, pos_dest):
+ elif action_type in ('up', 'right', 'down', 'left'):
+ pos_map = {
+ 'up': (pos[0], pos[1]-1),
+ 'right': (pos[0]+1, pos[1]),
+ 'down': (pos[0], pos[1]+1),
+ 'left': (pos[0]-1, pos[1]),
+ }
+ pos_dest = pos_map[action_type]
+ if kana.type_name == 'slim':
+ kana2 = self.get_kana(pos_dest)
+ if kana2.type_name in Kana.slime_merge_types and kana2.kana:
+ new_grid = self.copy()
+ new_grid.action_count += 1
+ new_kana1 = Kana('void')
+ new_kana2 = Kana(
+ kana2.type_name,
+ kana2.kana[0] + kana.kana[0],
+ )
+ new_grid.set_kana(pos, new_kana1)
+ new_grid.set_kana(pos_dest, new_kana2)
+ return new_grid
+ elif self.is_swappable(pos, pos_dest):
new_grid = self.copy()
new_grid.action_count += 1
new_grid.swap_kana(pos, pos_dest)
@@ -124,7 +142,7 @@ class KanaGrid:
for y in range(self.height):
for x in range(self.width):
kana = self.get_kana((x, y))
- if kana.kana:
+ if kana.kana and kana.type_name != 'slim':
yield (x, y)
def populate_chain(self, pos1, chain_positions):
@@ -145,7 +163,7 @@ class KanaGrid:
if pos2 in chain_positions:
continue
kana2 = self.get_kana(pos2)
- if kana2.kana:
+ if kana2.kana and kana2.type_name != 'slim':
if is_kana_compatible(kana1, kana2):
myst_count += self.populate_chain(pos2, chain_positions)
return myst_count
@@ -257,6 +275,7 @@ def repr_grid(grid, grid_size):
'froz': ('\x1b[36m[', ']\x1b[0m'),
'rock': (' \x1b[1;40m', '\x1b[0m '),
'myst': ('\x1b[33m?', '?\x1b[0m'),
+ 'slim': ('\x1b[32m~', '~\x1b[0m'),
'ar_u': ('\x1b[31m∧\x1b[0m', '\x1b[31m∧\x1b[0m'),
'ar_r': ('\x1b[31m>\x1b[0m', '\x1b[31m>\x1b[0m'),
'ar_d': ('\x1b[31m∨\x1b[0m', '\x1b[31m∨\x1b[0m'),
@@ -275,7 +294,7 @@ def repr_grid(grid, grid_size):
if tname == 'void':
line += ' '
elif tname in indicator_map:
- line += '|%s%s%s|' % (
+ line += '|%s%2s%s|' % (
indicator_map[tname][0],
kkana,
indicator_map[tname][1],
@@ -289,6 +308,8 @@ def display_grid(grid, grid_size):
def is_kana_compatible(kana1, kana2):
+ if kana1.type_name == 'slim' or kana2.type_name == 'slim':
+ return False
if kana1.kana[0] == kana2.kana[0] or kana1.kana[1] == kana2.kana[1]:
return True
return False
@@ -297,7 +318,7 @@ def is_kana_compatible(kana1, kana2):
def generate_possible_grids(kanagrid):
for y in range(kanagrid.height):
for x in range(kanagrid.width):
- for action_type in ("reveal", "up", "right", "down", "left"):
+ for action_type in KanaGrid.actions:
new_grid = kanagrid.action((x, y), action_type)
if new_grid and new_grid.grid != kanagrid.grid:
yield (x, y), action_type, new_grid