Skip to content

Commit

Permalink
Transposition table - caching states goodness
Browse files Browse the repository at this point in the history
Thanks to that we are never evaluating same state twice, 
which gives a speed up.
  • Loading branch information
AdamStelmaszczyk committed Sep 26, 2015
1 parent 28b984c commit 9f7ed4a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 2 deletions.
9 changes: 9 additions & 0 deletions examples/Isola.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ def set_player_cords(self, player, cords):
def __repr__(self):
return '\n'.join(['|'.join(row) for row in self.board]) + '\n'

def __eq__(self, other):
return self.board == other.board

def __ne__(self, other):
return not self.__eq__(self, other)

def __hash__(self):
return hash(tuple(tuple(row) for row in self.board))


class IsolaMove(Move):
def __init__(self, from_x, from_y, step_x, step_y, remove_x, remove_y):
Expand Down
13 changes: 11 additions & 2 deletions examples/TicTacToe.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ def count_players_on_lines(self, current_player, next_player):
def __repr__(self):
return '\n'.join(['|'.join(row) for row in self.board]) + '\n'

def __eq__(self, other):
return self.board == other.board

def __ne__(self, other):
return not self.__eq__(self, other)

def __hash__(self):
return hash(tuple(tuple(row) for row in self.board))


class TicTacToeMove(Move):
def __init__(self, x, y):
Expand Down Expand Up @@ -124,8 +133,8 @@ def read(self):
"___"
"___")

algorithm_1 = Human(PLAYER_1, PLAYER_2, TicTacToeMoveReader(state))
algorithm_2 = Minimax(PLAYER_2, PLAYER_1, 1)
algorithm_1 = Minimax(PLAYER_1, PLAYER_2, 10)
algorithm_2 = Minimax(PLAYER_2, PLAYER_1, 10)

tester = Tester(state, algorithm_1, algorithm_2)
tester.start()
28 changes: 28 additions & 0 deletions gtsa/gtsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class Algorithm(object):
def __init__(self, our_symbol, enemy_symbol):
self.our_symbol = our_symbol
self.enemy_symbol = enemy_symbol
self.state_cache = {}

def get_current_player(self):
return self.our_symbol
Expand All @@ -12,6 +13,14 @@ def get_next_player(self):
def get_move(self, state):
raise NotImplementedError("Implement get_move in Algorithm subclass")

def get_cached_goodness(self, state):
key = hash(state)
return self.state_cache.get(key, None)

def set_cached_goodness(self, state, goodness):
key = hash(state)
self.state_cache[key] = goodness

def __repr__(self):
return "{} {}".format(self.our_symbol, self.enemy_symbol)

Expand Down Expand Up @@ -52,6 +61,9 @@ def get_move(self, state):
return best_move

def _minimax(self, state, depth, analyzed_player):
cached_goodness = self.get_cached_goodness(state)
if cached_goodness:
return cached_goodness
legal_moves = state.get_legal_moves(analyzed_player)
if depth <= 0 or state.is_terminal(self.our_symbol, self.enemy_symbol):
return state.get_goodness(self.our_symbol, self.enemy_symbol)
Expand All @@ -71,6 +83,7 @@ def _minimax(self, state, depth, analyzed_player):
state.undo_move(move, analyzed_player)
if best_goodness > goodness:
best_goodness = goodness
self.set_cached_goodness(state, best_goodness)
return best_goodness


Expand All @@ -93,6 +106,15 @@ def is_terminal(self, current_player, next_player):
def __repr__(self):
raise NotImplementedError("Implement __repr__ in State subclass")

def __eq__(self, other):
raise NotImplementedError("Implement __eq__ in State subclass")

def __ne__(self, other):
raise NotImplementedError("Implement __ne__ in State subclass")

def __hash__(self):
raise NotImplementedError("Implement __hash__ in State subclass")


class Move(object):
def __repr__(self):
Expand All @@ -101,6 +123,12 @@ def __repr__(self):
def __eq__(self, other):
raise NotImplementedError("Implement __eq__ in Move subclass")

def __ne__(self, other):
raise NotImplementedError("Implement __ne__ in Move subclass")

def __hash__(self):
raise NotImplementedError("Implement __hash__ in State subclass")


class MoveReader(object):
def __init__(self, state):
Expand Down

0 comments on commit 9f7ed4a

Please sign in to comment.