// SEE (Static Exchange Evaluation) int moves_sort_see(s_board *board, s_move *moves, int num_moves) { assert(moves != NULL); assert(num_moves >= 0); assert(num_moves < MAX_MOVES); if(num_moves < 2) {return 0;} int scores[MAX_MOVES] = {0}; int a; for(a = 0; a < num_moves; ++a) { scores[a] = see_capture(board, moves[a]); } for(a = 0; a < num_moves-1; ++a) { int b; for(b = a+1; b < num_moves; ++b) { if(scores[a] < scores[b]) { s_move store = moves[a]; moves[a] = moves[b]; moves[b] = store; int store2 = scores[a]; scores[a] = scores[b]; scores[b] = store2; } } } return 0; }
int qsearch(s_search_info *info, s_stack *stack, s_board *board, int alpha, int beta) { assert(info != NULL); assert(stack != NULL); assert(board != NULL); assert(alpha < beta); int stand_pat = evaluate(board); if(stack->ply > info->seldepth) { info->seldepth = stack->ply-1; } if(stand_pat >= beta) { return beta; } #ifdef DELTA_PRUNING const int safety = 900; // The value of a queen if(stand_pat < alpha - safety && !is_endgame(board)) { return alpha; } #endif if(stand_pat > alpha) { alpha = stand_pat; } if(stack->ply >= MAX_DEPTH) { return stand_pat; } // Set old permissions s_irreversible permissions; store_irreversible(&permissions, board); s_move moves[MAX_MOVES]; int num_moves = find_moves_captures(board, moves, board->turn); #ifdef SORT_MOVES moves_sort_see(board, moves, num_moves); #endif for(int m = 0; m < num_moves; ++m) { int val = see_capture(board, moves[m]); if(val < -50) { break; } move_make(board, &moves[m]); if(square_attacked(board, board->pieces[KINGS]&board->colour[!board->turn], board->turn)) { // Restore old permissions restore_irreversible(&permissions, board); move_undo(board, &moves[m]); continue; } info->nodes++; int score = -qsearch(info, stack+1, board, -beta, -alpha); // Restore old permissions restore_irreversible(&permissions, board); move_undo(board, &moves[m]); if(score >= beta) { #ifndef NDEBUG info->num_cutoffs[m]++; #endif return beta; } if(score > alpha) { alpha = score; } } return alpha; }
int next_move(s_board *board, s_move_generator *generator, s_move *move) { assert(board); assert(generator); assert(move); while(generator->move_num >= generator->num_moves) { generator->move_num = 0; /* if(generator->stage == NEXT_HASH) { generator->stage++; if(!move_is_legal(board, &generator->hash_move)) {continue;} generator->moves[0] = generator->hash_move; generator->num_moves = 1; } else if(generator->stage == NEXT_KILLER) { generator->stage++; if(!move_is_legal(board, &generator->killer_move)) {continue;} generator->moves[0] = generator->killer_move; generator->num_moves = 1; } else if(generator->stage == NEXT_CAPTURES) { generator->stage++; generator->num_moves = find_moves_captures(board, &generator->moves[0], board->turn); #ifdef SORT_MOVES moves_sort(generator->moves, generator->num_moves); #endif } else if(generator->stage == NEXT_QUIETS) { generator->stage++; generator->num_moves = find_moves_quiet(board, &generator->moves[generator->num_moves], board->turn); } else { return 0; } */ if(generator->stage == 0) { int i; generator->stage++; // Captures generator->num_moves = find_moves_captures(board, &generator->moves[0], board->turn); for(i = 0; i < generator->num_moves; ++i) { // MVV-LVA (Most Valuable Victim - Least Valuable Aggressor) //generator->scores[i] = 400 + 10*generator->moves[i].taken - generator->moves[i].piece_type; // SEE (Static Exchange Evaluation) generator->scores[i] = 50000 + see_capture(board, generator->moves[i]); assert(generator->scores[i] >= 0); } // Quiets generator->num_moves += find_moves_quiet(board, &generator->moves[generator->num_moves], board->turn); /* for(; i < generator->num_moves; ++i) { //if(is_same_move(generator->moves[i], generator->killer_move)) //{ // generator->scores[i] = 19000; // continue; //} generator->scores[i] = 0; if(generator->moves[i].piece_type == KINGS) {continue;} int to = pst_value(generator->moves[i].piece_type, generator->moves[i].to); int from = pst_value(generator->moves[i].piece_type, generator->moves[i].from); generator->scores[i] += 100 + (to - from); assert(generator->scores[i] >= 0); } */ /* int pos = 3; if(num_captures < pos) { pos = num_captures; } */ /* int pos = num_captures; for(i = num_captures; i < generator->num_moves; ++i) { if(is_same_move(generator->moves[i], generator->killer_move)) { s_move store = generator->moves[i]; int n; for(n = i; n > pos; --n) { generator->moves[n] = generator->moves[n-1]; } generator->moves[pos] = store; break; } } for(i = 0; i < generator->num_moves; ++i) { if(is_same_move(generator->moves[i], generator->hash_move)) { s_move store = generator->moves[i]; int n; for(n = i; n > 0; --n) { generator->moves[n] = generator->moves[n-1]; } generator->moves[0] = store; break; } } */ // Hash & killer moves for(i = 0; i < generator->num_moves; ++i) { #ifdef HASHTABLE if(is_same_move(generator->moves[i], generator->hash_move)) { generator->scores[i] = 100000; //break; //int store2 = generator->scores[0]; //generator->scores[0] = generator->scores[i]; //generator->scores[i] = store2; //s_move store = generator->moves[0]; //generator->moves[0] = generator->moves[i]; //generator->moves[i] = store; } #endif #ifdef KILLER_MOVES if(is_same_move(generator->moves[i], generator->killer_move)) { generator->scores[i] = 50000; //int store2 = generator->scores[1]; //generator->scores[1] = generator->scores[i]; //generator->scores[i] = store2; //s_move store = generator->moves[1]; //generator->moves[1] = generator->moves[i]; //generator->moves[i] = store; } #endif } } else { return 0; } } /* if(generator->stage == NEXT_CAPTURES) { if(is_same_move(generator->moves[generator->move_num], generator->hash_move)) { generator->move_num++; return next_move(board, generator, move); } } else if(generator->stage >= NEXT_QUIETS) { if(is_same_move(generator->moves[generator->move_num], generator->hash_move) || is_same_move(generator->moves[generator->move_num], generator->killer_move)) { generator->move_num++; return next_move(board, generator, move); } } */ /* if(show) { printf("Swap'd: %i\n", show-1); int n; for(n = 0; n < generator->num_moves; ++n) { printf("%i) ", generator->scores[n]); print_move(generator->moves[n]); } getchar(); } */ /* */ // New method int best_move = -1; int best_score = -99999; int i; for(i = 0; i < generator->num_moves; ++i) { if(generator->scores[i] > best_score) { best_move = i; best_score = generator->scores[i]; } } *move = generator->moves[best_move]; generator->scores[best_move] = -1; generator->move_num++; /* *move = generator->moves[generator->move_num]; generator->move_num++; */ return 1; }