First semi-functional version of the libboard-based implementation

This commit is contained in:
Anna Rose 2012-04-13 00:38:11 -04:00
parent 61d1965292
commit 5ad1eb46e9
2 changed files with 124 additions and 82 deletions

View File

@ -5,21 +5,26 @@
# I'm only implementing what I need for my own purposes. # I'm only implementing what I need for my own purposes.
# Further API is welcome! # Further API is welcome!
from ctypes import * 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): class board_state(Structure):
BOARDSIZE = 19
MAX_MOVE_HISTORY = 361
_fields_ = [ _fields_ = [
('board_size', c_int), ('board_size', c_int),
('board', c_char * BOARDSIZE), ('board', c_char * BOARDSIZE),
('board_ko_pos', c_int), ('board_ko_pos', c_int),
('black_captured', c_int), ('black_captured', c_int),
('white_captured', c_int), ('white_captured', c_int),
('initial_board', c_int * BOARDSIZE), ('initial_board', c_char * BOARDSIZE),
('initial_board_ko_pos', c_int), ('initial_board_ko_pos', c_int),
('initial_white_captured', 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: class Goban:
# This is our dynamic interface to the gnugo libraries
libboard = None libboard = None
BLACK = 2
WHITE = 1
EMPTY = 0
def __init__(self): def __init__(self):
if not Goban.libboard: if not Goban.libboard:
Goban.libboard = CDLL('lib/libboard.so') Goban.libboard = CDLL('lib/libboard.so')
self.board = board_state()
Goban.libboard.clear_board() 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 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): if Goban.libboard.is_legal(realpos, color):
Goban.libboard.play_move(realpos, color) Goban.libboard.play_move(realpos, color)
return True return True
@ -67,95 +92,113 @@ class Goban:
def undo_move(self, n): def undo_move(self, n):
"""Undo n moves. Return True on success, False on failure. On failure, no moves are removed.""" """Undo n moves. Return True on success, False on failure. On failure, no moves are removed."""
return Goban.libboard.undo_move(n) return Goban.libboard.undo_move(n)
def _update_board(self): def set_hover(self, pos):
"""Updates our internal cache of the board state. Needed before most accessor functions.""" x,y = pos
Goban.libboard.store_board(self.board) 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): def clear_hover(self):
"""Use our cached board to update libboard's internal state.""" self.hover = None
Goban.libboard.restore_board(self.board)
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. """ Return a pygame.Surface() with an image of the board.
If pygame isn't available, this function prints an error and returns harmlessly.""" 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): def draw_info(self):
""" Return a pygame.Surface() with an image of text describing the game state. """ 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.""" If pygame isn't available, this function prints an error and returns harmlessly."""
pass
if not have_pygame:
# def draw_board(self, size, img_res): return
# ret = pygame.Surface((size,size))
# inc = size / 19; textbox = pygame.Surface((150, 300))
# i = 0 textbox = textbox.convert()
# for row in self.board: textbox.fill((250, 250, 250))
# 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: font = pygame.font.Font(None, 24)
# c = img_res['bH'] # heading = font.render('Captures', 1, (10, 10, 10))
# if self.turn == 1: # black_cap = font.render('Black: {}'.format(self.captures[0]), 1, (10, 10, 10))
# c = img_res['wH'] # white_cap = font.render('White: {}'.format(self.captures[1]), 1, (10, 10, 10))
# c = pygame.transform.scale(c, (inc, inc)) # turn = font.render('Turn: {}'.format(['Black', 'White'][self.turn]), 1, (10, 10, 10))
# ret.blit(c, (j*inc,i*inc))
# j += 1 # textbox.blit(heading, (0, 0))
# i += 1 # 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): def _get_draw_code(self, pos, board_value):
# textbox = pygame.Surface((150, 300)) if board_value == Goban.BLACK:
# textbox = textbox.convert() return 'b'
# textbox.fill((250, 250, 250)) if board_value == Goban.WHITE:
return 'w'
# font = pygame.font.Font(None, 24) if pos == 0:
# time = font.render('Time: {:02d}:{:02d}'.format(self.elapsed_time / 60, self.elapsed_time % 60), 1, (10, 10, 10)) return 'ul'
# heading = font.render('Captures', 1, (10, 10, 10)) if pos == 18:
# black_cap = font.render('Black: {}'.format(self.captures[0]), 1, (10, 10, 10)) return 'ur'
# white_cap = font.render('White: {}'.format(self.captures[1]), 1, (10, 10, 10)) if pos == 341:
# turn = font.render('Turn: {}'.format(['Black', 'White'][self.turn]), 1, (10, 10, 10)) return 'dl'
if pos == 360:
# textbox.blit(heading, (0, 0)) return 'dr'
# textbox.blit(black_cap, (0, 28)) if pos in [60, 66, 72, 174, 180, 186, 288, 294, 300]:
# textbox.blit(white_cap, (0, 56)) return 'h'
# textbox.blit(turn, (0, 100)) if pos < 18:
# textbox.blit(time, (0, 150)) return 'u'
if pos % 19 == 0:
# return textbox return 'l'
if pos > 341:
return 'd'
if pos % 19 == 18:
# if (self.x, self.y) == (1,1): return 'r'
# self.default_draw_code = 'ul' else:
# elif (self.x, self.y) == (1,19): return 'm'
# 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'

View File

@ -86,7 +86,6 @@ def main():
screen.blit(background, (0, 0)) screen.blit(background, (0, 0))
pygame.display.flip() pygame.display.flip()
while True: while True:
event = pygame.event.wait() event = pygame.event.wait()