# HG changeset patch # User Neil Muller # Date 1316705558 -7200 # Node ID c014f5023cd274dc5a93a9f7a89c90871401f8b0 # Parent b308ebaa96f3fa58391c72fdb64fa0c3b4f30ddb Test run replays diff -r b308ebaa96f3 -r c014f5023cd2 mamba/engine.py --- a/mamba/engine.py Fri Sep 23 22:17:46 2011 +0200 +++ b/mamba/engine.py Thu Sep 22 17:32:38 2011 +0200 @@ -129,6 +129,15 @@ super(FlipArrowsEvent, cls).post() +class ReplayEvent(UserEvent): + + TYPE = "REPLAY_EVENT" + + @classmethod + def post(cls, run, replay_pos): + super(ReplayEvent, cls).post(run=run, replay_pos=replay_pos) + + class HabitatSetupEvent(UserEvent): TYPE = "SETUP_HABITAT" diff -r b308ebaa96f3 -r c014f5023cd2 mamba/habitats/editor.py --- a/mamba/habitats/editor.py Fri Sep 23 22:17:46 2011 +0200 +++ b/mamba/habitats/editor.py Thu Sep 22 17:32:38 2011 +0200 @@ -74,6 +74,7 @@ self.sprite_mode = 'Add' self.sprite_cls = None # Map for test mode lookups + self.replays = {} self.action_map = { K_UP: UP, K_DOWN: DOWN, @@ -213,6 +214,22 @@ tile_button.add_callback('clicked', self.sprite_tool, name, None, None) tool_list.append(tile_button) + elif self.mode == 'Test': + for replay in [1, 2]: + store_button = TextButton((0, 0), + 'Store run as %s' % replay) + store_button.add_callback('clicked', self.store_replay, + replay) + tool_list.append(store_button) + replay_button = TextButton((0, 0), + 'Replay run %s' % replay) + replay_button.add_callback('clicked', self.do_replay, + replay) + tool_list.append(replay_button) + last_button = TextButton((0, 0), + 'Replay last run') + last_button.add_callback('clicked', self.do_replay, None) + tool_list.append(last_button) self.tool_widget = ToolListWidget((button_left, button_height), tool_list, MAX_TOOLS, start_key=K_2) self.toolbar[self.mode] = self.tool_widget @@ -396,6 +413,7 @@ self.edit_widget = EditLevelWidget(self.level) self.edit_widget.add_callback(SnakeDiedEvent, self.halt_test) self.edit_widget.add_callback(LevelCompletedEvent, self.halt_test) + self.replays = {} self.container.add(self.edit_widget) self.clear_toolbar() self.setup_toolbar() @@ -546,3 +564,17 @@ self.level.replace_sprite(sprite) self.level.restart() return True + + def store_replay(self, ev, widget, number): + self.replays[number] = self.edit_widget.get_replay() + + def do_replay(self, ev, widget, number): + if number: + # We do nothing if the user tries to replay something thay + # isn't there + if number in self.replays: + # Replay stored replay + self.edit_widget.replay(self.replays[number]) + else: + # Replaying last run + self.edit_widget.replay() diff -r b308ebaa96f3 -r c014f5023cd2 mamba/widgets/level.py --- a/mamba/widgets/level.py Fri Sep 23 22:17:46 2011 +0200 +++ b/mamba/widgets/level.py Thu Sep 22 17:32:38 2011 +0200 @@ -5,7 +5,7 @@ from mamba.widgets.base import Widget from mamba.constants import TILE_SIZE from mamba.snake import Snake -from mamba.engine import FlipArrowsEvent +from mamba.engine import FlipArrowsEvent, ReplayEvent class EditLevelWidget(Widget): @@ -22,11 +22,34 @@ self.add_callback(MOUSEBUTTONUP, self.end_draw) self.add_callback(MOUSEMOTION, self.draw_tiles) self.add_callback(FlipArrowsEvent, self.flip_arrows) + self.add_callback(ReplayEvent, self.handle_replay) self.snake = None self.snake_alive = False + self.replay_data = [] + self.last_run = [] + self.replay_pos = 0 + + def get_replay(self): + return self.replay_data[:] + + def replay(self, run=None): + if run is None: + # We exclude the last couple of steps, so we don't redo + # the final crash in this run + run = self.last_run[:-4] + if len(run) > 0: + self.start_test() + ReplayEvent.post(run, 0) + + def handle_replay(self, ev, widget): + self.apply_action(ev.run[ev.replay_pos]) + if ev.replay_pos < len(ev.run) - 1: + ReplayEvent.post(ev.run, ev.replay_pos + 1) def start_test(self): self.level.update_tiles_ascii() + self.last_run = self.replay_data + self.replay_data = [] self.level.restart() tile_pos, orientation = self.level.get_entry() self.snake = Snake(tile_pos, orientation) @@ -62,6 +85,7 @@ return self.level.extra_sprites[sprite_id] def apply_action(self, orientation): + self.replay_data.append(orientation) if not self.snake or not self.snake_alive: return # We choose numbers that are close to, but not exactly, move 0.5 tiles