void bot_mtdf::do_move_search(const board* b, board* res) { stats.start_timer(); last_search_exact = exact; board children[32]; int child_count = b->get_children(children) - children; output() << "bot_" << get_name() << " searching "; if(exact){ output() << "perfectly at depth " << b->count_empty_fields() << '\n'; } else{ output() << "at depth " << get_search_depth() << '\n'; } moves_left = exact ? get_perfect_depth() : get_search_depth(); do_sorting(children,child_count); int best_heur = exact ? MIN_PERFECT_HEURISTIC : MIN_HEURISTIC; int first_guess; { int tmp = moves_left - 6; if(tmp < 0){ first_guess = heuristic(); } else{ std::swap(tmp,moves_left); first_guess = mtdf<false,false>(0,best_heur); std::swap(tmp,moves_left); } } for(int id=0;id<child_count;++id){ inspected = children[id]; moves_left--; int cur_heur = mtdf<true,exact>(id==0 ? first_guess : best_heur,best_heur); moves_left++; if(cur_heur > best_heur){ best_heur = cur_heur; *res = children[id]; } output() << "move " << (id+1) << "/" << (child_count); output() << " (" << board::index_to_position(b->get_move_index(children+id)) << ')'; output() << ": " << best_heur << '\n'; } stats.stop_timer(); output() << big_number(stats.get_nodes()) << " nodes in "; output() << stats.get_seconds() << " seconds: "; output() << big_number(stats.get_nodes_per_second()) << " nodes / sec\n"; }
DomineeringMove Moderator::next_move(const DomineeringState& state) { // Set the starting node searcher.set_root(Node(state.getWho(), 0)); Node best_child = searcher.search(state, get_search_depth(state)); return best_child.parent_move.to_move(); }
/** * @brief Builds move tree. * * Builds a complete move tree recursively. * * @param[in] color Color to move * @param[out] *i_selected Pointer to horizontal coordinate of selected move. * @param[out] *j_selected Pointer to vertical coordinate of selected move. * @return Nothing * @note If no move is selected i and j are INVALID. */ void search_tree( int color, int *i_selected, int *j_selected ) { // Index variables: int k; int d; //int m; //DEBUG int i, j; // Variables for search tree: int depth = 0; int best_value; int search_level_incr; int alpha; int beta; // Variables for move list: int valid_moves[BOARD_SIZE_MAX * BOARD_SIZE_MAX][4]; int nr_of_valid_moves; int nr_of_valid_moves_cut; // Variables for measuring time: time_t start; time_t stop; time_t diff_time; // Variables needed for logging: char x[2]; char y[3]; // Setting to root level values: alpha = INT_MIN; beta = INT_MAX; hash_hit = 0; alpha_break = 0; beta_break = 0; search_level_incr = 0; count_quiet_search = 0; //init_brains(); init_search_stats(); //init_hash_table(); best_value = ( color == BLACK ) ? INT_MIN : INT_MAX; node_count = 0; if ( do_log ) { log_file = fopen( LOG_FILE, "w" ); if ( log_file == NULL ) { printf( "# Cannot open log file\n" ); exit(1); } } (void) time(&start); nr_of_valid_moves = get_valid_move_list( color, valid_moves ); nr_of_valid_moves_cut = nr_of_valid_moves; // Loop start: search_level_incr = get_search_depth(); for ( d = 0; d <= search_level_incr; d++ ) { set_search_depth(d); //set_search_level(search_level_incr); //l = search_level_incr; // Go through move list: for ( k = 0; k < nr_of_valid_moves_cut; k++ ) { i = valid_moves[k][0]; j = valid_moves[k][1]; // Make move: node_count++; //printf( "# Level: %d make: %d,%d value: %d\n", l, i, j, best_value ); make_move( color, i, j ); //i_to_x( i, x ); //j_to_y( j, y ); //printf( "## %s%s\n", x, y ); // Start recursion: valid_moves[k][2] = add_node( color * -1, depth, alpha, beta ); if ( color == BLACK ) { // For black: remember highest value if ( valid_moves[k][2] > best_value ) { best_value = valid_moves[k][2]; if ( best_value > alpha ) { alpha = best_value; } } } else { // For white: remember lowest value if ( valid_moves[k][2] < best_value ) { best_value = valid_moves[k][2]; if ( best_value < beta ) { beta = best_value; } } } if ( do_log ) { i_to_x( i, x ); j_to_y( j, y ); fprintf( log_file, "%s%s (%d) (a: %d, b: %d)\n" , x, y, valid_moves[k][2], alpha, beta ); } undo_move(); } // Sort move list by value: if ( color == BLACK ) { qsort( valid_moves, (size_t)nr_of_valid_moves_cut, sizeof(valid_moves[0]), compare_value_black ); } else { qsort( valid_moves, (size_t)nr_of_valid_moves_cut, sizeof(valid_moves[0]), compare_value_white ); } // DEBUG: /* printf( "# Level: %d (%d) - ", l, nr_of_valid_moves_cut ); for ( m = 0; m < nr_of_valid_moves_cut; m++ ) { i_to_x( valid_moves[m][0], x ); j_to_y( valid_moves[m][1], y ); printf( "%s%s (%d,%d), ", x, y, valid_moves[m][2], valid_moves[m][3] ); } printf("\n"); */ if ( nr_of_valid_moves_cut / 2 > 5 ) { nr_of_valid_moves_cut = nr_of_valid_moves_cut / 2; } } // Loop end (void) time(&stop); diff_time = stop - start; if ( diff_time == 0 ) { diff_time = 1; } // Save some stats about this search: search_stats.color[0] = '\0'; if ( color == BLACK ) { my_strcpy( search_stats.color, "Black", 6 ); } else { my_strcpy( search_stats.color, "White", 6 ); } i_to_x( valid_moves[0][0], x ); j_to_y( valid_moves[0][1], y ); search_stats.move[0] = '\0'; strcat( search_stats.move, x ); strcat( search_stats.move, y ); search_stats.level = search_depth; search_stats.duration = stop - start; search_stats.node_count = node_count; search_stats.nodes_per_sec = node_count / diff_time; search_stats.qsearch_count = count_quiet_search; search_stats.hash_hit = hash_hit; search_stats.alpha_cut = alpha_break; search_stats.beta_cut = beta_break; search_stats.value = valid_moves[0][2]; *i_selected = valid_moves[0][0]; *j_selected = valid_moves[0][1]; if ( log_file != NULL ) { fclose(log_file); } return; }