void tron_state_ai(tron_state_t* state, tron_bike_t* bike) { if ( state->player == NULL ) { return; } int their_x = bike->x; int their_y = bike->y; int my_x = state->player->x; int my_y = state->player->y; int a = -1000000; int b = 1000000; p2move = 0; p1score = 0; p2score = 0; p1dist = NULL; p2dist = NULL; negamax(state, their_x, their_y, my_x, my_y, 6, a, b); free(p1dist); free(p2dist); bike->dir = p2move; }
int computer_move(int board[9], int human) { int computer = human * -1; int diff = difficulty(); // start at random if (empty_board(board)) return (rand() % 9); // check if there is winning move int i; for (i=0; i<9; i++) { // for all the positions if (board[i]==0) { // if the position is empty board[i] = computer; // try the move if (iswon(board) == computer) { board[i] = 0; return i; } board[i] = 0; } } // for medium difficulty, check if there is blocking move if (diff >= 1) { for (i=0; i<9; i++) { if (board[i] == 0) { board[i] = human; if (iswon(board) == human) { board[i] = 0; return i; } board[i] = 0; } } } // for hard difficulty, make the computer unbeatable int bestMove, best = -2; if (diff >= 2) { for (i=0; i<9; i++) { if (board[i]==0) { board[i] = computer; int score = -negamax(board, human); board[i] = 0; if (score > best) { best = score; bestMove = i; } } } return bestMove; } // or place anywhere in the blank spot int blank[9] = {0,0,0,0,0,0,0,0,0}; int blank_count = 0; for (i=0; i<9; i++) if (board[i] == 0) blank[blank_count++] = i; return blank[rand() % blank_count]; }
unsigned int negamax(tron_state_t* state, int my_x, int my_y, int their_x, int their_y, int depth, int a, int b) { if ( depth == 0) { free(p1dist); free(p2dist); unsigned int res = evaluate_pos(state, my_x, my_y, their_x, their_y); return res; } int bestmove = 0; int bestaltmove = 0; for ( int move = 0; move < 4; move++ ) { int x = my_x + dx[move]; int y = my_y + dy[move]; if ( _filled(state, x, y) ) { continue; } state->grid[POS(x, y)].color = 1; int* _p1 = p1dist; int* _p2 = p2dist; int _p1s = p1score; int _p2s = p2score; int score = -negamax(state, their_x, their_y, my_x, my_y, depth - 1, b, a); state->grid[POS(x, y)].bike = 0; if ( score >= a ) { a = score; bestmove = move; bestaltmove = p2move; if ( a >= b ) { break; } } else { free(p1dist); free(p2dist); p1dist = _p1; p1score = _p1s; p2dist = _p2; p2score = _p2s; } } p2move = bestmove; return a; }
int main(int argc, char **argv) { int reps = 1; if (argc > 0) reps = atoi(argv[1]); volatile int j; for (int i = 0; i < reps; i++) { asm("cpuid" ::: "rax", "rbx", "rcx", "rdx"); j = negamax(1, board); } printf("%d\n", j); return 0; }
int negamax(int board[9], int player) { // check if terminal node if (iswon(board)) return iswon(board)*player; else if (filled(board) && !iswon(board)) return 0; int best = -2; int i; for (i=0; i<9; i++) { if (board[i] == 0) { board[i] = player; int score = -negamax(board, player*-1); board[i] = 0; best = maximum(best, score); } } return best; }
int negamax(int onmove, int board[3][3]) { int v = gamevalue(onmove, board); if (v != -2) /* game is over */ return v; v = -1; for (int r = 0; r < 3; r++) { for (int c = 0; c < 3; c++) { if (board[r][c] == 0) { board[r][c] = onmove; int v0 = -negamax(-onmove, board); if (v0 > v) v = v0; board[r][c] = 0; } } } return v; }
struct search_result search(const struct position *root_pos, enum player debug_player_to_move, struct search_description sd, volatile bool *run_flag, const move *prev_pv) { struct node *nodes; struct nodes_common_data common; struct node *root_node; struct pv_store *pv_store; pv_store = xmalloc(sizeof(*pv_store)); pv_store->count = 0; nodes = xaligned_calloc(pos_alignment, sizeof(nodes[0]), node_array_length); memset(&common, 0, sizeof common); common.run_flag = run_flag; common.sd = sd; common.debug_root_player_to_move = debug_player_to_move; setup_node_array(node_array_length, nodes, sd, &common, prev_pv); root_node = setup_root_node(nodes, root_pos); if (setjmp(common.terminate_jmp_buf) == 0) { negamax(root_node); extract_pv(pv_store, &common.result, root_node); common.result.value = root_node->value; common.result.best_move = root_node->best_move; common.result.selective_depth = find_selective_depth(nodes); common.result.qdepth = find_qdepth(nodes); } else { common.result.is_terminated = true; } xaligned_free(nodes); free(pv_store); return common.result; }
int AI::negamax(const t_flag& team, const int& profondeur) { int max; int tmp; max = eval(); if (profondeur == 0 || verifWin() != 0) return max; for (int y = 0; y != 19; y++) { for (int x = 0; x != 19; x++) { if (_mapRule[y][x] == FREE) { _mapRule[y][x] = team; tmp = negamax(invertTeam(team), profondeur - 1); if ((tmp > max)) max = tmp; _mapRule[y][x] = FREE; } } } return max; }
Board search_move(Board board, bool output){ board.scorefunc = scorefunc; Board children[288]; int numchildren = board.getchildren(children, true); depths[maxdepth] = numchildren; int best = 0; //index to element in children with the highest score int ret; int alpha = 2000000000; //can only choose one best move, because all after it also claim to be best, even if they're not for(int i = 0; i < numchildren; i++){ ret = negamax(children[i], maxdepth, -2000000000, alpha); if(alpha > ret){ alpha = ret; best = i; } } return children[best]; }
int AI::minMax(const t_flag& team) { int max = -1000000000; int tmp, maxY = 0, maxX = 0; int profondeur = 1; for (int y = 0; y != 19; y++) { for (int x = 0; x != 19; x++) { if (_mapRule[y][x] == FREE) { _mapRule[y][x] = team; tmp = negamax(invertTeam(team), profondeur - 1); if (tmp > max) { max = tmp; maxY = y; maxX = x; } _mapRule[y][x] = FREE; } } } return (maxY * 19) + maxX; }
static int negamax_child(struct node *node) { if (node[1].beta < - mate_value && node[1].beta > - max_value) node[1].beta--; if (node[1].alpha < - mate_value && node[1].alpha > - max_value) node[1].alpha--; if (node[1].beta > mate_value && node[1].beta < max_value) node[1].beta++; if (node[1].alpha > mate_value && node[1].alpha < max_value) node[1].alpha++; negamax(node + 1); if (node->forced_pv == 0) node[1].forced_pv = 0; int value = -node[1].value; if (node->common->sd.settings.use_strict_repetition_check) { node->repetition_affected_any = max( node->repetition_affected_any, node[1].repetition_affected_best - 1); } /* * Decrement a mate value each time it is passed down towards root, * so represent that "mate in 5" is better than "mate in 6" --> the * closer to the root the checkmate is, the better is is. */ if (value > mate_value) return value - 1; else if (value < - mate_value) return value + 1; else return value; }
bool Medium::move() { srand((unsigned)time(0)); int rnd=rand()%2; if(rnd==0) { ReversiBoard* b=ReversiBoard::getBoardInstance(); std::vector<std::pair<int, std::vector<std::pair<int, int>>>> moves=b->GetMoves(BLACK); if(moves.empty()) return false; srand((unsigned)time(0)); int rnd=(int)((moves.size()*rand())/(RAND_MAX+1.0)); b->MakeMove(moves[rnd].first/8,moves[rnd].first%8,BLACK,moves[rnd].second); return true; } else { ReversiBoard* b=ReversiBoard::getBoardInstance(); int x = negamax(BLACK, 3); std::vector<std::pair<int, std::vector<std::pair<int, int>>>> moves=b->GetMoves(BLACK); for(auto it=moves.begin(); it != moves.end(); it++) { if(x==((*it).first)) { b->MakeMove(x/8, x%8, BLACK, (*it).second); return true; } } return false; } }
//https://en.wikipedia.org/wiki/Negamax#Negamax_with_alpha_beta_pruning int negamax(Game *game, int alpha, int beta, int depth, int *best) { int j; //current column int cut = 0; //did we get a CUT at some point? int best_score = DEFEAT; //best score we've seen so far int one_decision = 0; //have we ever taken a real decision? if (!depth) return CUT; //the search space is often way too large for (j=0; j<game->cols; j++) { if (can_play(game, j)) { play(game, j); { int v; if (victory(game, j)) //this has to be done here v = VICTORY; //since the last move is unknown... else { int trash; //we don't care about the next move v = -negamax(game, -beta, -alpha, depth-1, &trash); } if (-v == CUT) //check the original return value cut = 1; else { v /= 2; //so, longer paths are less interesting one_decision = 1; //update best* variables if (best_score < v) { best_score = v; *best = j; } alpha = MAX(alpha, v); } } undo(game, j); if (alpha >= beta) break; //prune } } return (!one_decision && cut) ? CUT : best_score; }
/// /// Returns struct move {slot, value}, where slot is the index of the move on the game grid which yields the best value. /// struct move negamax(int game_grid[], int player) { // To start with, we have to check if the game is still on. int situation = check_situation(game_grid); int max = -1; move best_move = {-1, -1}; // check_situation() returns 0 if the game hasn't ended yet. if (situation == 0) { // For each legal move on the board, find the one which maximizes the minimum gain. int i; for(i = 0; i < GRID_SIZE; i++) { if (game_grid[i] == 0) { int* temp_grid = malloc(sizeof(int)*GRID_SIZE); if (temp_grid != NULL) { int n; for (n = 0; n < GRID_SIZE; n++) { temp_grid[n] = game_grid[n]; } int current_slot = i; temp_grid[i] = player; move x = negamax(temp_grid, ((player%2)+1)); if (-(x.max) > max) { best_move.max = -(x.max); best_move.slot = current_slot; max = -(x.max); } free(temp_grid); } else { printf("I CAN HAS NO MEMORY!!1\n"); exit(EXIT_FAILURE); } } } } // Now, if the game has indeed ended, check_situation() returns: // 1 if X has won // -1 if O has won // 10 if the end result was a tie. else if (situation == 1) { if (player == 1) { best_move.max = 1; } else best_move.max = -1; } else if (situation == -1) { if (player == 2) { best_move.max = 1; } else best_move.max = -1; } else if (situation == 10) { best_move.max = 0; } else { printf("An unknown error has occured.\n"); exit(EXIT_FAILURE); } return best_move; }
int main(int argc, char *argv[]) { Game *game = create_game(ROWS, COLS); if (argc==3 && !strcmp(argv[1], "display")) { char *p = argv[2]; char *err; while (*p) { int col = *p - '0'; if (col>=0 && col<COLS) { if (can_play(game, col)) { play(game, col); if (victory(game, col)) printf("victory!\n"); } else { err = "illegal move"; goto err_handler; } } else { int i; err = "unknown move syntax"; err_handler: fprintf(stderr, "error: %s.\n%s\n", err, argv[2]); for (i=0; i<p-argv[2]; i++) fprintf(stderr, " "); fprintf(stderr, "^\n"); return 2; } p++; } print_board(game); } else if ((argc==2 || argc==3) && !strcmp(argv[1], "play")) { int j; if (argc==3 && !strcmp(argv[2], "red")) goto red; while (1) { print_board(game); do { printf("Your move: "); if (scanf("%d", &j) != 1) { printf("\n"); goto out; } } while (!can_play(game, j)); play(game, j); if (victory(game, j)) { printf("You've won!\n"); break; } else { int ret = negamax(game, DEFEAT, VICTORY, 12, &j); red: if (ret == CUT) printf("I've got no idea what to do...\n" "I'm gonna try %d.\n", j); else printf("I'll play %d (score %d)\n", j, ret); play(game, j); if (victory(game, j)) { printf("You've lost!\n"); break; } } } print_board(game); } else { fprintf(stderr, "usage:\t%s display moves\n", argv[0]); fprintf(stderr, "\t%s play [yellow|red]\n", argv[0]); fprintf(stderr, "try:\t%s display 01221\n", argv[0]); fprintf(stderr, "\t%s play\n", argv[0]); return 1; } out: destroy_game(game); return 0; }
//================================================================= // Negamax Function. //================================================================= static s32bit negamax(s32bit depth_remaining, s32bit whos_turn_t, s32bit alpha, s32bit beta) { Move movelist[MAXMOVES], best; s32bit whos_turn = whos_turn_t & PLAYER_MASK; s32bit opponent = whos_turn_t ^ PLAYER_MASK; s32bit value; s32bit init_alpha = alpha, init_beta = beta; u32bit start_nodes = g_num_nodes; Move forcefirst; s32bit who_wins_value; s32bit stage = 0, state = 0, true_count, i = 0, num_moves = 1; #ifdef DYNAMIC_POSITION_VALUES s32bit dyn_set; #endif // increment a couple of stats g_num_nodes++; #ifdef COLLECT_STATS stat_nodes[starting_depth - depth_remaining]++; #endif // if no depth remaining stop search. if( depth_remaining <= 0 ){ s32bit a = 0, b = 0; if( (a = does_next_player_win(whos_turn, 0)) > 0 ) { // current player wins. return 5000; } if( (b = does_who_just_moved_win(opponent, 0)) >= 0 ) { // opponent wins. return -5000; } return a - b; } //------------------------------------------ // Can we determine a winner yet (simple check). //------------------------------------------ // does current player win if(g_info_totals[whos_turn].safe > g_info_totals[opponent].real){ #ifdef COLLECT_STATS cut1++; #endif return 5000; } // does opponent win if(g_info_totals[opponent].safe >= g_info_totals[whos_turn].real){ #ifdef COLLECT_STATS cut2++; #endif return -5000; } //------------------------------------------ // check transposition table //------------------------------------------ forcefirst.array_index = -1; if(hashlookup(&value, &alpha, &beta, depth_remaining, &forcefirst, whos_turn)) return value; // since we aren't using iter deep not interested in forcefirst. forcefirst.array_index = -1; //------------------------------------------ // Can we determine a winner yet (look harder). //------------------------------------------ // does current player win if( (who_wins_value = does_next_player_win(whos_turn, 0)) > 0 ) { #ifdef DEBUG_NEGAMAX if(random() % 1000000 == -1){ does_next_player_win(whos_turn, 1); print_board(whos_turn); } #endif #ifdef COLLECT_STATS cut3++; #endif return 5000; } // does opponent win if( (who_wins_value = does_who_just_moved_win(opponent, 0)) >= 0 ) { #ifdef DEBUG_NEGAMAX if(who_wins_value < 3){ // && random() % 500 == -1){ does_who_just_moved_win(opponent, 1); // print_board(opponent); } #endif #ifdef COLLECT_STATS cut4++; #endif return -5000; } #if 0 { s32bit num; num = move_generator_stage1(movelist, whos_turn); num = move_generator_stage2(movelist, num, whos_turn); if(move_generator(movelist, whos_turn) != num) fatal_error(1, "NOPE\n"); } #endif //------------------------------------------ // Generate child nodes and examine them. //------------------------------------------ // initialize a few variables. (some of them don't really need to be.) stage = state = true_count = i = 0; num_moves = 1; #ifdef TWO_STAGE_GENERATION true_count = move_generator_stage1(movelist, whos_turn); if(true_count == 0){ true_count = move_generator_stage2(movelist, 0, whos_turn); stage = 1; if(true_count == 0) fatal_error(1, "Should always have a move.\n"); } #else true_count = move_generator(movelist, whos_turn); stage = 1; if(true_count == 0) fatal_error(1, "Should always have a move.\n"); #endif // score all the moves and move the best to the front. score_and_get_first(movelist, true_count, whos_turn, forcefirst); best = movelist[0]; // need to sort moves and generate more moves in certain situations. while(state < 3){ if(state == 0) { state = 1; } else if(state == 1){ sort_moves(movelist, 1, true_count); num_moves = true_count; if(stage == 0) state = 2; else state = 3; } else { num_moves = move_generator_stage2(movelist, num_moves, whos_turn); state = 3; } // Iterate through all the moves. for(; i < num_moves; i++){ // A few statistics g_move_number[starting_depth - depth_remaining] = i; #ifdef RECORD_MOVES g_move_player[starting_depth - depth_remaining] = whos_turn; g_move_position[starting_depth - depth_remaining] = movelist[i]; #endif // make move. g_empty_squares -= 2; toggle_move(movelist[i], whos_turn); toggle_hash_code (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]); #ifdef DYNAMIC_POSITION_VALUES dyn_set = set_move_value(movelist[i], whos_turn); #endif // recurse. value = -negamax(depth_remaining-1,whos_turn^PLAYER_MASK, -beta, -alpha); // undo move. g_empty_squares += 2; toggle_move(movelist[i], whos_turn); toggle_hash_code (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]); #ifdef DYNAMIC_POSITION_VALUES if(dyn_set != 0) unset_move_value(movelist[i], whos_turn); #endif #if 0 if(starting_depth - depth_remaining == 8) { s32bit g; printf("goof:"); for(g = 0; g < 8; g++){ printf(" :%c:%d(%d,%d)", (g_move_player[g] == VERTICAL) ? 'V' : 'H', g_move_number[g], g_move_position[g].array_index - 1, g_move_position[g].mask_index - 1); } printf("\n"); } #endif // If this is a cutoff, break. if(value >= beta){ alpha = value; best = movelist[i]; #ifdef COLLECT_STATS stat_cutoffs[starting_depth - depth_remaining]++; if(i < 5) stat_nth_try[starting_depth - depth_remaining][i]++; else stat_nth_try[starting_depth - depth_remaining][5]++; #endif break; } // If the current value is greater than alpha, increase alpha. if(value > alpha) { alpha = value; best = movelist[i]; } } // If we have broken out of previous FOR loop make sure we break out // of this loop as well. if(value >= beta) break; } // save the position in the hashtable hashstore(alpha, init_alpha, init_beta, (g_num_nodes - start_nodes) >> 5, depth_remaining, best, whos_turn); return alpha; }
//================================================================= // Search for move function. (Negamax Driver) //================================================================= extern s32bit search_for_move(char dir, s32bit *row, s32bit *col, u64bit *nodes) { s32bit d, i, value = 0, num_moves; Move movelist[MAXMOVES]; s32bit whos_turn; Move forcefirst; // Set who's turn it is. if(toupper(dir) == 'V') whos_turn = VERTICAL; else if(toupper(dir) == 'H') whos_turn = HORIZONTAL; else { fatal_error(1, "Invalid player.\n"); exit(1); } // initialize the number of empty squares. g_empty_squares = 0; for(i = 0; i < g_board_size[0]; i++) g_empty_squares += countbits32( (~g_board[0][i+1]) ); // zero out all the statistics variables. init_stats(); // Can we already determine a winner? { s32bit opponent = whos_turn ^ PLAYER_MASK; // stop search if game over. if(g_info_totals[whos_turn].safe > g_info_totals[opponent].real){ // current player wins. *col = *row = -1; *nodes = 0; return 5000; } if(g_info_totals[opponent].safe >= g_info_totals[whos_turn].real){ // opponent wins. *col = *row = -1; *nodes = 0; return -5000; } } // generate all possible moves for current player given current position. num_moves = move_generator(movelist, whos_turn); // This should never happen. if(num_moves == 0) fatal_error(1, "No moves"); // should possibly sort the whole list instead of just get first. forcefirst.array_index = -1; score_and_get_first(movelist, num_moves, whos_turn, forcefirst); sort_moves(movelist, 1, num_moves); // Really this is for iterative deepening. for(d = 1; d < 50; d += 44){ // Initialize alpha and beta. s32bit alpha = -5000, beta = 5000; // Re-initialize the statistics for each iteration. g_num_nodes = 0; init_stats(); // set what the starting max depth is. starting_depth = d; // iterate through all the possible moves. for(i = 0; i < num_moves; i++){ #ifdef DYNAMIC_POSITION_VALUES init_move_value(); set_move_value(movelist[i], whos_turn); #else set_position_values(); #endif g_move_number[0] = i; #ifdef RECORD_MOVES g_move_player[0] = whos_turn; g_move_position[0] = movelist[i]; #endif g_empty_squares -= 2; toggle_move(movelist[i], whos_turn); toggle_hash_code (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]); check_hash_code_sanity(); value = -negamax(d-1, whos_turn^PLAYER_MASK, -beta, -alpha); #ifdef DYNAMIC_POSITION_VALUES unset_move_value(movelist[i], whos_turn); #endif g_empty_squares += 2; toggle_move(movelist[i], whos_turn); toggle_hash_code (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]); check_hash_code_sanity(); printf("Move (%d,%d), value %d: %s.\n", movelist[i].array_index, movelist[i].mask_index, value, u64bit_to_string(g_num_nodes)); printf("alpha %d, beta %d.\n", alpha, beta); movelist[i].info = value; if(value >= beta){ alpha = value; break; } if(value > alpha) { alpha = value; } } if(value >= 5000){ printf("Winner found: %d.\n", value); if(whos_turn == HORIZONTAL){ *row = movelist[i].array_index; *col = movelist[i].mask_index; } else if(whos_turn == VERTICAL){ *col = movelist[i].array_index; *row = movelist[i].mask_index; } else { fatal_error(1, "oops."); } *nodes = g_num_nodes; print_stats(); return value; } // remove lossing moves from movelist. { s32bit rem = 0; for(i = 0; i < num_moves; i++){ if(movelist[i].info <= -5000) rem++; else if(rem > 0) movelist[i-rem] = movelist[i]; } num_moves -= rem; /* for(i = 0; i < num_moves; i++){ printf("(%d,%d): %d.\n", movelist[i].array_index, movelist[i].mask_index, movelist[i].info); } */ } print_stats(); if(num_moves == 0){ break; } // use a stable sort algorithm { Move swp; s32bit max, index, j; for(i=0; i<num_moves; i++) { max = movelist[i].info; index = i; for(j=i+1; j < num_moves; j++) if(movelist[j].info > max){ max = movelist[j].info; index = j; } if(index != i){ swp = movelist[index]; // printf("%d %d\n", index, i); for(j = index; j != i; j--){ movelist[j] = movelist[j-1]; } movelist[i] = swp; } } } printf("The value is %d at a depth of %d.\n", value, d); printf("Nodes: %u.\n", (u32bit)g_num_nodes); } *col = *row = -1; *nodes = g_num_nodes; return value; }
void iterate( dict *d, lin_dict *ko_ld, node_value *base_nodes, node_value *pass_nodes, node_value *ko_nodes, value_t *leaf_nodes, state *s, size_t key_min, int japanese_rules ) { state child_; state *child = &child_; size_t num_states = num_keys(d); int changed = 1; while (changed) { changed = 0; size_t key = key_min; for (size_t i = 0; i < 2 * num_states + ko_ld->num_keys; i++) { if (i < 2 * num_states) { assert(from_key(s, key)); if (i % 2 == 1) { s->passes = 1; } } else { key = ko_ld->keys[i - 2 * num_states]; size_t ko_pos = key % STATE_SIZE; key /= STATE_SIZE; assert(from_key(s, key)); s->ko = 1UL << ko_pos; } node_value new_v = (node_value) {VALUE_MIN, VALUE_MIN, DISTANCE_MAX, 0}; for (int j = -1; j < STATE_SIZE; j++) { size_t child_key; node_value child_v; *child = *s; stones_t move; if (j == -1){ move = 0; } else { move = 1UL << j; } if (make_move(child, move)) { canonize(child); child_key = to_key(child); if (child->passes == 2){ value_t score = leaf_nodes[key_index(d, child_key)]; child_v = (node_value) {score, score, 0, 0}; } else if (child->passes == 1) { child_v = pass_nodes[key_index(d, child_key)]; } else if (child->ko) { child_key = child_key * STATE_SIZE + bitscan(child->ko); child_v = ko_nodes[lin_key_index(ko_ld, child_key)]; } else { child_v = base_nodes[key_index(d, child_key)]; } if (japanese_rules) { int prisoners = (popcount(s->opponent) - popcount(child->player)) * PRISONER_VALUE; if (child_v.low > VALUE_MIN) { child_v.low = child_v.low - prisoners; } if (child_v.high < VALUE_MAX) { child_v.high = child_v.high - prisoners; } } new_v = negamax(new_v, child_v); } } assert(new_v.high_distance > 0); if (i < 2 * num_states) { if (i % 2 == 0) { assert(new_v.low_distance > 1); assert(new_v.high_distance > 1); assert(new_v.low >= base_nodes[i / 2].low); assert(new_v.high <= base_nodes[i / 2].high); changed = changed || !equal(base_nodes[i / 2], new_v); base_nodes[i / 2] = new_v; } else { changed = changed || !equal(pass_nodes[i / 2], new_v); pass_nodes[i / 2] = new_v; key = next_key(d, key); } } else { changed = changed || !equal(ko_nodes[i - 2 * num_states], new_v); ko_nodes[i - 2 * num_states] = new_v; } } print_node(base_nodes[0]); } for (size_t i = 0; i < ko_ld->num_keys; i++) { assert(ko_nodes[i].low_distance > 2); assert(ko_nodes[i].high_distance > 2); } for (size_t i = 0; i < num_states; i++) { assert(base_nodes[i].low_distance > 1); assert(base_nodes[i].high_distance > 1); assert(pass_nodes[i].low_distance > 0); assert(pass_nodes[i].high_distance > 0); } }
static void extract_pv(struct pv_store *pv_store, struct search_result *result, struct node *root) { int pv_len = 0; int iteration = 0; #ifndef NDEBUG char debug_move_stack[0x1000]; char *c; #endif int extension_location = -1; next_iteration: pv_len = 0; #ifndef NDEBUG c = debug_move_stack; #endif while (root->pv[pv_len] != 0) { #ifndef NDEBUG *c++ = ' '; c = print_coor_move(root->pv[pv_len], c, ((pv_len % 2) ? opponent_of(root->debug_player_to_move) : (int)root->debug_player_to_move)); #endif result->pv[pv_len] = root->pv[pv_len]; root[pv_len].forced_pv = root->pv[pv_len]; pv_store->pvs[pv_store->count][pv_len] = root->pv[pv_len]; ++pv_len; } result->pv[pv_len] = 0; if (!root->common->sd.settings.use_pv_cleanup) return; pv_store->pvs[pv_store->count][pv_len] = 0; if (++iteration > 98) return; if (root->depth < 3 * PLY) return; if (pv_len == 0) return; if (has_same_pv_in_pv_store(pv_store, root->pv)) { if (extension_location == 1) return; if (extension_location != -1) root[extension_location].forced_extension = 0; int new_ext = find_common_prefix_length(pv_store) - 1; if (new_ext < 1) return; if (extension_location == -1 || new_ext < extension_location) extension_location = new_ext; else --extension_location; root[extension_location].forced_extension = 1; pv_store->pvs[0][0] = root->best_move; pv_store->pvs[0][1] = 0; pv_store->count = 1; goto next_iteration; } pv_store->count++; for (int i = pv_len; i < node_array_length - 1; ++i) root[i].forced_pv = 0; if (root->value == 0) return; if (root->value <= -mate_value || root->value >= mate_value) return; if (pv_len >= root->depth / PLY - 1) return; root->alpha = -max_value; root->beta = max_value; root->expected_type = PV_node; negamax(root); goto next_iteration; }
/* Calculate the power of left and right motors */ void DetermineMouseAction(double *lPow, double *rPow, int *, RobotMap *map,externalRobot *robots) { static int counter=0; static float left; //value of frontal left sonar sensor static float right; //value of frontal rigth sonar sensor static float center; //value of frontal center sonar sensor static bool Collision;// collision sensor static float Compass = 0; //compass sensor static float X = -1; // GPS x value static float Y = -1; //GPS yvalue // SENSORS ACCESS /*Access to values from Sensors - Only ReadSensors() gets new values */ if(IsObstacleReady(LEFT)) left= GetObstacleSensor(LEFT); if(IsObstacleReady(RIGHT)) right= GetObstacleSensor(RIGHT); if(IsObstacleReady(CENTER)) center= GetObstacleSensor(CENTER); if(IsBumperReady()) Collision= GetBumperSensor(); if(IsCompassReady()){ Compass= GetCompassSensor(); //printf("orientation %f\n", Compass); } if(IsGPSReady()){ if(X < 0 || Y < 0){ map->setOffset(GetX(),GetY()); } X= GetX(); Y= GetY(); } float multiplier[8] = {1,1,1,1,1,1,1,1}; if(center>3.0 || right> 4.0 || left>4.0 || Collision) { /* Close Obstacle - Rotate */ if(right < left) { *lPow=0.06; *rPow=-0.06; } else { *lPow=-0.06; *rPow=0.06; } } else { if(left > 1.0){ //give a penalty on score if theres an obstacle on the left side multiplier[side_frontleft] = multiplier[side_left] = multiplier[side_backleft] = 1/left; } if(right > 1.0){ //give a penalty on score if theres an obstacle on the right side multiplier[side_frontright] = multiplier[side_right] = multiplier[side_backright] = 1/right; } if(center > 1.0){ //give a penalty on score if theres an obstacle on the front multiplier[side_frontright] = multiplier[side_frontleft] = multiplier[side_front] = 1.25/right; } //always favor going to front to avoid slowing down multiplier[side_frontright] *= 1.25; multiplier[side_frontleft] *= 1.25; multiplier[side_front] *= 1.25; float orientations[8] = {Compass,Compass + 45,Compass + 90,Compass + 135,Compass + 180, Compass - 135,Compass - 90,Compass - 45}; float distance = 2; float score[8]; float maxScore = 0; int maxScoreSide = 0; for(int i=0;i<8;++i){ float x= X + distance * cos(M_PI * orientations[i] / 180); float y= Y + distance * sin(M_PI * orientations[i] / 180); if(i == side_front){ double val = map->getValue(x,y); if(center < 2.0){ val += 0.2; map->setValue(x,y,(val > 1.0)?1.0:val); } else { val -= 0.2; map->setValue(x,y,(val < 0.0)?0.0:val); } } else if(i == side_frontleft){ double val = map->getValue(x,y); if(left < 2.0){ val += 0.2; map->setValue(x,y,(val > 1.0)?1.0:val); } else { val -= 0.2; map->setValue(x,y,(val < 0.0)?0.0:val); } }else if(i == side_frontright){ double val = map->getValue(x,y); if(right < 2.0){ val += 0.2; map->setValue(x,y,(val > 1.0)?1.0:val); } else { val -= 0.2; map->setValue(x,y,(val < 0.0)?0.0:val); } } float points = 0; for(int j=0;j<5;++j){ if(robots[j].isCat){ points += negamax(x,y,robots[j].x,robots[j].y); } } multiplier[i] -= penaltyScore(map,x,y); points *= multiplier[i]; score[i] = points; if(i==0){ maxScore = points; } else if(points > maxScore){ maxScore = points; maxScoreSide = i; } } switch (maxScoreSide) { case side_front: *lPow=0.1; *rPow=0.1; break; case side_frontleft: *lPow=0.08; *rPow=0.1; break; case side_left: *lPow=0.03; *rPow=0.1; break; case side_backleft: *lPow=-0.02; *rPow=0.1; break; case side_back: if(score[3] > score[5]){ *lPow=-0.1; *rPow=0.1; } else { *lPow=0.1; *rPow=-0.1; } break; case side_backright: *rPow=-0.02; *lPow=0.1; break; case side_right: *rPow=0.03; *lPow=0.1; break; case side_frontright: *rPow=0.08; *lPow=0.1; break; default: break; } } counter++; }