+
+ def get_level_data(self):
+ return '\n'.join(reversed([''.join(x) for x in self._data]))
+
+ 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
+ elif self._data[y][x - 1] == WALL:
+ left = True
+ if x == len(self._data[0]) - 1:
+ right = True
+ elif self._data[y][x + 1] == WALL:
+ right = True
+ if y == 0:
+ top = True
+ elif self._data[y - 1][x] == WALL:
+ top = True
+ if y == len(self._data) - 1:
+ bottom = True
+ elif self._data[y + 1][x] == WALL:
+ bottom = True
+ if top and bottom and left and right:
+ return load_image('tiles/cwall.png')
+ elif bottom and left and right:
+ return load_image('tiles/bottom_wall.png')
+ elif top and left and right:
+ return load_image('tiles/top_wall.png')
+ elif top and bottom and right:
+ return load_image('tiles/left_wall.png')
+ elif top and bottom and left:
+ return load_image('tiles/right_wall.png')
+ elif top and bottom:
+ return load_image('tiles/vert_wall.png')
+ elif left and right:
+ return load_image('tiles/horiz_wall.png')
+ elif left and top:
+ return load_image('tiles/corner_lt.png')
+ elif left and bottom:
+ return load_image('tiles/corner_lb.png')
+ elif right and top:
+ return load_image('tiles/corner_rt.png')
+ elif right and bottom:
+ return load_image('tiles/corner_rb.png')
+ elif top:
+ return load_image('tiles/end_top.png')
+ elif bottom:
+ return load_image('tiles/end_bottom.png')
+ elif left:
+ return load_image('tiles/end_right.png')
+ elif right:
+ 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
+ if pos[1] < 0:
+ return True
+ try:
+ tile = self._data[pos[1]][pos[0]]
+ except IndexError:
+ return True
+ if tile == WALL or tile == ENTRY:
+ return True
+ if tile == GATE:
+ 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
+ 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
+ if self._gates[pos] == -1 or self._gates[pos] == 0:
+ return
+ self._gates[pos] = self._gates[pos] - 1
+ self._fix_tile(pos)
+
+ def get_changed_tiles(self):
+ ret = self._changed[:]
+ self._changed = []
+ return ret
+
+
+class LevelList(object):
+
+ LEVELS = 'level_list'
+
+ def __init__(self):
+ self._levels = []
+ self._level_names = []
+ self._errors = []
+ level_list = load(self.LEVELS)
+ for line in level_list:
+ line = line.strip()
+ if os.path.exists(filepath(line)):
+ level_file = load(line)
+ level = Level(level_file, line)
+ level_file.close()
+ try:
+ level.validate()
+ self._levels.append(level)
+ self._level_names.append(line)
+ except RuntimeError as err:
+ self._errors.append(
+ 'Invalid level %s in level_list: %s' % (line, err))
+ else:
+ self._errors.append(
+ 'Level list includes non-existant level %s' % line)
+ level_list.close()
+ self._cur_level = 0
+
+ def get_current_level(self):
+ if self._cur_level < len(self._levels):
+ return self._levels[self._cur_level]
+ else:
+ return None
+
+ def get_errors(self):
+ return self._errors
+
+ def get_level_names(self):
+ return self._level_names
+
+ def set_level_to(self, level_name):
+ if level_name in self._level_names:
+ self._cur_level = self._level_names.index(level_name)
+
+ def advance_to_next_level(self):
+ self._cur_level += 1
+ return self.get_current_level()
+
+ def reset(self):
+ self._cur_level = 0