Implemented basic scoring code, so that scoring estimates are drawn at the end of a game

This commit is contained in:
Anna Rose 2012-04-21 02:50:52 -04:00
parent c8e8379308
commit 700a6a2f32
6 changed files with 92 additions and 31 deletions

View File

@ -5,8 +5,11 @@ class Goban:
EMPTY=0 EMPTY=0
WHITE=1 WHITE=1
BLACK=2 BLACK=2
# GRAY_WHITE=3 SCORE_BLACK=3
# GRAY_BLACK=4 SCORE_WHITE=4
SCORE_DAME=5
SCORING=6
def __init__(self, board_size=19): def __init__(self, board_size=19):
# Build the board intersections # 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): def pass_move(self, color=None):
if color is None: if color is None:
color = self.to_move color = self.to_move
@ -122,6 +124,9 @@ class Goban:
if self.passed_last: if self.passed_last:
self.to_move = Goban.EMPTY self.to_move = Goban.EMPTY
self.winner = Goban.SCORING
self.auto_score()
return range(len(self.board))
else: else:
self.to_move = self._other_color(color) self.to_move = self._other_color(color)
self.passed_last = True self.passed_last = True
@ -294,8 +299,9 @@ class Goban:
return None return None
point = self.board[pos] 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] code = self.def_draw_codes[pos]
elif point == Goban.BLACK: elif point == Goban.BLACK:
code = 'b' code = 'b'
@ -305,6 +311,10 @@ class Goban:
code = 'w' code = 'w'
if pos == self.last_move: if pos == self.last_move:
code += 'Cb' 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: if pos == self.ko:
code += 'S' code += 'S'
@ -312,6 +322,51 @@ class Goban:
return code 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): def _make_default_draw_codes(self):
ret = [] ret = []

View File

@ -62,6 +62,8 @@ class Pygo():
self.games.append_page(game, gtk.Label('Local Game')) self.games.append_page(game, gtk.Label('Local Game'))
self.games.set_tab_reorderable(game, True) self.games.set_tab_reorderable(game, True)
game.show_all() game.show_all()
game.winner_box.hide()
def on_net_direct(self, widget): def on_net_direct(self, widget):

View File

@ -128,29 +128,6 @@
<child> <child>
<placeholder/> <placeholder/>
</child> </child>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">label1</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">tab</property>
</packing>
</child>
</widget> </widget>
<packing> <packing>
<property name="padding">0</property> <property name="padding">0</property>

BIN
ui/res/go_bs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
ui/res/go_ws.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@ -50,6 +50,13 @@ class GoGame(gtk.HBox):
for row in info_rows: for row in info_rows:
info_box.pack_start(row, expand=False) 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.pass_button = gtk.Button('Pass')
self.resign_button = gtk.Button('Resign') self.resign_button = gtk.Button('Resign')
self.pass_button.connect('clicked', self.on_pass) self.pass_button.connect('clicked', self.on_pass)
@ -185,6 +192,16 @@ class GoGame(gtk.HBox):
move = 'White' move = 'White'
else: else:
move = 'None' 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.to_move_value.set_text(move)
self.black_cap_value.set_text(str(self.goban.black_captures)) self.black_cap_value.set_text(str(self.goban.black_captures))
self.white_cap_value.set_text(str(self.goban.white_captures)) self.white_cap_value.set_text(str(self.goban.white_captures))
@ -210,9 +227,8 @@ def _build_img_res():
circle_black = _load_png('go_circle_black.png') circle_black = _load_png('go_circle_black.png')
circle_white = _load_png('go_circle_white.png') circle_white = _load_png('go_circle_white.png')
square = _load_png('go_square.png') square = _load_png('go_square.png')
bs = _load_png('go_bs.png')
ret['wH'] = _load_png('go_wH.png') ws = _load_png('go_ws.png')
ret['bH'] = _load_png('go_bH.png')
ret['wT'] = _load_png('go_w.png') ret['wT'] = _load_png('go_w.png')
width = ret['wT'].get_width() width = ret['wT'].get_width()
@ -236,7 +252,7 @@ def _build_img_res():
ret['d'] = base.copy().rotate_simple(180) ret['d'] = base.copy().rotate_simple(180)
ret['r'] = base.copy().rotate_simple(270) 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') ret[d] = _load_png('go_' + d + '.png')
for d in ('u', 'd', 'l', 'r', 'm', 'dl', 'dr', 'ul', 'ur', 'h', 'w', 'b'): 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() height = ret[d + 'S'].get_height()
square.composite(ret[d + 'S'], 0, 0, width, height, 0, 0, 1, 1, gtk.gdk.INTERP_NEAREST, 255) 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 return ret