First semi-functional version of the libboard-based implementation
This commit is contained in:
parent
61d1965292
commit
5ad1eb46e9
205
lib/goban.py
205
lib/goban.py
|
@ -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'
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user