Improve hashtable, add replacement strategies
[owl.git] / quiesce.c
blobfa5d4e137d0675c95dbdb26dca5fb0c245c0d0f3
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 #include <assert.h>
17 #include <stdio.h>
18 #include "common.h"
19 #include "attacks.h"
20 #include "board.h"
21 #include "engine.h"
22 #include "evaluate.h"
23 #include "move.h"
24 #include "search.h"
26 int quiesce(int alpha, int beta, int depth, int ply, int flag)
28 int i, j;
29 int is_pv;
30 int best_score;
31 int score;
32 int check;
33 int moves_count;
34 uint64_t target;
35 struct moves_t moves;
37 assert(alpha >= -MATE_VALUE && alpha < +MATE_VALUE);
38 assert(beta > alpha && beta <= +MATE_VALUE);
39 assert(board_is_legal(&brd));
41 if (evaluate_draw())
42 return 0;
44 is_pv = (alpha != beta - 1);
45 /* don't store PV at non-PV nodes */
46 if (is_pv)
47 pv_length[ply] = ply;
49 check = IS_CHECKED(brd.wtm);
50 if (check) {
51 if (is_pv)
52 return search_pv(alpha, beta, 1, ply, TRUE);
53 else
54 return zwsearch(beta, 1, ply, TRUE);
57 target = side_boards[1 ^ brd.wtm];
59 /* stand pat */
60 best_score = evaluate(alpha, beta);
62 /* already got cutoff */
63 if (best_score >= beta)
64 return best_score;
66 /* we are too deep */
67 if (ply >= MAX_PLY - 1)
68 return best_score;
70 if (best_score > alpha)
71 alpha = best_score;
72 else if (e.delta_pruning && !check && !is_pv && !flag && best_score < (alpha - 250)) {
73 target &= ~PAWNS(1 ^ brd.wtm);
75 if (best_score < (alpha - 475)) {
76 target &= ~KNIGHTS(1 ^ brd.wtm);
77 target &= ~BISHOPS(1 ^ brd.wtm);
80 if (best_score < (alpha - 650))
81 target &= ~ROOKS(1 ^ brd.wtm);
83 if (best_score < (alpha - 1125))
84 target &= ~QUEENS(1 ^ brd.wtm);
86 gen_quiescent_moves(&moves, target);
88 moves_count = 0;
90 /* don't use hash move and killers in QS */
91 hash_moves[ply] = 0;
92 killers[ply].mate_killer = 0;
93 killers[ply].killer1 = 0;
94 killers[ply].killer2 = 0;
96 for (i = 0; i < moves.count; i++) {
97 assert(MOVE_IS_TACTICAL(moves.move[i]));
98 sort_moves(&moves, i, ply);
100 if (e.delta_pruning && moves_count && !flag && !is_pv && !check && MOVE_IS_TACTICAL(moves.move[i]) && \
101 !SCORE_IS_MATE(beta) && moves.see[i] < 0) {
102 #ifdef STATISTIC_COUNTERS
103 counters.delta_prunings++;
104 #endif
105 return best_score;
108 if (!make_move(moves.move[i], FALSE))
109 continue;
111 counters.searched_nodes++;
112 moves_count++;
114 score = -quiesce(-beta, -alpha, depth - 1, ply + 1, flag);
115 if (abort_search)
116 return 65535;
118 takeback();
120 if (score > best_score) {
121 best_score = score;
122 if (score > alpha) {
123 if (score >= beta) {
124 #ifdef STATISTIC_COUNTERS
125 counters.failed_high_total++;
126 if (moves_count == 1)
127 counters.failed_high_first++;
128 #endif
130 return score;
132 alpha = score;
134 if (is_pv) {
135 pv[ply][ply] = moves.move[i];
137 for (j = ply + 1; j < pv_length[ply + 1]; j++)
138 pv[ply][j] = pv[ply + 1][j];
139 pv_length[ply] = pv_length[ply + 1];
144 assert(best_score > -MATE_VALUE);
145 return best_score;