Speed up arrival of the nemesis
[erdslangetjie.git] / erdslangetjie / level.py
index c722b563873c76034e73548e2a723c1ba0cfdf14..f430f5dd53a27e2def6254aaca778917dd32f7aa 100644 (file)
@@ -75,8 +75,13 @@ class Level(object):
                     # gate up
                     image = load_image('tiles/gate_up.png')
         elif c == BUTTON:
-            image = load_image('tiles/button.png')
-            self._buttons[pos] = 'active'
+            if not pos in self._buttons:
+                image = load_image('tiles/button.png')
+                self._buttons[pos] = 'active'
+            elif self._buttons[pos] == 'active':
+                image = load_image('tiles/button.png')
+            else:
+                image = load_image('tiles/floor.png')
         if image is None:
             raise RuntimeError('Unknown tile type %s at %s' % (c, pos))
         return image
@@ -84,17 +89,25 @@ class Level(object):
     def validate(self):
         entry_points = 0
         exit_points = 0
+        gates = 0
+        buttons = 0
         for line in self._data:
             if ENTRY in line:
                 entry_points += line.count(ENTRY)
             if EXIT in line:
                 exit_points += line.count(EXIT)
+            if BUTTON in line:
+                buttons += line.count(BUTTON)
+            if GATE in line:
+                gates += line.count(GATE)
         if entry_points == 0:
             raise RuntimeError('No entry point')
         if entry_points > 1:
             raise RuntimeError('Multiple entry points')
         if exit_points == 0:
             raise RuntimeError('No exit')
+        if gates != buttons:
+            raise RuntimeError('The number of buttons and gates differ')
 
     def get_tiles(self):
         return self._tiles
@@ -122,10 +135,14 @@ class Level(object):
                 (pos[0] - 1, pos[1] + 1), (pos[0] + 1, pos[1] - 1)]:
             if not self._in_limits(new_pos):
                 continue
-            tile = self._data[new_pos[1]][new_pos[0]]
-            new_tile = self._get_tile_image(new_pos, tile)
-            self._tiles[new_pos[1]][new_pos[0]] = new_tile
-            self._changed.append((new_pos, new_tile))
+            # Update display to changed status
+            self._fix_tile(new_pos)
+
+    def _fix_tile(self, pos):
+        tile = self._data[pos[1]][pos[0]]
+        new_tile = self._get_tile_image(pos, tile)
+        self._tiles[pos[1]][pos[0]] = new_tile
+        self._changed.append((pos, new_tile))
 
     def get_size(self):
         return len(self._tiles[0]), len(self._tiles)
@@ -211,36 +228,54 @@ class Level(object):
         if tile == WALL or tile == ENTRY:
             return True
         if tile == GATE:
-            if self._gates[pos] != -1:
+            if self._gates[pos] > 0:
                 return True
         return False
 
+    def calc_dist(self, pos1, pos2):
+        return abs(pos1[0] - pos2[0]) + abs(pos1[1] - pos2[1])
+
     def is_gate(self, pos):
+        if not self._in_limits(pos):
+            return False
         return self._data[pos[1]][pos[0]] == GATE
 
     def is_button(self, pos):
+        if not self._in_limits(pos):
+            return False
         return self._data[pos[1]][pos[0]] == BUTTON
 
+    def is_wall(self, pos):
+        if not self._in_limits(pos):
+            return True
+        return self._data[pos[1]][pos[0]] == WALL
+
     def trigger_button(self, pos):
         if not self.is_button(pos):
             return False
         if not self._buttons[pos] == 'active':
             return False
         # Find the closest gate down gate and trigger it
-        gate_pos = pos
-
-        self._changed.append((pos, self.get_single_tile(pos)))
-        self._changed.append((gate_pos, self.get_single_tile(pos)))
+        mindist = 99999
+        gate_pos = None
+        for cand in self._gates:
+            dist = self.calc_dist(pos, cand)
+            if dist < mindist:
+                gate_pos = cand
+                mindist = dist
+        if gate_pos:
+            self._buttons[pos] = 'pressed'
+            self._gates[gate_pos] = 3  # Raise gate
+            self._fix_tile(pos)
+            self._fix_tile(gate_pos)
 
     def damage_gate(self, pos):
         if not self.is_gate(pos):
-            return False
+            return
         if self._gates[pos] == -1 or self._gates[pos] == 0:
-            return False
+            return
         self._gates[pos] = self._gates[pos] - 1
-        self._fix_gate_tile(pos)
-        self._changed.append((pos, self.get_single_tile(pos)))
-        return True
+        self._fix_tile(pos)
 
     def get_changed_tiles(self):
         ret = self._changed[:]