move_c* solver_c::calculate_move(const board_c& board) const { if(board.moves_number < guaranteed_best*2) return best_move(board); double bid = util_c::random_double(0.0, worst_weight+modest_weight+best_weight); if(bid < worst_weight) return worst_move(board); if(bid < worst_weight+modest_weight) if(type == TYPE_NORMAL) return modest_normal_move(board); else return modest_reverse_move(board); return best_move(board); }
void move(board_type board, char player, int move_num, bool humans_only, char computer) { int square; if(humans_only) { do { printf("What is your move?: "); fflush(stdin); scanf("%d", &square); square--; } while(board[square] != empty); play(board, square, player); } else { if(player == computer) { total_nodes = 0; //describe(best_move(board, computer, &square, move_num, -infinity, infinity), computer); best_move(board, computer, &square, move_num, -infinity, infinity); //printf("Analyzed %d nodes\n", total_nodes); //getchar(); getchar(); play(board, square, computer); } else { do { printf("What is your move?: "); fflush(stdin); scanf("%d", &square); square--; } while(board[square] != empty); play(board, square, other_player(computer)); } } }
move_t best_move(int (*board)[N], int player) { int e; int i, j; int best = -10000; move_t t; move_t r; e = evaluate(board, player); if (e != CONTINUE) { r.result = e; r.p1 = -1; r.p2 = -1; return r; } for (i = 0; i < N; i++) for (j = 0; j < N; j++) if (board[i][j] == 0) { board[i][j] = player; t = best_move(board, player * (-1)); if ((-t.result) > best) { r.result = -t.result; r.p1 = i; r.p2 = j; best = -t.result; } board[i][j] = 0; } return r; }
TEST(gogameab_basic_check, simple_ab_uniform) { uint8_t board_size = 5; int depth = 1; GoGame test_game(board_size); GoGameNN test_network(board_size, true); test_game.generate_moves(0); double best_move_value, temp_best_move_value = 0; GoMove best_move(test_game.get_board()); best_move_value = -std::numeric_limits<double>::infinity(); // For each possible move, calculate Alpha Beta for (const GoMove &element : test_game.get_move_list()) { GoGame temp_game(test_game); temp_game.make_move(element, 0); temp_best_move_value = scalable_go_ab_prune(test_network, temp_game, depth, -std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity(), 1, false, 0); if (temp_best_move_value > best_move_value) { best_move_value = temp_best_move_value; best_move = element; } } EXPECT_NO_THROW(test_game.make_move(best_move, 0)); }
solver_c::rate_t solver_c::rate(const board_c& board) const noexcept { if(board.status.is_draw()) return 0; switch(speed) { case SPEED_FAST: switch(board.next_player.player) { case player_c::PLAYER_X: if(board.status.is_win_o()) return board.size*board.size; break; case player_c::PLAYER_O: if(board.status.is_win_x()) return board.size*board.size; break; } break; case SPEED_SLOW: switch(board.next_player.player) { case player_c::PLAYER_X: if(board.status.is_win_o()) return 1; break; case player_c::PLAYER_O: if(board.status.is_win_x()) return 1; break; } break; } board_c board_copy(board); move_c* move = best_move(board_copy); board_copy.play(*move); delete move; rate_t new_rate = rate(board_copy); switch(speed) { case SPEED_FAST: if(new_rate > 0) new_rate--; else if(new_rate < 0) new_rate++; break; case SPEED_SLOW: if(new_rate > 0) new_rate++; else if(new_rate < 0) new_rate--; break; } return -new_rate; }
/** * Makes a move, Using Alph-Beta Pruning *@param board the game board visualization *@param score my score *@param opponentScore the opponent's score *@param pointsRemaining how many points are left this game *@return my move */ int AlphaBetaAI::makeMove(int* board, int score, int opponentScore, int pointsRemaining) { AlphaBetaNode* root = trim_tree(board, score, opponentScore, pointsRemaining); if (!run) { run = true; pthread_create(&thread, NULL, ab_thread, (void *)this); } int start = time(0); while (time(0)-start < 1); return best_move(root); }
int main(){ //printf("%s", ANSI_WHITE); //init_board //hide_cursor(); clear_all(); init_board(BOARD_ROW, BOARD_COL); init_board(ANALYSIS_ROW, ANALYSIS_COL); move_cursor(20, 0); printf("Pick a color: 0(white), 1(black): "); int usrcolor; scanf("%d", &usrcolor); int to_move = 0; move_cursor(20, 0); //printf("usr_color: %d\n" ,usrcolor); while(!check_win(to_move)){ move_cursor(20, 0); //printf("to_move: %d\n", to_move); //printf("usrcolor: %d\n", usrcolor); //display_board(); if(usrcolor == to_move){ move_cursor(20, 0); clear_line(); //printf("user move\n"); uint16_t move; printf("Pick a space to play: "); //printf("&uscolor: %p, &move: %p\n", &move); scanf("%hd", &move); move = 1 << move; //printf("move: %d\n", move); update_board(move, to_move); update_analysis(move, to_move); } else { //move_cursor(20, 0); //printf("computer move\n"); //printf("%x, %x\n", bboards[0], bboards[1]); uint16_t move = best_move(to_move); //printf("%x, %x\n", bboards[0], bboards[1]); //printf("is_legal(%d): %d\n", move, is_legal(move)); //printf("bestmove: %x\n", move); update_board(move, to_move); update_analysis(move, to_move); } to_move ^= 1; } //printf("check_win: %d", check_win(to_move)); //display_board(); }
int main() { int board[N][N]; int i, j; move_t t; int x, y; int turn; for (i = 0; i < N; i++) for (j = 0; j < N; j++) board[i][j] = 0; turn = 0; while (1) { printf("Your turn: "); scanf("%d %d", &x, &y); board[x][y] = -1; turn++; print_board(board); if (evaluate(board, -1) != CONTINUE) break; t = best_move(board, 1); if (t.result == WIN) printf("I will win!\n"); board[t.p1][t.p2] = 1; turn++; print_board(board); if (evaluate(board, 1) != CONTINUE) break; } return 0; }
std::vector<int> score_networks(std::vector<GoGameNN> networks, const uint8_t board_size) { // Vector to hold win counts for networks std::vector<int> scores(networks.size(), 0); // Each network plays every other network as each team, storing total score for each neural network. #pragma omp parallel for firstprivate(networks) schedule(dynamic, 1) for (unsigned int i = 0; i < networks.size(); i++) { for (unsigned int j = 0; j < networks.size(); j++) { // GoGame instance used for training matches GoGame training_game(board_size); GoMove best_move(training_game.get_board()); // Bool to determine if game should continue bool continue_match = true; // Value of best move double best_move_value, temp_best_move_value = 0; while (continue_match) { // Generate and take black move training_game.generate_moves(0); best_move_value = -std::numeric_limits<double>::infinity(); // For each possible move, calculate Alpha Beta for (const GoMove &element : training_game.get_move_list()) { GoGame temp_game(training_game); temp_game.make_move(element, 0); temp_best_move_value = scalable_go_ab_prune(networks[i], temp_game, DEPTH, -std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity(), 1, false, 0); if (temp_best_move_value > best_move_value) { best_move_value = temp_best_move_value; best_move = element; } } // Make Black Move training_game.make_move(best_move, 0); // Generate and take white move training_game.generate_moves(1); best_move_value = -std::numeric_limits<double>::infinity(); // For each possible move, calculate Alpha Beta for (const GoMove &element : training_game.get_move_list()) { GoGame temp_game(training_game); temp_game.make_move(element, 1); temp_best_move_value = scalable_go_ab_prune(networks[j], temp_game, DEPTH, -std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity(), 0, false, 1); if (temp_best_move_value > best_move_value) { best_move_value = temp_best_move_value; best_move = element; } } // Make White move training_game.make_move(best_move, 1); // Game end detection std::vector<GoMove> history(training_game.get_move_history()); // Check if the last 2 moves were passes. If so, end if (history[history.size() - 1].check_pass() && history[history.size() - 2].check_pass()) { std::array<uint8_t, 2> game_score = training_game.calculate_scores(); if (game_score[0] > game_score[1]) { // Black Wins scores[i] += 1; scores[j] -= 1; } else if (game_score[1] > game_score[0]) { // White wins scores[j] += 1; scores[i] -= 1; } // Else, draw... assign no scores. continue_match = false; } } } } return scores; }
// return the score of the best move found for a board // the best square is stored in *square // note - recursive function, searches nodes and childs int best_move(board_type board, char player, int *square, int move_num, int alpha, int beta) { int best_square = -1; int moves = 0; int i; move_heuristic_type move_heuristic[SQUARES]; // an array of 9 heuristc structs total_nodes++; // times we call best_move // we find calculate the heuristic value of each move // and sort the structs in descending order // this way, we speed things up a bit for(i=0; i<SQUARES; i++) { // if the square is available for play if(board[i] == empty) { int heuristic; int j; play(board, i, player); // we play the empty square heuristic = evaluate(board, player); // we get the heuristic value play(board, i, empty); // we reverse the play // now we must sort the picked up structs in descending order for(j = moves-1; j>=0 && move_heuristic[j].heuristic < heuristic; j--) { move_heuristic[j+1].heuristic = move_heuristic[j].heuristic; move_heuristic[j+1].square = move_heuristic[j].square; } move_heuristic[j+1].heuristic = heuristic; move_heuristic[j+1].square = i; moves++; } // we can store the structs and use qsort here instead. } for(i=0; i<moves; i++) { int score; int sq = move_heuristic[i].square; char w; // we make a move and get the score play(board, sq, player); w = winner(board); if(w == 'X') score = (max_moves + 1) - move_num; else if(w == 'O') score = move_num - (max_moves + 1); else if(w == 'T') score = 0; else // haven't finished board score = best_move(board, other_player(player), square, move_num + 1, alpha, beta); // we recurse // reverse the play play(board, sq, empty); // now we prune alpha-beta if(player == 'X') { if(score >= beta) { // cut off *square = sq; return score; } else if(score > alpha) { // we found a better alpha (alpha only increases) alpha = score; best_square = sq; } } else { if(score <= alpha) { // cut off *square = sq; return score; } else if(score < beta) { // we found that oponent has a best worse beta (beta only decreases) beta = score; best_square = sq; } } } *square = best_square; if(player == 'X') return alpha; else return beta; }
int main(void) { int dir; srand(time(NULL)); uint8_t nb_empty_box, nb_merge; #if USE_BIN /* Creation of a grid */ grid_t grid = create_empty_grid_bin(); /* Grid backup */ grid_t saved_grid; /* Initialisation of the grid */ grid = init_grid_bin(grid, &nb_empty_box); /* Display the grid */ display_grid_bin(grid); /* Main loop for a game */ while (nb_empty_box > 0 || merge_possible_bin(grid)) { do { saved_grid = grid; /* While the move does not lead to a change on the grid */ // dir = random_move(); dir = best_move_bin(grid, nb_empty_box); /* Trying to play the move */ grid = move_bin(grid, dir, &nb_merge); nb_empty_box += nb_merge; } while (grid == saved_grid); /* Add tile */ grid = add_tile_bin(grid); nb_empty_box--; /* Display the new grid */ display_grid_bin(grid); printf("Empty boxes: %u\n", nb_empty_box); } #else /* Creation of a grid */ uint16_t **grid = create_empty_grid(); /* Initialisation of the grid */ init_grid(grid); /* Display the grid */ display_grid(grid); #if DEBUG printf("Value: %i\n", evaluate(grid)); #endif /* Main loop for a game */ while (!game_over(grid)) { /* While the move does not lead to a change on the grid */ do { #if IA #if RANDOM dir = random_move(); #else dir = best_move(grid); #endif #else dir = ask_dir(); #endif /* Trying to play the move */ } while (!move(grid, dir)); /* Add a new tile at the end of each round */ add_tile(grid); /* Display the new grid */ display_grid(grid); #if DEBUG printf("Value: %i\n", evaluate(grid)); #endif } #endif return 0; }