From 5ad1eb46e91ebc40381cf892c5793c507289e7de Mon Sep 17 00:00:00 2001 From: Anna Wiggins Date: Fri, 13 Apr 2012 00:38:11 -0400 Subject: [PATCH] First semi-functional version of the libboard-based implementation --- lib/goban.py | 205 +++++++++++++++++++++++++++++++-------------------- pygo.py | 1 - 2 files changed, 124 insertions(+), 82 deletions(-) diff --git a/lib/goban.py b/lib/goban.py index ae99532..0ae9992 100644 --- a/lib/goban.py +++ b/lib/goban.py @@ -5,21 +5,26 @@ # I'm only implementing what I need for my own purposes. # Further API is welcome! - from ctypes import * +try: + import pygame + have_pygame = True +except ImportError: + print 'Warning: pygame is not installed. Goban.draw_board() and Goban.draw_info() will fail.' + have_pygame = False + +BOARDSIZE=361 +MAX_MOVE_HISTORY=361 class board_state(Structure): - BOARDSIZE = 19 - MAX_MOVE_HISTORY = 361 - _fields_ = [ ('board_size', c_int), ('board', c_char * BOARDSIZE), ('board_ko_pos', c_int), ('black_captured', c_int), ('white_captured', c_int), - ('initial_board', c_int * BOARDSIZE), + ('initial_board', c_char * BOARDSIZE), ('initial_board_ko_pos', c_int), ('initial_white_captured', c_int), @@ -41,23 +46,43 @@ class SGFTree(Structure): ] +# class Gameinfo(Structure): +# _fields_ = [ +# ('handicap', c_int), +# ('to_move', c_int), +# ('game_record', SGFTree), +# ('computer_player', c_int), +# ('outfilename', c_char * 128), +# ('outfile', c_void_p) +# ] + + class Goban: + # This is our dynamic interface to the gnugo libraries libboard = None + BLACK = 2 + WHITE = 1 + EMPTY = 0 def __init__(self): if not Goban.libboard: Goban.libboard = CDLL('lib/libboard.so') - self.board = board_state() - Goban.libboard.clear_board() + self.to_move = Goban.BLACK + self.hover = None - def play_move(self, pos, color): + def play_move(self, pos, color=None): + """Make a move.""" + x,y = pos - realpos = x * 19 + y - + realpos = x*19 + y + + if color is None: + color = self.to_move + if Goban.libboard.is_legal(realpos, color): Goban.libboard.play_move(realpos, color) return True @@ -67,95 +92,113 @@ class Goban: def undo_move(self, n): """Undo n moves. Return True on success, False on failure. On failure, no moves are removed.""" + return Goban.libboard.undo_move(n) - def _update_board(self): - """Updates our internal cache of the board state. Needed before most accessor functions.""" - Goban.libboard.store_board(self.board) + def set_hover(self, pos): + x,y = pos + realpos = x*19 + y + + if self.hover == realpos: + return + + if Goban.libboard.is_legal(realpos): + self.hover = realpos + else: + self.clear_hover() - def _restore_board(self): - """Use our cached board to update libboard's internal state.""" - Goban.libboard.restore_board(self.board) + def clear_hover(self): + self.hover = None - def draw_board(self, board_size, img_res): + def OTHER_COLOR(self, color): + if color == Goban.WHITE: + return Goban.BLACK + elif color == Goban.BLACK: + return Goban.WHITE + else: + return Goban.EMPTY + + + def draw_board(self, size, img_res): """ Return a pygame.Surface() with an image of the board. If pygame isn't available, this function prints an error and returns harmlessly.""" - pass + + if not have_pygame: + return + ret = pygame.Surface((size,size)) + + inc = size / 19 + + p = c_int * 361 + board = p.in_dll(Goban.libboard, 'board') + + for pos in range(361): + s = img_res[self._get_draw_code(pos, board[pos])] + s = pygame.transform.scale(s, (inc, inc)) + ret.blit(s, ((pos%19)*inc, (pos/19)*inc)) + + if self.hover == pos: + c = img_res['bH'] + if self.to_move == Goban.WHITE: + c = img_res['wH'] + + c = pygame.transform.scale(c, (inc, inc)) + ret.blit(c, ((pos%19)*inc, (pos/19)*inc)) + + return ret.convert_alpha() + def draw_info(self): """ Return a pygame.Surface() with an image of text describing the game state. If pygame isn't available, this function prints an error and returns harmlessly.""" - pass - -# def draw_board(self, size, img_res): -# ret = pygame.Surface((size,size)) + if not have_pygame: + return -# inc = size / 19; -# i = 0 -# for row in self.board: -# j = 0 -# for square in row: -# s = img_res[square.get_draw_code()] -# s = pygame.transform.scale(s, (inc, inc)) -# ret.blit(s, (j*inc,i*inc)) + textbox = pygame.Surface((150, 300)) + textbox = textbox.convert() + textbox.fill((250, 250, 250)) -# if self.hover == square: -# c = img_res['bH'] -# if self.turn == 1: -# c = img_res['wH'] -# c = pygame.transform.scale(c, (inc, inc)) -# ret.blit(c, (j*inc,i*inc)) + font = pygame.font.Font(None, 24) + # heading = font.render('Captures', 1, (10, 10, 10)) + # black_cap = font.render('Black: {}'.format(self.captures[0]), 1, (10, 10, 10)) + # white_cap = font.render('White: {}'.format(self.captures[1]), 1, (10, 10, 10)) + # turn = font.render('Turn: {}'.format(['Black', 'White'][self.turn]), 1, (10, 10, 10)) -# j += 1 -# i += 1 + # textbox.blit(heading, (0, 0)) + # textbox.blit(black_cap, (0, 28)) + # textbox.blit(white_cap, (0, 56)) + # textbox.blit(turn, (0, 100)) -# return ret.convert_alpha() + return textbox -# def draw_info(self): -# textbox = pygame.Surface((150, 300)) -# textbox = textbox.convert() -# textbox.fill((250, 250, 250)) - -# font = pygame.font.Font(None, 24) -# time = font.render('Time: {:02d}:{:02d}'.format(self.elapsed_time / 60, self.elapsed_time % 60), 1, (10, 10, 10)) -# heading = font.render('Captures', 1, (10, 10, 10)) -# black_cap = font.render('Black: {}'.format(self.captures[0]), 1, (10, 10, 10)) -# white_cap = font.render('White: {}'.format(self.captures[1]), 1, (10, 10, 10)) -# turn = font.render('Turn: {}'.format(['Black', 'White'][self.turn]), 1, (10, 10, 10)) - -# textbox.blit(heading, (0, 0)) -# textbox.blit(black_cap, (0, 28)) -# textbox.blit(white_cap, (0, 56)) -# textbox.blit(turn, (0, 100)) -# textbox.blit(time, (0, 150)) - -# return textbox - - - -# if (self.x, self.y) == (1,1): -# self.default_draw_code = 'ul' -# elif (self.x, self.y) == (1,19): -# self.default_draw_code = 'ur' -# elif (self.x, self.y) == (19,1): -# self.default_draw_code = 'dl' -# elif (self.x, self.y) == (19,19): -# self.default_draw_code = 'dr' -# elif (self.x, self.y) in [(4,4), (4,10), (4,16), (10,4), (10,10), (10,16), (16,4), (16,10), (16,16)]: -# self.default_draw_code = 'h' -# elif self.x == 1: -# self.default_draw_code = 'u' -# elif self.y == 1: -# self.default_draw_code = 'l' -# elif self.x == 19: -# self.default_draw_code = 'd' -# elif self.y == 19: -# self.default_draw_code = 'r' -# else: -# self.default_draw_code = 'm' + def _get_draw_code(self, pos, board_value): + if board_value == Goban.BLACK: + return 'b' + if board_value == Goban.WHITE: + return 'w' + if pos == 0: + return 'ul' + if pos == 18: + return 'ur' + if pos == 341: + return 'dl' + if pos == 360: + return 'dr' + if pos in [60, 66, 72, 174, 180, 186, 288, 294, 300]: + return 'h' + if pos < 18: + return 'u' + if pos % 19 == 0: + return 'l' + if pos > 341: + return 'd' + if pos % 19 == 18: + return 'r' + else: + return 'm' diff --git a/pygo.py b/pygo.py index f3822ea..590ed05 100755 --- a/pygo.py +++ b/pygo.py @@ -86,7 +86,6 @@ def main(): screen.blit(background, (0, 0)) pygame.display.flip() - while True: event = pygame.event.wait()