Splits mcts code into separate file
This commit is contained in:
parent
5449cc2a25
commit
e38012b8fd
|
@ -6,3 +6,4 @@ python/
|
||||||
*.pyx
|
*.pyx
|
||||||
*.so
|
*.so
|
||||||
*.bin
|
*.bin
|
||||||
|
*.pyc
|
||||||
|
|
115
gothok/game.py
115
gothok/game.py
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import capnp
|
import capnp
|
||||||
import state_capnp as game
|
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/
|
# https://blog.theofekfoundation.org/artificial-intelligence/2016/06/27/what-is-the-monte-carlo-tree-search/
|
||||||
|
|
||||||
|
@ -24,8 +25,9 @@ class State():
|
||||||
|
|
||||||
def playMove(self, move):
|
def playMove(self, move):
|
||||||
(xx, yy) = move
|
(xx, yy) = move
|
||||||
|
picked_card = self.board[xx][yy]
|
||||||
|
|
||||||
varys = self.findVarys
|
varys = self.findVarys()
|
||||||
vx = varys.board.x
|
vx = varys.board.x
|
||||||
vy = varys.board.y
|
vy = varys.board.y
|
||||||
|
|
||||||
|
@ -42,13 +44,20 @@ class State():
|
||||||
else:
|
else:
|
||||||
raise Exception("Invalid move")
|
raise Exception("Invalid move")
|
||||||
|
|
||||||
|
picked_cards = []
|
||||||
|
|
||||||
|
# TODO: switch this to a filter on cards_attempted
|
||||||
|
|
||||||
for (row, col) in cards_attempted:
|
for (row, col) in cards_attempted:
|
||||||
card = self.board[row][col]
|
card = self.board[row][col]
|
||||||
|
print(card.house, picked_card.house)
|
||||||
# If it is of the same house as declared
|
# If it is of the same house as declared
|
||||||
if (card == picked_card):
|
if (card.house == picked_card.house):
|
||||||
# Pick it up
|
# Pick it up
|
||||||
state['cards'][current].append(picked_card)
|
picked_cards.append(card)
|
||||||
state['board'][row][col] = self.EMPTY
|
self.board[row][col] = game.House.empty
|
||||||
|
|
||||||
|
print(picked_cards)
|
||||||
|
|
||||||
def findVarys(self):
|
def findVarys(self):
|
||||||
for card in self.state.cardlist:
|
for card in self.state.cardlist:
|
||||||
|
@ -106,102 +115,8 @@ class State():
|
||||||
seen[str(house)] = True
|
seen[str(house)] = True
|
||||||
|
|
||||||
|
|
||||||
class GameNode(object):
|
|
||||||
"""docstring for GameNode"""
|
|
||||||
|
|
||||||
def __init__(self, state, parent):
|
|
||||||
super(GameNode, self).__init__()
|
|
||||||
self.state = state
|
|
||||||
self.parent = parent
|
|
||||||
|
|
||||||
self.hits = 0
|
|
||||||
self.misses = 0
|
|
||||||
self.totalTrials = 0
|
|
||||||
|
|
||||||
def backPropagate(self, simulation):
|
|
||||||
if (simulation > 0):
|
|
||||||
self.hits += 1
|
|
||||||
elif (simulation < 0):
|
|
||||||
self.misses += 1
|
|
||||||
self.totalTrials += 1
|
|
||||||
|
|
||||||
if self.parent:
|
|
||||||
self.parent.backPropagate(-simulation)
|
|
||||||
|
|
||||||
def childPotential(self, child):
|
|
||||||
w = child.misses
|
|
||||||
n = child.totalTrials
|
|
||||||
|
|
||||||
# Chosen empirically
|
|
||||||
c = math.sqrt(2)
|
|
||||||
t = self.totalTrials
|
|
||||||
|
|
||||||
return (w / n) + (c * math.sqrt(log(t) / n))
|
|
||||||
|
|
||||||
def runSimulation(self):
|
|
||||||
self.backPropagate(self.simulate())
|
|
||||||
|
|
||||||
def simulate(self):
|
|
||||||
state = self.state
|
|
||||||
|
|
||||||
while not state.gameOver:
|
|
||||||
moves = state.getPossibleMoves()
|
|
||||||
randomMove = random.choice(possibleMoves)
|
|
||||||
state = state.playMove(randomMove)
|
|
||||||
|
|
||||||
return self.state.result(state)
|
|
||||||
|
|
||||||
def getChildren(self):
|
|
||||||
possibleMoves = self.state.getPossibleMoves()
|
|
||||||
children = []
|
|
||||||
|
|
||||||
for move in possibleMoves:
|
|
||||||
newState = self.state.playMove(move)
|
|
||||||
childNode = GameNode(newState, self.state)
|
|
||||||
children.append(childNode)
|
|
||||||
|
|
||||||
return children
|
|
||||||
|
|
||||||
def chooseChild(self):
|
|
||||||
# Define children nodes
|
|
||||||
if(not self.children):
|
|
||||||
self.children = self.getChildren()
|
|
||||||
|
|
||||||
# Run simulation on leaf nodes
|
|
||||||
if(len(self.children) == 0):
|
|
||||||
self.runSimulation()
|
|
||||||
else:
|
|
||||||
unexplored = []
|
|
||||||
|
|
||||||
# Get all unexplored nodes
|
|
||||||
for child in self.children:
|
|
||||||
if (child.totalTrials == 0):
|
|
||||||
unexplored.append(child)
|
|
||||||
|
|
||||||
# Pick a random unexplored node
|
|
||||||
# and run the simulation on it
|
|
||||||
if (len(unexplored) > 0):
|
|
||||||
random.choice(unexplored).runSimulation()
|
|
||||||
else:
|
|
||||||
# Find the best child
|
|
||||||
bestChild = self.children[0]
|
|
||||||
bestPotential = self.childPotential(bestChild)
|
|
||||||
|
|
||||||
for child in self.children:
|
|
||||||
potential = self.childPotential(child)
|
|
||||||
|
|
||||||
if (potential > bestPotential):
|
|
||||||
bestPotential = potential
|
|
||||||
bestChild = child
|
|
||||||
|
|
||||||
bestChild.chooseChild()
|
|
||||||
|
|
||||||
|
|
||||||
f = open('state.bin', 'rb')
|
f = open('state.bin', 'rb')
|
||||||
initial_state = game.State.read_packed(f)
|
initial_state = game.State.read_packed(f)
|
||||||
|
|
||||||
# print(initial_state)
|
|
||||||
s = State(initial_state)
|
s = State(initial_state)
|
||||||
print((s.getPossibleMoves()))
|
root_node = GameNode(s, None)
|
||||||
|
print(root_node.chooseChild())
|
||||||
# 3,2
|
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
class GameNode(object):
|
||||||
|
"""docstring for GameNode"""
|
||||||
|
|
||||||
|
def __init__(self, state, parent):
|
||||||
|
super(GameNode, self).__init__()
|
||||||
|
self.state = state
|
||||||
|
self.parent = parent
|
||||||
|
|
||||||
|
self.hits = 0
|
||||||
|
self.misses = 0
|
||||||
|
self.totalTrials = 0
|
||||||
|
|
||||||
|
def backPropagate(self, simulation):
|
||||||
|
if (simulation > 0):
|
||||||
|
self.hits += 1
|
||||||
|
elif (simulation < 0):
|
||||||
|
self.misses += 1
|
||||||
|
self.totalTrials += 1
|
||||||
|
|
||||||
|
if self.parent:
|
||||||
|
self.parent.backPropagate(-simulation)
|
||||||
|
|
||||||
|
def childPotential(self, child):
|
||||||
|
w = child.misses
|
||||||
|
n = child.totalTrials
|
||||||
|
|
||||||
|
# Chosen empirically
|
||||||
|
c = math.sqrt(2)
|
||||||
|
t = self.totalTrials
|
||||||
|
|
||||||
|
return (w / n) + (c * math.sqrt(log(t) / n))
|
||||||
|
|
||||||
|
def runSimulation(self):
|
||||||
|
self.backPropagate(self.simulate())
|
||||||
|
|
||||||
|
def simulate(self):
|
||||||
|
state = self.state
|
||||||
|
|
||||||
|
while not state.gameOver:
|
||||||
|
moves = state.getPossibleMoves()
|
||||||
|
randomMove = random.choice(possibleMoves)
|
||||||
|
state = state.playMove(randomMove)
|
||||||
|
|
||||||
|
return self.state.result(state)
|
||||||
|
|
||||||
|
def getChildren(self):
|
||||||
|
possibleMoves = self.state.getPossibleMoves()
|
||||||
|
children = []
|
||||||
|
|
||||||
|
for move in possibleMoves:
|
||||||
|
newState = self.state.playMove(move)
|
||||||
|
childNode = GameNode(newState, self.state)
|
||||||
|
children.append(childNode)
|
||||||
|
|
||||||
|
return children
|
||||||
|
|
||||||
|
def chooseChild(self):
|
||||||
|
# Define children nodes
|
||||||
|
try:
|
||||||
|
self.children
|
||||||
|
except Exception as e:
|
||||||
|
self.children = self.getChildren()
|
||||||
|
|
||||||
|
if(len(self.children) == 0):
|
||||||
|
self.runSimulation()
|
||||||
|
else:
|
||||||
|
unexplored = []
|
||||||
|
|
||||||
|
# Get all unexplored nodes
|
||||||
|
for child in self.children:
|
||||||
|
if (child.totalTrials == 0):
|
||||||
|
unexplored.append(child)
|
||||||
|
|
||||||
|
# Pick a random unexplored node
|
||||||
|
# and run the simulation on it
|
||||||
|
if (len(unexplored) > 0):
|
||||||
|
random.choice(unexplored).runSimulation()
|
||||||
|
else:
|
||||||
|
# Find the best child
|
||||||
|
bestChild = self.children[0]
|
||||||
|
bestPotential = self.childPotential(bestChild)
|
||||||
|
|
||||||
|
for child in self.children:
|
||||||
|
potential = self.childPotential(child)
|
||||||
|
|
||||||
|
if (potential > bestPotential):
|
||||||
|
bestPotential = potential
|
||||||
|
bestChild = child
|
||||||
|
|
||||||
|
bestChild.chooseChild()
|
Loading…
Reference in New Issue