def test_apply_player_action_ab(): test_board1 = cm.initialize_game_state() test_board2 = cm.initialize_game_state() player_map, mask_map = cm.board_to_bitmap(test_board1, cm.PLAYER1) n_rows = test_board1.shape[0] moves = np.array([3, 4, 3, 2, 2, 2, 2, 4, 1, 3, 4, 1, 0, 5]) player = cm.PLAYER1 for mv in moves: print('\n') cm.apply_player_action(test_board2, mv, player) player = cm.BoardPiece(player % 2 + 1) test2_map = cm.board_to_bitmap(test_board2, player)[1] print(bin(test2_map)) player_map, mask_map = cm.apply_player_action_ab( player_map, mask_map, mv, n_rows) print(bin(mask_map)) test_board1 = cm.initialize_game_state() player_map, mask_map = cm.board_to_bitmap(test_board1, cm.PLAYER1) n_rows = test_board1.shape[0] moves = np.array([3, 3, 3, 3, 3, 3, 3]) for mv in moves: print('\n') player_map, mask_map = cm.apply_player_action_ab( player_map, mask_map, mv, n_rows) print(bin(mask_map))
def test_check_end_state(): test_board = cm.initialize_game_state() test_board = np.ones(test_board.shape) * 3 board_map, board_mask = cm.board_to_bitmap(test_board, cm.PLAYER1) empty_board = mpz('0' * test_board.size) board_map = mpz(board_map) board_mask = mpz(board_mask) assert cm.check_end_state(board_map, board_mask, empty_board, test_board.shape) == cm.GameState.IS_DRAW test_board[0, 1] = cm.PLAYER1 test_board[1, 2] = cm.PLAYER1 test_board[2, 3] = cm.PLAYER1 test_board[3, 4] = cm.PLAYER1 board_map, board_mask = cm.board_to_bitmap(test_board, cm.PLAYER1) empty_board = mpz('0' * test_board.size) board_map = mpz(board_map) board_mask = mpz(board_mask) assert cm.check_end_state(board_map, board_mask, empty_board, test_board.shape) == cm.GameState.IS_WIN board_map, board_mask = cm.board_to_bitmap(test_board, cm.PLAYER1) empty_board = mpz('0' * test_board.size) board_map = mpz(board_map) board_mask = mpz(board_mask) assert cm.check_end_state(board_map, board_mask, empty_board, test_board.shape) == cm.GameState.IS_WIN
def generate_move_mcts( board: Board, player: BoardPiece, saved_state: Optional[SavedState] ) -> Tuple[PlayerAction, Optional[SavedState]]: """ Agent selects a move based on a minimax depth first search, with alpha-beta pruning. :param board: 2d array representing current state of the game :param player: the player who made the last move (active player) :param saved_state: ??? :return: the agent's selected move """ # TODO: return chosen action subtree using saved_state, to improve # performance # Calculate the board shape bd_shp = board.shape # If the board is empty, play in the center column if np.all(board == NO_PLAYER): action = np.floor(np.median(np.arange(bd_shp[1]))) return PlayerAction(action), saved_state # Convert the board to bitmaps and define the max_player board max_board, mask_board = board_to_bitmap(board, player) # Create a root node root_mcts = Connect4Node(max_board, mask_board, bd_shp, -1, True) # Call MCTS action = mcts(root_mcts) return PlayerAction(action), saved_state
def generate_move_alpha_beta( board: Board, player: BoardPiece, saved_state: Optional[SavedState] ) -> Tuple[PlayerAction, Optional[SavedState]]: """ Agent selects a move based on a minimax depth first search, with alpha-beta pruning. :param board: 2d array representing current state of the game :param player: the player who made the last move (active player) :param saved_state: ??? :return: the agent's selected move """ # If the board is empty, play in the center column if np.all(board == NO_PLAYER): action = np.floor(np.median(np.arange(board.shape[1]))) return PlayerAction(action), saved_state # Convert the board to bitmaps and define the min_player board max_board, mask_board = board_to_bitmap(board, player) # Call alpha_beta alpha0 = -100000 beta0 = 100000 score, action = alpha_beta(max_board, mask_board, True, 0, alpha0, beta0, board.shape) return PlayerAction(action), saved_state
def heuristic_solver_bits(board: Board, player: BoardPiece, max_player: bool = True): """ """ # Convert the boards to bitmaps and define the min_player board max_board, mask_board = board_to_bitmap(board, player) min_board = max_board ^ mask_board empty_board = ~mask_board # Convert bitmaps to mpz objects max_board = mpz(max_board) min_board = mpz(min_board) empty_board = mpz(empty_board) # Initialize the score and point values score = 0 # Define the shift constants b_cols = board.shape[1] # Shift order: horizontal, vertical, \, / shift_list = [1, b_cols + 1, b_cols, b_cols + 2] # Accumulate score for max_player position for shift in shift_list: score += bit_solver(shift, max_board, empty_board) # Reduce score for min_player position for shift in shift_list: score -= bit_solver(shift, min_board, empty_board) if max_player: return GameScore(score) else: return GameScore(-score)
def generate_full_board(player, empty_spaces=0): # Generate an empty board arr_board = cm.initialize_game_state() # Convert board to bitmap bit_board, bit_mask = cm.board_to_bitmap(arr_board, player) # Calculate the board shape bd_shp = arr_board.shape # While the board is not full, continue placing pieces while popcount(bit_mask) != bd_shp[0] * bd_shp[1] - empty_spaces: # Select a random move in a column that is not full move = -1 while not (0 <= move < bd_shp[1]): move = np.random.choice(bd_shp[1]) try: move = cm.PlayerAction(move) cm.top_row(arr_board, move) except IndexError: move = -1 # Apply the move to both boards cm.apply_action(arr_board, move, player) bit_board, bit_mask = cm.apply_action_cp(bit_board, bit_mask, move, bd_shp) # Switch to the next player player = cm.BoardPiece(player % 2 + 1) return arr_board, bit_board, bit_mask, player
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_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)))
def test_alpha_beta_oracle(): # Generate an empty board arr_board = cm.initialize_game_state() # Convert board to bitmap player = cm.PLAYER1 bit_board, bit_mask = cm.board_to_bitmap(arr_board, player) # Calculate the board shape bd_shp = arr_board.shape a0 = -100000 b0 = 100000 # Define a list of moves move_list = [3, 3, 4, 4, 5, 5] for mv in move_list[:-2]: # Apply the move to both boards cm.apply_action(arr_board, mv, player) bit_board, bit_mask = cm.apply_action_cp(bit_board, bit_mask, mv, bd_shp) # Switch to the next player player = cm.BoardPiece(player % 2 + 1) print(cm.pretty_print_board(arr_board)) score, depth = alpha_beta_oracle(bit_board, bit_mask, True, a0, b0, bd_shp, 0) print('Player {} should win in {} moves.'.format( ('X' if player == cm.BoardPiece(1) else 'O'), depth)) assert depth == 3 # Apply next move to both boards cm.apply_action(arr_board, move_list[-2], player) bit_board, bit_mask = cm.apply_action_cp(bit_board, bit_mask, move_list[-2], bd_shp) # Switch to the next player player = cm.BoardPiece(player % 2 + 1) print(cm.pretty_print_board(arr_board)) score, depth = alpha_beta_oracle(bit_board, bit_mask, True, a0, b0, bd_shp, 0) print('Player {} should lose in {} moves.'.format( ('X' if player == cm.BoardPiece(1) else 'O'), depth)) assert depth == 2 # Apply next move to both boards cm.apply_action(arr_board, move_list[-1], player) bit_board, bit_mask = cm.apply_action_cp(bit_board, bit_mask, move_list[-1], bd_shp) # Switch to the next player player = cm.BoardPiece(player % 2 + 1) print(cm.pretty_print_board(arr_board)) score, depth = alpha_beta_oracle(bit_board, bit_mask, True, a0, b0, bd_shp, 0) print('Player {} should win in {} move.'.format( ('X' if player == cm.BoardPiece(1) else 'O'), depth)) assert depth == 1 print('\n##########################################################\n') # Generate an empty board arr_board = cm.initialize_game_state() # Convert board to bitmap player = cm.PLAYER1 bit_board, bit_mask = cm.board_to_bitmap(arr_board, player) # Full game # move_list = [3, 2, 3, 3, 3, 2, 2, 2, 5, 4, 0, 4, 4, 4, 1, 1, 5, 2, 6] move_list = [3, 2, 3, 3, 3, 2, 2, 2, 5, 4, 0, 4, 4, 4] for mv in move_list[:-1]: # Apply the move to both boards cm.apply_action(arr_board, mv, player) bit_board, bit_mask = cm.apply_action_cp(bit_board, bit_mask, mv, bd_shp) # Switch to the next player player = cm.BoardPiece(player % 2 + 1) print(cm.pretty_print_board(arr_board)) action, _ = generate_move(arr_board.copy(), player, None) print('MCTS plays in column {}'.format(action)) try: assert (action == 2 or action == 5) except AssertionError: print('NOTE: MCTS doesn\'t block this win unless it is given ' 'over 5s to search. It should play in column 2 or 5.') # Apply next move to both boards cm.apply_action(arr_board, move_list[-1], player) bit_board, bit_mask = cm.apply_action_cp(bit_board, bit_mask, move_list[-1], bd_shp) # Switch to the next player player = cm.BoardPiece(player % 2 + 1) print(cm.pretty_print_board(arr_board)) score, depth = alpha_beta_oracle(bit_board, bit_mask, True, a0, b0, bd_shp, 0) print('Player {} should win in {} move.'.format( ('X' if player == cm.BoardPiece(1) else 'O'), depth)) assert depth == 5 print('\n##########################################################\n') # Test other hard coded boards move_list_list = [[3, 4, 3, 3, 1, 0, 4, 4, 1, 1, 3, 0, 0, 4, 5, 5], [ 3, 3, 4, 5, 1, 2, 4, 4, 3, 4, 3, 4, 4, 3, 1, 1, 0, 5, 1, 5, 5, 1, 0, 0 ]] # Full games # [3, 4, 3, 3, 1, 0, 4, 4, 1, 1, 3, 0, 0, 4, 5, 5, 4, 6, 2, 2, 2] # [3, 4, 3, 3, 1, 0, 4, 4, 1, 1, 3, 0, 0, 4, 4, 1, 1, 5, 5, 5, 3, # 5, 5, 4, 5, 0, 2, 0, 2] for move_list in move_list_list: # Generate an empty board arr_board = cm.initialize_game_state() # Convert board to bitmap player = cm.PLAYER1 bit_board, bit_mask = cm.board_to_bitmap(arr_board, player) for mv in move_list: # Apply the move to both boards cm.apply_action(arr_board, mv, player) bit_board, bit_mask = cm.apply_action_cp(bit_board, bit_mask, mv, bd_shp) # Switch to the next player player = cm.BoardPiece(player % 2 + 1) # Print the current board state print(cm.pretty_print_board(arr_board)) # Check for guaranteed wins score, depth = alpha_beta_oracle(bit_board, bit_mask, True, a0, b0, bd_shp, 0) print('It is Player {}\'s turn. They should win in {} moves.'.format( ('X' if player == cm.BoardPiece(1) else 'O'), depth)) action, _ = generate_move(arr_board.copy(), player, None) print('Player {} plays in column {}'.format( ('X' if player == cm.BoardPiece(1) else 'O'), action)) print('\n##########################################################\n')
def test_heuristic_solver(): max_depth = 0 # test_board = cm.initialize_game_state() # test_board[0, 1:4] = cm.PLAYER1 # test_board[1, 3] = cm.PLAYER2 # board_str = cm.pretty_print_board(test_board) # print('') # print(board_str) # assert (agm.heuristic_solver_bits(test_board, cm.PLAYER1, True) == # agm.heuristic_solver(test_board, cm.PLAYER1, True)) # # test_board = cm.initialize_game_state() # test_board[0, 2:5] = cm.PLAYER1 # test_board[1, 2:5] = cm.PLAYER2 # board_str = cm.pretty_print_board(test_board) # print('') # print(board_str) # assert (agm.heuristic_solver_bits(test_board, cm.PLAYER2, False) == # agm.heuristic_solver(test_board, cm.PLAYER1, True)) # test_board = cm.initialize_game_state() # test_board[0, 2:4] = cm.PLAYER1 # test_board[1, 2] = cm.PLAYER1 # test_board[0, 1] = cm.PLAYER2 # test_board[2, 2] = cm.PLAYER2 # test_board[1, 3] = cm.PLAYER2 # board_str = cm.pretty_print_board(test_board) # print('') # print(board_str) # # assert agm.heuristic_solver(test_board, cm.PLAYER1, True) == 0 # test_board_cp = test_board.copy() # assert agm.alpha_beta(test_board_cp, cm.PLAYER1, True, max_depth, # -1000, 1000)[1] == 4 # # test_board = cm.initialize_game_state() # test_board[0, 3:6] = cm.PLAYER1 # test_board[1, 3] = cm.PLAYER2 # test_board[0, 2] = cm.PLAYER2 # board_str = cm.pretty_print_board(test_board) # print('') # print(board_str) # # assert agm.heuristic_solver(test_board, cm.PLAYER2, True) == -3 # test_board_cp = test_board.copy() # assert agm.alpha_beta(test_board_cp, cm.PLAYER2, True, max_depth, # -1000, 1000)[1] == 6 # # test_board = cm.initialize_game_state() # test_board[:3, 1] = cm.PLAYER1 # test_board[0, 3] = cm.PLAYER1 # test_board[3, 1] = cm.PLAYER2 # test_board[0, 2] = cm.PLAYER2 # test_board[1, 3] = cm.PLAYER2 # test_board[0, 4] = cm.PLAYER2 # board_str = cm.pretty_print_board(test_board) # print('') # print(board_str) # # assert agm.heuristic_solver(test_board, cm.PLAYER2, True) == 5 # test_board_cp = test_board.copy() # assert not agm.alpha_beta(test_board_cp, cm.PLAYER2, True, max_depth, # -1000, 1000)[1] == 2 # # test_board = cm.initialize_game_state() # moves = np.array([3, 1, 2, 2, 5, 4, 4, 1, 2, 4, 2, 4, 2, 2, 3]) # player = cm.PLAYER1 # for mv in moves: # cm.apply_player_action(test_board, mv, player, False) # player = cm.switch_player(player) # # board_str = cm.pretty_print_board(test_board) # print('') # print(board_str) # test_board_cp = test_board.copy() # assert agm.alpha_beta(test_board_cp, cm.PLAYER2, True, max_depth, # -1000, 1000)[1] == 3 # # test_board = cm.initialize_game_state() # moves = np.array([3, 1, 4, 5, 3, 3, 4, 5, 4, 4, 3, 5, 5, 5, 4, 6, 3, 3, # 5, 0, 1, 1, 1, 1, 1, 0, 4, 6, 0, 6]) # player = cm.PLAYER1 # for mv in moves: # cm.apply_player_action(test_board, mv, player, False) # player = cm.switch_player(player) # # board_str = cm.pretty_print_board(test_board) # print('') # print(board_str) # test_board_cp = test_board.copy() # assert agm.alpha_beta(test_board_cp, cm.PLAYER1, True, max_depth, # -1000, 1000)[1] == 6 # # test_board = cm.initialize_game_state() # moves = np.array([3, 1, 2, 3, 2, 4, 2, 2, 3, 3, 2, 3, 2, 0, 3, 0, 0, # 5, 0, 6, 0, 0, 6, 5, 5, 5, 5, 5]) # player = cm.PLAYER1 # for mv in moves: # cm.apply_player_action(test_board, mv, player, False) # player = cm.switch_player(player) # # board_str = cm.pretty_print_board(test_board) # print('') # print(board_str) # test_board_cp = test_board.copy() # assert agm.alpha_beta(test_board_cp, cm.PLAYER1, True, max_depth, # -1000, 1000)[1] == 6 # # test_board = cm.initialize_game_state() # moves = np.array([3, 3, 2, 4, 0, 1, 0, 3, 0, 0, 2, 3, 3, 2, 2, 2, 0, 6, # 2, 5, 6, 5, 5, 5, 3, 5]) # player = cm.PLAYER1 # for mv in moves: # cm.apply_player_action(test_board, mv, player, False) # player = cm.switch_player(player) # # board_str = cm.pretty_print_board(test_board) # print('') # print(board_str) # test_board_cp = test_board.copy() # assert agm.alpha_beta(test_board_cp, cm.PLAYER1, True, max_depth, # -1000, 1000)[1] != 4 test_board = cm.initialize_game_state() # test_board[0, 2:5] = cm.PLAYER1 test_board[0, 2:4] = cm.PLAYER1 test_board[0, 1] = cm.PLAYER2 # test_board[0, 4] = cm.PLAYER2 test_board[0, 5] = cm.PLAYER1 # test_board[0, 5] = cm.PLAYER1 # test_board[0, 2] = cm.PLAYER1 board_str = cm.pretty_print_board(test_board) print('') print(board_str) test_board_cp = test_board.copy() board_map, board_mask = cm.board_to_bitmap(test_board_cp, cm.PLAYER1) print(agm.heuristic_solver_bits(board_map, board_mask, test_board_cp.shape[0], True))
def test_connect_four_bits(): # Test a diagonal test_board = cm.initialize_game_state() test_board[0, 3] = cm.PLAYER1 test_board[1, 4] = cm.PLAYER1 test_board[2, 5] = cm.PLAYER1 test_board[3, 6] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.connect_four(player_map, test_board.shape[0]) # Test the same diagonal for the other player test_board = cm.initialize_game_state() test_board[0, 3] = cm.PLAYER2 test_board[1, 4] = cm.PLAYER2 test_board[2, 5] = cm.PLAYER2 test_board[3, 6] = cm.PLAYER2 player_map, mask_board = cm.board_to_bitmap(test_board, cm.PLAYER1) player_map2 = player_map ^ mask_board board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.connect_four(player_map2, test_board.shape[0]) # Rotate the diagonal test_board = cm.initialize_game_state() test_board[0, 6] = cm.PLAYER1 test_board[1, 5] = cm.PLAYER1 test_board[2, 4] = cm.PLAYER1 test_board[3, 3] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.connect_four(player_map, test_board.shape[0]) # Test a row at the top test_board = cm.initialize_game_state() test_board[5, 3] = cm.PLAYER1 test_board[5, 4] = cm.PLAYER1 test_board[5, 5] = cm.PLAYER1 test_board[5, 6] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.connect_four(player_map, test_board.shape[0]) # Test a row at the bottom test_board = cm.initialize_game_state() test_board[0, 0] = cm.PLAYER1 test_board[0, 1] = cm.PLAYER1 test_board[0, 2] = cm.PLAYER1 test_board[0, 3] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.connect_four(player_map, test_board.shape[0]) # Test a column on the left test_board = cm.initialize_game_state() test_board[2, 0] = cm.PLAYER1 test_board[3, 0] = cm.PLAYER1 test_board[4, 0] = cm.PLAYER1 test_board[5, 0] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.connect_four(player_map, test_board.shape[0]) # Test a column on the right test_board = cm.initialize_game_state() test_board[0, 6] = cm.PLAYER1 test_board[1, 6] = cm.PLAYER1 test_board[2, 6] = cm.PLAYER1 test_board[3, 6] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.connect_four(player_map, test_board.shape[0]) # Test some things in the middle test_board = cm.initialize_game_state() test_board[2, 5] = cm.PLAYER1 test_board[3, 4] = cm.PLAYER1 test_board[4, 3] = cm.PLAYER1 test_board[5, 2] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.connect_four(player_map, test_board.shape[0]) test_board = cm.initialize_game_state() test_board[0, 2] = cm.PLAYER1 test_board[1, 3] = cm.PLAYER1 test_board[2, 4] = cm.PLAYER1 test_board[3, 5] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.connect_four(player_map, test_board.shape[0]) # Test the last_action option for column 6 test_board = cm.initialize_game_state() test_board[0, 3] = cm.PLAYER1 test_board[1, 4] = cm.PLAYER1 test_board[2, 5] = cm.PLAYER1 test_board[3, 6] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.connect_four(player_map, test_board.shape[0]) # Test the last_action option for column 5 test_board = cm.initialize_game_state() test_board[0, 2] = cm.PLAYER1 test_board[1, 3] = cm.PLAYER1 test_board[2, 4] = cm.PLAYER1 test_board[3, 5] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.connect_four(player_map, test_board.shape[0]) # Test the last_action option for column 1 test_board = cm.initialize_game_state() test_board[0, 1] = cm.PLAYER1 test_board[1, 1] = cm.PLAYER1 test_board[2, 1] = cm.PLAYER1 test_board[3, 1] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.connect_four(player_map, test_board.shape[0]) # Test the last_action option for column 2 diagonal pattern test_board = cm.initialize_game_state() test_board[0, 1] = cm.PLAYER1 test_board[1, 2] = cm.PLAYER1 test_board[2, 3] = cm.PLAYER1 test_board[3, 4] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert cm.connect_four(player_map, test_board.shape[0]) # Test for overflow issues - horizontal test_board = cm.initialize_game_state() test_board[0, 4] = cm.PLAYER1 test_board[0, 5] = cm.PLAYER1 test_board[0, 6] = cm.PLAYER1 test_board[1, 0] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert not cm.connect_four(player_map, test_board.shape[0]) # Test for overflow issues - diagonal test_board = cm.initialize_game_state() test_board[0, 2] = cm.PLAYER1 test_board[1, 1] = cm.PLAYER1 test_board[2, 0] = cm.PLAYER1 test_board[2, 6] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert not cm.connect_four(player_map, test_board.shape[0]) # Test for overflow issues - vertical test_board = cm.initialize_game_state() test_board[3, 1] = cm.PLAYER1 test_board[3, 2] = cm.PLAYER1 test_board[3, 3] = cm.PLAYER1 test_board[4, 0] = cm.PLAYER1 test_board[2, 0] = cm.PLAYER1 player_map = cm.board_to_bitmap(test_board, cm.PLAYER1)[0] board_str = cm.pretty_print_board(test_board) print('') print(board_str) assert not cm.connect_four(player_map, test_board.shape[0])