diff --git a/lib/goban.py b/lib/goban.py index 54a3e25..a1f19d5 100644 --- a/lib/goban.py +++ b/lib/goban.py @@ -32,6 +32,7 @@ class Goban: self.hover = None self.elapsed_time = 0 self.winner = Goban.EMPTY + self.move = 0 self.file_name = file_name @@ -79,7 +80,7 @@ class Goban: def _play_node(self, node): color, pos = node.get_move() if color is not None: - if pos == 'pass': + if pos is None: self.pass_move(color) else: self.play_move(self._sgf_to_move(pos), color, add_sgf=False) @@ -88,7 +89,7 @@ class Goban: # Play all moves up to and including node, which should be # an sgf.Tree_node - def _play_to_node(self, node): + def play_to_node(self, node): self.soft_reset() for n in self.sgf_game.get_main_sequence(): self._sgf_play_node(self, n) @@ -96,9 +97,13 @@ class Goban: return - # Play to the nth move - def _play_to_move_n(self, n): + def play_to_move_n(self, n=None): + ''' Play to the nth move. If n is None, play to the latest move ''' self.soft_reset() + + if n is None or len(self.sgf_game.get_main_sequence()) < n: + n = len(self.sgf_game.get_main_sequence()) + portion = self.sgf_game.get_main_sequence()[:n] for node in portion: self._play_node(node) @@ -146,6 +151,7 @@ class Goban: self.hover = None self.elapsed_time = 0 self.winner = Goban.EMPTY + self.move = 0 def reset(self): @@ -159,21 +165,33 @@ class Goban: reset the board to a blank state, but will *not* reset captures, etc (call reset() first if you want that)""" self.board_size = new_size - num_points = board_size * board_size - self.board = [Goban.EMPTY] * num_points + num_points = self.board_size * self.board_size + self.board = [Goban.EMPTY] * num_points def clear_hover(self): self.hover = None - # For performance reasons (to help with drawing code) - # any modified positions are returned in a list. - # This is self._changed, which is modified by this - # function and by _delete_group_r(). - # This list will *also* contain the last move and any - # previous or new ko positions. def play_move(self, pos, color=None, add_sgf=True): + ''' + Plays a move + + pos: a tuple containing row and column to play on + + color: which color is playing. If not specified, the player whose turn it is is assumed + + add_sgf: if True, this is a new move and should be recorded in the move history + + return: + To help with drawing code efficiency, any modified positions are returned in a list. + This includes anything that the GUI may want to redraw in the wake of this move. + + + ''' + if add_sgf and self.move != len(self.sgf_game.get_main_sequence()): + return + if color is None: color = self.to_move @@ -209,6 +227,8 @@ class Goban: if self.ko is not None: self._changed.append(self.ko) + self.move += 1 + return self._changed @@ -540,6 +560,9 @@ class Goban: # Convert an sgf vector to a move tuple def _sgf_to_move(self, move): + if move is None: + return None + x,y = move new_x = self.board_size - 1 - x return (new_x, y) diff --git a/widgets/gogame.py b/widgets/gogame.py index 3f06ec8..d7e1008 100644 --- a/widgets/gogame.py +++ b/widgets/gogame.py @@ -83,6 +83,25 @@ class GoGame(gtk.HBox): self.pack_start(self.board_area, expand=False) self.pack_end(info_box, expand=False) + + nav_row = gtk.HBox() + fwd_button = gtk.Button(stock=gtk.STOCK_GO_FORWARD) + back_button = gtk.Button(stock=gtk.STOCK_GO_BACK) + first_button = gtk.Button(stock=gtk.STOCK_GOTO_FIRST) + last_button = gtk.Button(stock=gtk.STOCK_GOTO_LAST) + + nav_row.pack_start(first_button) + nav_row.pack_start(back_button) + nav_row.pack_start(fwd_button) + nav_row.pack_start(last_button) + + first_button.connect('clicked', self.do_first_move) + back_button.connect('clicked', self.do_back_move) + fwd_button.connect('clicked', self.do_forward_move) + last_button.connect('clicked', self.do_last_move) + + info_box.pack_start(nav_row, expand=False) + self.update_info() @@ -122,6 +141,26 @@ class GoGame(gtk.HBox): self.update(changed) + def do_back_move(self, widget): + self.goban.play_to_move_n(self.goban.move - 1) + self.update() + + + def do_forward_move(self, widget): + self.goban.play_to_move_n(self.goban.move + 1) + self.update() + + + def do_first_move(self, widget): + self.goban.soft_reset() + self.update() + + + def do_last_move(self, widget): + self.goban.play_to_move_n() + self.update() + + def do_board_configure(self, widget, event): gc = widget.get_style().fg_gc[gtk.STATE_NORMAL] x,y,width,height = widget.get_allocation()