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.
25 /* save move to killers if needed and update history */
27 history_store(int move
, int depth
, int ply
, int score
)
29 history
[brd
.wtm
][PIECE(move
)][move
& 0xFFF] += depth
* depth
;
31 if (SCORE_IS_MATE(score
)) {
32 /* save mate killer separately */
33 if (!killers
[ply
].mate_killer
)
34 killers
[ply
].mate_killer
= move
;
36 if (killers
[ply
].killer1
!= move
) {
37 killers
[ply
].killer2
= killers
[ply
].killer1
;
38 killers
[ply
].killer1
= move
;
44 search_pv(int alpha
, int beta
, int depth
, int ply
, int check
)
55 assert(alpha
>= -MATE_VALUE
&& alpha
< +MATE_VALUE
);
56 assert(beta
> alpha
&& beta
<= +MATE_VALUE
);
57 assert(depth
>= 0 && depth
<= MAX_PLY
);
58 assert(board_is_legal(&brd
));
69 if (reps() || evaluate_draw())
72 /* if we are too deep */
73 if (ply
>= MAX_PLY
- 1)
74 return evaluate(alpha
, beta
);
76 if (depth
<= 0 && !check
)
77 return quiesce(alpha
, beta
, 0, ply
, 0);
83 /* always try to follow previous PV */
86 for (i
= 0; i
< moves
.count
; i
++)
87 if (moves
.move
[i
] == pv
[0][ply
]) {
89 hash_moves
[ply
] = pv
[0][ply
];
94 if (!hash_moves
[ply
] && e
.main_hash_enabled
)
95 if (hashtable_get(brd
.wtm
, depth
, ply
, &hash_moves
[ply
], &score
)) {
96 #ifdef STATISTIC_COUNTERS
97 counters
.transposition
++;
101 /* internal iterative deeping if we haven't hash move */
102 if (!hash_moves
[ply
] && get_engine_value(&e
.iid
) && depth
> 3) {
103 i
= MIN(depth
- 2, depth
/ 2);
105 score
= search_pv(alpha
, beta
, i
, ply
, check
);
109 if (score
<= alpha
) {
110 score
= search_pv(-MATE_VALUE
, beta
, i
, ply
, check
);
114 hash_moves
[ply
] = pv
[ply
][ply
];
117 for (i
= 0; i
< moves
.count
; i
++) {
118 /* get move with largest score */
119 sort_moves(&moves
, i
, ply
);
120 if (!make_move(moves
.move
[i
], FALSE
))
125 is_check
= IS_CHECKED(brd
.wtm
);
127 /* search first move with full window */
129 score
= -search_pv(-beta
, -alpha
, depth
+ check
- 1, ply
+ 1, is_check
);
133 /* examine if we can reduce or extend move */
134 extend
= moves_count
> NOLMR_MOVES
? \
135 get_extensions(moves
.move
[i
], check
, is_check
, depth
, ply
) : \
138 extend
= MIN(-MIN(depth
- 2, (moves_count
> 2)? 2 : 1), 0);
141 score
= -zwsearch(-alpha
, depth
+ extend
- 1, ply
+ 1, is_check
, 1);
145 if (score
> alpha
&& extend
< 0) {
146 score
= -zwsearch(-alpha
, depth
- 1, ply
+ 1, is_check
, 1);
151 if (score
> alpha
&& score
< beta
) {
152 int reset_fhr
= FALSE
;
153 if (!fail_high_root
&& ply
== 1) {
154 fail_high_root
= TRUE
;
157 score
= -search_pv(-beta
, -alpha
, depth
+ check
- 1, ply
+ 1, is_check
);
159 fail_high_root
= FALSE
;
167 searching_pv
= FALSE
;
171 #ifdef STATISTIC_COUNTERS
172 counters
.failed_high_total
++;
173 if (moves_count
== 1)
174 counters
.failed_high_first
++;
176 if (!MOVE_IS_TACTICAL(moves
.move
[i
]))
177 history_store(moves
.move
[i
], depth
, ply
, beta
);
182 pv
[ply
][ply
] = moves
.move
[i
];
184 for (j
= ply
+ 1; j
< pv_length
[ply
+ 1]; j
++)
185 pv
[ply
][j
] = pv
[ply
+ 1][j
];
186 pv_length
[ply
] = pv_length
[ply
+ 1];
191 alpha
= check
? -MATE_VALUE
+ ply
: 0;