def mc_update_scores(scores, board, player): """ This function takes a grid of scores (a list of lists) with the same dimensions as the Tic-Tac-Toe board, a board from a completed game, and which player the machine player is. The function should score the completed board and update the scores grid. As the function updates the scores grid directly, it does not return anything, """ grid_scores = [[0 for dummy_col in range(board.get_dim())] for dummy_row in range(board.get_dim())] if board.check_win() == player: for dummy_row in range(board.get_dim()): for dummy_col in range(board.get_dim()): if board.square(dummy_row, dummy_col) == player: grid_scores[dummy_row][dummy_col] = SCORE_CURRENT elif board.square(dummy_row, dummy_col) == provided.switch_player(player): grid_scores[dummy_row][dummy_col] = -SCORE_OTHER elif board.check_win() == provided.switch_player(player): for dummy_row in range(board.get_dim()): for dummy_col in range(board.get_dim()): if board.square(dummy_row, dummy_col) == player: grid_scores[dummy_row][dummy_col] = -SCORE_CURRENT elif board.square(dummy_row, dummy_col) == provided.switch_player(player): grid_scores[dummy_row][dummy_col] = SCORE_OTHER for dummy_row in range(board.get_dim()): for dummy_col in range(board.get_dim()): scores[dummy_row][dummy_col] += grid_scores[dummy_row][dummy_col]
def mc_move(board, player, trials): """ Use the Monte Carlo simulation to return a move for the machine player in the form of a (row, column) tuple. """ scores = [ [0 for dummy_col in range(board.get_dim())] for dummy_row in range(board.get_dim())] # For obvious player winning move for dummy_idx in board.get_empty_squares(): temp_obj = board.clone() temp_obj.move(dummy_idx[0], dummy_idx[1], player) if temp_obj.check_win() == player: return dummy_idx # For obvious opponent winning move for dummy_idx in board.get_empty_squares(): temp_obj = board.clone() temp_obj.move(dummy_idx[0], dummy_idx[1], provided.switch_player(player)) if temp_obj.check_win() == provided.switch_player(player): return dummy_idx # Random move for dummy_idx in range(trials): temp_obj = board.clone() mc_trial(temp_obj, player) mc_update_scores(scores, temp_obj, player) if board.get_empty_squares() != []: return get_best_move(board, scores)
def mc_update_scores(scores, board, player): """ This function takes a grid of scores (a list of lists) with the same dimensions as the Tic-Tac-Toe board, a board from a completed game, and which player the machine player is. The function should score the completed board and update the scores grid. As the function updates the scores grid directly, it does not return anything. """ opponent = provided.switch_player(player) if player == board.check_win(): me_winner = True elif opponent == board.check_win(): me_winner = False else: return 0 for index_row, row in enumerate(scores): for index_col, _col in enumerate(row): current_cell = board.square(index_row, index_col) if current_cell == player: if me_winner: scores[index_row][index_col] += SCORE_CURRENT else: scores[index_row][index_col] -= SCORE_CURRENT elif current_cell == provided.switch_player(player): if me_winner: scores[index_row][index_col] -= SCORE_OTHER else: scores[index_row][index_col] += SCORE_OTHER
def mc_update_scores(scores, board, player): """ This function takes a grid of scores (a list of lists) with the same dimensions as the Tic-Tac-Toe board, a board from a completed game, and which player the machine player is. The function should score the completed board and update the scores grid. As the function updates the scores grid directly, it does not return anything. """ winner = board.check_win() if winner == player: player_score = MCMATCH other_player_score = -MCOTHER elif winner == provided.switch_player(player): player_score = -MCMATCH other_player_score = MCOTHER else: player_score = 0 other_player_score = 0 dimension = board.get_dim() for row in range(dimension): for col in range(dimension): status = board.square(row, col) if status == player: scores[row][col] += player_score elif status == provided.switch_player(player): scores[row][col] += other_player_score else: scores[row][col] += 0 return None
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ #clone board clone = board.clone() score = [] move = [] if clone.check_win() != None: return SCORES[provided.switch_player(player)], (-1, -1) #get empty squares empty_squares = clone.get_empty_squares() for each_square in empty_squares: #if clone.check_win() != player: clone.move(each_square[0], each_square[1], player) score_move = mm_move(clone, provided.switch_player(player)) score.append(score_move[0]) move.append(each_square) if player == provided.PLAYERX: idx = score.index(max(score)) else: idx = score.index(min(score)) #return score(idx), move(idx) return score[idx], move[idx]
def mc_update_scores(scores, board, player): """ This function takes a grid of scores, a board from a completed game, and which player the machine player is. The function scores the completed board and update the scores grid. """ winner = board.check_win() # assign score to earn based on the result if winner == player: player_score = SCORE_CURRENT other_score = -SCORE_OTHER elif winner == provided.switch_player(player): player_score = -SCORE_CURRENT other_score = SCORE_OTHER else: player_score = 0 other_score = 0 for dummyrow in range(board.get_dim()): for dummycol in range(board.get_dim()): if board.square(dummyrow,dummycol) == player: scores[dummyrow][dummycol] += player_score elif board.square(dummyrow,dummycol) == provided.switch_player(player): scores[dummyrow][dummycol] += other_score
def mc_update_scores(scores, board, player): """ This function takes a grid of scores (a list of lists) with the same dimensions as the Tic-Tac-Toe board, a board from a completed game, and which player the machine player is. The function should score the completed board and update the scores grid. As the function updates the scores grid directly, it does not return anything, """ print "start update" print str(board) print "scores start", scores if board.check_win() == provided.DRAW: print "draw" return elif board.check_win() == player: print "win" for dummy_row in range(board.get_dim()): for dummy_col in range(board.get_dim()): if board.square(dummy_row, dummy_col) == player: scores[dummy_row][dummy_col] = SCORE_CURRENT elif board.square(dummy_row, dummy_col) == provided.switch_player(player): scores[dummy_row][dummy_col] = -SCORE_OTHER elif board.check_win() == provided.switch_player(player): print "lose" for dummy_row in range(board.get_dim()): for dummy_col in range(board.get_dim()): if board.square(dummy_row, dummy_col) == player: scores[dummy_row][dummy_col] = -SCORE_CURRENT elif board.square(dummy_row, dummy_col) == provided.switch_player(player): scores[dummy_row][dummy_col] = SCORE_OTHER print "scores updated", scores
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ status = board.check_win() if status != None: return SCORES[status], (-1, -1) else: empty_squares = board.get_empty_squares() min_rival_score = 1 min_rival_move = (-1, -1) for square in empty_squares: board_temp = board.clone() board_temp.move(square[0], square[1], player) if player == provided.PLAYERO: rival_mm = mm_move(board_temp, provided.switch_player(player)) else: temp = mm_move(board_temp, provided.switch_player(player)) rival_mm = (-temp[0], temp[1]) if rival_mm[0] == -1: return (-1, square) if player == provided.PLAYERO else (1, square) elif rival_mm[0] <= min_rival_score: min_rival_score = rival_mm[0] min_rival_move = square return (-min_rival_score, min_rival_move) if player == provided.PLAYERO else (min_rival_score, min_rival_move)
def mc_update_scores(scores, board, player): """ This function takes a grid of scores (a list of lists) with the same dimensions as the Tic-Tac-Toe board, a board from a completed game, and which player the machine player is. The function should score the completed board and update the scores grid. As the function updates the scores grid directly, it does not return anything. """ game_res = board.check_win() if game_res == provided.DRAW: return dim = board.get_dim() if game_res == player: for row in range(dim): for col in range(dim): if board.square(row, col) == player: scores[row][col] += MCMATCH elif board.square(row, col) == provided.switch_player(player): scores[row][col] += -MCOTHER else: for row in range(dim): for col in range(dim): if board.square(row, col) == player: scores[row][col] += -MCMATCH elif board.square(row, col) == provided.switch_player(player): scores[row][col] += MCOTHER return scores
def mc_update_scores(scores, board, player): """ This function should update the scores """ # If current player win, then add the scores from the # current player and subtract the scores from the # other player if board.check_win() == player: for dummy_row in range(board.get_dim()): for dummy_col in range(board.get_dim()): if board.square(dummy_row, dummy_col) == player: scores[dummy_row][dummy_col] += SCORE_CURRENT if board.square(dummy_row, dummy_col) == provided.switch_player(player): scores[dummy_row][dummy_col] -= SCORE_OTHER # If lose then subtract score of the other player and # add the scores from the other player elif board.check_win() == provided.switch_player(player): for dummy_row in range(board.get_dim()): for dummy_col in range(board.get_dim()): if board.square(dummy_row, dummy_col) == player: scores[dummy_row][dummy_col] -= SCORE_CURRENT if board.square(dummy_row, dummy_col) == provided.switch_player(player): scores[dummy_row][dummy_col] += SCORE_OTHER # If draw, then do nothing else: pass
def mc_update_scores(scores, board, player): """ This function takes a grid of scores, a board from a completed game, and which player the machine player is. The function score the completed board and update the scores grid. """ # first, let's determine who's who winner = board.check_win() other = provided.switch_player(player) loser = provided.switch_player(winner) # changing signs whether we lose or win if winner == player: winner_score = SCORE_CURRENT loser_score = -SCORE_OTHER elif winner == other: winner_score = SCORE_OTHER loser_score = -SCORE_CURRENT else: return # cycling through the board and counting points for tic in range(board.get_dim()): for tac in range(board.get_dim()): if board.square(tic, tac) == winner: scores[tic][tac] += winner_score if board.square(tic, tac) == loser: scores[tic][tac] += loser_score
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ if board.check_win() != None: return SCORES[board.check_win()], (-1,-1) empty_squares = board.get_empty_squares() # choose the move with minimum max-loss(score) desired_move = (-1, -1) # for X player, get the minimum score from children if player == provided.PLAYERX: max_score = -2 # 1 for PLAYERX win, we want to choose the maximum of all for square in empty_squares: row, col = square[0], square[1] # get a clone board and make a move temp_board = board.clone() temp_board.move(row, col, player) # calling help recursive function get min score # Only get first return value temp_score, _ = mm_move(temp_board, provided.switch_player(player)) if max_score < temp_score : max_score = temp_score desired_move = (row, col) return max_score, desired_move # for O player, get the maximum score from children if player == provided.PLAYERO: min_score = 2 # -1 for PLAYERO to win, we want to choose the minimum of all for square in empty_squares: row, col = square[0], square[1] # get a clone board and make a move temp_board = board.clone() temp_board.move(row, col, player) # Only get first return value temp_score, _ = mm_move(temp_board, provided.switch_player(player)) #print "O's temp_score", temp_score if min_score > temp_score: min_score = temp_score desired_move = (row, col) return min_score, desired_move # undefined player return 0, (-1, -1)
def mc_trial(board, player): ''' This function takes a current board and the next player to move. The function should play a game starting with the given player by making random moves, alternating between players. The function should return when the game is over. ''' in_progress = lambda: not board.check_win() while in_progress(): row, col = random.choice(board.get_empty_squares()) board.move(row, col, player) provided.switch_player(player)
def mc_trial(board, player): """ The function plays a game starting with the given player by making random moves. Returns when the game is over. Modified board contains the state of the game, so it does not return anything. """ while board.check_win() == None: available_squares = board.get_empty_squares() random_square = random.choice(available_squares) board.move(random_square[0], random_square[1], player) provided.switch_player(player)
def mc_trial(board, player): """ Runs a random trial of the game """ while board.check_win() == None: empty_squares = board.get_empty_squares() # get empty squares and put into a new list random_choice = random.choice(empty_squares) board.move(random_choice[0],random_choice[1],player) # make a move randomly provided.switch_player(player)
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ if board.check_win() != None: return SCORES[board.check_win()], (-1, -1) else: lst = [] for square in board.get_empty_squares(): temp_board = board.clone() row, col = square[0], square[1] temp_board.move(row, col, player) result = mm_move(temp_board, provided.switch_player(player)) if result[0] == SCORES[player]: return result[0], square else: lst.append((result[0], square)) if player == provided.PLAYERX: score = max(lst)[0] best_move = max(lst)[1] else: score = min(lst)[0] best_move = min(lst)[1] return score, best_move
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ winner = board.check_win() # regression base case if winner: #print "the winner is", winner, ":", SCORES[winner] #print board return SCORES[winner], (-1, -1) # inductive case - check minimax score for all possible player moves res_score = None res_move = (-1, -1) for cell in board.get_empty_squares(): # checking cell move for player mm_board = board.clone() mm_board.move(cell[0], cell[1], player) mm_player = provided.switch_player(player) # the best (minimal) score according to all possible moves by other player score = mm_move(mm_board, mm_player)[0] # this move is better than others if res_score == None or score*SCORES[player] > res_score*SCORES[player]: res_score, res_move = score, cell # this move makes the player win, no need to check other possible moves if res_score*SCORES[player] == 1: return (res_score, res_move) return (res_score, res_move)
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ if board.check_win() != None: score = SCORES[board.check_win()] return score, (-1,-1) else: best_score = -2 score_list = [] move_list = [] for each_cell in board.get_empty_squares(): passboard = board.clone() passboard.move(each_cell[0], each_cell[1], player) other_player = provided.switch_player(player) nextmove = mm_move(passboard, other_player) score_list.append(nextmove[0]) move_list.append(nextmove[1]) if nextmove[0] == SCORES[player]: return nextmove[0], each_cell #print score_list #print move_list #print "" if player == provided.PLAYERX: best_score = max(score_list) else: best_score = min (score_list) best_move = move_list[score_list.index(best_score)] return best_score, best_move
def mc_trial(board, player): """ This function takes a current board and the next player to move. """ curplayer = player winner = None #scores = [[0 for dummycol in range(board._dim)] # for dummyrow in range(board._dim)] print board.__str__() while winner == None: # Pick an empty square randomly empty = board.get_empty_squares() empty_sq = empty[random.randrange(len(empty))] row = empty_sq[0] col = empty_sq[1] # Move board.move(row, col, curplayer) # Update state winner = board.check_win() curplayer = provided.switch_player(curplayer) # Display board print board.__str__()
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ desired_move = (-1, -1) winner = board.check_win() if winner: #print board #print (SCORES[winner], desired_move), SCORES[player] return (SCORES[winner], desired_move) else: emptys = board.get_empty_squares() maximum = (-900, (-1, -1)) for place in emptys: new_board = board.clone() new_board.move(place[0], place[1], player) now = mm_move(new_board, provided.switch_player(player)) if (SCORES[player] * now[0] > maximum[0]): maximum = (SCORES[player] * now[0], place) #print board #print (maximum[0] * SCORES[player], maximum[1]), SCORES[player] return (maximum[0] * SCORES[player], maximum[1])
def mc_trial(board, player): """ This function takes a current board and the next player to move. The function should play a game starting with the given player by making random moves, alternating between players. The function should return when the game is over. The modified board will contain the state of the game, so the function does not return anything. In other words, the function should modify the board input. """ #print board current_player = player won_game = False while won_game == False: # choise a random empty square: try: empty_square = random.choice(board.get_empty_squares()) #print "Ures :", empty_square #print "Current Player:", current_player board.move(empty_square[0], empty_square[1], current_player) #print board if board.check_win() == None: current_player = provided.switch_player(current_player) else: won_game = True except IndexError: # List is no more empty_square #print "Empty LIST - END" break
def mc_update_scores(scores, board, player): """ Score the completed board and update the scores grid """ # Here the game must be ended # There is something to do only if the game is not a draw machine_player = player human_player = provided.switch_player(machine_player) # Assumes that the machine player wins the game machine_player_score_adjustment = SCORE_CURRENT human_player_score_adjustment = -SCORE_OTHER game_status = board.check_win() # The game cannot be a draw if score needs to be modified if game_status != provided.DRAW: # In case the machine player fails if game_status != machine_player: machine_player_score_adjustment = -SCORE_CURRENT human_player_score_adjustment = SCORE_OTHER for row in range(board.get_dim()): for col in range(board.get_dim()): # The value from square is a number, not a string ("X" or "O" or "") cell_value = board.square(row, col) if cell_value == machine_player: scores[row][col] += machine_player_score_adjustment elif cell_value == human_player: scores[row][col] += human_player_score_adjustment else: scores[row][col] += 0.0
def mc_trial(working_board, player): """ Takes a given board state and plays the game to completion with alternating player moves made at random - each call to this function is used to run one trial """ inturn = player game_over = 0 while game_over == 0: # Check if win if working_board.check_win() != None: game_over = 1 #print working_board return # Check empty cells empty_cells = working_board.get_empty_squares() # Choose position and move turn_pos = random.choice(empty_cells) working_board.move(turn_pos[0],turn_pos[1],inturn) # Switch player inturn = provided.switch_player(inturn)
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ # completed board case no_more_moves = board.check_win() if no_more_moves != None: return SCORES[no_more_moves], (-1, -1) else: score_move_list = [] empty_squares = board.get_empty_squares() for next_move in empty_squares: board_copy = board.clone() board_copy.move(next_move[0], next_move[1], player) # case where the game ends after the above move is_game_over = board_copy.check_win() if is_game_over != None: return SCORES[is_game_over], next_move else: next_player = provided.switch_player(player) score = mm_move(board_copy, next_player)[0] score_move_list.append((score, next_move)) # sort the list for scoring purposes score_move_list.sort() if player == provided.PLAYERX: best_score = score_move_list[-1][0] best_move = score_move_list[-1][1] if player == provided.PLAYERO: best_score = score_move_list[0][0] best_move = score_move_list[0][1] return best_score, best_move
def mc_trial(board, player): """ Using the currnet board determine next move through random selection of of empty cells. Completed the move, switch players and continues until one of the players wins. Arguments: board (list): a 2D array representing the game board player (int): represents the AI player """ while board.check_win() == None: # Find all empty squares available_moves = board.get_empty_squares() # Randomly select an available position next_move = random.choice(available_moves) # Make the move for current player board.move(next_move[0], next_move[1], player) # Switch players player = provided.switch_player(player) # Check for win, end game if true if board.check_win() != None: break
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ #Base case if board.check_win() != None: return SCORES[board.check_win()], (-1,-1) # worst values results = (-1, (-1,-1)) scores = [] for poss_move in board.get_empty_squares(): new_board = board.clone() new_board.move(poss_move[0], poss_move[1], player) score, dummy_move = mm_move(new_board, provided.switch_player(player)) scores.append((score, poss_move)) if score * SCORES[player] == 1: return (score, poss_move) elif score * SCORES[player] == 0: results = (score, poss_move) elif results[0] == -1: results = (results[0], poss_move) return results[0] * SCORES[player], results[1]
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ # base case # detect if the game is effectively over if board.check_win() is not None: return SCORES[board.check_win()], (-1, -1) # recursive cases # start with the worst possible initial values result = (-1, (-1, -1)) # depth fist search along the tree for move in board.get_empty_squares(): cloned_board = board.clone() cloned_board.move(move[0], move[1], player) score = mm_move(cloned_board, provided.switch_player(player))[0] # best move found if score * SCORES[player] == 1: return score, move # update initial values elif score * SCORES[player] > result[0]: result = (score, move) elif result[0] == -1: result = (result[0], move) return result[0] * SCORES[player], result[1]
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ result = board.check_win() if result is provided.PLAYERX: return SCORES[provided.PLAYERX], (-1, -1) if result is provided.PLAYERO: return SCORES[provided.PLAYERO], (-1, -1) if result is provided.DRAW: return SCORES[provided.DRAW], (-1, -1) if player is provided.PLAYERX: best_score = -2, (-1, -1) else: best_score = 2, (-1, -1) for square in board.get_empty_squares(): clone_board = board.clone() clone_board.move(square[0], square[1], player) score = mm_move(clone_board, provided.switch_player(player)) if player is provided.PLAYERX and score[0] > best_score[0]: best_score = score[0], square elif player is provided.PLAYERO and score[0] < best_score[0]: best_score = score[0], square return best_score
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ board_clone = board.clone() moves = board_clone.get_empty_squares() if moves == [] or board_clone.check_win() == provided.DRAW: return 0, (-1, -1) elif board_clone.check_win() == provided.PLAYERX: return SCORES[provided.PLAYERX], (-1, -1) elif board_clone.check_win() == provided.PLAYERO: return SCORES[provided.PLAYERO], (-1, -1) scores_moves = [] for move in moves: temp_board_clone = board_clone.clone() temp_board_clone.move(move[0], move[1], player) if temp_board_clone.check_win() == None: scores_moves.append(mm_move(temp_board_clone, provided.switch_player(player))) elif temp_board_clone.check_win() == provided.PLAYERX: scores_moves.append((SCORES[provided.PLAYERX], (-1, -1))) elif temp_board_clone.check_win() == provided.PLAYERO: scores_moves.append((SCORES[provided.PLAYERO], (-1, -1))) elif temp_board_clone.check_win() == provided.DRAW: scores_moves.append((SCORES[provided.DRAW], (-1, -1))) scores = [score for score, move in scores_moves] if player == provided.PLAYERX: return max(scores), moves[scores.index(max(scores))] elif player == provided.PLAYERO: return min(scores), moves[scores.index(min(scores))]
def mc_update_scores(scores, board, player): """ Updates the scores """ board_dim = range(board.get_dim()) for row in board_dim: for col in board_dim: square = board.square(row, col) if board.check_win() == player: if square == player: scores[row][col] += SCORE_CURRENT elif square == provided.EMPTY: scores[row][col] += 0 else: scores[row][col] -= SCORE_OTHER elif board.check_win() == provided.DRAW: scores[row][col] += 0 elif board.check_win() == provided.switch_player(player): square = board.square(row, col) if square == player: scores[row][col] -= SCORE_CURRENT elif square == provided.EMPTY: scores[row][col] += 0 else: scores[row][col] += SCORE_OTHER
def mc_trial(board, player): """ This function takes a current board and the next player to move. """ current_status = board.check_win() while current_status == None: empty_list = board.get_empty_squares() length = len(empty_list) will_move = empty_list[random.randrange(0, length)] board.move(will_move[0], will_move[1], player) # return when the game is over current = board.check_win() if current == provided.PLAYERX or current == provided.PLAYERO or current == provided.DRAW: break # Switch player player = provided.switch_player(player)
def mc_trial(board, player): """ This function takes a current board and the next player to move. The function plays a game starting with the given player by making random moves, alternating between players. The modified board will contain the state of the game. """ while board.check_win() == None: # we select a board with empty squares board_empty_squares = board.get_empty_squares() # we select a random square in order to move there random_square = random.choice(board_empty_squares) #we make the move board.move(random_square[0], random_square[1], player) # we switch the player player = provided.switch_player(player)
def mc_update_scores(scores, board, player): """ This function scores the completed board and updates the scores grid """ # get the winner player winner = board.check_win() # get board dim dim = board.get_dim() # when DRAW, no need to calculate score if winner == provided.DRAW: return else: player_loss = winner player_loss = provided.switch_player(player_loss) for row in range(dim): for col in range(dim): if board.square(row, col) == winner: scores[row][col] += 1 if board.square(row, col) == player_loss: scores[row][col] -= 1
def mc_trial(board, player): """ This function plays a game with the given board and the next player by making random moves """ current_board = board # print current_board # print current_board.check_win() while current_board.check_win() == None: empty_squares = current_board.get_empty_squares() # print empty_squares random_square = random.choice(empty_squares) # print random_square current_board.move(random_square[0], random_square[1], player) # print current_board player = provided.switch_player(player)
def mc_trial(board, player): """ This function takes a current board and the next player to move then move turn by turn till someone wins or draw modify the board """ cnt = 0 while board.check_win() == None: # print ("moves done in a trial: ", cnt) # ## shall only consider the board.get_valid_moves() # print ("# of valid moves: ", len(board.get_valid_moves())) ### changed to get_all_empty_ add_pos = random.choice(board.get_valid_moves( )) # return list of tuple (boxrow, boxcol, row, col) # 4 positions defines a move board.move(add_pos[0], add_pos[1], add_pos[2], add_pos[3], player) # move(self, boxrow, boxcol, row, col, player): player = provided.switch_player(player) cnt += 1 return board.check_win()
def mc_trial(board, player): """ This function takes a current board and the next player to move. """ current_player = player win = False while not win: empty_squares = board.get_empty_squares() #print empty_squares #print board square_coord = random.choice(empty_squares) board.move(square_coord[0], square_coord[1], current_player) if board.check_win(): win = True #print 'Win \n', board return #print board #print board.check_win() #return board else: current_player = provided.switch_player(current_player)
def mc_update_scores(scores, board, player): """ Updates global scores from an iteration of a Monte Carlo trial. """ winner = board.check_win() opp_player = provided.switch_player(player) if winner == player: for r_idx in range(board.get_dim()): for c_idx in range(board.get_dim()): if board.square(r_idx, c_idx) == player: scores[r_idx][c_idx] += SCORE_CURRENT elif board.square(r_idx, c_idx) == opp_player: scores[r_idx][c_idx] -= SCORE_OTHER elif winner == opp_player: for r_idx in range(board.get_dim()): for c_idx in range(board.get_dim()): if board.square(r_idx, c_idx) == player: scores[r_idx][c_idx] -= SCORE_CURRENT elif board.square(r_idx, c_idx) == opp_player: scores[r_idx][c_idx] += SCORE_OTHER
def mc_trial(board, player): """ Runs a Monte Carlo trial based on the current player and state of the board. """ winner = None cur_player = player # Run trial while winner == None: # Determine which squares are still empty empty_squares = board.get_empty_squares() # Randomly select one of the empty squares to be the player's next move random_move = empty_squares[random.randrange(len(empty_squares))] row, col = random_move board.move(row, col, cur_player) # Update state winner = board.check_win() cur_player = provided.switch_player(cur_player)
def mc_update_scores(scores, board, player): """ This function scores the current state of a mc game. inputs: Scores - Is a list of list with the same dimensions of a tic-tac-toe board. board - Is a TTTBoard object of a completed game player - player is the player that is the machine outputs: This funcion does not return anything It modifes the scores grid """ out_come = board.check_win() if out_come == player: score_winning_game(scores, board, player) elif out_come == provided.switch_player(player): score_losing_game(scores, board, player)"""
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ sim_board = board.clone() current_score = score_board(sim_board, player) if current_score == 1: return 1, (-1,-1) if current_score == 0: return 0, (-1,-1) if current_score == -1: return -1, (-1,-1) else: empty_cells = sim_board.get_empty_squares() child_board = {} for cell in empty_cells: board_child = sim_board.clone() board_child.move(cell[0], cell[1], player) new_current_score = score_board(board_child,player) if new_current_score == SCORES[player]: return new_current_score, cell child_board[cell] = board_child max_score = current_score cell_move = (-1,-1) for cell_key, board_value in child_board.items(): child_board_cell_score = mm_move(board_value, provided.switch_player(player)) if child_board_cell_score[0] * SCORES[player] >= max_score: max_score = child_board_cell_score[0] * SCORES[player] cell_move = cell_key return max_score * SCORES[player], cell_move
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ # Base case winner = board.check_win() if winner != None: return SCORES[winner], (-1, -1) # Recursive case else: if player == provided.PLAYERX: best_score = float("-inf") elif player == provided.PLAYERO: best_score = float("inf") best_move = (-1, -1) for move in board.get_empty_squares(): clone = board.clone() clone.move(move[0], move[1], player) if clone.__str__() in VALUE_DICT: values = VALUE_DICT[clone.__str__()] else: # Call function recursively values = mm_move(clone, provided.switch_player(player)) VALUE_DICT[clone.__str__()] = values[0], move if SCORES[player] == values[0]: return values[0], move if values[0] * SCORES[player] > best_score * SCORES[player]: best_score = values[0] best_move = move return best_score, best_move
def __init__(self, size, aiplayer, aifunction, ntrials, reverse=False): # Game board self._size = size self._bar_spacing = GUI_WIDTH // (self._size * self._size) self._turn = provided.PLAYERX self._reverse = reverse # AI setup self._humanplayer = provided.switch_player(aiplayer) self._aiplayer = aiplayer self._aifunction = aifunction self._parameter = ntrials # Set up data structures self.setup_frame() # Start new game self.newgame() # set valid region highlight self.boxrow_valid = None self.boxcol_valid = None
def mc_trial(board, player): ''' Plays a game with next player to move and current board by making random moves, alternating between players. ''' while True: move = random.choice(board.get_empty_squares()) board.move(move[0], move[1], player) # print board if board.check_win() is not None: # print board.check_win() return player = provided.switch_player(player) move = random.choice(board.get_empty_squares()) board.move(move[0], move[1], player) # print board if board.check_win() is not None: # print board.check_win() return
def mc_move(board, player, trials): """ Function that chooses the best move for the machine player based on MonteCarlo simulations. """ # Sets score to a grid of zeros scores = [[0 for dummycol in range(board.get_dim())] for dummyrow in range(board.get_dim())] # Switches who the machine player is play = provided.switch_player(player) # Decrements trials by one for each iteration and runs a # Monte Carlo simulation/ updates scores while trials > 0: trials -= 1 empty_board = board.clone() mc_trial(empty_board, play) mc_update_scores(scores, empty_board, play) return get_best_move(board, scores)
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ if board.check_win() != None: return SCORES[board.check_win()], (-1, -1) candidates = [] for square in board.get_empty_squares(): aboard = board.clone() aboard.move(square[0], square[1], player) if aboard.check_win() != None: return SCORES[aboard.check_win()], square candidates.append((mm_move(aboard, provided.switch_player(player))[0], square)) if player == provided.PLAYERX: return max(candidates) if player == provided.PLAYERO: return min(candidates)
def mc_trial(board, player): """ Takes a current board and the next player to move. Plays a game starting with the given player by making random moves on the provided board, alternating between players. """ curr_player = player size = board.get_dim() # Keep playing until the game has ended. while (board.check_win() == None): next_row = random.randrange(size) next_col = random.randrange(size) # Ensure a move is being made to an empty square. while board.square(next_row, next_col) != provided.EMPTY: next_row = random.randrange(size) next_col = random.randrange(size) # Make the move. board.move(next_row, next_col, curr_player) # Switch players. curr_player = provided.switch_player(curr_player)
def mc_trial(board, player): """ This function takes a current board and the next player to move. The function should play a game starting with the given player by making random moves, alternating between players. The function should return when the game is over. The modified board will contain the state of the game, so the function does not return anything. In other words, the function should modify the board input. """ #dimension = board.get_dim() #for dummy_i in range(NTRIALS): empty_squares = board.get_empty_squares() while len(empty_squares) > 0 and board.check_win() == None: ran_index = random.randrange(len(empty_squares)) row = empty_squares[ran_index][0] col = empty_squares[ran_index][1] board.move(row, col, player) player = provided.switch_player(player) #caution empty_squares.pop(ran_index)
def mc_update_scores(scores, board, player): """ Scores a completed board and update the scorse grid. """ winner = board.check_win() board_dim = board.get_dim() other_player = provided.switch_player(player) # No need to check for draw to stop function as this already exists in provided.play_game() # Go through all squares in board for row in range(board_dim): for col in range(board_dim): if winner == player: if board.square(row, col) == player: scores[row][col] += SCORE_CURRENT elif board.square(row, col) == other_player: scores[row][col] -= SCORE_OTHER elif winner == other_player: if board.square(row, col) == player: scores[row][col] -= SCORE_CURRENT elif board.square(row, col) == other_player: scores[row][col] += SCORE_OTHER
def mc_update_scores(scores, board, player): """ This function takes a board from a completed game, and which player the machine player is. The function should score the completed board and update the scores grid. As the function updates the scores grid directly, it does not return anything, If you won the game, each square that matches your player should get a positive score (MCMATCH) and each square that matches the other player should get a negative score (-MCOTHER). Conversely, if you lost the game, each square that matches your player should get a negative score (-MCMATCH) and and each square that matches the other player should get a positive score (MCOTHER). All empty squares should get a score of 0. """ dim = board.get_dim() machine = player user = provided.switch_player(player) if board.check_win() == provided.DRAW: #for row in range( dim ): # for col in range( dim ): # scores[row][col] = 0 return if board.check_win() == machine: for row in range(dim): for col in range(dim): status = board.square(row, col) if status == machine: scores[row][col] += MCMATCH elif status == user: scores[row][col] -= MCOTHER if board.check_win() == user: for row in range(dim): for col in range(dim): status = board.square(row, col) if status == machine: scores[row][col] -= MCMATCH elif status == user: scores[row][col] += MCOTHER
def mc_update_scores(scores, board, player): """ :param scores: A 2D array which we will edit with the updated scores :param board: The completed board :param player: Which player is the machine :return: Updates the scores parameter """ other_player = provided.switch_player(player) for index_i in range(board.get_dim()): for index_j in range(board.get_dim()): if board.square(index_i, index_j) == player: if board.check_win() == player: scores[index_i][index_j] += SCORE_CURRENT if board.check_win() == other_player: scores[index_i][index_j] += -SCORE_CURRENT if board.square(index_i, index_j) == other_player: if board.check_win() == player: scores[index_i][index_j] += -SCORE_OTHER if board.check_win() == other_player: scores[index_i][index_j] += SCORE_OTHER
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ # check for win check_win = board.check_win() if check_win != None: return SCORES[check_win], (-1, -1) # create temporary dictionary to store possible moves and scores possible_moves = { SCORES[provided.PLAYERX]: [], SCORES[provided.PLAYERO]: [], SCORES[provided.DRAW]: [] } # clone board # play possible moves # recursively call mm_move for move in board.get_empty_squares(): clone = board.clone() clone.move(move[0], move[1], player) score, dummy_move = mm_move(clone, provided.switch_player(player)) if score * SCORES[player] == 1: return score, move possible_moves[score].append(move) # add calculated score to move dictionary scores = [ score * SCORES[player] for score in possible_moves.keys() if len(possible_moves[score]) > 0 ] # find best score score = max(scores) * SCORES[player] return score, random.choice(possible_moves[score])
def max_move(board, player): """ To simulate PLAYERX's action in this game. Select the position with maximal score. """ best_score = 0 best_pos = (-1, -1) empty_squares = board.get_empty_squares() for position in empty_squares: cur_board = board.clone() row, col = position cur_board.move(row, col, player) if player == cur_board.check_win(): return SCORES[player], (row, col) elif provided.DRAW == cur_board.check_win(): return SCORES[provided.DRAW], (row, col) else: score, dummy_pos = min_move(cur_board, provided.switch_player(player)) if best_pos == (-1, -1) or score >= best_score: best_score = score best_pos = position return best_score, best_pos
def mc_update_scores(scores, board, player): """ takes a grid of scores (a list of lists) # with the same dimensions as the Tic-Tac-Toe board, # a board from a completed game, and which player the machine player is. # The function should score the completed board and update the scores grid. # not return anything. # If the current player (the player for which your code is currently selecting a move) won the game, # each square that matches the current player should get a positive score # (corresponding to SCORE_CURRENT in the template # each square that matches the other player should get a negative score # (corresponding to -SCORE_OTHER in the template # Conversely, if the current player lost the game, # each square that matches the current player should get a negative score (-SCORE_CURRENT) # each square that matches the other player should get a positive score (SCORE_OTHER). # All empty squares should get a score of 0. """ current_player = player other_player = provided.switch_player(current_player) print scores if board.check_win() == current_player: for row in range(board.get_dim()): for col in range(board.get_dim()): if current_player == board.square(row, col): scores[row][col] += SCORE_CURRENT elif other_player == board.square(row, col): scores[row][col] -= SCORE_OTHER elif board.check_win() == other_player: for row in range(board.get_dim()): for col in range(board.get_dim()): if current_player == board.square(row, col): scores[row][col] -= SCORE_CURRENT elif other_player == board.square(row, col): scores[row][col] += SCORE_OTHER print board print scores
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ if board.check_win() != None: return [SCORES[board.check_win()], (-1, -1)] empty_squares = board.get_empty_squares() best_score = -2 best_move = [-1, -1] factor = 0 if player == 3: factor = -1 else: factor = 1 for square in empty_squares: clone_board = board.clone() clone_board.move(square[0], square[1], player) score = mm_move(clone_board, provided.switch_player(player)) if score[0] * factor == 1: best_score = score[0] * factor best_move = [square[0], square[1]] return best_score * factor, (best_move[0], best_move[1]) elif score[0] * factor > best_score: best_score = score[0] * factor best_move = [square[0], square[1]] return best_score * factor, (best_move[0], best_move[1])
def mc_trial(board, player): """ plays a game, alternating between players """ # plays a game starting with the given player by making random moves alternating between players; # takes a current board and the next player to move # should return when the game is over # modified board will contain state of the game # doesn't return anything because it updates the board directly game_state = board.check_win() print "game_state:", STATES[game_state] print "player going first:", STATES[player] # keep playing until the game is over while game_state not in [ provided.PLAYERX, provided.PLAYERO, provided.DRAW ]: # retrieve a list of all possible moves (open squares) available_moves = board.get_empty_squares() # randomly pick an open square to place a move, checking that there are # available moves left try: random_index = random.randrange(0, len(available_moves)) except ValueError: # exit the while loop if there are no moves left print "No values left in available_moves" return random_square = available_moves[random_index] row = random_square[0] col = random_square[1] # move to randomly-picked open square board.move(row, col, player) # switch players player = provided.switch_player(player) # update the game state game_state = board.check_win()
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ if board.check_win() != None: #print 'base case' #print 'current player', player #print 'current board\n', board #print 'the score for best move of oppo:', SCORES[player]*SCORES[board.check_win()] #print '\n\n\n' return SCORES[board.check_win()], (-1, -1) else: #print 'recursed' empty_squares = board.get_empty_squares() max_score = -2 best_move = (-1, -1) for square in empty_squares: copy_board = board.clone() copy_board.move(square[0], square[1], player) new_player = provided.switch_player(player) score = mm_move(copy_board, new_player)[0] compare_score = score * SCORES[player] if compare_score > max_score: max_score = compare_score best_move = square if max_score == 1: return score, best_move #print 'current player', player #print 'current board\n', board #print 'the square to play', square #print 'the score for best move of oppo:', score #print '\n\n\n' return max_score * SCORES[player], best_move
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ # base case: winner = board.check_win() if (winner != None): return (SCORES[winner], (-1, -1)) # recursive case else: possible_moves = board.get_empty_squares() # score_list is a list of tuple containing score and move score_list = [] next_player = provided.switch_player(player) for idx in range(len(possible_moves)): next_move = possible_moves[idx] new_board = board.clone() # current player make the move new_board.move(next_move[0], next_move[1], player) result = mm_move(new_board, next_player) # multiply the score by SCORES[player] to always maximize the score # even with PLAYERO score = SCORES[player] * result[0] score_list.append((score, next_move)) # if the score is 1, aka maximum score, we stop searching if (score == 1): break # return the ideal move ideal_result = max(score_list) # multiply the score by SCORES[player] to get the correct score for # PLAYERO ideal_result = (SCORES[player] * ideal_result[0], ideal_result[1]) return ideal_result
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ score_max = -2 score_min = 2 pos_max = (-1, -1) pos_min = (-1, -1) if board.check_win() != None: return SCORES[board.check_win()], (-1, -1) for move in board.get_empty_squares(): board_copy = board.clone() board_copy.move(move[0], move[1], player) temp_score, _ = mm_move(board_copy, provided.switch_player(player)) if player == provided.PLAYERX: if temp_score > score_max: pos_max = move score_max = temp_score if player == provided.PLAYERO: if temp_score < score_min: pos_min = move score_min = temp_score if player == provided.PLAYERX: return score_max, pos_max elif player == provided.PLAYERO: return score_min, pos_min else: return 0, (-1, -1)
def mc_update_scores(scores, board, player): ''' inputs are a scores grid, a completed board and the machine player. Updates the scores board accordingly ''' other_player = provided.switch_player(player) mach_player_lst = [] other_player_lst = [] board_dim = board.get_dim() for row in range(board_dim): for col in range(board_dim): if board.square(row, col) == player: co_ord = (row, col) mach_player_lst.append(co_ord) elif board.square(row, col) == other_player: co_ord = (row, col) other_player_lst.append(co_ord) if board.check_win() == player: for ind_1 in range(len(mach_player_lst)): temp_list = list(mach_player_lst[ind_1]) scores[temp_list[0]][temp_list[1]] += SCORE_CURRENT for jnd_1 in range(len(other_player_lst)): temp_list_1 = list(other_player_lst[jnd_1]) scores[temp_list_1[0]][temp_list_1[1]] += -SCORE_OTHER elif board.check_win() == other_player: for ind_1 in range(len(mach_player_lst)): temp_list = list(mach_player_lst[ind_1]) scores[temp_list[0]][temp_list[1]] += -SCORE_CURRENT for jnd_1 in range(len(other_player_lst)): temp_list_1 = list(other_player_lst[jnd_1]) scores[temp_list_1[0]][temp_list_1[1]] += SCORE_OTHER elif board.check_win() == provided.DRAW: pass
def mm_move(board, player): """ Make a move on the board. Returns a tuple with two elements. The first element is the score of the given board and the second element is the desired move as a tuple, (row, col). """ if board.check_win(): return SCORES[board.check_win()], (-1, -1) move_dict = {} for square in board.get_empty_squares(): move_dict[square] = -1 new_board = board.clone() new_board.move(square[0], square[1], player) next_move = mm_move(new_board, provided.switch_player(player)) if next_move[0] * SCORES[player] == 1: return SCORES[player], square move_dict[square] = next_move[0] best_move = max_key(move_dict, lambda x: SCORES[player] * move_dict[x]) return move_dict[best_move], best_move