Implemented basic scoring code, so that scoring estimates are drawn at the end of a game
This commit is contained in:
parent
c8e8379308
commit
700a6a2f32
63
lib/goban.py
63
lib/goban.py
|
@ -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 = []
|
||||||
|
|
2
pygo.py
2
pygo.py
|
@ -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):
|
||||||
|
|
|
@ -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
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
BIN
ui/res/go_ws.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.9 KiB |
|
@ -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,10 +227,9 @@ 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')
|
||||||
|
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')
|
ret['wT'] = _load_png('go_w.png')
|
||||||
width = ret['wT'].get_width()
|
width = ret['wT'].get_width()
|
||||||
height = ret['wT'].get_height()
|
height = ret['wT'].get_height()
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user