+
+ def is_gate(self, pos):
+ return self._data[pos[1]][pos[0]] == GATE
+
+ def is_button(self, pos):
+ return self._data[pos[1]][pos[0]] == BUTTON
+
+ 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)))
+
+ def damage_gate(self, pos):
+ if not self.is_gate(pos):
+ return False
+ if self._gates[pos] == -1 or self._gates[pos] == 0:
+ return False
+ self._gates[pos] = self._gates[pos] - 1
+ self._fix_gate_tile(pos)
+ self._changed.append((pos, self.get_single_tile(pos)))
+ return True
+
+ def get_changed_tiles(self):
+ ret = self._changed[:]
+ self._changed = []
+ return ret
+
+
+class LevelList(object):
+
+ LEVELS = 'level_list'
+
+ def __init__(self):
+ self.levels = []
+ 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)
+ level_file.close()
+ try:
+ level.validate()
+ except RuntimeError as err:
+ raise RuntimeError(
+ 'Invalid level %s in level_list: %s' % (line, err))
+ self.levels.append(level)
+ else:
+ raise RuntimeError('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 advance_to_next_level(self):
+ self._cur_level += 1
+ return self.get_current_level()
+
+ def reset(self):
+ self._cur_level = 0