def test_optimized_combined_heuristic(self): """test that the optimized, stateful heuristic provides the same values as the non-optimized one""" heuristic = CombinedHeuristic() optimized_heuristic = OptimizedCombinedHeuristic() game_1 = CCGame(width=5, visitors=[optimized_heuristic]) def heuristics_agree(): for player in [1, 2]: self.assertAlmostEqual(heuristic.value(game_1, player), optimized_heuristic.value(game_1, player), 2) game_1.move(2, 1, CCMovement.LS) heuristics_agree() game_1.move(7, 1, CCMovement.RN) heuristics_agree() game_1.undo_last_move() game_1.rotate_turn() heuristics_agree() game_1.undo_last_move() heuristics_agree()
def test_zobrist_hashing(self): game = CCGame(width=5) hasher = CCZobristHash(game) game_2 = CCGame(width=5) self.assertEqual(hasher.get_hash(game), hasher.get_hash(game_2)) game.move(2, 0, CCMovement.LS) self.assertFalse(hasher.get_hash(game) == hasher.get_hash(game_2))
def test_available_moves_depth_2(self): game = CCGame(width=5) game.move(2, 0, CCMovement.RS) game.rotate_turn() moves = CCReasoner.available_moves(game, 1) self.assertTrue( CCMove([(0, 0), (2, 0), (4, 2)], [CCMovement.LS, CCMovement.RS]) in moves) self.assertTrue( CCMove([(1, 0), (3, 2), (3, 0)], [CCMovement.RS, CCMovement.L]) in moves) self.assertTrue( CCMove([(2, 2), (2, 0), (4, 2)], [CCMovement.L, CCMovement.RS]) in moves)
def _available_moves(game: CCGame, row: int, column: int, player: int, previous_moves: list = [], previous_positions: list = []) -> List[CCMove]: """ Returns a dict a list of movements that the player can make, considering the piece found at 'row' and 'column' """ moves: List[CCMove] = [] jumping = game.player_can_only_jump def undo_movement(): if game.player_turn != player: game.rotate_turn() game.undo_last_move() if not jumping and game.player_can_only_jump: # reset jumping state game.player_can_only_jump = False for movement in CCMovement: if game.can_move(row, column, movement): turn = game.move(row, column, movement) if (game.moved_to_row[-1], game.moved_to_column[-1]) in previous_positions: # we already passed through this state, avoid # infinite recursion undo_movement() continue previous_positions.append( (game.moved_to_row[-1], game.moved_to_column[-1])) previous_moves.append(movement) moves.append(CCMove([*previous_positions], [*previous_moves])) if turn == player: # turn hasn't rotated -> current piece can still jump more moves += (CCReasoner._available_moves( game, game.moved_to_row[-1], game.moved_to_column[-1], player, previous_moves, previous_positions)) previous_positions.pop() previous_moves.pop() undo_movement() return moves