def human_vs_agent( generate_move_1: GenMove, generate_move_2: GenMove, player_1: str = "Player 1", player_2: str = "Player 2", args_1: tuple = (), args_2: tuple = (), init_1: Callable = lambda board, player: None, init_2: Callable = lambda board, player: None, ): import time from agents.common import PLAYER1, PLAYER2, PLAYER1_PRINT, PLAYER2_PRINT, GameState from agents.common import initialize_game_state, pretty_print_board, apply_player_action, check_end_state players = (PLAYER1, PLAYER2) for play_first in (1, -1): for init, player in zip((init_1, init_2)[::play_first], players): init(initialize_game_state(), player) saved_state = {PLAYER1: None, PLAYER2: None} board = initialize_game_state() gen_moves = (generate_move_1, generate_move_2)[::play_first] player_names = (player_1, player_2)[::play_first] gen_args = (args_1, args_2)[::play_first] if play_first == 1: machine_player = PLAYER1 else: machine_player = PLAYER2 playing = True while playing: for player, player_name, gen_move, args in zip( players, player_names, gen_moves, gen_args, ): print(player, player_name) t0 = time.time() print(pretty_print_board(board)) print( f'{player_name} you are playing with {PLAYER1_PRINT if player == PLAYER1 else PLAYER2_PRINT}' ) action, saved_state[player] = gen_move(board.copy(), player, saved_state[player], *args) print(f"Move time: {time.time() - t0:.3f}s") apply_player_action(board, action, player) end_state = check_end_state(board, player) if end_state != GameState.STILL_PLAYING: print(pretty_print_board(board)) if end_state == GameState.IS_DRAW: print("Game ended in draw") else: print( f'{player_name} won playing {PLAYER1_PRINT if player == PLAYER1 else PLAYER2_PRINT}' ) playing = False break
def testPrettyPrintBoard(self): from agents.common import pretty_print_board, string_to_board board1 = np.ones((6, 7)) board1[1:, 2:] = np.zeros((5, 5)) * player board2 = np.zeros((6, 7)) board2[:4, :4] = np.eye(4) * PLAYER2 board3 = initialize_game_state() board3[0, 0] = player #checks that (0,0) is bottom left corner #representation of empty board: str0 = '|===============================|\n' \ '|\t \t \t \t \t \t \t \t|\n' \ '|\t \t \t \t \t \t \t \t|\n' \ '|\t \t \t \t \t \t \t \t|\n' \ '|\t \t \t \t \t \t \t \t|\n' \ '|\t \t \t \t \t \t \t \t|\n' \ '|\t \t \t \t \t \t \t \t|\n' \ '|===============================|\n' \ '|\t0\t1\t2\t3\t4\t5\t6\t|\n' #representation of board1: str1 = '|===============================|\n' \ '|\tX\tX\t \t \t \t \t \t|\n' \ '|\tX\tX\t \t \t \t \t \t|\n' \ '|\tX\tX\t \t \t \t \t \t|\n' \ '|\tX\tX\t \t \t \t \t \t|\n' \ '|\tX\tX\t \t \t \t \t \t|\n' \ '|\tX\tX\tX\tX\tX\tX\tX\t|\n' \ '|===============================|\n' \ '|\t0\t1\t2\t3\t4\t5\t6\t|\n' #representation of board2: str2 ='|===============================|\n' \ '|\t \t \t \t \t \t \t \t|\n' \ '|\t \t \t \t \t \t \t \t|\n' \ '|\t \t \t \tO\t \t \t \t|\n' \ '|\t \t \tO\t \t \t \t \t|\n' \ '|\t \tO\t \t \t \t \t \t|\n' \ '|\tO\t \t \t \t \t \t \t|\n' \ '|===============================|\n' \ '|\t0\t1\t2\t3\t4\t5\t6\t|\n' #representation of board3: str3 = '|===============================|\n' \ '|\t \t \t \t \t \t \t \t|\n' \ '|\t \t \t \t \t \t \t \t|\n' \ '|\t \t \t \t \t \t \t \t|\n' \ '|\t \t \t \t \t \t \t \t|\n' \ '|\t \t \t \t \t \t \t \t|\n' \ '|\tX\t \t \t \t \t \t \t|\n' \ '|===============================|\n' \ '|\t0\t1\t2\t3\t4\t5\t6\t|\n' self.assertEqual(pretty_print_board(initialize_game_state()), str0) self.assertEqual(pretty_print_board(board1), str1) self.assertEqual(pretty_print_board(board2), str2) self.assertEqual(pretty_print_board(board3), str3)
def generate_move( board: np.ndarray, player: cm.BoardPiece, saved_state: Optional[cm.SavedState] ) -> Tuple[cm.PlayerAction, Optional[cm.SavedState]]: gamestate = cm.check_end_state(board, player) current_state = State(board, player, gamestate, None) root = Node.make_root(current_state) cm.pretty_print_board(root.state.board) bestmove, _ = Node.mcts(root) return bestmove, saved_state
def test_pretty_print_board(): from agents.common import pretty_print_board from agents.common import board ret = pretty_print_board(board) ret2 = pretty_print_board( np.array([[0, 2, 2, 1, 2, 1, 1], [0, 2, 2, 1, 2, 1, 2], [0, 1, 1, 2, 2, 1, 1], [0, 1, 2, 0, 0, 0, 1], [0, 2, 0, 0, 0, 0, 2], [0, 0, 0, 0, 0, 0, 0]])) assert isinstance(ret, str) assert ret2 == '| - - - - - - - |\n| . . . . . . . |\n| . X . . . . X |\n| . O X . . . O |\n| . O O X X O O |\n| . X X O X O X |\n| . X X O X O O |\n| - - - - - - - |\n| 0 1 2 3 4 5 6 |' with pytest.raises(ValueError): pretty_print_board('hello')
def run_simulation(start_node: MCTSNode, root_player: BoardPiece, print_final=False) -> (np.ndarray, GameState): """ The 3rd part of the algorithm. This function runs a complete game with random moves from the start node board until one player wins. This is one simulation in the MCTS algorithm. :param start_node: the expended node from which we start the simulation :param root_player: :param print_final: flag variable for printing the final board of the game :return: the final board state (np.narray), the game end state (GameState) """ current_board = start_node.board.copy() current_player = start_node.player while check_end_state(current_board, current_player) == GameState.STILL_PLAYING: # action = np.random.randint(0, 7) possible_actions = possible_moves(current_board) action = possible_actions[np.random.randint(len(possible_actions))] current_board = apply_player_action(current_board, np.int8(action), current_player) current_player = find_opponent(current_player) game_result = check_end_state(current_board, root_player) if print_final: print(pretty_print_board(current_board)) return current_board, game_result
def test_string_to_board() -> str: board = initialize_game_state() board_test = pretty_print_board(board) ret = string_to_board(board_test) assert isinstance(ret, np.ndarray)
def test_pretty_print_board(): from agents.common import pretty_print_board from agents.common import initialize_game_state dummy_board = initialize_game_state() ret = pretty_print_board(dummy_board) # Split string at newlines rows = ret.split('\n') # 1. Evaluate board area # number of rows (excluding borders) = 1st dim of board assert len(rows[1:-2]) == dummy_board.shape[0] # length of each row (excluding border rows) = 2nd dim of board assert all((len(r) - 1) / 2 == dummy_board.shape[1] for r in rows[1:-2]) # div by 2 to account for space # 2. Evaluate border area borderForm = '|{}|'.format('=' * (2 * (dummy_board.shape[1]) - 1)) column_label_form = '|{}|'.format(' '.join( [str(n) for n in range(dummy_board.shape[1])])) assert rows[0] == borderForm assert rows[-2] == borderForm assert rows[-1] == column_label_form
def test_pretty_print_board(): board = initialize_game_state() pp_string = pretty_print_board(board) assert isinstance(pp_string, str) print(pp_string) return pp_string
def testStringtoBoard(self): from agents.common import string_to_board, pretty_print_board #It's enough to check that string_to_board ° pretty_print = id: board = np.random.choice([player, PLAYER2], ((6, 7))) self.assertTrue( np.array_equal(board, string_to_board(pretty_print_board(board))))
def test_pretty_print_board(board=board_to_test): """ Test the printing of the board and also the function of num:to char included :param board : Selected board """ from agents.common import pretty_print_board ret = pretty_print_board(board) assert isinstance(ret, str) print(ret)
def test_pretty_print_board(): from agents.common import pretty_print_board pretty_boards = [ pretty_print_board(game_state) for game_state in game_states ] for ind, board in enumerate(pretty_boards): assert isinstance(board, str) assert board == boards[ind]
def test_pretty_print_board(): from agents.common import pretty_print_board assert pretty_print_board(b4) == "|==============|\n" \ "| |\n" \ "| |\n" \ "| X X |\n" \ "| O X X |\n" \ "| O O X X |\n" \ "| O O O X X |\n" \ "|==============|\n" \ "|0 1 2 3 4 5 6 |"
def test_string_to_board(): from agents.common import string_to_board from agents.common import pretty_print_board, initialize_game_state board = initialize_game_state() board_str = pretty_print_board(board) ret = string_to_board(board_str) assert isinstance(ret, np.ndarray) assert ret.shape == (6, 7) assert np.all(ret == NO_PLAYER)
def test_pretty_print_board(): from agents.common import pretty_print_board, initialize_game_state board = initialize_game_state() board_str = pretty_print_board(board) nlines = 9 assert len(board_str.splitlines()) == nlines assert board_str[-1] == '|' assert board_str[0] == '|' assert isinstance(board_str, str)
def test_string_to_board(): from agents.common import string_to_board from agents.common import pretty_print_board board1 = np.zeros((6, 7), dtype=np.int8) board1[0, :] = np.array([0, 1, 1, 1, 1, 1, 0]) board1[1, :] = np.array([0, 1, 1, 1, 1, 1, 0]) board1[2, :] = np.array([0, 1, 1, 1, 1, 1, 0]) board1[3, :] = np.array([0, 2, 2, 2, 2, 0, 0]) board2 = np.zeros((6, 7), dtype=np.int8) board2[:, 4] = np.array([2, 2, 2, 2, 0, 0]) ret = pretty_print_board(board1) ret1 = string_to_board(ret) ret2 = pretty_print_board(board2) ret3 = string_to_board(ret2) assert isinstance(ret1, np.ndarray) assert ret1.dtype == np.int8 assert (board1 == ret1).all() assert (board2 == ret3).all()
def test_string_to_board(board=board_to_test): """ Test the implementation of the function string to board :param board: Selected board """ from agents.common import string_to_board, pretty_print_board ret_test = string_to_board(pretty_print_board(board)) assert isinstance(ret_test, np.ndarray) assert ret_test.dtype == BoardPiece comparison = board == ret_test comparison.all() assert comparison.all()
def test_pretty_print_board() -> str: test_board = initialize_game_state() ret = pretty_print_board(test_board) test_board[0, 1] = PLAYER1 test_board[1, 1] = PLAYER2 test_board[0, 2] = PLAYER2 test_board[2, 2] = PLAYER2 test_board[1, 3] = PLAYER2 test_board[0, 0] = PLAYER1 assert isinstance(ret, str)
def test_pretty_print_board(): test_board = cm.initialize_game_state() test_board = np.random.randint(0, 3, test_board.shape) print('') print(test_board) board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert isinstance(board_str, str) return
def test_pretty_print_board(): from agents.common import pretty_print_board """ Test the given boards and see if they output the correct string representation """ board = np.array([[BoardPiece(2), BoardPiece(0), BoardPiece(2), BoardPiece(0), BoardPiece(1), BoardPiece(0), BoardPiece(1)], [BoardPiece(1), BoardPiece(2), BoardPiece(1), BoardPiece(2), BoardPiece(1), BoardPiece(2), BoardPiece(1)], [BoardPiece(2), BoardPiece(0), BoardPiece(2), BoardPiece(0), BoardPiece(1), BoardPiece(0), BoardPiece(1)], [BoardPiece(1), BoardPiece(2), BoardPiece(1), BoardPiece(2), BoardPiece(1), BoardPiece(2), BoardPiece(1)], [BoardPiece(2), BoardPiece(0), BoardPiece(2), BoardPiece(0), BoardPiece(1), BoardPiece(0), BoardPiece(1)], [BoardPiece(1), BoardPiece(2), BoardPiece(1), BoardPiece(2), BoardPiece(1), BoardPiece(2), BoardPiece(1)]]) test_pretty_board = '''|=======| |XOXOXOX| |O O X X| |XOXOXOX| |O O X X| |XOXOXOX| |O O X X| |=======| |0123456|''' assert pretty_print_board(board) == test_pretty_board empty_board = np.ndarray(shape=(6, 7), dtype=BoardPiece) empty_board[:] = NO_PLAYER test_empty_pretty_board = '''|=======| | | | | | | | | | | | | |=======| |0123456|''' assert pretty_print_board(empty_board) == test_empty_pretty_board
def test_string_to_board(): from agents.common import string_to_board from agents.common import initialize_game_state, pretty_print_board dummy_board = initialize_game_state() # pretty print the board to get a string dummy_string = pretty_print_board(dummy_board) # convert string back to board ret = string_to_board(dummy_string) # new board should match original board assert (ret == dummy_board).all()
def test_node_initialization(): # Initialize a game player = cm.PLAYER1 arr_bd, bit_bd, mask_bd, player = generate_full_board(player, 1) bd_shp = arr_bd.shape # Generate a board that is not a win, with only a single piece missing while cm.check_end_state(bit_bd, mask_bd, bd_shp) == cm.GameState.IS_WIN: arr_bd, bit_bd, mask_bd, player = generate_full_board(player, 1) print(cm.pretty_print_board(arr_bd)) # Test whether node initializes and plays in proper (only empty) column move = agmcts.generate_move_mcts(arr_bd, player, None)[0] empty_col = cm.valid_actions(mask_bd, bd_shp)[0] print('MCTS plays in column {}'.format(move)) assert move == empty_col
def test_string_to_board(): test_board = cm.initialize_game_state() test_board = np.random.randint(0, 3, test_board.shape) print('') print(test_board) board_str = cm.pretty_print_board(test_board) print('') print(board_str) board_arr = cm.string_to_board(board_str) print('') print(board_arr) assert isinstance(test_board, np.ndarray) assert board_arr.dtype == np.int8 assert board_arr.shape == test_board.shape return
def test_pretty_print_board(): from agents.common import pretty_print_board test_str = '|====|\n' test_str += '|' + NO_PLAYER_PRINT + ' ' + PLAYER1_PRINT + ' |\n' test_str += '|' + PLAYER2_PRINT + ' ' + NO_PLAYER_PRINT + ' |\n' test_str += '|====|\n' test_str += '|0 1 |' test_arr = np.full((2, 2), NO_PLAYER, dtype=BoardPiece) test_arr[0, 1] = PLAYER1 test_arr[1, 0] = PLAYER2 ret = pretty_print_board(test_arr) assert isinstance(ret, str) assert ret == test_str
def test_pretty_print_board(): from agents.common import pretty_print_board board = np.zeros((6, 7)) board[0, 0:7] = [1, 2, 2, 1, 1, 1, 2] board[1, 0:7] = [2, 1, 2, 1, 2, 2, 1] board[2, 0:7] = [1, 2, 1, 2, 0, 0, 0] board[3, 0:7] = [2, 2, 1, 0, 0, 0, 0] board[4, 0:7] = [1, 1, 0, 0, 0, 0, 0] board[5, 0:7] = [2, 0, 0, 0, 0, 0, 0] boardStr = '|==============|\n' \ '|O |\n' \ '|X X |\n' \ '|O O X |\n' \ '|X O X O |\n' \ '|O X O X O O X |\n' \ '|X O O X X X O |\n' \ '|==============|\n' \ '|0 1 2 3 4 5 6 |' assert boardStr == pretty_print_board(board)
def test_board_to_bitmap(): test_board = cm.initialize_game_state() test_board[0, 2] = cm.PLAYER1 test_board[0, 3] = cm.PLAYER2 test_board[0, 4] = cm.PLAYER2 test_board[0, 5] = cm.PLAYER1 test_board[1, 2] = cm.PLAYER1 test_board[1, 3] = cm.PLAYER1 test_board[1, 4] = cm.PLAYER2 test_board[2, 2] = cm.PLAYER1 test_board[2, 3] = cm.PLAYER2 test_board[3, 2] = cm.PLAYER2 test_board[3, 3] = cm.PLAYER2 test_board[4, 3] = cm.PLAYER1 # test_board[0, 2:4] = cm.PLAYER1 # test_board[0, 5] = cm.PLAYER1 board_str = cm.pretty_print_board(test_board) print('') print(board_str) # mask_pos = int('000000000000100000001100000011000001110000111100', 2) # p1_pos = int('000000000000100000000000000001000000110000100100', 2) # p2_pos = int('000000000000000000001100000010000001000000011000', 2) mask_pos = int('0000000000000100000110011111000111100000000000000', 2) p1_pos = int('000000000000010000000001001000001110000000000000', 2) p2_pos = int('0000000000000000000110001101000100000000000000000', 2) print('') # print(bin(p1_pos)) print(bin(cm.board_to_bitmap(test_board, cm.PLAYER1)[0])) # print(bin(p2_pos)) print(bin(cm.board_to_bitmap(test_board, cm.PLAYER2)[0])) # print(bin(mask_pos)) print(bin(cm.board_to_bitmap(test_board, cm.PLAYER2)[1])) # print(bin(cm.board_to_bitmap(test_board, cm.PLAYER1)[1])) assert cm.board_to_bitmap(test_board, cm.PLAYER2)[0] == p2_pos assert cm.board_to_bitmap(test_board, cm.PLAYER2)[1] == mask_pos assert cm.board_to_bitmap(test_board, cm.PLAYER1)[0] == \ (mask_pos ^ p2_pos)
def test_pretty_print_board_and_string_to_board(): """Test the printing of a board and the transformation back to an array""" # Check that the print of the board to a string and the transformation back to the board works for every position on # the board for each player for player in players: board = initialize_game_state() n_rows, n_cols = board.shape for i in range(n_rows): for j in range(n_cols): board[i, j] = player # Transform the board into a pretty string pp_board = pretty_print_board(board) # Transform it back to an ndarray trans_board = string_to_board(pp_board) # Check that everything worked assert isinstance(pp_board, str) assert len(pp_board) > 42 assert np.array_equal(board, trans_board)
def test_buildGameStateFromID(self): node = GameState(PLAYER1, '6421', self.board0) node2 = GameState(PLAYER2, '1420', self.board0) node.buildGameStateFromID() print(pretty_print_board(node.board)) print(pretty_print_board(self.board_6421)) assert node.possible and (node.board == self.board_6421).all() node2.buildGameStateFromID() print(pretty_print_board(node2.board)) print(pretty_print_board(self.board_1420)) assert node2.positionID and (node2.board == self.board_1420).all() node3 = GameState(PLAYER2, '1420', self.board1) node3.buildGameStateFromID() print(pretty_print_board(node3.board)) print(pretty_print_board(self.board1)) assert node3.possible
def test_top_row(): test_board = cm.initialize_game_state() test_board[0, 0] = cm.PLAYER1 test_board[:6, 1] = cm.PLAYER1 test_board[:2, 2] = cm.PLAYER1 test_board[:3, 3] = cm.PLAYER1 test_board[:4, 4] = cm.PLAYER1 board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.top_row(test_board, cm.PlayerAction(0)) == 1 assert cm.top_row(test_board, cm.PlayerAction(2)) == 2 assert cm.top_row(test_board, cm.PlayerAction(3)) == 3 assert cm.top_row(test_board, cm.PlayerAction(4)) == 4 assert cm.top_row(test_board, cm.PlayerAction(5)) == 0 assert cm.top_row(test_board, cm.PlayerAction(6)) == 0 try: assert not cm.top_row(test_board, cm.PlayerAction(1)) except IndexError: assert True
def test_pretty_print_board(): """ test for pretty_print_board - be str type - have a length of 153 - PLAYER1 and PLAYER2 tokens placed correctly [ visual inspection ] """ # Make transfer variables for ease of use n = NO_PLAYER o = PLAYER1 x = PLAYER2 # Define test board: # ARROW pointing UP # PLAYER1 -> 'O' make the head of the arrow # PLAYER2 -> 'X' make the body of the arrow test_board = np.array([ [n, n, n, o, n, n, n], [n, n, o, o, o, n, n], [n, o, o, o, o, o, n], [n, n, x, x, x, n, n], [n, n, x, x, x, n, n], [n, n, x, x, x, n, n], ]) # Function output out = cc.pretty_print_board(test_board) # Test output assert isinstance(out, str) assert len(out) == 153 # Visual inspection print( '\n\nThis should be an ARROW pointing DOWN \n \'O\': head\n \'X\': body' ) print(out)
def test_mcts_algorithm(): """ MCTS plays against itself and tries to catch guaranteed wins Use the oracle in the while loop. Calculates statistics based on how well it performs at playing optimally once a guaranteed win is detected by the oracle. """ # Set parameter values and initialize counters a0 = -100000 b0 = 100000 n_games = 40 n_wins = 0 n_wins_opt = 0 n_def_wins = 0 for i in range(n_games): # Generate an empty board arr_board = cm.initialize_game_state() # Convert board to bitmap player = cm.PLAYER1 bit_b, bit_m = cm.board_to_bitmap(arr_board, player) # Calculate the board shape bd_shp = arr_board.shape # Initialize the board state variable bd_state = cm.check_end_state(bit_b, bit_m, bd_shp) # Initialize a list of moves mv_list = [] # Initialize counters mv_cnt = 0 num_mvs = 0 def_win = False while bd_state == cm.GameState.STILL_PLAYING: # Generate an action using MCTS action, _ = generate_move(arr_board.copy(), player, None) # Update the list of moves mv_list.append(action) # Apply the action to both boards cm.apply_action(arr_board, action, player) bit_b, bit_m = cm.apply_action_cp(bit_b, bit_m, action, bd_shp) # Switch to the next player player = cm.BoardPiece(player % 2 + 1) # Check for guaranteed win, if none detected, continue playing if not def_win: score, depth = alpha_beta_oracle(bit_b, bit_m, True, a0, b0, bd_shp, 0) # If a win is guaranteed, determine when it should occur if score > 50 and abs(score) < 200: print('Score returned is {}'.format(score)) num_mvs = depth n_def_wins += 1 def_win = True print(cm.pretty_print_board(arr_board)) print('Last move by player {}, in column {}, player {} ' 'should win in {} move(s) at most'.format( player % 2 + 1, action, player, num_mvs)) # Once a win is detected, check whether MCTS finds it optimally else: mv_cnt += 1 print(cm.pretty_print_board(arr_board)) bd_state = cm.check_end_state(bit_b ^ bit_m, bit_m, bd_shp) if bd_state == cm.GameState.IS_WIN: print(mv_list) print('Player {} won in {} move(s)'.format( player % 2 + 1, mv_cnt)) n_wins += 1 if mv_cnt <= num_mvs: n_wins_opt += 1 break # Check the game state bd_state = cm.check_end_state(bit_b, bit_m, bd_shp) # Print the number of wins and how many were optimal print('The MCTS algorithm clinched {:4.1f}% of its guaranteed wins, ' 'and won in an optimal number of moves {}% of the time'.format( 100 * (n_wins / n_def_wins), 100 * (n_wins_opt / n_wins)))