From becf13e4ab3f3fe1d771214cffbce814c838d7a5 Mon Sep 17 00:00:00 2001 From: Anna Wiggins Date: Wed, 18 Apr 2012 11:33:20 -0400 Subject: [PATCH] Make update code on playing a stone much more efficient --- lib/goban.py | 47 +++++++++++++++++++++++++++++++++++++++-------- pygo.py | 2 +- widgets/gogame.py | 25 +++++++++++++++++-------- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/lib/goban.py b/lib/goban.py index 2b22cda..ba7e770 100644 --- a/lib/goban.py +++ b/lib/goban.py @@ -67,19 +67,33 @@ class Goban: 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): if color is None: color = self.to_move if self.to_move == Goban.EMPTY: - return + return None rpos = self._real_pos(pos) if not self._valid_move(rpos, color): - return + return None self.board[rpos] = color + self._changed = [] + self._changed.append(rpos) + + if self.ko is not None: + self._changed.append(self.ko) + if self.last_move is not None: + self._changed.append(self.last_move) + self._capture(rpos) self.last_move = rpos self.passed_last = False @@ -87,6 +101,12 @@ class Goban: self.to_move = self._other_color(color) self.clear_hover() + # If there is a new ko, send that back too + if self.ko is not None: + self._changed.append(self.ko) + + return self._changed + # fixme: need to handle post-game stuff here... scoring code @@ -94,6 +114,12 @@ class Goban: if color is None: color = self.to_move + self._changed = [] + if self.ko is not None: + self._changed.append(self.ko) + if self.last_move is not None: + self._changed.append(self.last_move) + if self.passed_last: self.to_move = Goban.EMPTY else: @@ -103,17 +129,27 @@ class Goban: self.last_move = None self.ko = None + return self._changed + def resign(self, color=None): if color is None: color = self.to_move + self._changed = [] + if self.ko is not None: + self._changed.append(self.ko) + if self.last_move is not None: + self._changed.append(self.last_move) + self.passed_last = False self.last_move = None self.ko = None self.winner = self._other_color(color) self.to_move = Goban.EMPTY + return self._changed + def _capture(self, pos, color=None): """Look for stones captured on the 4 sides of pos, remove them and increment @@ -232,12 +268,6 @@ class Goban: return self._delete_group_r(pos, who) - if who == Goban.EMPTY: - return 0 - - self.board[x][y].state = Goban.EMPTY - - def _delete_group_r(self, pos, who): if not self._on_board(pos): @@ -247,6 +277,7 @@ class Goban: return 0 self.board[pos] = Goban.EMPTY + self._changed.append(pos) num_deleted = 1 diff --git a/pygo.py b/pygo.py index 6f3dc27..36c9fcb 100755 --- a/pygo.py +++ b/pygo.py @@ -51,7 +51,7 @@ class Pygo(): self.gogame = gogame.GoGame(goban.Goban()) self.contents.pack_start(self.gogame) self.gogame.show_all() - self.gogame.update() + self.gogame.update() # Initial board draw def on_net_direct(self, widget): diff --git a/widgets/gogame.py b/widgets/gogame.py index f1c59ce..f4f6b9a 100644 --- a/widgets/gogame.py +++ b/widgets/gogame.py @@ -108,11 +108,14 @@ class GoGame(gtk.HBox): row = int(y / inc) col = int(x / inc) - self.goban.play_move((row,col)) - self.update() + changed = self.goban.play_move((row,col)) + print changed + self.update(changed) def do_board_configure(self, widget, event): + print 'configure' + gc = widget.get_style().fg_gc[gtk.STATE_NORMAL] x,y,width,height = widget.get_allocation() self.board_backbuf = gtk.gdk.Pixmap(widget.window, width, height, depth=-1) @@ -121,6 +124,8 @@ class GoGame(gtk.HBox): def do_board_expose(self, widget, event): + print 'expose' + x , y, width, height = event.area widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.board_backbuf, x, y, x, y, width, height) @@ -130,7 +135,11 @@ class GoGame(gtk.HBox): # fixme: rendering/updating the whole board is pretty slow. Eliminate the need to # render the whole board when a stone is played (we need a list of modified # locations from somewhere) + # fixme: the board doesn't get drawn initially, even though the backbuffer *should* + # have the board in it before our first expose event def update_board(self, to_update=None): + print 'update' + if to_update == None: to_update = range(len(self.goban.board)) @@ -169,13 +178,13 @@ class GoGame(gtk.HBox): def on_pass(self, widget): - self.goban.pass_move() - self.update() + changed = self.goban.pass_move() + self.update(changed) def on_resign(self, widget): - self.goban.resign() - self.update() + changed = self.goban.resign() + self.update(changed) # fixme: Add a widget to show the outcome @@ -191,9 +200,9 @@ class GoGame(gtk.HBox): self.white_cap_value.set_text(str(self.goban.white_captures)) - def update(self): + def update(self, changed): self.update_info() - self.update_board() + self.update_board(changed)