template<typename Tbot_impl, typename Tendgame_checker> static void walk_game_tree( const player& _test_player, std::vector<board> _board_debug_sequence, Tendgame_checker _endgame_checker ) { std::shared_ptr<move_coordinates_provider_intf> test_bot = std::shared_ptr<move_coordinates_provider_intf>{new Tbot_impl}; // generate current move and log it to debug sequence board board_for_current_move = _board_debug_sequence.back(); _test_player.make_move( board_for_current_move, test_bot->get_next_move( game{ { _test_player, player{ other_symbol( _test_player.get_symbol() ) } }, board_for_current_move } ) ); _board_debug_sequence.push_back(board_for_current_move); if( is_end_of_game(board_for_current_move, player{ other_symbol( _test_player.get_symbol() ) }) ) { _endgame_checker(_board_debug_sequence, _test_player); return; } // generating all possible opponent moves and log those for( const col c : get_ordered_col_values() ) { for( const row r : get_ordered_row_values() ) { if( !_board_debug_sequence.back().get_symbol(c, r) ) { board board_for_opponent_move = _board_debug_sequence.back(); board_for_opponent_move.add_symbol(c, r, other_symbol( _test_player.get_symbol() )); std::vector<board> sequence_including_opponent_move{_board_debug_sequence}; sequence_including_opponent_move.push_back(board_for_opponent_move); if( is_end_of_game(board_for_opponent_move, _test_player) ) { _endgame_checker( sequence_including_opponent_move, player{ other_symbol( _test_player.get_symbol() ) } ); continue; } walk_game_tree<Tbot_impl>(_test_player, sequence_including_opponent_move, _endgame_checker); } } } }
inline bool is_end_of_game(const board& _board, const player& _current_player) { game check_game{ { _current_player, player{other_symbol(_current_player.get_symbol())} }, _board }; if( check_game.get_winner() ) { return true; } if( check_game.is_tie() ){ return true; } return false; }
int move(board_t* board, symbol_t symbol, int depth, int alpha, int beta) { int n, i; move_t* max_move; int score = get_score(board, depth, symbol); if(score != 0) { return score; } move_t** moves = get_all_possible_moves(board, symbol, &n); if(depth == 0) { int max_score = -9999; board_t* b; #pragma omp parallel for private(i, score, b) shared(board, alpha, beta, moves, depth, symbol, max_score) schedule(guided, CHUNK_SIZE) for(i = 0; i < n; i++) { b = clone_board(board); put_symbol(b, symbol, moves[i]); score = -move(b, other_symbol(symbol), depth + 1, -beta, -max_score); #pragma omp critical { if(score > max_score) { max_score = score; max_move = moves[i]; } } free(b); } alpha = max_score; } else { for(i = 0; i < n; i++) { put_symbol(board, symbol, moves[i]); score = -move(board, other_symbol(symbol), depth + 1, -beta, -alpha); clear_symbol(board, moves[i]); if(score > alpha) { alpha = score; max_move = moves[i]; } if(alpha >= beta) { if(depth == 0) { printf("%i %i %i\n", i, beta, alpha); } break; } } } if(depth == 0) { put_symbol(board, symbol, max_move); } for(i = 0; i < n; i++) { free(moves[i]); } free(moves); return alpha; }