Refactor code and add some editor functions
authorNeil <neil@dip.sun.ac.za>
Thu, 18 Apr 2013 10:56:21 +0000 (12:56 +0200)
committerNeil <neil@dip.sun.ac.za>
Thu, 18 Apr 2013 10:56:21 +0000 (12:56 +0200)
erdslangetjie/level.py

index e1c534d71f064b75b6917e442b791504e3a3892b..8efc539e13a08d6b6ab7cafab4bd7fc1715f5197 100644 (file)
@@ -38,40 +38,84 @@ class Level(object):
         for j, line in enumerate(self._data):
             tile_line = []
             for i, c in enumerate(line):
-                if c == FLOOR:
-                    tile_line.append(load_image('tiles/floor.png'))
-                elif c == WALL:
-                    tile_line.append(self._get_wall_tile(i, j))
-                elif c == ENTRY:
-                    if self.enter_pos:
-                        raise RuntimeError('Multiple entry points')
-                    self.enter_pos = (i, j)
-                    tile_line.append(load_image('tiles/entry.png'))
-                elif c == EXIT:
-                    self.exit_pos.append((i, j))
-                    tile_line.append(load_image('tiles/door.png'))
-                elif c == GATE:
-                    tile_line.append('tiles/gate_down.png')
-                    self._gates[(i, j)] = -1  # down
-                elif c == BUTTON:
-                    tile_line.append('tiles/button.png')
-                    self._buttons[(i, j)] = 'active'
+                tile_image = self._get_tile_image((i, j), c)
+                tile_line.append(tile_image)
             self._tiles.append(tile_line)
 
+    def _get_tile_image(self, pos, c):
+        if pos in self._gates:
+            del self._gates[pos]
+        if pos in self._buttons:
+            del self._buttons[pos]
+        image = None
+        if c == FLOOR:
+            image = load_image('tiles/floor.png')
+        elif c == WALL:
+            image = self._get_wall_tile(pos)
+        elif c == ENTRY:
+            self.enter_pos = pos
+            image = load_image('tiles/entry.png')
+        elif c == EXIT:
+            self.exit_pos.append(pos)
+            image = load_image('tiles/door.png')
+        elif c == GATE:
+            image = load_image('tiles/gate_down.png')
+            self._gates[pos] = -1  # down
+        elif c == BUTTON:
+            image = load_image('tiles/button.png')
+            self._buttons[pos] = 'active'
+        if image is None:
+            raise RuntimeError('Unknown tile type %s at %s' % (c, pos))
+        return image
+
+    def validate(self):
+        entry_points = 0
+        exit_points = 0
+        for line in self._data:
+            if ENTRY in line:
+                entry_points += 1
+            if EXIT in line:
+                exit_points += 1
+        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')
+
     def get_tiles(self):
         return self._tiles
 
     def get_single_tile(self, pos):
         return self._tiles[pos[1]][pos[0]]
 
+    def get_tile_type(self, pos):
+        return self._data[pos[1]][pos[0]]
+
+    def set_tile_type(self, pos, new_type):
+        self._data[pos[1]][pos[0]] = new_type
+        new_tile = self._get_tile_image(new_type, pos)
+        self._tiles[pos[1]][pos[0]] = new_tile
+        self._changed.append((pos, new_tile))
+        # Also update neighbourhood for wall types, etc.
+        for new_pos in [(pos[0] - 1, pos[1]), (pos[0] + 1, pos[1]),
+                (pos[0], pos[1] - 1), (pos[0], 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(tile, pos)
+            self._tiles[new_pos[1]][new_pos[0]] = new_tile
+            self._changed.append((new_pos, new_tile))
+
     def get_size(self):
         return len(self._tiles[0]), len(self._tiles)
 
     def at_exit(self, pos):
         return pos in self.exit_pos
 
-    def _get_wall_tile(self, x, y):
+    def _get_wall_tile(self, pos):
         # Is the neighbour in this direction also a wall?
+        x, y = pos
         left = right = top = bottom = False
         if x == 0:
             left = True
@@ -121,6 +165,17 @@ class Level(object):
             return load_image('tiles/end_left.png')
         return load_image('tiles/pillar.png')
 
+    def _in_limits(self, pos):
+        if pos[0] < 0:
+            return False
+        if pos[1] < 0:
+            return False
+        try:
+            self._data[pos[1]][pos[0]]
+        except IndexError:
+            return False
+        return True
+
     def blocked(self, pos):
         if pos[0] < 0:
             return True