boardgame2vec/gothok/game.py

123 lines
3.4 KiB
Python

#!/usr/bin/env python
import capnp
import state_capnp as game
from mcts import GameNode
# https://blog.theofekfoundation.org/artificial-intelligence/2016/06/27/what-is-the-monte-carlo-tree-search/
class State():
def initBoard(self):
self.board = [[None]*6 for _ in range(6)]
for card in self.state.cardlist:
if (card.location.board):
x = card.location.board.x
y = card.location.board.y
self.board[x][y] = card
def __init__(self, state):
self.state = state
self.initBoard()
pass
def playMove(self, move):
(xx, yy) = move
picked_card = self.board[xx][yy]
varys = self.findVarys()
vx = varys.board.x
vy = varys.board.y
if (vx == xx):
left = min(yy, vy)
right = max(yy, vy)
# We want this to be inclusive
cards_attempted = [(vx, y) for y in range(left, right + 1)]
elif(vy == yy):
top = min(xx, vx)
bottom = max(xx, vx)
# We want this to be inclusive
cards_attempted = [(x, vy) for x in range(top, bottom + 1)]
else:
raise Exception("Invalid move")
picked_cards = []
# TODO: switch this to a filter on cards_attempted
for (row, col) in cards_attempted:
card = self.board[row][col]
print(card.house, picked_card.house)
# If it is of the same house as declared
if (card.house == picked_card.house):
# Pick it up
picked_cards.append(card)
self.board[row][col] = game.House.empty
print(picked_cards)
def findVarys(self):
for card in self.state.cardlist:
if card.house == 'varys':
return card.location
def getPossibleMoves(self):
moves = []
for x in range(0, 5):
for y in range(0, 5):
if (self.isLegalMoveLocation(x, y)):
moves.append((x, y))
return moves
def isLegalMoveLocation(self, x, y):
varys = self.findVarys()
vx = varys.board.x
vy = varys.board.y
# Row/Column must match
if (vx == x and vy == y):
return False
if (vx == x):
# Generate all y between y and vy
# See if this is the furthest for this card type
# newCardType = self.board
if (vy > y):
l = [(x, i) for i in range(0, vy)]
else:
l = [(x, i) for i in range(vy+1, 6)]
l.reverse()
elif (vy == y):
# Generate all x between x and vx
if (vx > x):
l = [(i, y) for i in range(0, vx)]
else:
l = [(i, y) for i in range(vx+1, 6)]
l.reverse()
pass
else:
return False
seen = {}
for (xx, yy) in l:
house = self.board[xx][yy].house
if str(house) in seen:
return False
# We stop testing as soon as we reach the new location
if (x == xx and y == yy):
return True
seen[str(house)] = True
f = open('state.bin', 'rb')
initial_state = game.State.read_packed(f)
s = State(initial_state)
root_node = GameNode(s, None)
print(root_node.chooseChild())