diff --git a/gothok/.gitignore b/gothok/.gitignore index 87bbc9d..4da9718 100644 --- a/gothok/.gitignore +++ b/gothok/.gitignore @@ -1,7 +1,6 @@ build/ python/ *.cpp -*.py *.cpp *.h *.pyx diff --git a/gothok/game.capnp b/gothok/game.capnp new file mode 100644 index 0000000..6527c0d --- /dev/null +++ b/gothok/game.capnp @@ -0,0 +1,5 @@ +@0x98bd43b3ed130136; + +interface Game { + +} diff --git a/gothok/game.py b/gothok/game.py new file mode 100644 index 0000000..bf2bb7e --- /dev/null +++ b/gothok/game.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python + +import capnp +import state_capnp as game + + +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 findVarys(self): + for card in self.state.cardlist: + if card.house == 'varys': + return card.location + + def getPossibleMoves(self): + moves = [] + + for x in xrange(0, 5): + for y in xrange(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 + + +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 chooseChild(self): + # Define children nodes + if(not self.children): + self.children = self.getChildren(self.state) + + # 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') +initial_state = game.State.read_packed(f) + +# print(initial_state) +s = State(initial_state) +print(s.getPossibleMoves()) + +# 3,2 diff --git a/gothok/init b/gothok/init index bcf3e21..815617f 100755 --- a/gothok/init +++ b/gothok/init @@ -26,12 +26,11 @@ cardlist = state.init('cardlist', 36) for index, card in enumerate(cards): location = game.Location.new_message() location.board.x = index / 6 - location.board.x = index % 6 + location.board.y = index % 6 card.location = location cardlist[index] = card -# print(state) - # Now we have an initial state of the game, write it down f = open('state.bin', 'w+b') state.write_packed(f) +f.close()