pachi_py/extra_unused.pyx (225 lines of code) (raw):
THIS IS UNUSED
assert False
cdef int count_liberties(board* b, int c):
assert MAX_LIBERTY_COUNT <= GROUP_REFILL_LIBS
return board_group_info(b, group_at(b, c)).libs
cdef int MAX_LIBERTY_COUNT = 4
# "player" is either S_BLACK or S_WHITE
# "move" is a Pachi coord_t
cdef class Transition:
cdef public int color
cdef public PyPachiBoard state
cdef public int move
cdef public PyPachiBoard next_state
def __init__(self, int color, PyPachiBoard state, int move, PyPachiBoard next_state):
assert color == 0 or color == 1
self.color = color
self.state = state
self.move = move
self.next_state = next_state
def __richcmp__(Transition self, Transition other, int op):
if op != 2 and op != 3: return NotImplemented
cdef bint eq = self.color == other.color and self.state == other.state and self.move == other.move and self.next_state == other.next_state
return eq if op == 2 else not eq
cdef class PyRolloutResult:
cdef RolloutResult r
def __cinit__(self, RolloutResult r_):
self.r = r_
property black_final_score:
def __get__(self):
return self.r.black_final_score
property white_final_score:
def __get__(self):
return self.r.white_final_score
property black_resigned:
def __get__(self):
return self.r.black_resigned
property white_resigned:
def __get__(self):
return self.r.white_resigned
property winner:
def __get__(self):
return color2player(Winner(self.r))
cdef object _opponent_policy = None
cdef coord_t _opponent_policy_wrapper(PachiBoardPtr b, stone color):
cdef int action = _opponent_policy(wrap_board(b), color2player(color))
return action2coord(b.get().pachiboard(), action)
cdef object collect_transitions(const vector[PachiBoardPtr]& bhist, const vector[move]& mhist):
transitions = []
cdef int i, a
for i in range(mhist.size()):
a = coord2action(bhist[i].get().pachiboard(), mhist[i].coord)
if a == RESIGN_ACTION_ID: break # don't expose resigns
transitions.append(Transition(
player=color2player(mhist[i].color),
state=wrap_board(bhist[i]),
action=a,
next_state=wrap_board(bhist[i+1])
))
return transitions
def rollout_against_pachi(
PyPachiBoard init_b, int starting_player,
int pachi_player, string pachi_engine_type, string pachi_engine_arg, string pachi_timestr,
object opponent_policy_func):
cdef vector[PachiBoardPtr] bhist
cdef vector[move] mhist
global _opponent_policy; _opponent_policy = opponent_policy_func
cdef PyRolloutResult result = PyRolloutResult(RolloutAgainstPachi(
init_b._bptr,
player2color(starting_player),
player2color(pachi_player), pachi_engine_type, pachi_engine_arg, pachi_timestr,
_opponent_policy_wrapper,
&bhist, &mhist))
assert bhist.size() == mhist.size() + 1
return result, collect_transitions(bhist, mhist)
### Serialization of transition lists ###
def save_games(games):
cdef int out_size = 0
for transitions in games:
out_size += 2 + 2*len(transitions)
cdef np.ndarray[np.uint8_t,ndim=1] out = np.empty(out_size, np.uint8)
cdef PyPachiBoard init_state
cdef Transition t
cdef unsigned int pos = 0
for transitions in games:
init_state = transitions[0].state
assert init_state.empty, "only supports games starting from the empty state"
assert 0 <= init_state.size() < 256
assert 0 <= len(transitions) < 256
out[pos] = init_state.size()
out[pos+1] = len(transitions)
pos += 2
for t in transitions:
assert 0 <= t.player < 256
assert 0 <= t.action < 256
out[pos] = t.player
out[pos+1] = t.action
pos += 2
assert pos == out_size
return out
def reconstruct_games(np.uint8_t[:] data):
cdef int i, gamelen, boardsize, pos = 0
cdef vector[np.uint8_t] players, actions
cdef PyPachiBoard b, b2
games = []
while pos < len(data):
# read board size, game length, and actions
boardsize = data[pos]
gamelen = data[pos+1]
players.clear(); actions.clear()
for i in range(gamelen):
players.push_back(data[pos+2 + 2*i])
actions.push_back(data[pos+2 + 2*i+1])
pos += 2 + 2*gamelen
# replay
transitions = []
b = CreateBoard(boardsize)
for i in range(gamelen):
b2 = b.play(actions[i], players[i])
transitions.append(Transition(
player=players[i], state=b, action=actions[i], next_state=b2))
b = b2
games.append(transitions)
if len(games) % 1000 == 0:
print '[%.2f%%]' % (100.*float(pos)/len(data))
assert pos == len(data)
return games
## Deserialization from SGF ###
cdef move move_from_gtp(board* b, char* colorstr, char* coordstr):
cdef move m
m.color = str2stone(colorstr)
cdef coord_t *c = str2coord(coordstr, board_size(b))
m.coord = deref(c)
coord_done(c)
return m
cdef PyPachiBoard play_move(PyPachiBoard b, move m):
return wrap_board(Play(b._bptr, m))
cdef PyPachiBoard play_gtp(PyPachiBoard b, char* colorstr, char* coordstr):
return play_move(b, move_from_gtp(b._b.pachiboard(), colorstr, coordstr))
from pygo.sgflib import SGFParser
def ReplaySGF(const char* filename):
# Adapted from sgf2gtp.py in pachi
with open(filename, 'r') as f:
sgfdata = f.read()
col = SGFParser(sgfdata).parse()
assert len(col) == 1
gametree = col[0]
class UnknownNode(Exception):
pass
def get_atr(node, atr):
try:
return node.data[atr].data[0]
except KeyError:
return None
def get_setup(node, atr):
try:
return node.data[atr].data[:]
except KeyError:
return None
def col2num(column, board_size):
a, o, z = map(ord, ['a', column, 'z'])
if a <= o <= z:
return a + board_size - o
raise Exception( "Wrong column character: '%s'"%(column,) )
def is_pass_move(coord, board_size):
# the pass move is represented either by [] ( = empty coord )
# OR by [tt] (for boards <= 19 only)
return len(coord) == 0 or ( board_size <= 19 and coord == 'tt' )
def record_step(PyPachiBoard b, object coord):
cdef move m
if is_pass_move(coord, bsize):
m = move_from_gtp(b._b.pachiboard(), player_next, 'pass')
else:
x, y = coord
# The reason for this incredibly weird thing is that
# the GTP protocol excludes `i` in the coordinates
# (do you see any purpose in this??)
if x >= 'i':
x = chr(ord(x)+1)
y = str(col2num(y, bsize))
m = move_from_gtp(b._b.pachiboard(), player_next, x+y)
cdef PyPachiBoard next_b = play_move(b, m)
return Transition(
m.color,
b,
m.coord,
next_b
)
# cursor for tree traversal
c = gametree.cursor()
# first node is the header
header = c.node
handicap = get_atr(header, 'HA')
bsize = int(get_atr(header, 'SZ') or 19)
# assert bsize == 19
komi = get_atr(header, 'KM')
player_next, player_other = 'B', 'W'
setup_black = get_setup(header, 'AB')
setup_white = get_setup(header, 'AW')
ruleset = get_atr(header, 'RU')
cdef PyPachiBoard b = CreateBoard(bsize)
# if komi:
# b._pachi_board.komi = float(komi)
if handicap and handicap != '0':
#board_handicap(b._pachi_board, int(handicap), NULL)
# The dataset seems to have explicit AB/AW for handicap stones
# so don't use Pachi's add-handicap method here
player_next, player_other = player_other, player_next
if setup_black:
for item in setup_black:
x, y = item
if x >= 'i':
x = chr(ord(x)+1)
y = str(col2num(y, bsize))
b = play_gtp(b, 'B', x+y)
if setup_white:
for item in setup_white:
x, y = item
if x >= 'i':
x = chr(ord(x)+1)
y = str(col2num(y, bsize))
b = play_gtp(b, 'W', x+y)
if ruleset:
if ruleset.lower() == 'nz':
# board_set_rules only takes new_zealand
ruleset = 'new_zealand'
if not board_set_rules(b._b.pachiboard(), ruleset):
print 'Unrecognized ruleset %s for %s, defaulting to Pachi default' % (ruleset, filename)
# walk the game tree forward
game_transitions = []
while True:
# sgf2gtp.pl ignores n = 0
if c.atEnd:
break
c.next()
coord = get_atr(c.node, player_next)
if coord != None:
game_transitions.append(record_step(b, coord))
b = game_transitions[-1].next_state
else:
# MAYBE white started?
# or one of the players plays two time in a row
player_next, player_other = player_other, player_next
coord = get_atr(c.node, player_next)
if coord != None:
game_transitions.append(record_step(b, coord))
b = game_transitions[-1].next_state
elif len(c.node) != 0:
# TODO handle weird sgf files better
raise UnknownNode
player_next, player_other = player_other, player_next
return game_transitions