diff --git a/lib/goban.py b/lib/goban.py index 1a1fd5a..5273cf3 100644 --- a/lib/goban.py +++ b/lib/goban.py @@ -5,8 +5,11 @@ class Goban: EMPTY=0 WHITE=1 BLACK=2 - # GRAY_WHITE=3 - # GRAY_BLACK=4 + SCORE_BLACK=3 + SCORE_WHITE=4 + SCORE_DAME=5 + SCORING=6 + def __init__(self, board_size=19): # Build the board intersections @@ -109,7 +112,6 @@ class Goban: - # fixme: need to handle post-game stuff here... scoring code def pass_move(self, color=None): if color is None: color = self.to_move @@ -122,6 +124,9 @@ class Goban: if self.passed_last: self.to_move = Goban.EMPTY + self.winner = Goban.SCORING + self.auto_score() + return range(len(self.board)) else: self.to_move = self._other_color(color) self.passed_last = True @@ -294,8 +299,9 @@ class Goban: return None point = self.board[pos] + code = None - if point == Goban.EMPTY: + if point == Goban.EMPTY or point == Goban.SCORE_DAME: code = self.def_draw_codes[pos] elif point == Goban.BLACK: code = 'b' @@ -305,6 +311,10 @@ class Goban: code = 'w' if pos == self.last_move: code += 'Cb' + elif point == Goban.SCORE_WHITE: + code = self.def_draw_codes[pos] + 'ws' + elif point == Goban.SCORE_BLACK: + code = self.def_draw_codes[pos] + 'bs' if pos == self.ko: code += 'S' @@ -312,6 +322,51 @@ class Goban: return code + def auto_score(self): + ''' + Detects regions and assigns them to the appropriate player + This may not always guess correctly, so we also have API that + can manually change these things. + + After calling this function, the entire board should be redrawn. + ''' + for i in range(len(self.board)): + if self.board[i] == Goban.EMPTY: + bs = self.board_size * self.board_size + checked = set() + score = self._score_space(i, checked) + + for c in checked: + self.board[c] = score + + + + def _score_space(self, pos, checked): + if pos in checked: + return None + + if self.board[pos] == Goban.BLACK: + return Goban.SCORE_BLACK + elif self.board[pos] == Goban.WHITE: + return Goban.SCORE_WHITE + + checked.add(pos) + + possible = set() + for i in self._neighbors(pos): + score = self._score_space(i, checked) + possible.add(score) + + if Goban.SCORE_DAME in possible or (Goban.SCORE_BLACK in possible and Goban.SCORE_WHITE in possible): + return Goban.SCORE_DAME + elif Goban.SCORE_BLACK in possible: + return Goban.SCORE_BLACK + elif Goban.SCORE_WHITE in possible: + return Goban.SCORE_WHITE + else: + return None + + def _make_default_draw_codes(self): ret = [] diff --git a/pygo.py b/pygo.py index 9010821..75280b1 100755 --- a/pygo.py +++ b/pygo.py @@ -62,6 +62,8 @@ class Pygo(): self.games.append_page(game, gtk.Label('Local Game')) self.games.set_tab_reorderable(game, True) game.show_all() + game.winner_box.hide() + def on_net_direct(self, widget): diff --git a/ui/default.glade b/ui/default.glade index a2a056b..95e58f5 100644 --- a/ui/default.glade +++ b/ui/default.glade @@ -128,29 +128,6 @@ - - - - True - label1 - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - tab - - 0 diff --git a/ui/res/go_bs.png b/ui/res/go_bs.png new file mode 100644 index 0000000..1bcb992 Binary files /dev/null and b/ui/res/go_bs.png differ diff --git a/ui/res/go_ws.png b/ui/res/go_ws.png new file mode 100644 index 0000000..73d4775 Binary files /dev/null and b/ui/res/go_ws.png differ diff --git a/widgets/gogame.py b/widgets/gogame.py index fec8954..31e6506 100644 --- a/widgets/gogame.py +++ b/widgets/gogame.py @@ -50,6 +50,13 @@ class GoGame(gtk.HBox): for row in info_rows: info_box.pack_start(row, expand=False) + self.winner_box = gtk.HBox() + self.winner_value = gtk.Label('None') + self.winner_box.pack_start(gtk.Label('Winner:'), expand=False, padding=5) + self.winner_box.pack_end(self.winner_value, expand=False, padding=5) + + info_box.pack_start(self.winner_box, expand=False) + self.pass_button = gtk.Button('Pass') self.resign_button = gtk.Button('Resign') self.pass_button.connect('clicked', self.on_pass) @@ -185,6 +192,16 @@ class GoGame(gtk.HBox): move = 'White' else: move = 'None' + + if self.goban.winner != goban.Goban.EMPTY: + if self.goban.winner == goban.Goban.BLACK: + self.winner_value.set_text('Black') + elif self.goban.winner == goban.Goban.WHITE: + self.winner_value.set_text('White') + elif self.goban.winner == goban.Goban.SCORING: + self.winner_value.set_text('Scoring') + self.winner_box.show() + self.to_move_value.set_text(move) self.black_cap_value.set_text(str(self.goban.black_captures)) self.white_cap_value.set_text(str(self.goban.white_captures)) @@ -210,10 +227,9 @@ def _build_img_res(): circle_black = _load_png('go_circle_black.png') circle_white = _load_png('go_circle_white.png') square = _load_png('go_square.png') + bs = _load_png('go_bs.png') + ws = _load_png('go_ws.png') - ret['wH'] = _load_png('go_wH.png') - ret['bH'] = _load_png('go_bH.png') - ret['wT'] = _load_png('go_w.png') width = ret['wT'].get_width() height = ret['wT'].get_height() @@ -236,7 +252,7 @@ def _build_img_res(): ret['d'] = base.copy().rotate_simple(180) ret['r'] = base.copy().rotate_simple(270) - for d in ('m', 'h', 'w', 'b'): + for d in ('m', 'h', 'w', 'b', 'wH', 'bH', 'ws', 'bs'): ret[d] = _load_png('go_' + d + '.png') for d in ('u', 'd', 'l', 'r', 'm', 'dl', 'dr', 'ul', 'ur', 'h', 'w', 'b'): @@ -260,6 +276,17 @@ def _build_img_res(): height = ret[d + 'S'].get_height() square.composite(ret[d + 'S'], 0, 0, width, height, 0, 0, 1, 1, gtk.gdk.INTERP_NEAREST, 255) + ret[d + 'ws'] = ret[d].copy() + width = ret[d + 'ws'].get_width() + height = ret[d + 'ws'].get_height() + ws.composite(ret[d + 'ws'], 0, 0, width, height, 0, 0, 1, 1, gtk.gdk.INTERP_NEAREST, 255) + + ret[d + 'bs'] = ret[d].copy() + width = ret[d + 'bs'].get_width() + height = ret[d + 'bs'].get_height() + bs.composite(ret[d + 'bs'], 0, 0, width, height, 0, 0, 1, 1, gtk.gdk.INTERP_NEAREST, 255) + + return ret