154 lines
4.2 KiB
Python
154 lines
4.2 KiB
Python
#!/usr/bin/env python
|
|
|
|
from __future__ import print_function
|
|
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 display(self):
|
|
map = {
|
|
"empty": " ", "varys": "*", "tully": "U",
|
|
"tyrell": "Y", "baratheon": "B", "targaryen": "T",
|
|
"lannister": "L", "greyjoy": "G", "stark": "S",
|
|
}
|
|
for row in self.board:
|
|
for card in row:
|
|
house = str(card.house)
|
|
print(map[house], end='')
|
|
print()
|
|
|
|
print()
|
|
|
|
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]
|
|
# If it is of the same house as declared
|
|
if (card.house == picked_card.house):
|
|
# Pick it up
|
|
picked_cards.append(card)
|
|
empty_card = game.Card.new_message()
|
|
empty_card.house = game.House.empty
|
|
self.board[row][col] = empty_card
|
|
|
|
self.display()
|
|
return self
|
|
|
|
def findVarys(self):
|
|
for card in self.state.cardlist:
|
|
if card.house == 'varys':
|
|
return card.location
|
|
|
|
"""
|
|
Returns true if the game has
|
|
reached the final state ie
|
|
there are no legal possible moves
|
|
"""
|
|
|
|
def gameOver(self):
|
|
return (len(self.getPossibleMoves()) == 0)
|
|
|
|
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))
|
|
|
|
print(len(moves))
|
|
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:
|
|
# print(self.board[xx][yy])
|
|
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
|
|
|
|
|
|
if(__name__ == "__main__"):
|
|
f = open('state.bin', 'rb')
|
|
initial_state = game.State.read_packed(f)
|
|
s = State(initial_state)
|
|
s.display()
|
|
|
|
root_node = GameNode(s, None)
|
|
print(root_node.chooseChild())
|