def test_check_lines(self): win_state = "XXX------" win_dict = Board._decompose_board(win_state) no_win_state = "XOX------" no_win_dict = Board._decompose_board(no_win_state) assert Board._check_lines(win_dict) is not None assert Board._check_lines(no_win_dict) is None
def train(self, player=Player('X'), board=Board(), previous_key=None, previous_move=None): memory_key = Model.MEMORY_KEY.format(player.char, board.key) if memory_key not in self.memory.keys(): self.memory[memory_key] = { 'weights': [0, 0, 0, 0, 0, 0, 0, 0, 0], 'childs': [], 'previous_key': previous_key, 'previous_move': previous_move } self._set_all_related(memory_key) for index in range(9): _board = Board(board.key) done, winner = _board.add(player, index) if done: if winner: self._set_weight( memory_key, index, 3.0 if winner.char == 'X' else -2.0 if winner.char == 'O' else -1.0) if winner is False: self.train( player=Player('X' if player.char == 'O' else 'O'), board=_board, previous_key=memory_key, previous_move=index) if not previous_key: self._cleanup()
def generateindex(self, b=None, s=''): if b == None: b = Board() self.values.update({b.tuplize(): 0.0}) if s == '' or s == b.circle: next_s = b.cross else: next_s = b.circle for m in b.status['moves']: b_next = b.copy() b_next.move(m, next_s) winner = b_next.winner() if winner == 'n': self.generateindex(b_next, next_s) elif winner == ' ': value = 0.5 self.values.update({b_next.tuplize(): value}) elif winner == b.cross: value = 1.0 self.values.update({b_next.tuplize(): value}) else: value = -1.0 self.values.update({b_next.tuplize(): value}) return self.values
def test_input(self): """Confirm inputMove properly encodes game data""" board = Board() board.inputMove(5, "X") self.assertEqual(board.gs[5], "X") self.assertEqual(board.gs[4], " ") self.assertEqual(board.gs[6], " ")
def test_create_lines(self): board = Board(dimensions=(0,0)) line = board.create_line(start=(0,7), vector=(1,-1), length=8) self.assertEqual( line, [(0, 7), (1, 6), (2, 5), (3, 4), (4, 3), (5, 2), (6, 1), (7, 0)] )
class TestDiagonal(unittest.TestCase): def setUp(self): self.game = Board() def test_diagonal1_player1(self): self.game.board = [['X', '_', '_'], ['_', 'X', '_'], ['_', '_', 'X']] self.assertEqual(self.game.check_diagonals(), 1) def test_diagonal1_player2(self): self.game.board = [['O', '_', '_'], ['_', 'O', '_'], ['_', '_', 'O']] self.assertEqual(self.game.check_diagonals(), 2) def test_diagonal2_player1(self): self.game.board = [['_', '_', 'X'], ['_', 'X', '_'], ['X', '_', '_']] self.assertEqual(self.game.check_diagonals(), 1) def test_empty(self): self.game.board = [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']] self.assertEqual(self.game.check_diagonals(), 0) def test_no_cols(self): self.game.board = [['X', 'X', 'X'], ['_', 'O', 'O'], ['_', 'X', 'O']] self.assertEqual(self.game.check_diagonals(), 0)
def test_render_position_returns_symbol_when_position_is_not_empty(self): board = Board() ui = ConsoleUI(board) player = ComputerPlayer(board) player.symbol = 'X' board.set_position(4, player) assert ui.render_position(4) == 'X'
def test_check_for_winning_line(self): board = Board(dimensions=(3,3), winning_length=3) for x in range(0,3): board.cells[(x,1)].mark(player=0) self.assertTrue(board.check_for_winning_line(player=0)) for y in range(0,3): board.cells[(1,y)].mark(player=1) self.assertTrue(board.check_for_winning_line(player=1))
def test_get_fingerprint(self): board = Board(dimensions=(3,3), winning_length=3) for x in range(0,3): board.cells[(x,1)].mark(player=0) for y in range(0,3): board.cells[(1,y)].mark(player=1) # player 0 has bits 3,5 set = 40 self.assertEqual(board.get_fingerprint(player=0), 40) # player 1 has bits 1,4,7 set = 146 self.assertEqual(board.get_fingerprint(player=1), 146)
def get_best_move(board, comp_sym, play_sym): best_score, best_move = -10, None temp_board = Board() for move in get_open_squares(board): temp_board.board = [row[:] for row in board.board] temp_board.add_move(*move, comp_sym) score = minimax(temp_board, False, comp_sym, play_sym, 1) if score > best_score: best_score = score best_move = move return best_move
class TestBoardFull(unittest.TestCase): def setUp(self): self.game = Board() def test_board_full(self): self.game.board = [['X', 'O', 'X'], ['X', 'O', 'O'], ['O', 'X', 'O']] self.assertTrue(self.game.board_full()) def test_board_not_empty(self): self.game.board = [['X', 'O', 'X'], ['X', 'O', 'O'], ['O', 'X', '_']] self.assertFalse(self.game.board_full())
def test_board_print_as_grid(self): """ Tests that board is printed as a grid. """ board = Board() board_grid_str = """ |0|1|2| |3|4|5| |6|7|8| """ self.assertEqual(board_grid_str, board.__str__())
def test_board_get_win_detection(self): """ Tests that a board can detect when a win is present. """ board = Board() self.assertFalse(board.get_win()) # create a player and mark a winning move player = Player(board, 'H', 'human') winning_move = choice(board.WINNING_POSITIONS) for space in winning_move: board.spaces[space] = player self.assertTrue(board.get_win())
def test_minimax(self): """ Tests that computer can block human. """ board = Board() computer = Player(board, 'C', 'computer', is_human=False, ai_strat=Minimax(board)) human = Player(board, 'H', 'human') # set up human about to win board.spaces[0] = human board.spaces[1] = human # set up computer to not have win cond board.spaces[4] = computer board.spaces[8] = computer """ |H|H|2| |3|C|5| |6|7|C| """ board.CURRENT_PLAYER = computer board.WAITING_PLAYER = human self.assertEqual(2, computer.make_play())
def test_no_winner(self): self.Board = Board() self.Player = Player(self) self.Board.mark_square(0, 0, "X") self.Board.mark_square(0, 1, "0") self.Board.mark_square(0, 2, "X") self.Board.mark_square(1, 0, "0") self.Board.mark_square(1, 1, "X") self.Board.mark_square(1, 2, "0") self.Board.mark_square(2, 1, "X") self.Board.mark_square(2, 2, "0") print("No Winner Test:") self.Board.print_board() print("\n") self.assertEqual(self.Board.has_winner(), True, "Unit pass for no winner")
def test_get_positions_multiple(self): board = Board(dimensions=(3,3), winning_length=3) for x in range(0,3): board.cells[(x,1)].mark(player=0) for y in range(0,3): board.cells[(1,y)].mark(player=1) self.assertItemsEqual( board.get_positions(player=0), [(0, 1), (2, 1)] ) self.assertItemsEqual( board.get_positions(player=1), [(1, 0), (1, 1), (1,2)] )
def test_get_symbol(self): board = Board() ui = ConsoleUI(board) human_player = HumanPlayer(board, ui) human_player.symbol = "S" assert human_player.get_symbol() == "S"
def test_board_init(): state = ( (None, None, None), (None, None, None), (None, None, None), ) board = Board(state) assert board.state == state
def test_default_init(): state = ( (None, None, None), (None, None, None), (None, None, None), ) board = Board() assert board.state == state
def test_row_last_complete(self): board = Board() board.mark_square(0, 2, 'x') board.mark_square(1, 2, 'x') board.mark_square(2, 2, 'x') board.has_winner self.assertEqual(board.has_winner(), "x")
def test_is_not_three_in_a_row(self): board = Board() player = ComputerPlayer(board) board.set_position(2, player) board.set_position(4, player) board.set_position(5, player) assert board.three_in_a_row(3, 4, 5) is False
def test_game_is_not_over(self): board = Board() player = ComputerPlayer(board) board.set_position(3, player) board.set_position(4, player) board.set_position(8, player) assert board.game_is_over() is False
class TestHasThreeInARow(unittest.TestCase): def setUp(self): self.game = Board() def test_player1_threeInARow(self): self.game.board = [['X', '_', 'O'], ['X', 'O', '_'], ['X', '_', '_']] self.assertEqual(self.game.has_three_in_a_row(), 1) def test_player2_threeInARow(self): self.game.board = [['X', '_', 'O'], ['O', 'O', 'O'], ['X', 'X', '_']] self.assertEqual(self.game.has_three_in_a_row(), 2) def test_empty(self): self.game.board = [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']] self.assertEqual(self.game.has_three_in_a_row(), 0) def test_cats_game(self): self.game.board = [['X', 'O', 'X'], ['X', 'O', 'O'], ['O', 'X', 'O']] self.assertEqual(self.game.has_three_in_a_row(), 0)
def test_calculate_winning_lines_3(self): board = Board(dimensions=(3,3), winning_length=3) self.assertEqual( board.calculate_winning_lines(), [ # 3 columns [(0,0,), (0,1), (0,2)], [(1,0,), (1,1), (1,2)], [(2,0,), (2,1), (2,2)], # diagonal [(0,0,), (1,1), (2,2)], # 3 rows [(0,0,), (1,0), (2,0)], [(0,1,), (1,1), (2,1)], [(0,2,), (1,2), (2,2)], # other diagonal [(0,2,), (1,1), (2,0)], ] )
def search(self, board: Board = None): if board is None: board = Board() board_hash = hash(board) if board_hash in self.board_evals: self.hits += 1 bestmove, bestscore, *_ = self.board_evals[board_hash].values() return bestscore if board.game_over(): winner = board.winner() if not winner: score = 0 else: nmoves = sum(bool(sq) for sq in board.board) score = -10 + nmoves self.board_evals[board_hash] = {'bestmove': None, 'score': score} return score bestscore = -999 bestmove = None moves = [] scores = [] for move in board.generate_unique_legal_moves(): score = -self.search(move) if score > bestscore: bestscore = score bestmove = move moves.append(move) scores.append(score) self.board_evals[board_hash] = { 'bestmove': bestmove, 'bestscore': bestscore, 'moves': moves, 'scores': scores, } return bestscore
def check_lose(board, moves, play_sym): temp_board = Board() for move in moves: temp_board.board = [row[:] for row in board.board] temp_board.add_move(*move, play_sym) if temp_board.check_winner()[0]: return move
class TestGetWinner(unittest.TestCase): def setUp(self): self.board = Board() def test_winner_horizontal(self): self.board.state = ['X', None, 'X', None, 'X', None, 'O', 'O', 'O'] self.assertEqual(self.board.getWinner(), 'O') def test_winner_vertical(self): self.board.state = [None, 'X', 'O', 'O', 'X', None, None, 'X', None] self.assertEqual(self.board.getWinner(), 'X') def test_winner_diagonal(self): self.board.state = ['X', None, 'O', None, 'O', 'X', 'O', None, 'X'] self.assertEqual(self.board.getWinner(), 'O') def test_no_winners(self): self.board.state = ['X', None, 'O', 'O', 'O', 'X', 'X', None, 'O'] self.assertIsNone(self.board.getWinner()) def test_board_filled(self): self.board.state = ['X', 'O', 'X', 'X', 'X', 'O', 'O', 'X', 'O'] self.assertIsNone(self.board.getWinner()) def test_board_empty(self): self.assertIsNone(self.board.getWinner())
class TestIsFinished(unittest.TestCase): def setUp(self): self.board = Board() def test_winner_horizontal(self): self.board.state = ['X', None, 'X', None, 'X', None, 'O', 'O', 'O'] self.assertTrue(self.board.isFinished()) def test_winner_vertical(self): self.board.state = [None, 'X', 'O', 'O', 'X', None, None, 'X', None] self.assertTrue(self.board.isFinished()) def test_winner_diagonal(self): self.board.state = ['X', None, 'O', None, 'O', 'X', 'O', None, 'X'] self.assertTrue(self.board.isFinished()) def test_no_winners(self): self.board.state = ['X', None, 'O', 'O', 'O', 'X', 'X', None, 'O'] self.assertFalse(self.board.isFinished()) def test_board_filled(self): self.board.state = ['X', 'O', 'X', 'X', 'X', 'O', 'O', 'X', 'O'] self.assertTrue(self.board.isFinished()) def test_board_empty(self): self.assertFalse(self.board.isFinished())
def test_no_winner(self): board = Board() board.mark_square(0, 2, 'x') board.mark_square(1, 2, 'o') board.mark_square(2, 2, 'x') board.has_winner self.assertEqual(board.has_winner, "n")
def test_draw(self): """Confirm Board object correctly determines a draw state""" board = Board() self.assertFalse(board.checkForDraw()) for i in range(0,9): board.inputMove(i, "X") self.assertTrue(board.checkForDraw())
def test_row_first_complete(self): board = Board() board.mark_square(0, 0, 'o') board.mark_square(1, 0, 'o') board.mark_square(2, 0, 'o') board.has_winner self.assertEqual(board.has_winner, "o")
def minimax(board, maximizing, comp_sym, play_sym, depth): if board.check_winner() == (True, comp_sym): #computer wins return 1 / depth elif board.check_winner()[0]: #player wins return -1 / depth elif len(get_open_squares(board)) == 0: #draw return 0 moves = get_open_squares(board) scores = [] temp_board = Board() for move in moves: temp_board.board = [row[:] for row in board.board] if maximizing: player = comp_sym else: player = play_sym temp_board.add_move(*move, player) scores.append(minimax(temp_board, not maximizing, comp_sym, play_sym, depth + 1)) if maximizing: return max(scores) return min(scores)
def test_newboard(self): """New boards should be empty""" board = Board() self.assertEqual("".join(board.gs), " " * 9) for i in range(0, 9): board.inputMove(i, "X") board.__init__() self.assertEqual("".join(board.gs), " " * 9)
def test_iter(self): board = Board(['X', 'O', ' ', 'X', ' ', 'O', 'O', 'X', 'O']) iterator = iter(board) self.assertEqual(next(iterator), 'X') self.assertEqual(next(iterator), 'O') self.assertEqual(next(iterator), ' ') self.assertEqual(next(iterator), 'X') self.assertEqual(next(iterator), ' ') self.assertEqual(next(iterator), 'O') self.assertEqual(next(iterator), 'O') self.assertEqual(next(iterator), 'X') self.assertEqual(next(iterator), 'O') with self.assertRaises(StopIteration): next(iterator)
def test_get_other_player_when_position_not_empty(self): board = Board() ui = ConsoleUI(board) computer = ComputerPlayer(board) human = HumanPlayer(board, ui) board.set_position(4, computer) board.set_position(5, human) assert computer.get_other_player() == human
def test_calculate_winning_lines_2(self): board = Board(dimensions=(3,3), winning_length=2) self.assertEqual( board.calculate_winning_lines(), [ # vertical pairs (top) [(0, 0), (0, 1)], [(1, 0), (1, 1)], [(2, 0), (2, 1)], # vertical pairs (bottom) [(0, 1), (0, 2)], [(1, 1), (1, 2)], [(2, 1), (2, 2)], # diagonal pairs (top) [(0, 0), (1, 1)], [(1, 0), (2, 1)], # diagonal pairs (bottom) [(0, 1), (1, 2)], [(1, 1), (2, 2)], # horizontal pairs (top) [(0, 0), (1, 0)], [(1, 0), (2, 0)], # horizontal pairs (middle) [(0, 1), (1, 1)], [(1, 1), (2, 1)], # horizontal pairs (bottom) [(0, 2), (1, 2)], [(1, 2), (2, 2)], # diagonal pairs (middle) [(0, 1), (1, 0)], [(1, 1), (2, 0)], # diagonal pairs (bottom) [(0, 2), (1, 1)], [(1, 2), (2, 1)], ] )
def check_over(board): print board state, winner = board.get_state() if state == 'WINNER': print state, winner return True elif state == 'TIE': print state return True return False if __name__ == '__main__': board = Board() print board print '\n---' while True: i, j = map(int, raw_input().split(' ')) board = board.add_move(Move(Piece(PLAYER1, i, j))) if check_over(board): break print '\n---' move = get_best_move(PLAYER2, PLAYER1, board, verbose=True) board = board.add_move(move) if check_over(board): break print '\n---'
def test_board(self): # tests all of Board's methods board = Board() lst = [] possible_choices = ['x', 'o'] self.assertFalse(bool(board), msg="The board should be empty") for x in range(9): num = random.randint(0, len(possible_choices)-1) board[x] = possible_choices[num] lst.append(possible_choices[num]) for place, testitem in zip(board, lst): self.assertEqual(place, testitem, msg="Improper iteration or improper __getitem__") self.assertEqual(board.as_list(), lst, msg="Board not properly converting to list") self.assertTrue(bool(board), msg="The board has a value in it and should be True") board.clear() self.assertFalse(board.check_win(), msg="When the board is empty, a win should be impossible") idx = random.randint(0, len(possible_choices)-1) board[6] = board[7] = board[8] = possible_choices[idx] self.assertEqual(board.check_win(), possible_choices[idx], msg="This should be a win") board.clear() board[0] = board[3] = board[6] = possible_choices[idx] self.assertEqual(board.check_win(), possible_choices[idx], msg="This should be a win") board.clear() board[1] = board[4] = possible_choices[idx] self.assertFalse(board.check_win(), msg="This should not be a win") board.clear() board[0] = board[4] = board[8] = possible_choices[idx] self.assertEqual(board.check_win(), possible_choices[idx], msg="This should be a win") board.clear() board[2] = board[4] = board[6] = possible_choices[idx] self.assertEqual(board.check_win(), possible_choices[idx], msg="This should be a win") board.clear() self.assertEqual(board.get_all_openings(), [(x,y) for x in range(3) for y in range(3)], msg="This board is entirely clear = all spaces should be open.") board[2] = board[5] = board[8] = possible_choices[idx] self.assertEqual(board.get_all_openings(), [(x,y) for x in range(3) for y in range(2)], msg="The third column should be occupied") board.clear() board[1] = 'x' with self.assertRaises(ValueError): board[1] = 'o'
def test_create_winning_lines(self): board = Board(dimensions=(10,10), winning_length=2) self.assertEqual( [wl.cells for wl in board.winning_lines], board.calculate_winning_lines() )
class BoardTests(TestCase): """Tests for the Board class.""" def setUp(self): self.board = Board() def test_init(self): """Init results in empty board.""" for x in range(3): for y in range(3): self.assertEqual(None, self.board.get_piece(x, y)) def test_play(self): """Playing a piece changes the board.""" player = 1 x = 1 y = 2 self.board.play(x, y, player) self.assertEqual(player, self.board.get_piece(x, y)) def test_out_of_bounds(self): """Playing out of bounds raises an exception.""" player = 1 self.assertRaises(InvalidPosition, self.board.play, 3, 1, player) self.assertRaises(InvalidPosition, self.board.play, 1, 3, player) self.assertRaises(InvalidPosition, self.board.play, -1, 1, player) self.assertRaises(InvalidPosition, self.board.play, 1, -1, player) def test_invalid_coordinate_values(self): """Non-integer coordinates raise an exception.""" player = 1 self.assertRaises(InvalidPosition, self.board.play, '3', 1, player) self.assertRaises( InvalidPosition, self.board.play, 1, 'wednesday', player) def test_occupied(self): """Playing to an occupied position raises an exception.""" player = 1 self.board.positions[2][2] = 2 self.assertRaises(InvalidPosition, self.board.play, 2, 2, player) def test_out_of_turn(self): """Playing out of turn raises an exception.""" player = 1 self.board.play(2, 2, player) self.assertRaises(OutOfTurn, self.board.play, 1, 2, player) def test_game_over_false(self): """Game over returns False when game is not over.""" player = 1 self.assertEqual(False, self.board.game_over) self.board.play(2, 2, player) self.assertEqual(False, self.board.game_over) def test_game_over_board_full(self): """Game over returns True when board is full.""" self.board.positions = [ [1, 2, 1], [2, 2, 1], [1, 1, 2]] self.assertEqual(True, self.board.game_over)
def check_over(board): print board state, winner = board.get_state() if state == 'WINNER': print state, winner return True elif state == 'TIE': print state return True return False if __name__ == '__main__': if len(argv) > 1 and argv[1] == '--nogui': board = Board() print board print '\n---' while True: i, j = map(int, raw_input().split(' ')) board = board.add_move(Move(Piece(PLAYER1, col=i, row=j))) if check_over(board): break print '\n---' move = get_best_move(PLAYER2, PLAYER1, board) board = board.add_move(move) if check_over(board): break print '\n---'
def setUp(self): self.board = Board()
def test_play_square(): board = Board() board = board.move('b0') assert board.state[1][0] == 'x'
def test_player_turn(): board = Board() assert board.turn() == 'x'
def test_winner_diag2(self): board = Board(['X', 'O', 'O', 'X', 'O', ' ', 'O', ' ', 'X']) self.assertEqual(board.check_winner(), 'O')
def test_winner_when_empty(self): board = Board() self.assertFalse(board.check_winner())
def test_get_positions_none(self): board = Board(dimensions=(3,3), winning_length=3) self.assertEqual(board.get_positions(player=0), [])
def test_board(self): b = Board() b.testattrib = "hey"