# A Python interface to libboard from gnugo # Also has functions for printing the board via pygame, # and for controlling that printing to some degree. # # I'm only implementing what I need for my own purposes. # Further API is welcome! from ctypes import * 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_ko_pos', c_int), ('initial_white_captured', c_int), ('initial_black_captured', c_int), ('move_history_color', c_int * MAX_MOVE_HISTORY), ('move_history_pos', c_int * MAX_MOVE_HISTORY), ('move_history_pointer', c_int), ('komi', c_float), ('move_number', c_int) ] class SGFTree(Structure): _fields_ = [ ('root', c_void_p), # SGFNode *root; ('lastnode', c_void_p) # SGFNode *lastnode; ] class Goban: libboard = None def __init__(self): if not Goban.libboard: Goban.libboard = CDLL('lib/libboard.so.0.0.0') self.board = board_state() Goban.libboard.clear_board() def play_move(pos, color): x,y = pos realpos = x * 19 + y if Goban.libboard.is_legal(realpos, color): Goban.libboard.play_move(realpos, color) return True else: return False def undo_move(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(): """Updates our internal cache of the board state. Needed before most accessor functions.""" Goban.libboard.store_board(self.board) def _restore_board(): """Use our cached board to update libboard's internal state.""" Goban.libboard.restore_board(self.board) def draw_board(): """ Return a pygame.Surface() with an image of the board. If pygame isn't available, this function prints an error and returns harmlessly.""" pass def draw_info(): """ 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)) # 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)) # 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)) # j += 1 # i += 1 # return ret.convert_alpha() # 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'