Rev 33 | Rev 154 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 33 | Rev 108 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | #include "chess.h" |
1 | #include "chess.h" |
- | 2 | #include "evaluate.h" |
|
2 | #include "data.h" |
3 | #include "data.h" |
3 | /* last modified |
4 | /* last modified 12/31/15 */ |
4 | /* |
5 | /* |
5 | ******************************************************************************* |
6 | ******************************************************************************* |
6 | * * |
7 | * * |
7 | * Evaluate() is used to evaluate the chess board. Broadly, it addresses * |
8 | * Evaluate() is used to evaluate the chess board. Broadly, it addresses * |
8 | * four (4) distinct areas: (1) material score which is simply a summing of * |
9 | * four (4) distinct areas: (1) material score which is simply a summing of * |
9 | * piece types multiplied by piece values; (2) pawn scoring which considers * |
10 | * piece types multiplied by piece values; (2) pawn scoring which considers * |
10 | * placement of pawns and also evaluates passed pawns, particularly in end- * |
11 | * placement of pawns and also evaluates passed pawns, particularly in end- * |
11 | * game situations; (3) piece scoring which evaluates the placement of each * |
12 | * game situations; (3) piece scoring which evaluates the placement of each * |
12 | * piece as well as things like piece mobility; (4) king safety which * |
13 | * piece as well as things like piece mobility; (4) king safety which * |
13 | * considers the pawn shelter around the king |
14 | * considers the pawn shelter around the king and enemy pieces and how close * |
14 | * |
15 | * they are to assist in a king-side attack. * |
15 | * * |
16 | * * |
16 | ******************************************************************************* |
17 | ******************************************************************************* |
17 | */ |
18 | */ |
18 | int Evaluate(TREE * RESTRICT tree, int ply, int wtm, int alpha, int beta) { |
19 | int Evaluate(TREE * RESTRICT tree, int ply, int wtm, int alpha, int beta) { |
19 | PAWN_HASH_ENTRY *ptable; |
20 | PAWN_HASH_ENTRY *ptable; |
20 | PXOR *pxtable; |
21 | PXOR *pxtable; |
21 | int score, side, |
22 | int score, side, can_win = 3, phase, lscore, cutoff; |
- | 23 | int full = 0; |
|
- | 24 | uint64_t *etable; |
|
22 |
|
25 | uint64_t temp_hashkey; |
23 | 26 | ||
24 | /* |
27 | /* |
25 | |
28 | ************************************************************* |
26 | * |
29 | * * |
- | 30 | * First thing we do is if -DSKILL was passed in to the * |
|
- | 31 | * compiler, we burn some time to slow the search down, * |
|
27 | * |
32 | * then we fall into the normal evaluation code. * |
28 | * |
33 | * * |
29 | |
34 | ************************************************************* |
30 | */ |
35 | */ |
31 | cutoff = (TotalPieces(white, occupied) && TotalPieces(black, occupied)) |
- | |
32 | ? KNIGHT_VALUE : ROOK_VALUE; |
- | |
33 | lscore = (wtm) ? Material : -Material; |
- | |
34 | if (lscore + cutoff < alpha || lscore - cutoff > beta) |
- | |
35 | return lscore; |
- | |
36 | tree->dangerous[white] = (Queens(white) && TotalPieces(white, occupied) > 9) |
- | |
37 | || (TotalPieces(white, rook) > 1 && TotalPieces(white, occupied) > 15); |
- | |
38 | tree->dangerous[black] = (Queens(black) && TotalPieces(black, occupied) > 9) |
- | |
39 | || (TotalPieces(black, rook) > 1 && TotalPieces(black, occupied) > 15); |
- | |
40 | tree->evaluations++; |
- | |
41 | tree->score_mg = 0; |
- | |
42 | tree->score_eg = 0; |
- | |
43 | EvaluateMaterial(tree, wtm); |
- | |
44 | #if defined(SKILL) |
36 | #if defined(SKILL) |
45 | if (skill < 100) { |
37 | if (skill < 100) { |
46 | int i, j; |
38 | int i, j; |
47 | for (i = 0; i < burnc[skill / 10]; i++) |
39 | for (i = 0; i < burnc[skill / 10] && !abort_search; i++) |
48 | for (j = 1; j < 10; j++) |
40 | for (j = 1; j < 10 && !abort_search; j++) |
49 | burner[j - 1] = burner[j - 1] * burner[j]; |
41 | burner[j - 1] = burner[j - 1] * burner[j]; |
- | 42 | if (TimeCheck(tree, 1)) |
|
- | 43 | abort_search = 1; |
|
50 | } |
44 | } |
51 | #endif |
45 | #endif |
52 | /* |
- | |
53 | ********************************************************************** |
- | |
54 | * * |
- | |
55 | * Check for draws due to insufficient material and adjust the score * |
- | |
56 | * as necessary. This code also handles a special endgame case * |
- | |
57 | * where one side has only a lone king, and the king has no legal * |
- | |
58 | * moves. This has been shown to break a few evaluation terms such * |
- | |
59 | * as bishop + wrong color rook pawn. If this case is detected, a * |
- | |
60 | * drawscore is returned. * |
- | |
61 | * * |
- | |
62 | ********************************************************************** |
- | |
63 | */ |
- | |
64 | if (TotalPieces(white, occupied) < 13 && TotalPieces(black, occupied) < 13) |
- | |
65 | do { |
- | |
66 | /* |
46 | /* |
67 | ************************************************************ |
47 | ************************************************************ |
68 | * * |
48 | * * |
- | 49 | * Next we check to see if this position has been handled * |
|
- | 50 | * before. If so, we can skip the work saved in the eval * |
|
- | 51 | * hash table and just return the score found there. Note * |
|
- | 52 | * that we only store FULL evaluations in the evaluation * |
|
69 | * |
53 | * hash, if an early (lazy) exit is taken, nothing is * |
70 | * |
54 | * stored. * |
71 | * * |
55 | * * |
72 | ************************************************************ |
56 | ************************************************************ |
73 |
|
57 | */ |
74 |
|
58 | temp_hashkey = (wtm) ? HashKey : ~HashKey; |
75 |
|
59 | etable = eval_hash_table + (temp_hashkey & eval_hash_mask); |
- | 60 | if (*etable >> 16 == temp_hashkey >> 16) { |
|
76 |
|
61 | score = (*etable & 0xffff) - 32768; |
77 |
|
62 | return (wtm) ? score : -score; |
- | 63 | } |
|
78 | /* |
64 | /* |
79 | ************************************************************ |
65 | ************************************************************* |
80 | * * |
66 | * * |
- | 67 | * First lazy cutoff attempt. If the material score is way * |
|
- | 68 | * below alpha or way above beta (way above means so far * |
|
- | 69 | * above it is very unlikely the positional score can bring * |
|
81 | * |
70 | * the total score back into the alpha / beta window) then * |
- | 71 | * we take what is known as a "lazy evaluation exit" and * |
|
- | 72 | * avoid the computational cost of a full evaluation in a * |
|
82 | * |
73 | * position where one side is way ahead or behind. * |
83 | * * |
74 | * * |
84 | ************************************************************ |
75 | ************************************************************* |
85 | */ |
76 | */ |
86 | majors = TotalMajors(white) - TotalMajors(black); |
- | |
87 | if (Abs(majors) == 1) { |
- | |
88 |
|
77 | cutoff = (TotalPieces(white, occupied) && TotalPieces(black, occupied)) |
89 |
|
78 | ? KNIGHT_VALUE : ROOK_VALUE; |
90 | if (TotalPieces(black, pawn) == 0) |
- | |
91 |
|
79 | lscore = MaterialSTM(wtm); |
92 | if (TotalPieces(white, pawn) == 0) |
- | |
93 |
|
80 | if (lscore + cutoff < alpha) |
94 |
|
81 | return alpha; |
95 |
|
82 | if (lscore - cutoff > beta) |
96 |
|
83 | return beta; |
97 | } |
- | |
98 | /* |
84 | /* |
99 | ************************************************************ |
85 | ************************************************************* |
- | 86 | * * |
|
- | 87 | * Check for draws where one side seems to be ahead, but * |
|
- | 88 | * has no actual winning chances. One simple example is a * |
|
- | 89 | * king, bishop and rook pawn, with the wrong colored * |
|
- | 90 | * bishop and the enemy king too close to the promotion * |
|
- | 91 | * square. * |
|
100 | * * |
92 | * * |
- | 93 | * The variable "can_win" uses 2 bits. If White can * |
|
- | 94 | * actually win in this position, bit 1 is set. If Black * |
|
- | 95 | * can actually win in this position, bit 0 is set. If * |
|
- | 96 | * both sides can win, both bits are set. This is used * |
|
101 | * |
97 | * later to drag the score closer to a draw score if the * |
- | 98 | * side with the better score can't actually win. * |
|
102 | * |
99 | * * |
- | 100 | * Note that we only set these bits in minimal material * |
|
- | 101 | * positions (both sides have < 13 points of material * |
|
- | 102 | * total). Otherwise we assume normal scoring should * |
|
- | 103 | * apply. * |
|
103 | * * |
104 | * * |
104 | ************************************************************ |
105 | ************************************************************* |
105 | */ |
106 | */ |
- | 107 | tree->evaluations++; |
|
- | 108 | tree->score_mg = 0; |
|
- | 109 | tree->score_eg = 0; |
|
106 |
|
110 | EvaluateMaterial(tree, wtm); |
- | 111 | if (TotalPieces(white, occupied) < 13 && TotalPieces(black, occupied) < 13) |
|
107 |
|
112 | for (side = black; side <= white; side++) |
108 | if (!EvaluateWinningChances(tree, |
113 | if (!EvaluateWinningChances(tree, side, wtm)) |
109 | can_win |
114 | can_win ^= (1 << side); |
110 | } while (0); |
- | |
111 | /* |
115 | /* |
112 | |
116 | ************************************************************* |
113 | * |
117 | * * |
114 | * Determine if this position should be evaluated to force |
118 | * Determine if this position should be evaluated to force * |
115 | * (neither side has pawns) or if it should be |
119 | * mate (neither side has pawns) or if it should be * |
- | 120 | * evaluated normally. * |
|
116 | * |
121 | * * |
117 | * Note the special case of no pawns, one side is ahead in |
122 | * Note the special case of no pawns, one side is ahead in * |
118 | * material, but the game is a hopeless draw. KRN vs |
123 | * total material, but the game is a hopeless draw. KRN vs * |
119 | * example. If EvaluateWinningChances() |
124 | * KR is one example. If EvaluateWinningChances() * |
- | 125 | * determines that the side with extra material can not * |
|
120 | * |
126 | * win, the score is pulled closer to a draw although it * |
121 | * |
127 | * can not collapse completely to the drawscore as it is * |
122 | * |
128 | * possible to lose KRB vs KR if the KR side lets the king * |
123 | * trapped on the edge of the board. |
129 | * get trapped on the edge of the board. * |
124 | * |
130 | * * |
125 | |
131 | ************************************************************* |
126 | */ |
132 | */ |
127 | tree->all_pawns = Pawns(black) | Pawns(white); |
133 | tree->all_pawns = Pawns(black) | Pawns(white); |
128 | if (!tree->all_pawns) { |
134 | if (!tree->all_pawns) { |
129 | if (TotalPieces(white, occupied) > 3 || TotalPieces(black, occupied) > 3) { |
135 | if (TotalPieces(white, occupied) > 3 || TotalPieces(black, occupied) > 3) { |
130 | if (Material > 0) |
136 | if (Material > 0) |
131 | EvaluateMate(tree, white); |
137 | EvaluateMate(tree, white); |
132 | else if (Material < 0) |
138 | else if (Material < 0) |
133 | EvaluateMate(tree, black); |
139 | EvaluateMate(tree, black); |
134 | if (tree->score_eg > DrawScore(1) && !(can_win & |
140 | if (tree->score_eg > DrawScore(1) && !(can_win & 2)) |
135 | tree->score_eg = tree->score_eg / |
141 | tree->score_eg = tree->score_eg / 16; |
136 | if (tree->score_eg < DrawScore(1) && !(can_win & |
142 | if (tree->score_eg < DrawScore(1) && !(can_win & 1)) |
137 | tree->score_eg = tree->score_eg / |
143 | tree->score_eg = tree->score_eg / 16; |
138 | #if defined(SKILL) |
144 | #if defined(SKILL) |
139 | if (skill < 100) |
145 | if (skill < 100) |
140 | tree->score_eg = |
146 | tree->score_eg = (int) // Pierre-Marie Baty -- added type cast |
141 |
|
147 | (skill * tree->score_eg / 100 + ((100 - |
142 | skill) * PAWN_VALUE * (uint64_t) Random32() / |
148 | skill) * PAWN_VALUE * (uint64_t) Random32() / |
143 | 0x100000000ull) / 100); |
149 | 0x100000000ull) / 100); |
144 | #endif |
150 | #endif |
145 | return (wtm) ? tree->score_eg : -tree->score_eg; |
151 | return (wtm) ? tree->score_eg : -tree->score_eg; |
146 | } |
152 | } |
147 | } |
153 | } |
148 | /* |
154 | /* |
149 | |
155 | ************************************************************* |
150 | * |
156 | * * |
151 | * Now evaluate pawns. If the pawn hash signature has not |
157 | * Now evaluate pawns. If the pawn hash signature has not * |
152 | * from the last entry to Evaluate() then we |
158 | * changed from the last entry to Evaluate() then we * |
153 | * |
159 | * already have everything we need in the pawn hash entry. * |
- | 160 | * In this case, we do not need to call EvaluatePawns() at * |
|
154 | * |
161 | * all. EvaluatePawns() does all of the analysis for * |
155 | * |
162 | * information specifically regarding only pawns. In many * |
156 | * |
163 | * cases, it merely records the presence/absence of * |
157 | * pawn features because those features also |
164 | * positional pawn features because those features also * |
- | 165 | * depends on pieces. * |
|
- | 166 | * * |
|
158 | * Note that anything put into EvaluatePawns() can only |
167 | * Note that anything put into EvaluatePawns() can only * |
159 | * |
168 | * consider the placement of pawns. Kings or other pieces * |
- | 169 | * can not influence the score because those pieces are not * |
|
160 | * |
170 | * hashed into the pawn hash signature. Violating this * |
161 | * |
171 | * principle leads to lots of very difficult and * |
162 | * |
172 | * challenging debugging problems. * |
163 | * |
173 | * * |
164 | |
174 | ************************************************************* |
165 | */ |
175 | */ |
166 | else { |
176 | else { |
167 | if (PawnHashKey == tree->pawn_score.key) { |
177 | if (PawnHashKey == tree->pawn_score.key) { |
168 | tree->score_mg += tree->pawn_score.score_mg; |
178 | tree->score_mg += tree->pawn_score.score_mg; |
169 | tree->score_eg += tree->pawn_score.score_eg; |
179 | tree->score_eg += tree->pawn_score.score_eg; |
170 | } |
180 | } |
171 | /* |
181 | /* |
172 | ************************************************************ |
182 | ************************************************************* |
173 | * * |
183 | * * |
174 | * First check to see if this position has been handled * |
184 | * First check to see if this position has been handled * |
175 | * before. If so, we can skip the work saved in the pawn * |
185 | * before. If so, we can skip the work saved in the pawn * |
176 | * hash table. * |
186 | * hash table. * |
177 | * * |
187 | * * |
178 | ************************************************************ |
188 | ************************************************************* |
179 | */ |
189 | */ |
180 | else { |
190 | else { |
181 | ptable = pawn_hash_table + (PawnHashKey & pawn_hash_mask); |
191 | ptable = pawn_hash_table + (PawnHashKey & pawn_hash_mask); |
182 | pxtable = (PXOR *) & (tree->pawn_score); |
192 | pxtable = (PXOR *) & (tree->pawn_score); |
183 | tree->pawn_score = *ptable; |
193 | tree->pawn_score = *ptable; |
184 | tree->pawn_score.key ^= |
- | |
185 |
|
194 | tree->pawn_score.key ^= pxtable->entry[1] ^ pxtable->entry[2]; |
186 | if (tree->pawn_score.key != PawnHashKey) { |
195 | if (tree->pawn_score.key != PawnHashKey) { |
187 | tree->pawn_score.key = PawnHashKey; |
196 | tree->pawn_score.key = PawnHashKey; |
188 | tree->pawn_score.score_mg = 0; |
197 | tree->pawn_score.score_mg = 0; |
189 | tree->pawn_score.score_eg = 0; |
198 | tree->pawn_score.score_eg = 0; |
190 | for (side = black; side <= white; side++) |
199 | for (side = black; side <= white; side++) |
191 | EvaluatePawns(tree, side); |
200 | EvaluatePawns(tree, side); |
192 | ptable->key = |
201 | ptable->key = |
193 | pxtable->entry[0] ^ pxtable->entry[1] ^ pxtable-> |
202 | pxtable->entry[0] ^ pxtable->entry[1] ^ pxtable->entry[2]; |
194 | entry[2] ^ pxtable->entry[3]; |
- | |
195 | memcpy((char *) ptable + 8, (char *) &(tree->pawn_score) + 8, |
203 | memcpy((char *) ptable + 8, (char *) &(tree->pawn_score) + 8, |
- | 204 | sizeof(PAWN_HASH_ENTRY) - 8); |
|
196 | } |
205 | } |
197 | tree->score_mg += tree->pawn_score.score_mg; |
206 | tree->score_mg += tree->pawn_score.score_mg; |
198 | tree->score_eg += tree->pawn_score.score_eg; |
207 | tree->score_eg += tree->pawn_score.score_eg; |
199 | } |
208 | } |
200 | /* |
209 | /* |
201 | |
210 | ************************************************************* |
202 | * |
211 | * * |
203 | * If there are any passed pawns, first call |
212 | * If there are any passed pawns, first call * |
204 | * to |
213 | * EvaluatePassedPawns() to evaluate them. Then, if one * |
- | 214 | * side has a passed pawn and the other side has no pieces, * |
|
205 | * |
215 | * call EvaluatePassedPawnRaces() to see if the passed pawn * |
206 | * |
216 | * can be stopped from promoting. * |
207 | * |
217 | * * |
208 | |
218 | ************************************************************* |
209 | */ |
219 | */ |
210 | if (tree->pawn_score.passed[black] || tree->pawn_score.passed[white]) { |
220 | if (tree->pawn_score.passed[black] || tree->pawn_score.passed[white]) { |
211 | for (side = black; side <= white; side++) |
221 | for (side = black; side <= white; side++) |
212 | if (tree->pawn_score.passed[side]) |
222 | if (tree->pawn_score.passed[side]) |
213 | EvaluatePassedPawns(tree, side, wtm); |
223 | EvaluatePassedPawns(tree, side, wtm); |
Line 217... | Line 227... | ||
217 | tree->pawn_score.passed[white])) |
227 | tree->pawn_score.passed[white])) |
218 | EvaluatePassedPawnRaces(tree, wtm); |
228 | EvaluatePassedPawnRaces(tree, wtm); |
219 | } |
229 | } |
220 | } |
230 | } |
221 | /* |
231 | /* |
222 | |
232 | ************************************************************* |
223 | * |
233 | * * |
224 | * Call |
234 | * Call EvaluateCastling() to evaluate castling potential. * |
225 | * |
235 | * Note we only do this when that side has not castled at * |
- | 236 | * the root. * |
|
226 | * |
237 | * * |
227 | |
238 | ************************************************************* |
228 | */ |
239 | */ |
229 | for (side = black; side <= white; side++) |
240 | for (side = black; side <= white; side++) |
- | 241 | if (Castle(1, side) > 0) |
|
230 |
|
242 | EvaluateCastling(tree, ply, side); |
231 | /* |
243 | /* |
232 | |
244 | ************************************************************* |
- | 245 | * * |
|
- | 246 | * The "dangerous" flag simply indicates whether that side * |
|
- | 247 | * has enough material to whip up a mating attack if the * |
|
- | 248 | * other side is careless (Q + minor or better, or RR + two * |
|
- | 249 | * minors or better). * |
|
233 | * |
250 | * * |
- | 251 | ************************************************************* |
|
- | 252 | */ |
|
- | 253 | tree->dangerous[white] = (Queens(white) && TotalPieces(white, occupied) > 9) |
|
- | 254 | || (TotalPieces(white, rook) > 1 && TotalPieces(white, occupied) > 15); |
|
- | 255 | tree->dangerous[black] = (Queens(black) && TotalPieces(black, occupied) > 9) |
|
- | 256 | || (TotalPieces(black, rook) > 1 && TotalPieces(black, occupied) > 15); |
|
- | 257 | /* |
|
- | 258 | ************************************************************* |
|
- | 259 | * * |
|
- | 260 | * Second lazy evaluation test. We have computed the large * |
|
- | 261 | * positional scores (except for king safety). If the * |
|
- | 262 | * score is too far outside the alpha/beta window, we skip * |
|
- | 263 | * the piece scoring which is the most expensive of all the * |
|
- | 264 | * evaluation terms, and simply use what we have at this * |
|
234 | * |
265 | * point. * |
235 | * |
266 | * * |
236 | |
267 | ************************************************************* |
237 | */ |
268 | */ |
238 | phase = |
269 | phase = |
239 | Min(62, TotalPieces(white, occupied) + TotalPieces(black, occupied)); |
270 | Min(62, TotalPieces(white, occupied) + TotalPieces(black, occupied)); |
240 | score = ((tree->score_mg * phase) + (tree->score_eg * (62 - phase))) / 62; |
271 | score = ((tree->score_mg * phase) + (tree->score_eg * (62 - phase))) / 62; |
241 | lscore = (wtm) ? score : -score; |
272 | lscore = (wtm) ? score : -score; |
- | 273 | int w_mat = (2 * TotalPieces(white, rook)) + TotalPieces(white, |
|
242 |
|
274 | knight) + TotalPieces(white, bishop); |
- | 275 | int b_mat = (2 * TotalPieces(black, rook)) + TotalPieces(black, |
|
- | 276 | knight) + TotalPieces(black, bishop); |
|
- | 277 | cutoff = 72 + (w_mat + b_mat) * 8 + abs(w_mat - b_mat) * 16; |
|
243 |
|
278 | if (tree->dangerous[white] || tree->dangerous[black]) |
- | 279 | cutoff += 35; |
|
- | 280 | /* |
|
- | 281 | ************************************************************* |
|
- | 282 | * * |
|
- | 283 | * Then evaluate pieces if the lazy eval test fails. * |
|
- | 284 | * * |
|
- | 285 | * Note: We MUST evaluate kings last, since their scoring * |
|
- | 286 | * depends on the tropism scores computed by the other * |
|
- | 287 | * piece evaluators. Do NOT try to collapse the following * |
|
- | 288 | * loops into one loop. That will break things since it * |
|
- | 289 | * would violate the kings last rule. More importantly * |
|
- | 290 | * there is no benefit as the loops below are unrolled by * |
|
- | 291 | * the compiler anyway. * |
|
- | 292 | * * |
|
- | 293 | ************************************************************* |
|
- | 294 | */ |
|
244 | if (lscore + cutoff > alpha && lscore - cutoff < beta) { |
295 | if (lscore + cutoff > alpha && lscore - cutoff < beta) { |
245 | tree->tropism[white] = 0; |
296 | tree->tropism[white] = 0; |
246 | tree->tropism[black] = 0; |
297 | tree->tropism[black] = 0; |
247 | for (side = black; side <= white; side++) |
298 | for (side = black; side <= white; side++) |
248 | EvaluateKnights(tree, side); |
299 | EvaluateKnights(tree, side); |
Line 251... | Line 302... | ||
251 | for (side = black; side <= white; side++) |
302 | for (side = black; side <= white; side++) |
252 | EvaluateRooks(tree, side); |
303 | EvaluateRooks(tree, side); |
253 | for (side = black; side <= white; side++) |
304 | for (side = black; side <= white; side++) |
254 | EvaluateQueens(tree, side); |
305 | EvaluateQueens(tree, side); |
255 | for (side = black; side <= white; side++) |
306 | for (side = black; side <= white; side++) |
256 |
|
307 | EvaluateKing(tree, ply, side); |
- | 308 | full = 1; |
|
257 | } |
309 | } |
258 | /* |
310 | /* |
259 | |
311 | ************************************************************* |
- | 312 | * * |
|
- | 313 | * Caclulate the final score, which is interpolated between * |
|
- | 314 | * the middlegame score and endgame score based on the * |
|
- | 315 | * material left on the board. * |
|
260 | * |
316 | * * |
261 | * Adjust the score if |
317 | * Adjust the score if one side can't win, but the score * |
262 | * |
318 | * actually favors that side significantly. * |
263 | * |
319 | * * |
264 | |
320 | ************************************************************* |
265 | */ |
321 | */ |
266 | score = ((tree->score_mg * phase) + (tree->score_eg * (62 - phase))) / 62; |
322 | score = ((tree->score_mg * phase) + (tree->score_eg * (62 - phase))) / 62; |
267 | score = EvaluateDraws(tree, ply, can_win, score); |
323 | score = EvaluateDraws(tree, ply, can_win, score); |
268 | #if defined(SKILL) |
324 | #if defined(SKILL) |
269 | if (skill < 100) |
325 | if (skill < 100) |
270 | score = |
326 | score = (int) // Pierre-Marie Baty -- added type cast |
271 |
|
327 | (skill * score / 100 + ((100 - |
272 | skill) * PAWN_VALUE * (uint64_t) Random32() / 0x100000000ull) / |
328 | skill) * PAWN_VALUE * (uint64_t) Random32() / 0x100000000ull) / |
273 | 100); |
329 | 100); |
274 | #endif |
330 | #endif |
- | 331 | if (full) |
|
- | 332 | *etable = (temp_hashkey & 0xffffffffffff0000) + score + 32768; |
|
275 | return (wtm) ? score : -score; |
333 | return (wtm) ? score : -score; |
276 | } |
334 | } |
277 | 335 | ||
278 | /* last modified |
336 | /* last modified 10/19/15 */ |
279 | /* |
337 | /* |
280 | ******************************************************************************* |
338 | ******************************************************************************* |
281 | * * |
339 | * * |
282 | * EvaluateBishops() is used to evaluate bishops. * |
340 | * EvaluateBishops() is used to evaluate bishops. * |
283 | * * |
341 | * * |
284 | ******************************************************************************* |
342 | ******************************************************************************* |
285 | */ |
343 | */ |
286 | void EvaluateBishops(TREE * RESTRICT tree, int side) { |
344 | void EvaluateBishops(TREE * RESTRICT tree, int side) { |
287 | uint64_t temp, moves; |
345 | uint64_t temp, moves; |
288 | int square, |
346 | int square, special, i, mobility; |
289 | int score_eg = 0, score_mg = 0, enemy = Flip(side); |
347 | int score_eg = 0, score_mg = 0, enemy = Flip(side), tpawns; |
290 | /* |
348 | /* |
291 | ************************************************************ |
349 | ************************************************************ |
292 | * * |
350 | * * |
293 | * First, locate each bishop and add in its piece/square * |
351 | * First, locate each bishop and add in its piece/square * |
294 | * |
352 | * table score. * |
295 | * * |
353 | * * |
296 | ************************************************************ |
354 | ************************************************************ |
297 | */ |
355 | */ |
298 | for (temp = Bishops(side); temp; temp &= temp - 1) { |
356 | for (temp = Bishops(side); temp; temp &= temp - 1) { |
299 | square = LSB(temp); |
357 | square = LSB(temp); |
Line 306... | Line 364... | ||
306 | * driven off by an enemy pawn, and which is supported by * |
364 | * driven off by an enemy pawn, and which is supported by * |
307 | * a friendly pawn. * |
365 | * a friendly pawn. * |
308 | * * |
366 | * * |
309 | * If the enemy has NO minor to take this bishop, then * |
367 | * If the enemy has NO minor to take this bishop, then * |
310 | * increase the bonus. * |
368 | * increase the bonus. * |
311 | * * |
- | |
312 | * Note that the bishop_outpost array is overloaded to * |
- | |
313 | * serve a dual prupose. A negative value is used to flag * |
- | |
314 | * squares A7 and H7 to test for a trapped bishop. This * |
- | |
315 | * is done for speed. * |
- | |
316 | * * |
369 | * * |
317 | ************************************************************ |
370 | ************************************************************ |
318 | */ |
371 | */ |
319 |
|
372 | special = bishop_outpost[side][square]; |
320 | if ( |
373 | if (special) { |
321 | if (t > 0) { |
- | |
322 |
|
374 | if (!(mask_pattacks[enemy][square] & Pawns(enemy))) { |
323 |
|
375 | if (pawn_attacks[enemy][square] & Pawns(side)) { |
324 |
|
376 | special += special / 2; |
325 |
|
377 | if (!Knights(enemy) && !(Color(square) & Bishops(enemy))) |
326 |
|
378 | special += bishop_outpost[side][square]; |
327 | } |
- | |
328 | score_eg += t; |
- | |
329 | score_mg += t; |
- | |
330 | } |
379 | } |
- | 380 | score_eg += special; |
|
- | 381 | score_mg += special; |
|
331 | } |
382 | } |
- | 383 | } |
|
332 | /* |
384 | /* |
333 | ************************************************************ |
385 | ************************************************************ |
334 | * * |
386 | * * |
- | 387 | * Next we count the number of friendly pawns on the same * |
|
335 | * |
388 | * color squares as the bishop. This is a bad thing since * |
- | 389 | * it restricts the bishop's ability to move. We only do * |
|
336 | * |
390 | * this if there is only one bishop for this side. * |
337 | * * |
391 | * * |
338 | ************************************************************ |
392 | ************************************************************ |
339 | */ |
393 | */ |
340 | else { |
- | |
341 |
|
394 | if (TotalPieces(side, bishop) == 1) { |
342 | if (SetMask(sqflip[side][B6]) & Pawns(enemy)) { |
- | |
343 |
|
395 | if (dark_squares & SetMask(square)) |
344 |
|
396 | tpawns = PopCnt(dark_squares & Pawns(side)); |
345 |
|
397 | else |
346 | } else if (square == sqflip[side][H7]) { |
- | |
347 |
|
398 | tpawns = PopCnt(~dark_squares & Pawns(side)); |
348 |
|
399 | score_mg -= tpawns * bishop_pawns_on_color[mg]; |
349 |
|
400 | score_eg -= tpawns * bishop_pawns_on_color[eg]; |
350 | } |
- | |
351 | } |
- | |
352 | } |
- | |
353 | } |
401 | } |
354 | /* |
402 | /* |
355 | ************************************************************ |
403 | ************************************************************ |
356 | * * |
404 | * * |
357 | * Mobility counts the number of squares the |
405 | * Mobility counts the number of squares the bishop * |
358 | * attacks, |
406 | * attacks, excluding squares with friendly pieces, and * |
359 | * |
407 | * weighs each square according to centralization. * |
360 | * * |
408 | * * |
361 | ************************************************************ |
409 | ************************************************************ |
362 | */ |
410 | */ |
363 | mobility = BishopMobility(square, OccupiedSquares); |
411 | mobility = BishopMobility(square, OccupiedSquares); |
364 | if (mobility < 0 && (pawn_attacks[enemy][square] & Pawns(side)) |
412 | if (mobility < 0 && (pawn_attacks[enemy][square] & Pawns(side)) |
Line 373... | Line 421... | ||
373 | * even more valuable against an enemy knight * |
421 | * even more valuable against an enemy knight * |
374 | * * |
422 | * * |
375 | ************************************************************ |
423 | ************************************************************ |
376 | */ |
424 | */ |
377 | if (tree->all_pawns & mask_fgh && tree->all_pawns & mask_abc) { |
425 | if (tree->all_pawns & mask_fgh && tree->all_pawns & mask_abc) { |
378 | score_mg += |
426 | score_mg += bishop_wing_pawns[mg]; |
379 | score_eg += |
427 | score_eg += bishop_wing_pawns[eg]; |
380 | } |
428 | } |
381 | /* |
429 | /* |
382 | ************************************************************ |
430 | ************************************************************ |
383 | * * |
431 | * * |
384 | * Adjust the tropism count for this piece. * |
432 | * Adjust the tropism count for this piece. * |
385 | * * |
433 | * * |
386 | ************************************************************ |
434 | ************************************************************ |
387 | */ |
435 | */ |
388 | if (tree->dangerous[side]) { |
436 | if (tree->dangerous[side]) { |
389 | moves = king_attacks[KingSQ(enemy)]; |
437 | moves = king_attacks[KingSQ(enemy)]; |
390 |
|
438 | i = ((bishop_attacks[square] & moves) && |
391 | && ((BishopAttacks(square, |
- | |
392 |
|
439 | ((BishopAttacks(square, OccupiedSquares & ~Queens(side))) & moves)) |
393 | Distance(square, KingSQ(enemy)); |
440 | ? 1 : Distance(square, KingSQ(enemy)); |
394 | tree->tropism[side] += king_tropism_b[ |
441 | tree->tropism[side] += king_tropism_b[i]; |
395 | } |
442 | } |
- | 443 | } |
|
- | 444 | /* |
|
- | 445 | ************************************************************ |
|
- | 446 | * * |
|
- | 447 | * Add a bonus if this side has a pair of bishops, which * |
|
- | 448 | * can become very strong in open positions. * |
|
- | 449 | * * |
|
- | 450 | ************************************************************ |
|
- | 451 | */ |
|
- | 452 | if (TotalPieces(side, bishop) > 1) { |
|
- | 453 | score_mg += bishop_pair[mg]; |
|
- | 454 | score_eg += bishop_pair[eg]; |
|
396 | } |
455 | } |
397 | tree->score_mg += sign[side] * score_mg; |
456 | tree->score_mg += sign[side] * score_mg; |
398 | tree->score_eg += sign[side] * score_eg; |
457 | tree->score_eg += sign[side] * score_eg; |
399 | } |
458 | } |
400 | 459 | ||
401 | /* last modified |
460 | /* last modified 01/03/15 */ |
402 | /* |
461 | /* |
403 | ******************************************************************************* |
462 | ******************************************************************************* |
404 | * * |
463 | * * |
405 | * |
464 | * EvaluateCastling() is called when "side" has not castled at the root. * |
406 | * |
465 | * Its main purpose is to determine if it has either castled somewhere in * |
407 | * |
466 | * the tree, or else has lost all (or some) castling rights, which reduces * |
408 | * developed; (2) advance the center pawns as soon as possible; (3) don't * |
- | |
409 | * |
467 | * options significantly. * |
410 | * * |
468 | * * |
411 | ******************************************************************************* |
469 | ******************************************************************************* |
412 | */ |
470 | */ |
413 | void |
471 | void EvaluateCastling(TREE * RESTRICT tree, int ply, int side) { |
414 | int score_mg = 0; |
- | |
415 | int enemy = Flip(side); |
472 | int enemy = Flip(side), oq, score_mg = 0;; |
416 | 473 | ||
417 | /* |
474 | /* |
418 | ************************************************************ |
475 | ************************************************************ |
419 | * * |
476 | * * |
- | 477 | * If the king castled during the search, we are done and * |
|
- | 478 | * we leave it to EvaluateKing() to figure out how safe it * |
|
420 | * |
479 | * is. If it has not castled, we give a significant * |
- | 480 | * penalty if the king moves since that loses all castling * |
|
- | 481 | * rights, otherwise we give a smaller penalty for moving * |
|
- | 482 | * a rook and giving up castling rights to that side of * |
|
- | 483 | * the board. The penalty is always increased if the * |
|
- | 484 | * opponent has a queen since the position is much more * |
|
421 | * |
485 | * dangerous. * |
422 | * * |
486 | * * |
423 | ************************************************************ |
487 | ************************************************************ |
424 | */ |
488 | */ |
425 | if (!(SetMask(sqflip[side][E4]) & Pawns(side)) |
- | |
426 | && SetMask(sqflip[side][D4]) & Pawns(side) |
- | |
427 | && SetMask(sqflip[side][C2]) & Pawns(side) |
- | |
428 | && SetMask(sqflip[side][C3]) & (Knights(side) | Bishops(side))) |
- | |
429 | score_mg -= development_thematic; |
- | |
430 | /* |
- | |
431 | ************************************************************ |
- | |
432 | * * |
- | |
433 | * If the king hasn't moved at the beginning of the * |
- | |
434 | * search, but it has moved somewhere in the current * |
- | |
435 | * search path, make *sure* it's a castle move or else * |
- | |
436 | * penalize the loss of castling privilege. * |
- | |
437 | * * |
- | |
438 | ************************************************************ |
- | |
439 | */ |
- | |
440 | if (Castle(1, side) > 0) { |
- | |
441 |
|
489 | oq = (Queens(enemy)) ? 3 : 1; |
442 | - | ||
443 |
|
490 | if (Castle(ply, side) != Castle(1, side)) { |
444 |
|
491 | if (Castle(ply, side) == 0) |
445 |
|
492 | score_mg -= oq * development_losing_castle; |
446 |
|
493 | else if (Castle(ply, side) > 0) |
447 |
|
494 | score_mg -= (oq * development_losing_castle) / 2; |
448 |
|
495 | } else |
449 |
|
496 | score_mg -= oq * development_not_castled; |
450 | } |
- | |
451 | /* |
- | |
452 | ************************************************************ |
- | |
453 | * * |
- | |
454 | * Check for an undeveloped knight/rook combo * |
- | |
455 | * * |
- | |
456 | ************************************************************ |
- | |
457 | */ |
- | |
458 | if (PcOnSq(sqflip[side][B1]) == pieces[side][knight] |
- | |
459 | && PcOnSq(sqflip[side][A1]) == pieces[side][rook]) |
- | |
460 | score_mg -= undeveloped_piece; |
- | |
461 | if (PcOnSq(sqflip[side][G1]) == pieces[side][knight] |
- | |
462 | && PcOnSq(sqflip[side][H1]) == pieces[side][rook]) |
- | |
463 | score_mg -= undeveloped_piece; |
- | |
464 | tree->score_mg += sign[side] * score_mg; |
497 | tree->score_mg += sign[side] * score_mg; |
465 | } |
498 | } |
466 | 499 | ||
467 | /* last modified |
500 | /* last modified 01/03/15 */ |
468 | /* |
501 | /* |
469 | ******************************************************************************* |
502 | ******************************************************************************* |
470 | * * |
503 | * * |
471 | * EvaluateDraws() is used to adjust the score based on whether the side * |
504 | * EvaluateDraws() is used to adjust the score based on whether the side * |
472 | * that appears to be better according the computed score can actually win * |
505 | * that appears to be better according the computed score can actually win * |
Line 478... | Line 511... | ||
478 | int EvaluateDraws(TREE * RESTRICT tree, int ply, int can_win, int score) { |
511 | int EvaluateDraws(TREE * RESTRICT tree, int ply, int can_win, int score) { |
479 | /* |
512 | /* |
480 | ************************************************************ |
513 | ************************************************************ |
481 | * * |
514 | * * |
482 | * If the ending has only bishops of opposite colors, the * |
515 | * If the ending has only bishops of opposite colors, the * |
483 | * score is pulled closer to a draw. |
516 | * score is pulled closer to a draw. * |
484 | * one side is winning, but that side doesn't have enough * |
- | |
485 | * material to win, the score is also pulled closer to a * |
- | |
486 | * draw. * |
- | |
487 | * * |
517 | * * |
488 | * If this is a pure BOC ending, it is very drawish unless * |
518 | * If this is a pure BOC ending, it is very drawish unless * |
489 | * one side has at least 4 pawns. More pawns makes it * |
519 | * one side has at least 4 pawns. More pawns makes it * |
490 | * harder for a bishop and king to stop them all from * |
520 | * harder for a bishop and king to stop them all from * |
491 | * advancing. * |
521 | * advancing. * |
- | 522 | * * |
|
- | 523 | * If the following are both true: * |
|
- | 524 | * * |
|
- | 525 | * black and white have less than a queen left (pieces * |
|
- | 526 | * only). * |
|
- | 527 | * * |
|
- | 528 | * both have one bishop and they are opposite colored. * |
|
- | 529 | * * |
|
- | 530 | * then either * |
|
- | 531 | * * |
|
- | 532 | * (a) both have just one bishop, both have less than 4 * |
|
- | 533 | * pawns or one side has only one more pawn than the * |
|
- | 534 | * other side then score is divided by 2 with draw score * |
|
- | 535 | * added in; or * |
|
- | 536 | * * |
|
- | 537 | * (b) pieces are equal, then score is reduced by 25% * |
|
- | 538 | * with draw score added in. * |
|
492 | * * |
539 | * * |
493 | ************************************************************ |
540 | ************************************************************ |
494 | */ |
541 | */ |
495 | if (TotalPieces(white, occupied) <= 8 && TotalPieces(black, occupied) <= 8) { |
542 | if (TotalPieces(white, occupied) <= 8 && TotalPieces(black, occupied) <= 8) { |
496 | if (TotalPieces(white, bishop) == 1 && TotalPieces(black, bishop) == 1) |
543 | if (TotalPieces(white, bishop) == 1 && TotalPieces(black, bishop) == 1) |
Line 504... | Line 551... | ||
504 | score = score / 2 + DrawScore(1); |
551 | score = score / 2 + DrawScore(1); |
505 | else if (TotalPieces(white, occupied) == TotalPieces(black, occupied)) |
552 | else if (TotalPieces(white, occupied) == TotalPieces(black, occupied)) |
506 | score = 3 * score / 4 + DrawScore(1); |
553 | score = 3 * score / 4 + DrawScore(1); |
507 | } |
554 | } |
508 | } |
555 | } |
- | 556 | /* |
|
- | 557 | ************************************************************ |
|
- | 558 | * * |
|
- | 559 | * Final score adjustment. If the score says white is * |
|
- | 560 | * better, but can_win says white can not win, or if the * |
|
- | 561 | * score says black is better, but can_win says black can * |
|
- | 562 | * not win, then we divide the score by 16, and then add * |
|
- | 563 | * in the draw score. If the can_win says neither side * |
|
- | 564 | * can win, we just set the score to draw score and exit. * |
|
- | 565 | * * |
|
- | 566 | ************************************************************ |
|
- | 567 | */ |
|
509 | if (can_win != 3) { |
568 | if (can_win != 3) { |
- | 569 | if (can_win & 1) { |
|
510 |
|
570 | if (score > DrawScore(1)) |
511 | score = score / |
571 | score = score / 16 + DrawScore(1); |
- | 572 | } else if (can_win & 2) { |
|
512 |
|
573 | if (score < DrawScore(1)) |
513 | score = score / |
574 | score = score / 16 + DrawScore(1); |
- | 575 | } else |
|
- | 576 | score = DrawScore(1); |
|
514 | } |
577 | } |
515 | /* |
578 | /* |
516 | ************************************************************ |
579 | ************************************************************ |
517 | * * |
580 | * * |
518 | * If we are running into the 50-move rule, then start * |
581 | * If we are running into the 50-move rule, then start * |
Line 525... | Line 588... | ||
525 | * to its correct value a bit more smoothly. * |
588 | * to its correct value a bit more smoothly. * |
526 | * * |
589 | * * |
527 | ************************************************************ |
590 | ************************************************************ |
528 | */ |
591 | */ |
529 | if (Reversible(ply) > 80) { |
592 | if (Reversible(ply) > 80) { |
530 | int |
593 | int closeness = 101 - Reversible(ply); |
531 | 594 | ||
532 | score = DrawScore(1) + score * |
595 | score = DrawScore(1) + score * closeness / 20; |
533 | } |
596 | } |
534 | return score; |
597 | return score; |
535 | } |
598 | } |
536 | 599 | ||
537 | /* last modified |
600 | /* last modified 01/03/15 */ |
538 | /* |
601 | /* |
539 | ******************************************************************************* |
602 | ******************************************************************************* |
540 | * * |
603 | * * |
541 | * EvaluateHasOpposition() is used to determine if one king stands in * |
604 | * EvaluateHasOpposition() is used to determine if one king stands in * |
542 | * "opposition" to the other. If the kings are opposed on the same file or * |
605 | * "opposition" to the other. If the kings are opposed on the same file or * |
Line 561... | Line 624... | ||
561 | if (!(file_distance & 1) && !(rank_distance & 1)) |
624 | if (!(file_distance & 1) && !(rank_distance & 1)) |
562 | return 1; |
625 | return 1; |
563 | return 0; |
626 | return 0; |
564 | } |
627 | } |
565 | 628 | ||
566 | /* last modified |
629 | /* last modified 01/03/15 */ |
567 | /* |
630 | /* |
568 | ******************************************************************************* |
631 | ******************************************************************************* |
569 | * * |
632 | * * |
570 | * |
633 | * EvaluateKing() is used to evaluate a king. * |
571 | * * |
634 | * * |
572 | ******************************************************************************* |
635 | ******************************************************************************* |
573 | */ |
636 | */ |
574 | void |
637 | void EvaluateKing(TREE * RESTRICT tree, int ply, int side) { |
575 | int score_eg = 0, score_mg = 0, defects; |
638 | int score_eg = 0, score_mg = 0, defects; |
576 | int ksq = KingSQ(side), enemy = Flip(side); |
639 | int ksq = KingSQ(side), enemy = Flip(side); |
577 | 640 | ||
578 | /* |
641 | /* |
579 | ************************************************************ |
642 | ************************************************************ |
580 | * * |
643 | * * |
581 | * First, check for where the king should be if this is an * |
644 | * First, check for where the king should be if this is an * |
582 | * endgame. |
645 | * endgame. The basic idea is to centralize unless the * |
583 | * be on that wing. With pawns on both wings, the king * |
- | |
584 | * |
646 | * king is needed to deal with a passed enemy pawn. * |
585 | * * |
647 | * * |
586 | ************************************************************ |
648 | ************************************************************ |
587 | */ |
649 | */ |
588 | if (tree->all_pawns) { |
- | |
589 | if (tree->all_pawns & mask_efgh && tree->all_pawns & mask_abcd) |
- | |
590 |
|
650 | score_eg += kval[side][ksq]; |
591 | else if (tree->all_pawns & mask_efgh) |
- | |
592 | score_eg += kval_k[side][ksq]; |
- | |
593 | else |
- | |
594 | score_eg += kval_q[side][ksq]; |
- | |
595 | } |
- | |
596 | /* |
651 | /* |
597 | ************************************************************ |
652 | ************************************************************ |
598 | * * |
653 | * * |
599 | * Do castle scoring, if the king has castled, the pawns * |
654 | * Do castle scoring, if the king has castled, the pawns * |
600 | * in front are important. If not castled yet, the pawns * |
655 | * in front are important. If not castled yet, the pawns * |
Line 603... | Line 658... | ||
603 | ************************************************************ |
658 | ************************************************************ |
604 | */ |
659 | */ |
605 | if (tree->dangerous[enemy]) { |
660 | if (tree->dangerous[enemy]) { |
606 | defects = 0; |
661 | defects = 0; |
607 | if (Castle(ply, side) <= 0) { |
662 | if (Castle(ply, side) <= 0) { |
608 | if (File(ksq) >= FILEE) { |
- | |
609 |
|
663 | if (File(ksq) > FILEE) |
610 |
|
664 | defects = tree->pawn_score.defects_k[side]; |
611 | else |
- | |
612 | defects = tree->pawn_score.defects_e[side]; |
- | |
613 | } else { |
- | |
614 |
|
665 | else if (File(ksq) < FILED) |
615 |
|
666 | defects = tree->pawn_score.defects_q[side]; |
616 |
|
667 | else |
617 |
|
668 | defects = tree->pawn_score.defects_m[side]; |
618 | } |
- | |
619 | } else { |
669 | } else { |
620 | if (Castle(ply, side) == 3) |
670 | if (Castle(ply, side) == 3) |
621 | defects = |
671 | defects = |
622 | Min(Min(tree->pawn_score.defects_k[side], |
672 | Min(Min(tree->pawn_score.defects_k[side], |
623 | tree->pawn_score. |
673 | tree->pawn_score.defects_m[side]), |
624 | tree->pawn_score.defects_q[side]); |
674 | tree->pawn_score.defects_q[side]); |
625 | else if (Castle(ply, side) == 1) |
675 | else if (Castle(ply, side) == 1) |
626 | defects = |
676 | defects = |
627 | Min(tree->pawn_score.defects_k[side], |
677 | Min(tree->pawn_score.defects_k[side], |
628 | tree->pawn_score. |
678 | tree->pawn_score.defects_m[side]); |
629 | else |
679 | else |
630 | defects = |
680 | defects = |
631 | Min(tree->pawn_score.defects_q[side], |
681 | Min(tree->pawn_score.defects_q[side], |
632 | tree->pawn_score. |
682 | tree->pawn_score.defects_m[side]); |
633 | if (defects < 3) |
683 | if (defects < 3) |
634 | defects = 3; |
684 | defects = 3; |
635 | } |
685 | } |
636 | /* |
686 | /* |
637 | ************************************************************ |
687 | ************************************************************ |
Line 651... | Line 701... | ||
651 | } |
701 | } |
652 | tree->score_mg += sign[side] * score_mg; |
702 | tree->score_mg += sign[side] * score_mg; |
653 | tree->score_eg += sign[side] * score_eg; |
703 | tree->score_eg += sign[side] * score_eg; |
654 | } |
704 | } |
655 | 705 | ||
656 | /* last modified |
706 | /* last modified 01/03/15 */ |
657 | /* |
707 | /* |
658 | ******************************************************************************* |
708 | ******************************************************************************* |
659 | * * |
709 | * * |
660 | * EvaluateKingsFile computes defects for a file, based on whether the file * |
710 | * EvaluateKingsFile computes defects for a file, based on whether the file * |
661 | * is open or half-open. If there are friendly pawns still on the file, * |
711 | * is open or half-open. If there are friendly pawns still on the file, * |
662 | * they are penalized for advancing in front of the king. * |
712 | * they are penalized for advancing in front of the king. * |
663 | * * |
713 | * * |
664 | ******************************************************************************* |
714 | ******************************************************************************* |
665 | */ |
715 | */ |
666 | int EvaluateKingsFile(TREE * RESTRICT tree, int |
716 | int EvaluateKingsFile(TREE * RESTRICT tree, int side, int first, int last) { |
667 | int defects = 0, file; |
- | |
668 | int enemy = Flip(side); |
717 | int defects = 0, file, enemy = Flip(side); |
669 | 718 | ||
670 | for (file = |
719 | for (file = first; file <= last; file++) |
671 | if (!(file_mask[file] & tree->all_pawns)) |
720 | if (!(file_mask[file] & tree->all_pawns)) |
672 | defects += open_file[file]; |
721 | defects += open_file[file]; |
673 | else { |
722 | else { |
674 | if (!(file_mask[file] & Pawns(enemy))) |
723 | if (!(file_mask[file] & Pawns(enemy))) |
675 | defects += half_open_file[file] / 2; |
724 | defects += half_open_file[file] / 2; |
676 | else |
725 | else |
677 | defects += |
726 | defects += |
678 | pawn_defects[side][Rank( |
727 | pawn_defects[side][Rank(MostAdvanced(enemy, |
679 | file_mask[file] & Pawns(enemy)))]; |
728 | file_mask[file] & Pawns(enemy)))]; |
680 | if (!(file_mask[file] & Pawns(side))) |
729 | if (!(file_mask[file] & Pawns(side))) |
681 | defects += half_open_file[file]; |
730 | defects += half_open_file[file]; |
682 | else if (!(Pawns(side) & SetMask(sqflip[side][A2] + file))) { |
731 | else if (!(Pawns(side) & SetMask(sqflip[side][A2] + file))) { |
683 | defects++; |
732 | defects++; |
Line 686... | Line 735... | ||
686 | } |
735 | } |
687 | } |
736 | } |
688 | return defects; |
737 | return defects; |
689 | } |
738 | } |
690 | 739 | ||
691 | /* last modified |
740 | /* last modified 10/19/15 */ |
692 | /* |
741 | /* |
693 | ******************************************************************************* |
742 | ******************************************************************************* |
694 | * * |
743 | * * |
695 | * EvaluateKnights() is used to evaluate knights. * |
744 | * EvaluateKnights() is used to evaluate knights. * |
696 | * * |
745 | * * |
697 | ******************************************************************************* |
746 | ******************************************************************************* |
698 | */ |
747 | */ |
699 | void EvaluateKnights(TREE * RESTRICT tree, int side) { |
748 | void EvaluateKnights(TREE * RESTRICT tree, int side) { |
700 | uint64_t temp; |
749 | uint64_t temp; |
701 | int square, |
750 | int square, special, i, score_eg = 0, score_mg = 0, enemy = Flip(side); |
702 | int enemy = Flip(side); |
- | |
703 | 751 | ||
704 | /* |
752 | /* |
705 | ************************************************************ |
753 | ************************************************************ |
706 | * * |
754 | * * |
707 | * First fold in centralization score from the piece/ * |
755 | * First fold in centralization score from the piece/ * |
Line 723... | Line 771... | ||
723 | * If the enemy has NO minor to take this knight, then * |
771 | * If the enemy has NO minor to take this knight, then * |
724 | * increase the bonus. * |
772 | * increase the bonus. * |
725 | * * |
773 | * * |
726 | ************************************************************ |
774 | ************************************************************ |
727 | */ |
775 | */ |
728 |
|
776 | special = knight_outpost[side][square]; |
729 | if ( |
777 | if (special && !(mask_pattacks[enemy][square] & Pawns(enemy))) { |
730 | if (pawn_attacks[enemy][square] & Pawns(side)) { |
778 | if (pawn_attacks[enemy][square] & Pawns(side)) { |
731 |
|
779 | special += special / 2; |
732 | if (!Knights(enemy) && !(Color(square) & Bishops(enemy))) |
780 | if (!Knights(enemy) && !(Color(square) & Bishops(enemy))) |
733 |
|
781 | special += knight_outpost[side][square]; |
734 | } |
782 | } |
735 | score_eg += |
783 | score_eg += special; |
736 | score_mg += |
784 | score_mg += special; |
737 | } |
785 | } |
738 | /* |
- | |
739 | ************************************************************ |
- | |
740 | * * |
- | |
741 | * Mobility counts the number of squares the piece * |
- | |
742 | * attacks, including squares with friendly pieces, and * |
- | |
743 | * weighs each square according to centralization. * |
- | |
744 | * * |
- | |
745 | ************************************************************ |
- | |
746 | */ |
- | |
747 | score_mg += knight_mobility_table[square]; |
- | |
748 | score_eg += knight_mobility_table[square]; |
- | |
749 | /* |
786 | /* |
750 | ************************************************************ |
787 | ************************************************************ |
751 | * * |
788 | * * |
752 | * Adjust the tropism count for this piece. * |
789 | * Adjust the tropism count for this piece. * |
753 | * * |
790 | * * |
754 | ************************************************************ |
791 | ************************************************************ |
755 | */ |
792 | */ |
756 | if (tree->dangerous[side]) { |
793 | if (tree->dangerous[side]) { |
757 |
|
794 | i = Distance(square, KingSQ(enemy)); |
758 | tree->tropism[side] += king_tropism_n[ |
795 | tree->tropism[side] += king_tropism_n[i]; |
759 | } |
796 | } |
760 | } |
797 | } |
761 | tree->score_mg += sign[side] * score_mg; |
798 | tree->score_mg += sign[side] * score_mg; |
762 | tree->score_eg += sign[side] * score_eg; |
799 | tree->score_eg += sign[side] * score_eg; |
763 | } |
800 | } |
764 | 801 | ||
765 | /* last modified |
802 | /* last modified 03/30/15 */ |
766 | /* |
803 | /* |
767 | ******************************************************************************* |
804 | ******************************************************************************* |
768 | * * |
805 | * * |
769 | * EvaluateMate() is used to evaluate positions where neither side has pawns * |
806 | * EvaluateMate() is used to evaluate positions where neither side has pawns * |
770 | * and one side has enough material to force checkmate. It simply trys to * |
807 | * and one side has enough material to force checkmate. It simply trys to * |
Line 772... | Line 809... | ||
772 | * where mates are easier to find. * |
809 | * where mates are easier to find. * |
773 | * * |
810 | * * |
774 | ******************************************************************************* |
811 | ******************************************************************************* |
775 | */ |
812 | */ |
776 | void EvaluateMate(TREE * RESTRICT tree, int side) { |
813 | void EvaluateMate(TREE * RESTRICT tree, int side) { |
777 | int mate_score = 0; |
- | |
778 | int enemy = Flip(side); |
814 | int mate_score = 0, enemy = Flip(side); |
779 | 815 | ||
780 | /* |
816 | /* |
781 | ************************************************************ |
817 | ************************************************************ |
782 | * * |
818 | * * |
783 | * If |
819 | * If the winning side has a bishop + knight and the other * |
784 | * no pieces or pawns, then use the special |
820 | * side has no pieces or pawns, then use the special * |
785 | * scoring |
821 | * bishop_knight scoring board for the losing king to * |
786 | * |
822 | * force it to the right corner for mate. * |
787 | * * |
823 | * * |
788 | ************************************************************ |
824 | ************************************************************ |
789 | */ |
825 | */ |
790 | if (!TotalPieces(enemy, occupied) && |
826 | if (!TotalPieces(enemy, occupied) && TotalPieces(side, bishop) == 1 && |
791 | TotalPieces(side, |
827 | TotalPieces(side, knight) == 1) { |
792 | if (dark_squares & Bishops(side)) |
828 | if (dark_squares & Bishops(side)) |
793 | mate_score = b_n_mate_dark_squares[KingSQ(enemy)]; |
829 | mate_score = b_n_mate_dark_squares[KingSQ(enemy)]; |
794 | else |
830 | else |
795 | mate_score = b_n_mate_light_squares[KingSQ(enemy)]; |
831 | mate_score = b_n_mate_light_squares[KingSQ(enemy)]; |
796 | } |
832 | } |
797 | /* |
833 | /* |
798 | ************************************************************ |
834 | ************************************************************ |
799 | * * |
835 | * * |
800 | * |
836 | * The winning side has to force the losing king to the * |
801 | * edge of the board. * |
837 | * edge of the board. * |
802 | * * |
838 | * * |
803 | ************************************************************ |
839 | ************************************************************ |
804 | */ |
840 | */ |
805 | else |
841 | else |
806 | mate_score = mate[KingSQ(enemy)]; |
842 | mate_score = mate[KingSQ(enemy)]; |
- | 843 | /* |
|
- | 844 | ************************************************************ |
|
- | 845 | * * |
|
807 |
|
846 | * And for either, it is important to bring the winning * |
- | 847 | * king to help force mate. * |
|
808 |
|
848 | * * |
- | 849 | ************************************************************ |
|
809 |
|
850 | */ |
810 |
|
851 | mate_score -= Distance(KingSQ(side), KingSQ(enemy)) * king_king_tropism; |
811 | tree->score_eg += sign[side] * mate_score; |
852 | tree->score_eg += sign[side] * mate_score; |
812 | } |
853 | } |
813 | 854 | ||
814 | /* last modified |
855 | /* last modified 10/19/15 */ |
815 | /* |
856 | /* |
816 | ******************************************************************************* |
857 | ******************************************************************************* |
817 | * * |
858 | * * |
818 | * EvaluateMaterial() is used to evaluate material on the board. It really * |
859 | * EvaluateMaterial() is used to evaluate material on the board. It really * |
819 | * accomplishes detecting cases where one side has made a 'bad trade' as the * |
860 | * accomplishes detecting cases where one side has made a 'bad trade' as the * |
820 | * comments below show. * |
861 | * comments below show. * |
821 | * * |
862 | * * |
822 | ******************************************************************************* |
863 | ******************************************************************************* |
823 | */ |
864 | */ |
824 | void EvaluateMaterial(TREE * RESTRICT tree, int wtm) { |
865 | void EvaluateMaterial(TREE * RESTRICT tree, int wtm) { |
825 | int score_mg, score_eg, majors, minors |
866 | int score_mg, score_eg, majors, minors; |
826 | static int bon[17] = |
- | |
827 | { 0, 40, 40, 35, 30, 24, 16, 12, 10, 8, 7, 6, 5, 4, 3, 2, 1 }; |
- | |
828 | 867 | ||
829 | /* |
868 | /* |
830 | |
869 | ************************************************************* |
831 | * |
870 | * * |
832 | * We start with the raw Material balance for the current |
871 | * We start with the raw Material balance for the current * |
833 | * then adjust this with a small bonus for the |
872 | * position, then adjust this with a small bonus for the * |
- | 873 | * side on move. * |
|
834 | * |
874 | * * |
835 | |
875 | ************************************************************* |
836 | */ |
876 | */ |
837 | score_mg = Material + ((wtm) ? wtm_bonus[mg] : -wtm_bonus[mg]); |
877 | score_mg = Material + ((wtm) ? wtm_bonus[mg] : -wtm_bonus[mg]); |
838 | score_eg = Material + ((wtm) ? wtm_bonus[eg] : -wtm_bonus[eg]); |
878 | score_eg = Material + ((wtm) ? wtm_bonus[eg] : -wtm_bonus[eg]); |
839 | /* |
879 | /* |
840 | |
880 | ************************************************************* |
- | 881 | * * |
|
- | 882 | * test 1. if Majors or Minors are not balanced, then if * |
|
- | 883 | * one side is only an exchange up or down, we give a * |
|
- | 884 | * penalty to the side that is an exchange down, but not as * |
|
- | 885 | * big a penalty as the bad trade case below. * |
|
841 | * |
886 | * * |
842 | * |
887 | * test 2. if Majors or Minors are not balanced, then if * |
- | 888 | * one side has more piece material points than the other * |
|
- | 889 | * (using normal piece values of 3, 3, 5, 9 for N, B, R * |
|
- | 890 | * and Q) then the side that is behind in piece material * |
|
843 | * |
891 | * gets a penalty. * |
844 | * |
892 | * * |
845 | |
893 | ************************************************************* |
846 | */ |
894 | */ |
847 | majors = 4 + TotalMajors(white) - TotalMajors(black); |
- | |
848 | minors = 4 + TotalMinors(white) - TotalMinors(black); |
- | |
849 | majors = Max(Min(majors, 8), 0); |
- | |
850 | minors = Max(Min(minors, 8), 0); |
- | |
851 | imbal = imbalance[majors][minors]; |
- | |
852 | score_mg += imbal; |
- | |
853 |
|
895 | majors = |
854 | /* |
- | |
855 | ************************************************************ |
- | |
856 | * * |
- | |
857 |
|
896 | TotalPieces(white, rook) + 2 * TotalPieces(white, |
858 | * which can become very strong in open positions. * |
- | |
859 |
|
897 | queen) - TotalPieces(black, rook) - 2 * TotalPieces(black, queen); |
860 | ************************************************************ |
- | |
861 |
|
898 | minors = |
862 |
|
899 | TotalPieces(white, knight) + TotalPieces(white, |
863 | score_mg += bishop_pair[mg]; |
- | |
864 | score_eg += bishop_pair[eg]; |
- | |
865 | } |
- | |
866 |
|
900 | bishop) - TotalPieces(black, knight) - TotalPieces(black, bishop); |
867 | score_mg -= bishop_pair[mg]; |
- | |
868 |
|
901 | if (majors || minors) { |
869 | } |
- | |
870 | /* |
- | |
871 | ************************************************************ |
- | |
872 | * * |
- | |
873 | * Check for pawns on both wings, which makes a bishop * |
- | |
874 | * even more valuable against an enemy knight (knight vs. * |
- | |
875 | * bishop in endgame) * |
- | |
876 | * * |
- | |
877 | ************************************************************ |
- | |
878 | */ |
- | |
879 | if ( |
902 | if (Abs(TotalPieces(white, occupied) - TotalPieces(black, occupied)) != 2 |
880 |
|
903 | && TotalPieces(white, occupied) - TotalPieces(black, occupied) != 0) { |
881 | if (Bishops(white)) { |
- | |
882 | score_mg += |
904 | score_mg += |
883 |
|
905 | Sign(TotalPieces(white, occupied) - TotalPieces(black, |
884 | } |
- | |
885 |
|
906 | occupied)) * bad_trade; |
886 |
|
907 | score_eg += |
- | 908 | Sign(TotalPieces(white, occupied) - TotalPieces(black, |
|
887 |
|
909 | occupied)) * bad_trade; |
888 | } |
910 | } |
889 | } |
911 | } |
890 | tree->score_mg += score_mg; |
912 | tree->score_mg += score_mg; |
891 | tree->score_eg += score_eg; |
913 | tree->score_eg += score_eg; |
892 | } |
914 | } |
893 | 915 | ||
894 | /* last modified |
916 | /* last modified 11/27/15 */ |
895 | /* |
917 | /* |
896 | ******************************************************************************* |
918 | ******************************************************************************* |
897 | * * |
919 | * * |
898 | * EvaluatePassedPawns() is used to evaluate passed pawns and the danger * |
920 | * EvaluatePassedPawns() is used to evaluate passed pawns and the danger * |
899 | * they produce. This code considers pieces as well, so it |
921 | * they produce. This code considers pieces as well, so it MUST NOT be done * |
900 | * |
922 | * in the normal EvaluatePawns() code since that hashes information based * |
901 | * |
923 | * only on the position of pawns. * |
- | 924 | * * |
|
- | 925 | * This is a significant rewrite of passed pawn evaluation, with the primary * |
|
- | 926 | * change being to collect the passed pawn scoring into one place, rather * |
|
- | 927 | * than have it scattered around all over the place. One example is the old * |
|
- | 928 | * rook_behind_passed_pawn scoring term that was done in rook scoring. It * |
|
- | 929 | * is now done here along with other passed pawn terms such as blockaded and * |
|
- | 930 | * the ability to advance or not. * |
|
902 | * * |
931 | * * |
903 | ******************************************************************************* |
932 | ******************************************************************************* |
904 | */ |
933 | */ |
905 | void EvaluatePassedPawns(TREE * RESTRICT tree, int side, int wtm) { |
934 | void EvaluatePassedPawns(TREE * RESTRICT tree, int side, int wtm) { |
906 | uint64_t behind; |
935 | uint64_t behind, forward, backward, attacked, defended, thispawn; |
907 | int file, square, score_mg = 0, score_eg = 0; |
936 | int file, square, score, score_mg = 0, score_eg = 0, next_sq; |
908 | int pawns, rank; |
937 | int pawns, rank, mg_base, eg_base, bonus, enemy = Flip(side); |
909 |
|
938 | uint64_t fsliders = Queens(side) | Rooks(side); |
- | 939 | uint64_t esliders = Queens(enemy) | Rooks(enemy); |
|
910 | 940 | ||
911 | /* |
941 | /* |
912 | ************************************************************ |
942 | ************************************************************ |
913 | * * |
943 | * * |
- | 944 | * Initialize. The base value "passed_pawn[rank]" is * |
|
- | 945 | * almost the "square" of the rank. That got a bit too * |
|
- | 946 | * big, so a hand-tuned set of values, one per rank, * |
|
914 | * |
947 | * proved to be a better value. * |
915 | * * |
948 | * * |
916 | ************************************************************ |
949 | ************************************************************ |
917 | */ |
950 | */ |
918 | for (pawns = tree->pawn_score.passed[side]; pawns; pawns &= pawns - 1) { |
951 | for (pawns = tree->pawn_score.passed[side]; pawns; pawns &= pawns - 1) { |
919 | file = LSB8Bit(pawns); |
952 | file = LSB8Bit(pawns); |
920 |
|
953 | thispawn = Pawns(side) & file_mask[file]; |
- | 954 | if (thispawn) { |
|
- | 955 | square = MostAdvanced(side, thispawn); |
|
921 | rank = rankflip[side][Rank(square)]; |
956 | rank = rankflip[side][Rank(square)]; |
- | 957 | score = passed_pawn[rank]; |
|
922 | /* |
958 | /* |
923 | ************************************************************ |
959 | ************************************************************ |
924 | * * |
960 | * * |
- | 961 | * For endgame only, we add in a bonus based on how close * |
|
925 | * |
962 | * our king is to this pawn and a penalty based on how * |
926 | * |
963 | * close the enemy king is. We also try to keep our king * |
- | 964 | * ahead of the pawn so it can escort it to promotion. We * |
|
- | 965 | * only do this for passed pawns whose base score value is * |
|
- | 966 | * greater than zero (ie pawns on ranks 4-7 since those * |
|
- | 967 | * are the ones threatening to become a major problem.) * |
|
- | 968 | * Also, if you happen to think that a small bonus for a * |
|
- | 969 | * passed pawn on the 3rd rank might be useful, consider * |
|
- | 970 | * speed. If the 3rd rank score is non-zero, that will * |
|
- | 971 | * trigger a significant amount of work below. In testing * |
|
- | 972 | * the additional cost more than offset the gain and so it * |
|
- | 973 | * is basically ignored unless rank > 3. * |
|
927 | * |
974 | * * |
928 | ************************************************************ |
975 | ************************************************************ |
929 | */ |
976 | */ |
- | 977 | if (score) { |
|
930 |
|
978 | mg_base = score * passed_pawn_base[mg]; |
931 |
|
979 | eg_base = score * passed_pawn_base[eg]; |
- | 980 | next_sq = square + direction[side]; |
|
- | 981 | eg_base += |
|
- | 982 | Distance(KingSQ(enemy), |
|
- | 983 | next_sq) * 2 * score - Distance(KingSQ(side), next_sq) * score; |
|
- | 984 | if (rank < RANK7) |
|
- | 985 | eg_base -= |
|
- | 986 | Distance(KingSQ(side), next_sq + direction[side]) * score / 2; |
|
932 | /* |
987 | /* |
933 | ************************************************************ |
988 | ************************************************************ |
934 | * * |
989 | * * |
- | 990 | * If the pawn is not blockaded, we need to see whether it * |
|
- | 991 | * can actually advance or not. Note that this directly * |
|
935 | * |
992 | * gives a bonus for blockading a passed pawn since the * |
- | 993 | * mobility evaluation below will not be applied when the * |
|
936 | * |
994 | * pawn is blockaded by any piece. * |
937 | * * |
995 | * * |
938 | ************************************************************ |
- | |
939 | */ |
- | |
940 |
|
996 | * Step one is to determine if the squares in front of the * |
941 | score_mg += passed_pawn_connected[mg][rank]; |
- | |
942 |
|
997 | * pawn are attacked by the enemy. If not, we add in a * |
943 | } |
- | |
944 | /* |
- | |
945 | ************************************************************ |
- | |
946 | * |
998 | * significant score bonus. If some are attacked, we look * |
947 | * |
999 | * to see if at least the square directly in front of the * |
948 | * |
1000 | * pawn is not attacked so that we can advance one square, * |
949 | * |
1001 | * anyway. This gets a smaller score bonus. * |
950 | * * |
1002 | * * |
951 | ************************************************************ |
1003 | ************************************************************ |
952 | */ |
1004 | */ |
953 | if ( |
1005 | if (!(OccupiedSquares & SetMask(next_sq))) { |
954 |
|
1006 | bonus = 0; |
955 | ((side) |
1007 | if (Pawns(side) & pawn_attacks[enemy][next_sq]) |
956 |
|
1008 | bonus = passed_pawn_free_advance; |
957 |
|
1009 | else { |
958 |
|
1010 | attacked = 0; |
959 |
|
1011 | forward = (side) ? plus8dir[square] : minus8dir[square]; |
960 |
|
1012 | backward = (side) ? minus8dir[square] : plus8dir[square]; |
961 |
|
1013 | if ((behind = backward & esliders) && |
962 |
|
1014 | (FileAttacks(square) & behind)) |
963 |
|
1015 | attacked = forward; |
964 |
|
1016 | else |
- | 1017 | attacked = Attacked(tree, enemy, forward); |
|
965 | |
1018 | if (!attacked) |
966 |
|
1019 | bonus = passed_pawn_free_advance; |
- | 1020 | else if (!(attacked & SetMask(next_sq))) |
|
- | 1021 | bonus = passed_pawn_free_advance_1; |
|
967 | /* |
1022 | /* |
968 | ************************************************************ |
1023 | ************************************************************ |
969 | * * |
1024 | * * |
970 | * |
1025 | * Step two is to determine if the squares in front of the * |
971 | * |
1026 | * pawn are are defended by the friendly side. If all are * |
972 | * |
1027 | * defended (such as with a rook or queen behind the pawn * |
973 | * |
1028 | * or the king in front and to one side of the pawn, then * |
- | 1029 | * we give a bonus (but smaller than the previous cases). * |
|
974 | * |
1030 | * As a last resort, if we at least defend the square in * |
975 | * |
1031 | * front of the pawn, we give a small bonus. * |
976 | * * |
1032 | * * |
977 | ************************************************************ |
1033 | ************************************************************ |
978 | */ |
1034 | */ |
979 |
|
1035 | if ((behind = backward & fsliders) && |
980 |
|
1036 | (FileAttacks(square) & behind)) |
981 |
|
1037 | defended = forward; |
- | 1038 | else |
|
982 |
|
1039 | defended = Attacked(tree, side, forward); |
983 |
|
1040 | if (defended == forward) |
984 |
|
1041 | bonus += passed_pawn_defended; |
985 |
|
1042 | else if (defended & SetMask(next_sq)) |
986 |
|
1043 | bonus += passed_pawn_defended_1; |
987 | } |
1044 | } |
988 | /* |
1045 | /* |
989 | ************************************************************ |
1046 | ************************************************************ |
990 | * * |
1047 | * * |
991 | * |
1048 | * Fold in the bonus for this pawn and move on to the next * |
992 | * promotion square, then we give a bonus. If the pawn is * |
- | |
993 | * |
1049 | * (if there is one). Note that the bonus computed above * |
994 | * |
1050 | * is multiplied by the base passed pawn score for this * |
995 | * |
1051 | * particular rank. * |
996 | * * |
1052 | * * |
997 | ************************************************************ |
1053 | ************************************************************ |
998 | */ |
1054 | */ |
- | 1055 | mg_base += bonus * score; |
|
- | 1056 | eg_base += bonus * score; |
|
999 |
|
1057 | } |
1000 |
|
1058 | score_mg += mg_base; |
1001 | score_eg += |
1059 | score_eg += eg_base; |
1002 | else |
1060 | } else |
1003 | score_eg += |
1061 | score_eg += 4; |
1004 | } |
1062 | } |
1005 | /* |
- | |
1006 | ************************************************************ |
- | |
1007 | * * |
- | |
1008 | * Add in a bonus based on how close the friendly king is, * |
- | |
1009 | * and a penalty based on how close the enemy king is. * |
- | |
1010 | * The bonus/penalty is based on how advanced the pawn is * |
- | |
1011 | * to attract the kings toward the most advanced (and most * |
- | |
1012 | * dangerous) passed pawn. * |
- | |
1013 | * * |
- | |
1014 | ************************************************************ |
- | |
1015 | */ |
- | |
1016 | square += direction[side]; |
- | |
1017 | score_eg -= |
- | |
1018 | (Distance(square, KingSQ(side)) - Distance(square, |
- | |
1019 | KingSQ(enemy))) * pp_dist_bonus[rank]; |
- | |
1020 | } |
1063 | } |
1021 | /* |
1064 | /* |
1022 | ************************************************************ |
1065 | ************************************************************ |
1023 | * * |
1066 | * * |
- | 1067 | * All pawns done, add score to the two evaluation values * |
|
1024 | * |
1068 | * and return. * |
1025 | * * |
1069 | * * |
1026 | ************************************************************ |
1070 | ************************************************************ |
1027 | */ |
1071 | */ |
1028 | if (tree->pawn_score.passed[side] |
- | |
1029 | && is_outside[tree->pawn_score.passed[side]] |
- | |
1030 | [tree->pawn_score.all[enemy]]) { |
- | |
1031 | score_mg += outside_passed[mg]; |
- | |
1032 | score_eg += outside_passed[eg]; |
- | |
1033 | } |
- | |
1034 | tree->score_mg += sign[side] * score_mg; |
1072 | tree->score_mg += sign[side] * score_mg; |
1035 | tree->score_eg += sign[side] * score_eg; |
1073 | tree->score_eg += sign[side] * score_eg; |
1036 | } |
1074 | } |
1037 | 1075 | ||
1038 | /* last modified |
1076 | /* last modified 11/27/15 */ |
1039 | /* |
1077 | /* |
1040 | ******************************************************************************* |
1078 | ******************************************************************************* |
1041 | * * |
1079 | * * |
1042 | * EvaluatePassedPawnRaces() is used to evaluate passed pawns when one * |
1080 | * EvaluatePassedPawnRaces() is used to evaluate passed pawns when one * |
1043 | * side has passed pawns and the other side (or neither) has pieces. In * |
1081 | * side has passed pawns and the other side (or neither) has pieces. In * |
1044 | * such a case, the critical question is can the defending king stop the |
1082 | * such a case, the critical question is can the defending king stop the * |
1045 | * from queening or is it too far away? If only one side has pawns |
1083 | * pawn from queening or is it too far away? If only one side has pawns * |
1046 | * "run" then the situation is simple. When both sides have pawns |
1084 | * that can "run" then the situation is simple. When both sides have pawns * |
1047 | * "run" it becomes more complex as it then becomes necessary to |
1085 | * that can "run" it becomes more complex as it then becomes necessary to * |
1048 | * one side can use a forced king move to stop the other side, while |
1086 | * see if one side can use a forced king move to stop the other side, while * |
1049 | * other side doesn't have the same ability to stop ours. |
1087 | * the other side doesn't have the same ability to stop ours. * |
1050 | * * |
1088 | * * |
1051 | * In the case of king and pawn endings with exactly one pawn, the simple * |
1089 | * In the case of king and pawn endings with exactly one pawn, the simple * |
1052 | * evaluation rules are used: if the king is two squares in front of the * |
1090 | * evaluation rules are used: if the king is two squares in front of the * |
1053 | * pawn then it is a win, if the king is one one square in front with the * |
1091 | * pawn then it is a win, if the king is one one square in front with the * |
1054 | * opposition, then it is a win, if the king is on the 6th rank with the * |
1092 | * opposition, then it is a win, if the king is on the 6th rank with the * |
Line 1057... | Line 1095... | ||
1057 | * pawn blocking promotion. * |
1095 | * pawn blocking promotion. * |
1058 | * * |
1096 | * * |
1059 | ******************************************************************************* |
1097 | ******************************************************************************* |
1060 | */ |
1098 | */ |
1061 | void EvaluatePassedPawnRaces(TREE * RESTRICT tree, int wtm) { |
1099 | void EvaluatePassedPawnRaces(TREE * RESTRICT tree, int wtm) { |
1062 | int file, square; |
- | |
1063 | int queen_distance; |
- | |
1064 | int pawnsq; |
- | |
1065 | uint64_t pawns; |
1100 | uint64_t pawns, thispawn; |
1066 | int passed; |
- | |
1067 | int side, enemy; |
1101 | int file, square, queen_distance, pawnsq, passed, side, enemy; |
1068 | int queener[2] = { 8, 8 }; |
1102 | int queener[2] = { 8, 8 }; |
1069 | int forced_km[2] = { 0, 0 }; |
- | |
1070 | /* |
1103 | /* |
1071 | ************************************************************ |
1104 | ************************************************************ |
1072 | * * |
1105 | * * |
1073 | * Check to see if side has one pawn and neither side has * |
1106 | * Check to see if side has one pawn and neither side has * |
1074 | * any pieces. If so, use the simple pawn evaluation * |
1107 | * any pieces. If so, use the simple pawn evaluation * |
Line 1133... | Line 1166... | ||
1133 | if (sign[side] * Rank(KingSQ(side)) > |
1166 | if (sign[side] * Rank(KingSQ(side)) > |
1134 | sign[side] * (Rank(pawnsq) - 1 + 2 * side)) { |
1167 | sign[side] * (Rank(pawnsq) - 1 + 2 * side)) { |
1135 | tree->score_eg += sign[side] * pawn_can_promote; |
1168 | tree->score_eg += sign[side] * pawn_can_promote; |
1136 | return; |
1169 | return; |
1137 | } |
1170 | } |
1138 | if (Rank(KingSQ(side)) == |
1171 | if (Rank(KingSQ(side)) == rank6[side]) { |
1139 | tree->score_eg += sign[side] * pawn_can_promote; |
1172 | tree->score_eg += sign[side] * pawn_can_promote; |
1140 | return; |
1173 | return; |
1141 | } |
1174 | } |
1142 | /* |
1175 | /* |
1143 | ************************************************************ |
1176 | ************************************************************ |
Line 1167... | Line 1200... | ||
1167 | */ |
1200 | */ |
1168 | if (TotalPieces(enemy, occupied) == 0 && tree->pawn_score.passed[side]) { |
1201 | if (TotalPieces(enemy, occupied) == 0 && tree->pawn_score.passed[side]) { |
1169 | passed = tree->pawn_score.passed[side]; |
1202 | passed = tree->pawn_score.passed[side]; |
1170 | for (; passed; passed &= passed - 1) { |
1203 | for (; passed; passed &= passed - 1) { |
1171 | file = LSB8Bit(passed); |
1204 | file = LSB8Bit(passed); |
1172 |
|
1205 | thispawn = Pawns(side) & file_mask[file]; |
1173 |
|
1206 | if (thispawn) { |
1174 |
|
1207 | square = MostAdvanced(side, thispawn); |
1175 | (pawn_race[side][Flip(wtm)][square] & Kings(enemy)); |
- | |
1176 | if (!(pawn_race[side][wtm][square] & Kings(enemy))) { |
1208 | if (!(pawn_race[side][wtm][square] & Kings(enemy))) { |
1177 | queen_distance |
1209 | queen_distance = Abs(rank8[side] - Rank(square)); |
1178 | if (Kings(side) & ((side) ? plus8dir[square] : minus8dir[square])) { |
1210 | if (Kings(side) & ((side) ? plus8dir[square] : minus8dir[square])) { |
1179 | if (file == FILEA || file == FILEH) |
1211 | if (file == FILEA || file == FILEH) |
1180 | queen_distance = 99; |
1212 | queen_distance = 99; |
1181 | queen_distance++; |
1213 | queen_distance++; |
- | 1214 | } |
|
- | 1215 | if (Rank(square) == rank2[side]) |
|
- | 1216 | queen_distance--; |
|
- | 1217 | if (queen_distance < queener[side]) |
|
- | 1218 | queener[side] = queen_distance; |
|
1182 | } |
1219 | } |
1183 | if (Rank(square) == rankflip[side][RANK2]) |
- | |
1184 | queen_distance--; |
- | |
1185 | if (queen_distance < queener[side]) |
- | |
1186 | queener[side] = queen_distance; |
- | |
1187 | } |
1220 | } |
1188 | } |
1221 | } |
1189 | } |
1222 | } |
1190 | } |
1223 | } |
1191 | if (queener[white] == 8 && queener[black] == 8) |
- | |
1192 | return; |
- | |
1193 | /* |
1224 | /* |
1194 | ************************************************************ |
1225 | ************************************************************ |
1195 | * * |
1226 | * * |
1196 | * Now that we know which pawns can outrun the kings for * |
1227 | * Now that we know which pawns can outrun the kings for * |
1197 | * each side, we need to do |
1228 | * each side, we need to do determine if one side queens * |
1198 | * |
1229 | * before the other. If so, that side wins. If they * |
1199 | * |
1230 | * queen at the same time, then we will have to rely on * |
1200 | * prevent the opponent from promoting, we let the * |
- | |
1201 | * |
1231 | * the search to handle queening with check or queening * |
1202 | * * |
- | |
1203 | * (2) If white can run while black can not, then white * |
- | |
1204 | * wins, or vice-versa. * |
- | |
1205 | * * |
- | |
1206 | * (3) If white queens and black's king can't stop it * |
- | |
1207 | * no matter who moves first, while black has a pawn * |
- | |
1208 | * |
1232 | * and attacking the opponent's queening square. * |
1209 | * immediately, then white wins, and vice-versa. * |
- | |
1210 | * * |
- | |
1211 | * (4) Other situations are left to the search to * |
- | |
1212 | * resolve. * |
- | |
1213 | * * |
1233 | * * |
1214 | ************************************************************ |
1234 | ************************************************************ |
1215 | */ |
1235 | */ |
1216 | if (forced_km[white] & forced_km[black]) |
- | |
1217 | return; |
- | |
1218 | if (queener[white] < |
1236 | if (queener[white] < queener[black]) |
1219 | tree->score_eg += pawn_can_promote + (5 - queener[white]) * 10; |
1237 | tree->score_eg += pawn_can_promote + (5 - queener[white]) * 10; |
1220 | return; |
- | |
1221 |
|
1238 | else if (queener[black] < queener[white]) |
1222 | tree->score_eg += -(pawn_can_promote + (5 - queener[black]) * 10); |
- | |
1223 | return; |
- | |
1224 | } |
- | |
1225 | if (queener[white] < queener[black] && forced_km[white]) { |
- | |
1226 | tree->score_eg += pawn_can_promote + (5 - queener[white]) * 10; |
- | |
1227 | return; |
- | |
1228 | } else if (queener[black] < queener[white] && forced_km[white]) { |
- | |
1229 | tree->score_eg |
1239 | tree->score_eg -= pawn_can_promote + (5 - queener[black]) * 10; |
1230 | return; |
- | |
1231 | } |
- | |
1232 | } |
1240 | } |
1233 | 1241 | ||
1234 | /* last modified |
1242 | /* last modified 11/27/15 */ |
1235 | /* |
1243 | /* |
1236 | ******************************************************************************* |
1244 | ******************************************************************************* |
1237 | * * |
1245 | * * |
1238 | * EvaluatePawns() is used to evaluate pawns. It evaluates pawns for only * |
1246 | * EvaluatePawns() is used to evaluate pawns. It evaluates pawns for only * |
1239 | * one side, and fills in the pawn hash entry information. It requires two * |
1247 | * one side, and fills in the pawn hash entry information. It requires two * |
1240 | * calls to evaluate all pawns on the board. Comments below indicate the * |
1248 | * calls to evaluate all pawns on the board. Comments below indicate the * |
1241 | * particular pawn structure features that are evaluated. * |
1249 | * particular pawn structure features that are evaluated. * |
1242 | * * |
1250 | * * |
1243 | * This procedure also |
1251 | * This procedure also flags which pawns are passed, since this is scored in * |
- | 1252 | * another part of the evaluation because that includes piece information * |
|
1244 | * |
1253 | * which can not be used here since the pawn hash signature does not include * |
- | 1254 | * piece information of any kind. * |
|
1245 | * |
1255 | * * |
- | 1256 | * Note that a pawn is not penalized for two different reasons. If it is * |
|
- | 1257 | * isolated, it is not backward. Etc. This simplifies evaluation tuning * |
|
- | 1258 | * not to mention eliminating the overlap and interaction that was happening * |
|
- | 1259 | * previously when multiple penalties could be applied. * |
|
1246 | * * |
1260 | * * |
1247 | ******************************************************************************* |
1261 | ******************************************************************************* |
1248 | */ |
1262 | */ |
1249 | void EvaluatePawns(TREE * RESTRICT tree, int side) { |
1263 | void EvaluatePawns(TREE * RESTRICT tree, int side) { |
1250 | uint64_t pawns; |
1264 | uint64_t pawns, attackers, defenders; |
1251 | uint64_t temp; |
- | |
1252 | uint64_t |
1265 | uint64_t doubled, supported, connected, passed, backward; |
1253 | int square, file, rank, score_eg = 0, score_mg = 0; |
1266 | int square, file, rank, score_eg = 0, score_mg = 0, enemy = Flip(side); |
1254 | int |
1267 | unsigned int isolated, pawn_files = 0; |
1255 | int enemy = Flip(side); |
- | |
1256 | 1268 | ||
1257 | /* |
1269 | /* |
1258 | ************************************************************ |
1270 | ************************************************************ |
1259 | * * |
1271 | * * |
1260 | * |
1272 | * Loop through all pawns for this side. * |
1261 | * * |
1273 | * * |
1262 | ************************************************************ |
1274 | ************************************************************ |
1263 | */ |
1275 | */ |
1264 | tree->pawn_score.all[side] = 0; |
- | |
1265 | tree->pawn_score.passed[side] = 0; |
1276 | tree->pawn_score.passed[side] = 0; |
1266 | /* |
- | |
1267 | ************************************************************ |
- | |
1268 | * * |
- | |
1269 | * First, determine which squares pawns can reach. * |
- | |
1270 | * * |
- | |
1271 | ************************************************************ |
- | |
1272 | */ |
- | |
1273 | p_moves[side] = 0; |
- | |
1274 | for (pawns = Pawns(side); pawns; pawns &= pawns - 1) { |
- | |
1275 | square = LSB(pawns); |
- | |
1276 | tree->pawn_score.all[side] |= 1 << File(square); |
- | |
1277 | for (sq = square; sq != File(square) + ((side) ? RANK7 << 3 : RANK2 << 3); |
- | |
1278 | sq += direction[side]) { |
- | |
1279 | p_moves[side] |= SetMask(sq); |
- | |
1280 | if (SetMask(sq + direction[side]) & tree->all_pawns) |
- | |
1281 | break; |
- | |
1282 | defenders = |
- | |
1283 | PopCnt(pawn_attacks[enemy][sq + direction[side]] & Pawns(side)); |
- | |
1284 | attackers = |
- | |
1285 | PopCnt(pawn_attacks[side][sq + direction[side]] & Pawns(enemy)); |
- | |
1286 | if (attackers - defenders > 0) |
- | |
1287 | break; |
- | |
1288 | } |
- | |
1289 | } |
- | |
1290 | /* |
- | |
1291 | ************************************************************ |
- | |
1292 | * * |
- | |
1293 | * Loop through all pawns for this side. * |
- | |
1294 | * * |
- | |
1295 | ************************************************************ |
- | |
1296 | */ |
- | |
1297 | for (pawns = Pawns(side); pawns; pawns &= pawns - 1) { |
1277 | for (pawns = Pawns(side); pawns; pawns &= pawns - 1) { |
1298 | square = LSB(pawns); |
1278 | square = LSB(pawns); |
1299 | file = File(square); |
1279 | file = File(square); |
1300 | rank = rankflip[side][Rank(square)]; |
1280 | rank = rankflip[side][Rank(square)]; |
- | 1281 | pawn_files |= 1 << file; |
|
1301 | /* |
1282 | /* |
1302 | ************************************************************ |
1283 | ************************************************************ |
1303 | * * |
1284 | * * |
1304 | * Evaluate pawn advances. Center pawns are encouraged to * |
1285 | * Evaluate pawn advances. Center pawns are encouraged to * |
1305 | * |
1286 | * occupy central squares, edge pawns are penalized on all * |
- | 1287 | * edge squares to encourage capture toward the center, * |
|
1306 | * |
1288 | * the rest are neutral. * |
1307 | * * |
1289 | * * |
1308 | ************************************************************ |
1290 | ************************************************************ |
1309 | */ |
1291 | */ |
1310 | score_mg += pval[mg][side][square]; |
1292 | score_mg += pval[mg][side][square]; |
1311 | score_eg += pval[eg][side][square]; |
1293 | score_eg += pval[eg][side][square]; |
1312 | /* |
1294 | /* |
1313 | ************************************************************ |
1295 | ************************************************************ |
1314 | * * |
1296 | * * |
1315 | * Evaluate isolated pawns, which |
1297 | * Evaluate isolated pawns, which are penalized based on * |
1316 | * the file, with central isolani being worse than when on * |
- | |
1317 | * |
1298 | * which file they occupy. * |
1318 | * * |
1299 | * * |
1319 | ************************************************************ |
1300 | ************************************************************ |
1320 | */ |
1301 | */ |
1321 |
|
1302 | isolated = !(Pawns(side) & mask_pawn_isolated[square]); |
1322 |
|
1303 | if (isolated) { |
1323 | score_eg -= pawn_isolated[eg]; |
- | |
1324 | if (!(Pawns(enemy) & file_mask[file])) { |
- | |
1325 |
|
1304 | score_mg -= pawn_isolated[mg][file]; |
1326 |
|
1305 | score_eg -= pawn_isolated[eg][file]; |
1327 | } |
- | |
1328 | } |
1306 | } |
1329 | /* |
1307 | /* |
1330 | ************************************************************ |
1308 | ************************************************************ |
1331 | * * |
1309 | * * |
1332 | * Evaluate |
1310 | * Evaluate unsupported pawns, which provide a target * |
1333 | * |
1311 | * since they are undefended by a pawn. We exclude pawns * |
1334 | * it isn't weak; (2) if a pawn is undefended by a pawn * |
- | |
1335 | * and advances one (or two if it hasn't moved yet) ranks * |
- | |
1336 | * and is defended fewer times than it is attacked, it is * |
- | |
1337 | * weak. Note that the penalty is greater if the pawn is * |
- | |
1338 | * |
1312 | * that are isolated since they have already been given a * |
1339 | * another case of a weak pawn, since it can never be * |
- | |
1340 | * defended by a pawn. * |
- | |
1341 | * |
1313 | * penalty. * |
1342 | * First, test the pawn where it sits to determine if it * |
- | |
1343 | * is defended more times than attacked. If so, it is not * |
- | |
1344 | * weak and we are done. If it is weak where it sits, can * |
- | |
1345 | * it advance one square and become not weak. If so we * |
- | |
1346 | * are again finished with this pawn. Otherwise we fall * |
- | |
1347 | * into the next test. * |
- | |
1348 | * * |
1314 | * * |
1349 | ************************************************************ |
1315 | ************************************************************ |
1350 | */ |
1316 | */ |
1351 | else { |
- | |
1352 | do { |
- | |
1353 | attackers = 0; |
- | |
1354 | defenders = 0; |
- | |
1355 | temp = |
- | |
1356 |
|
1317 | supported = Pawns(side) & pawn_attacks[enemy][square]; |
1357 |
|
1318 | if (!isolated && !supported) { |
1358 |
|
1319 | score_mg += pawn_unsupported[mg]; |
1359 | defenders = PopCnt(pawn_attacks[enemy][sq] & Pawns(side)); |
- | |
1360 | attackers = PopCnt(pawn_attacks[side][sq] & Pawns(enemy)); |
- | |
1361 |
|
1320 | score_eg += pawn_unsupported[eg]; |
1362 | break; |
- | |
1363 |
|
1321 | } |
1364 | if (defenders && defenders >= attackers) |
- | |
1365 | break; |
- | |
1366 | /* |
1322 | /* |
1367 | ************************************************************ |
1323 | ************************************************************ |
1368 | * * |
1324 | * * |
- | 1325 | * Evaluate doubled pawns. If there are other pawns on * |
|
1369 | * |
1326 | * this file in front of this pawn, penalize this pawn. * |
- | 1327 | * Note that this will NOT penalize both pawns, just the * |
|
- | 1328 | * most rearward one that is really almost worthless. * |
|
- | 1329 | * * |
|
1370 | * |
1330 | * The farther apart two doubled pawns (same file) are, * |
- | 1331 | * the less weak they are, so the penalty is reduced as * |
|
1371 | * this |
1332 | * this distance increases. * |
1372 | * * |
1333 | * * |
1373 | ************************************************************ |
1334 | ************************************************************ |
1374 | */ |
1335 | */ |
1375 |
|
1336 | doubled = Pawns(side) & ((side) ? plus8dir[square] : minus8dir[square]); |
1376 |
|
1337 | if (doubled) { |
1377 |
|
1338 | score_mg -= |
1378 |
|
1339 | pawn_doubled[mg][file] / RankDistance(square, MostAdvanced(side, |
1379 |
|
1340 | doubled)); |
1380 |
|
1341 | score_eg -= |
- | 1342 | pawn_doubled[eg][file] / RankDistance(square, MostAdvanced(side, |
|
1381 |
|
1343 | doubled)); |
- | 1344 | } |
|
1382 | /* |
1345 | /* |
1383 | ************************************************************ |
1346 | ************************************************************ |
1384 | * * |
1347 | * * |
1385 | * |
1348 | * Test the pawn to see if it is connected to a neighbor * |
1386 | * |
1349 | * which makes it easier to defend. * |
1387 | * * |
1350 | * * |
1388 | ************************************************************ |
1351 | ************************************************************ |
1389 | */ |
1352 | */ |
1390 |
|
1353 | connected = Pawns(side) & mask_pawn_connected[side][square]; |
- | 1354 | if (connected) { |
|
1391 |
|
1355 | score_mg += pawn_connected[rank][file]; |
1392 |
|
1356 | score_eg += pawn_connected[rank][file]; |
1393 |
|
1357 | } |
1394 | /* |
1358 | /* |
1395 | ************************************************************ |
1359 | ************************************************************ |
1396 | * * |
1360 | * * |
1397 | * |
1361 | * Flag passed pawns for use later when we finally call * |
1398 | * |
1362 | * EvaluatePassedPawns. * |
1399 | * * |
1363 | * * |
1400 | ************************************************************ |
1364 | ************************************************************ |
1401 | */ |
1365 | */ |
1402 |
|
1366 | passed = !(Pawns(enemy) & mask_passed[side][square]); |
1403 |
|
1367 | if (passed) |
1404 |
|
1368 | tree->pawn_score.passed[side] |= 1 << file; |
1405 | } |
- | |
1406 | } |
- | |
1407 | /* |
1369 | /* |
1408 | ************************************************************ |
1370 | ************************************************************ |
1409 | * * |
1371 | * * |
- | 1372 | * Test the pawn to see if it is backward which makes it a * |
|
1410 | * |
1373 | * target that ties down pieces to defend it. * |
1411 | * * |
1374 | * * |
1412 | ************************************************************ |
1375 | ************************************************************ |
1413 | */ |
1376 | */ |
- | 1377 | backward = 0; |
|
- | 1378 | if (!(passed | isolated | connected | (Pawns(side) & |
|
1414 |
|
1379 | mask_pattacks[side][square]) | (Pawns(enemy) & |
- | 1380 | PawnAttacks(side, square)))) |
|
- | 1381 | backward = Pawns(enemy) & PawnAttacks(side, square + direction[side]); |
|
- | 1382 | if (backward) { |
|
- | 1383 | score_mg -= pawn_backward[mg][file]; |
|
1415 |
|
1384 | score_eg -= pawn_backward[eg][file]; |
- | 1385 | } |
|
1416 | /* |
1386 | /* |
1417 | ************************************************************ |
1387 | ************************************************************ |
1418 | * * |
1388 | * * |
1419 | * Determine if this pawn is a candidate |
1389 | * Determine if this pawn is a candidate passed pawn, * |
1420 | * |
1390 | * which is a pawn on a file with no enemy pawns in front * |
1421 | * |
1391 | * of it, and if it advances until it contacts an enemy * |
1422 | * |
1392 | * pawn, and it is defended at least as many times as it * |
1423 | * |
1393 | * is attacked when it reaches that pawn, then it will end * |
1424 | * reaches that pawn, then all that is left is to see if * |
- | |
1425 | * |
1394 | * up passed. * |
1426 | * * |
1395 | * * |
1427 | ************************************************************ |
1396 | ************************************************************ |
1428 | */ |
1397 | */ |
1429 |
|
1398 | if (!(passed | backward | isolated) && |
1430 | && mask_pawn_isolated[square] & Pawns(side) |
- | |
1431 |
|
1399 | !(Pawns(enemy) & ((side) ? plus8dir[square] : minus8dir[square]))) { |
1432 | attackers = 1; |
- | |
1433 | defenders = 0; |
- | |
1434 | for (sq = square; |
- | |
1435 | sq != File(square) + ((side) ? RANK7 << 3 : RANK2 << 3); |
- | |
1436 | sq += direction[side]) { |
- | |
1437 | if (SetMask(sq + direction[side]) & tree->all_pawns) |
- | |
1438 | break; |
- | |
1439 |
|
1400 | defenders = mask_pattacks[side][square + direction[side]] & Pawns(side); |
1440 |
|
1401 | attackers = mask_pattacks[enemy][square] & Pawns(enemy); |
1441 | if (attackers) |
- | |
1442 | break; |
- | |
1443 | } |
- | |
1444 | if ( |
1402 | if (PopCnt(defenders) >= PopCnt(attackers)) { |
1445 | if (!(mask_passed[side][sq + direction[side]] & Pawns(enemy))) { |
- | |
1446 |
|
1403 | score_mg += passed_pawn_candidate[mg][rank]; |
1447 |
|
1404 | score_eg += passed_pawn_candidate[eg][rank]; |
1448 | } |
- | |
1449 | } |
1405 | } |
1450 | } |
1406 | } |
- | 1407 | } |
|
1451 | /* |
1408 | /* |
1452 | ************************************************************ |
1409 | ************************************************************ |
1453 | * * |
1410 | * * |
1454 | * |
1411 | * Give a bonus for distance between left-most pawn and * |
1455 | * |
1412 | * right-most pawn. The idea is that the wider the gap * |
1456 | * |
1413 | * between the pawns, the harder they are for a lone king * |
- | 1414 | * to control in the endgame. Botvinnik referred to this * |
|
- | 1415 | * concept as "trousers" (pants with two legs, the farther * |
|
1457 | * |
1416 | * the legs are apart, the better for the side with those * |
1458 | * |
1417 | * pawns). * |
1459 | * * |
1418 | * * |
1460 | ************************************************************ |
1419 | ************************************************************ |
1461 | */ |
1420 | */ |
1462 | if (Rank(square) == ((side) ? RANK6 : RANK3) |
- | |
1463 | && SetMask(square + direction[side]) & Pawns(enemy) |
- | |
1464 | && ((File(square) < FILEH && |
- | |
1465 | SetMask(square + 9 - 16 * side) & Pawns(side) |
- | |
1466 |
|
1421 | score_eg += pawn_file_width * (MSB8Bit(pawn_files) - LSB8Bit(pawn_files)); |
1467 | || (File(square) > FILEA && |
- | |
1468 | SetMask(square + 7 - 16 * side) & Pawns(side) |
- | |
1469 | && !(mask_hidden_left[side][File(square)] & Pawns(enemy))))) { |
- | |
1470 | score_mg += passed_pawn_hidden[mg]; |
- | |
1471 | score_eg += passed_pawn_hidden[eg]; |
- | |
1472 | } |
- | |
1473 | } |
- | |
1474 | /* |
1422 | /* |
1475 | ************************************************************ |
1423 | ************************************************************ |
1476 | * * |
1424 | * * |
1477 | * Evaluate king safety. * |
1425 | * Evaluate king safety. * |
1478 | * * |
1426 | * * |
1479 | * This uses the function EvaluateKingsFile() |
1427 | * This uses the function EvaluateKingsFile() and looks at * |
1480 | * |
1428 | * three possible positions for the king, either castled * |
1481 | * kingside, queenside or else standing on the d or e file * |
1429 | * kingside, queenside or else standing on the d or e file * |
1482 | * stuck in the middle. This essentially is about the * |
1430 | * stuck in the middle. This essentially is about the * |
1483 | * pawns in front of the king and what kind of "shelter" * |
1431 | * pawns in front of the king and what kind of "shelter" * |
1484 | * they provide for the king during the middlegame. * |
1432 | * they provide for the king during the middlegame. * |
1485 | * * |
1433 | * * |
1486 | ************************************************************ |
1434 | ************************************************************ |
1487 | */ |
1435 | */ |
1488 | tree->pawn_score.defects_q[side] = |
1436 | tree->pawn_score.defects_q[side] = |
- | 1437 | EvaluateKingsFile(tree, side, FILEA, FILEC); |
|
1489 | tree->pawn_score. |
1438 | tree->pawn_score.defects_m[side] = |
1490 |
|
1439 | EvaluateKingsFile(tree, side, FILEC, FILEF); |
1491 | tree->pawn_score.defects_k[side] = |
1440 | tree->pawn_score.defects_k[side] = |
- | 1441 | EvaluateKingsFile(tree, side, FILEF, FILEH); |
|
- | 1442 | /* |
|
- | 1443 | ************************************************************ |
|
- | 1444 | * * |
|
- | 1445 | * Done. Add mg/eg scores to final result (sign-corrected * |
|
- | 1446 | * so that black = -, white = +) and return. * |
|
- | 1447 | * * |
|
- | 1448 | ************************************************************ |
|
- | 1449 | */ |
|
1492 | tree->pawn_score.score_mg += sign[side] * score_mg; |
1450 | tree->pawn_score.score_mg += sign[side] * score_mg; |
1493 | tree->pawn_score.score_eg += sign[side] * score_eg; |
1451 | tree->pawn_score.score_eg += sign[side] * score_eg; |
1494 | } |
1452 | } |
1495 | 1453 | ||
1496 | /* last modified |
1454 | /* last modified 10/19/15 */ |
1497 | /* |
1455 | /* |
1498 | ******************************************************************************* |
1456 | ******************************************************************************* |
1499 | * * |
1457 | * * |
1500 | * EvaluateQueens() is used to evaluate queens. * |
1458 | * EvaluateQueens() is used to evaluate queens. * |
1501 | * * |
1459 | * * |
1502 | ******************************************************************************* |
1460 | ******************************************************************************* |
1503 | */ |
1461 | */ |
1504 | void EvaluateQueens(TREE * RESTRICT tree, int side) { |
1462 | void EvaluateQueens(TREE * RESTRICT tree, int side) { |
1505 | uint64_t temp; |
1463 | uint64_t temp; |
1506 | int square, |
1464 | int square, i, score_mg = 0, score_eg = 0, enemy = Flip(side); |
1507 | int enemy = Flip(side); |
- | |
1508 | 1465 | ||
1509 | /* |
1466 | /* |
1510 | ************************************************************ |
1467 | ************************************************************ |
1511 | * * |
1468 | * * |
1512 | * First locate each queen and obtain it's centralization * |
1469 | * First locate each queen and obtain it's centralization * |
Line 1532... | Line 1489... | ||
1532 | * Adjust the tropism count for this piece. * |
1489 | * Adjust the tropism count for this piece. * |
1533 | * * |
1490 | * * |
1534 | ************************************************************ |
1491 | ************************************************************ |
1535 | */ |
1492 | */ |
1536 | if (tree->dangerous[side]) { |
1493 | if (tree->dangerous[side]) { |
1537 |
|
1494 | i = KingSQ(enemy); |
1538 | tree->tropism[side] += king_tropism_q[Distance(square, |
1495 | tree->tropism[side] += king_tropism_q[Distance(square, i)]; |
1539 |
|
1496 | i = 8 - (RankDistance(square, i) + FileDistance(square, i)); |
1540 | score_mg += |
1497 | score_mg += i; |
1541 | score_eg += |
1498 | score_eg += i; |
1542 | } |
1499 | } |
1543 | } |
1500 | } |
1544 | tree->score_mg += sign[side] * score_mg; |
1501 | tree->score_mg += sign[side] * score_mg; |
1545 | tree->score_eg += sign[side] * score_eg; |
1502 | tree->score_eg += sign[side] * score_eg; |
1546 | } |
1503 | } |
1547 | 1504 | ||
1548 | /* last modified |
1505 | /* last modified 10/19/15 */ |
1549 | /* |
1506 | /* |
1550 | ******************************************************************************* |
1507 | ******************************************************************************* |
1551 | * * |
1508 | * * |
1552 | * EvaluateRooks() is used to evaluate rooks. * |
1509 | * EvaluateRooks() is used to evaluate rooks. * |
1553 | * * |
1510 | * * |
1554 | ******************************************************************************* |
1511 | ******************************************************************************* |
1555 | */ |
1512 | */ |
1556 | void EvaluateRooks(TREE * RESTRICT tree, int side) { |
1513 | void EvaluateRooks(TREE * RESTRICT tree, int side) { |
1557 | uint64_t temp, moves; |
1514 | uint64_t temp, moves; |
1558 | int square, rank, |
1515 | int square, rank, file, i, mobility, score_mg = 0, score_eg = 0; |
1559 | int score_mg = 0, score_eg = 0; |
- | |
1560 | int enemy = Flip(side); |
1516 | int enemy = Flip(side); |
1561 | 1517 | ||
1562 | /* |
1518 | /* |
1563 | ************************************************************ |
1519 | ************************************************************ |
1564 | * * |
1520 | * * |
Line 1568... | Line 1524... | ||
1568 | */ |
1524 | */ |
1569 | for (temp = Rooks(side); temp; temp &= temp - 1) { |
1525 | for (temp = Rooks(side); temp; temp &= temp - 1) { |
1570 | square = LSB(temp); |
1526 | square = LSB(temp); |
1571 | file = File(square); |
1527 | file = File(square); |
1572 | rank = Rank(square); |
1528 | rank = Rank(square); |
1573 | fRank = rankflip[side][rank]; |
- | |
1574 | /* |
1529 | /* |
1575 | ************************************************************ |
1530 | ************************************************************ |
1576 | * * |
1531 | * * |
1577 | * Determine if the rook is on an open file or on a half- * |
1532 | * Determine if the rook is on an open file or on a half- * |
1578 | * open file, either of which increases its ability to * |
1533 | * open file, either of which increases its ability to * |
Line 1587... | Line 1542... | ||
1587 | } else { |
1542 | } else { |
1588 | score_mg += rook_half_open_file[mg]; |
1543 | score_mg += rook_half_open_file[mg]; |
1589 | score_eg += rook_half_open_file[eg]; |
1544 | score_eg += rook_half_open_file[eg]; |
1590 | } |
1545 | } |
1591 | } |
1546 | } |
- | 1547 | /* |
|
- | 1548 | ************************************************************ |
|
- | 1549 | * * |
|
- | 1550 | * Mobility counts the number of squares the rook attacks, * |
|
- | 1551 | * excluding squares with friendly pieces, and weighs each * |
|
- | 1552 | * square according to a complex formula that includes * |
|
- | 1553 | * files as well as total number of squares attacked. * |
|
- | 1554 | * * |
|
- | 1555 | ************************************************************ |
|
- | 1556 | */ |
|
- | 1557 | mobility = RookMobility(square, OccupiedSquares); |
|
- | 1558 | score_mg += mobility; |
|
- | 1559 | score_eg += mobility; |
|
1592 | /* |
1560 | /* |
1593 | ************************************************************ |
1561 | ************************************************************ |
1594 | * * |
1562 | * * |
1595 | * Check to see if the king has been forced to move and * |
1563 | * Check to see if the king has been forced to move and * |
1596 | * has trapped a rook at a1/b1/g1/h1, if so, then penalize * |
1564 | * has trapped a rook at a1/b1/g1/h1, if so, then penalize * |
1597 | * the trapped rook to help extricate it. |
1565 | * the trapped rook to help extricate it. We only need to * |
- | 1566 | * check this if the rooks mobility is very low. * |
|
1598 | * * |
1567 | * * |
1599 | ************************************************************ |
1568 | ************************************************************ |
1600 | */ |
1569 | */ |
1601 | if (fRank == RANK1) { |
- | |
1602 |
|
1570 | if (mobility < 0 && rank == rank1[side] && rank == Rank(KingSQ(side))) { |
1603 |
|
1571 | i = File(KingSQ(side)); |
1604 |
|
1572 | if (i > FILEE) { |
1605 |
|
1573 | if (file > i) { |
1606 | score_mg -= rook_trapped; |
- | |
1607 | score_eg -= rook_trapped; |
- | |
1608 | } |
- | |
1609 | } else if (i < FILED && file < i) { |
- | |
1610 | score_mg |
1574 | score_mg += mobility * 3; |
1611 | score_eg |
1575 | score_eg += mobility * 3; |
1612 | } |
1576 | } |
- | 1577 | } else if (i < FILED && file < i) { |
|
- | 1578 | score_mg += mobility * 3; |
|
- | 1579 | score_eg += mobility * 3; |
|
1613 | } |
1580 | } |
1614 | } |
1581 | } |
1615 | /* |
1582 | /* |
1616 | ************************************************************ |
1583 | ************************************************************ |
1617 | * * |
1584 | * * |
- | 1585 | * finally check to see if any rooks are on the 7th rank, * |
|
- | 1586 | * with the opponent having pawns on that rank or the * |
|
- | 1587 | * opponent's king being hemmed in on the 7th/8th rank. * |
|
1618 | * |
1588 | * If so, we give a bonus for the strong rook. If there * |
- | 1589 | * is another rook or queen on the 7th that is connected * |
|
- | 1590 | * with this one, then the positional advantage is even * |
|
1619 | * |
1591 | * stronger. * |
1620 | * * |
1592 | * * |
1621 | ************************************************************ |
1593 | ************************************************************ |
1622 | */ |
1594 | */ |
- | 1595 | else if (rank == rank7[side] && (Rank(KingSQ(enemy)) == rank8[side] |
|
1623 |
|
1596 | || Pawns(enemy) & rank_mask[rank])) { |
1624 | score_mg += rook_on_7th[mg]; |
1597 | score_mg += rook_on_7th[mg]; |
1625 | score_eg += rook_on_7th[eg]; |
1598 | score_eg += rook_on_7th[eg]; |
- | 1599 | if (RankAttacks(square) & (Queens(side) | Rooks(side))) { |
|
- | 1600 | score_mg += rook_connected_7th[mg]; |
|
- | 1601 | score_eg += rook_connected_7th[eg]; |
|
- | 1602 | } |
|
1626 | } |
1603 | } |
1627 | /* |
- | |
1628 | ************************************************************ |
- | |
1629 | * * |
- | |
1630 | * Mobility counts the number of squares the piece * |
- | |
1631 | * attacks, and weighs each square according to a complex * |
- | |
1632 | * formula that includes files as well as total number of * |
- | |
1633 | * squares attacked. * |
- | |
1634 | * * |
- | |
1635 | * For efficiency, we use a pre-computed mobility score * |
- | |
1636 | * that is accessed just like a magic attack generation. * |
- | |
1637 | * * |
- | |
1638 | ************************************************************ |
- | |
1639 | */ |
- | |
1640 | mobility = RookMobility(square, OccupiedSquares); |
- | |
1641 | score_mg += mobility; |
- | |
1642 | score_eg += mobility; |
- | |
1643 | /* |
1604 | /* |
1644 | ************************************************************ |
1605 | ************************************************************ |
1645 | * * |
1606 | * * |
1646 | * Adjust the tropism count for this piece. * |
1607 | * Adjust the tropism count for this piece. * |
1647 | * * |
1608 | * * |
1648 | ************************************************************ |
1609 | ************************************************************ |
1649 | */ |
1610 | */ |
1650 | if (tree->dangerous[side]) { |
1611 | if (tree->dangerous[side]) { |
1651 | moves = king_attacks[KingSQ(enemy)]; |
1612 | moves = king_attacks[KingSQ(enemy)]; |
1652 |
|
1613 | i = (rook_attacks[square] & moves && |
1653 | RookAttacks(square, |
1614 | RookAttacks(square, |
1654 | OccupiedSquares & ~(Queens(side) | |
1615 | OccupiedSquares & ~(Queens(side) | Rooks(side))) & moves) ? 1 : |
1655 |
|
1616 | Distance(square, KingSQ(enemy)); |
1656 | tree->tropism[side] += king_tropism_r[ |
1617 | tree->tropism[side] += king_tropism_r[i]; |
1657 | } |
1618 | } |
1658 | } |
1619 | } |
1659 | tree->score_mg += sign[side] * score_mg; |
1620 | tree->score_mg += sign[side] * score_mg; |
1660 | tree->score_eg += sign[side] * score_eg; |
1621 | tree->score_eg += sign[side] * score_eg; |
1661 | } |
1622 | } |
1662 | 1623 | ||
1663 | /* last modified |
1624 | /* last modified 01/03/15 */ |
1664 | /* |
1625 | /* |
1665 | ******************************************************************************* |
1626 | ******************************************************************************* |
1666 | * * |
1627 | * * |
1667 | * EvaluateWinningChances() is used to determine if one side has reached a * |
1628 | * EvaluateWinningChances() is used to determine if one side has reached a * |
1668 | * position which can not be won, period, even though side may be ahead in * |
1629 | * position which can not be won, period, even though side may be ahead in * |
1669 | * material in some way. * |
1630 | * material in some way. * |
1670 | * * |
1631 | * * |
1671 | * Return values: * |
1632 | * Return values: * |
1672 | * 0 -> side on move can not win. |
1633 | * 0 -> side on move can not win. * |
1673 | * 1 -> side on move can win. |
1634 | * 1 -> side on move can win. * |
1674 | * * |
1635 | * * |
1675 | ******************************************************************************* |
1636 | ******************************************************************************* |
1676 | */ |
1637 | */ |
1677 | int EvaluateWinningChances(TREE * RESTRICT tree, int side, int wtm) { |
1638 | int EvaluateWinningChances(TREE * RESTRICT tree, int side, int wtm) { |
1678 | int square, ekd, promote; |
1639 | int square, ekd, promote, majors, minors, enemy = Flip(side); |
1679 | int enemy = Flip(side); |
- | |
1680 | 1640 | ||
- | 1641 | if (!Pawns(side)) { |
|
1681 | /* |
1642 | /* |
1682 | ************************************************************ |
1643 | ************************************************************ |
1683 | * * |
1644 | * * |
1684 | * If side has a piece and no pawn, it can not possibly * |
1645 | * If side has a piece and no pawn, it can not possibly * |
1685 | * win. If side is a piece ahead, the only way it can win * |
1646 | * win. If side is a piece ahead, the only way it can win * |
Line 1687... | Line 1648... | ||
1687 | * board (special case to handle KRB vs KR which can be * |
1648 | * board (special case to handle KRB vs KR which can be * |
1688 | * won if the king gets trapped). * |
1649 | * won if the king gets trapped). * |
1689 | * * |
1650 | * * |
1690 | ************************************************************ |
1651 | ************************************************************ |
1691 | */ |
1652 | */ |
1692 | if (TotalPieces(side, pawn) == 0) { |
- | |
1693 | if (TotalPieces(side, occupied) <= 3) |
1653 | if (TotalPieces(side, occupied) <= 3) |
1694 | return 0; |
1654 | return 0; |
1695 | if (TotalPieces(side, occupied) - TotalPieces(enemy, occupied) <= 3 && |
1655 | if (TotalPieces(side, occupied) - TotalPieces(enemy, occupied) <= 3 && |
1696 | mask_not_edge & Kings(enemy)) |
1656 | mask_not_edge & Kings(enemy)) |
1697 | return 0; |
1657 | return 0; |
- | 1658 | /* |
|
- | 1659 | ************************************************************ |
|
- | 1660 | * * |
|
- | 1661 | * If one side is an exchange up, but has no pawns, then * |
|
- | 1662 | * that side can not possibly win. * |
|
- | 1663 | * * |
|
- | 1664 | ************************************************************ |
|
- | 1665 | */ |
|
- | 1666 | majors = |
|
- | 1667 | TotalPieces(white, rook) + 2 * TotalPieces(white, |
|
- | 1668 | queen) - TotalPieces(black, rook) - 2 * TotalPieces(black, queen); |
|
- | 1669 | if (Abs(majors) == 1) { |
|
- | 1670 | minors = |
|
- | 1671 | TotalPieces(black, knight) + TotalPieces(black, |
|
- | 1672 | bishop) - TotalPieces(white, knight) - TotalPieces(white, bishop); |
|
- | 1673 | if (majors == minors) |
|
- | 1674 | return 0; |
|
- | 1675 | } |
|
- | 1676 | } else { |
|
- | 1677 | /* |
|
- | 1678 | ************************************************************ |
|
- | 1679 | * * |
|
- | 1680 | * If neither side has any pieces, and both sides have * |
|
- | 1681 | * non-rookpawns, then either side can win. * |
|
- | 1682 | * * |
|
- | 1683 | ************************************************************ |
|
- | 1684 | */ |
|
- | 1685 | if (TotalPieces(white, occupied) == 0 && TotalPieces(black, occupied) == 0 |
|
- | 1686 | && Pawns(white) & not_rook_pawns && Pawns(black) & not_rook_pawns) |
|
- | 1687 | return 1; |
|
1698 | } |
1688 | } |
1699 | /* |
1689 | /* |
1700 | ************************************************************ |
1690 | ************************************************************ |
1701 | * * |
1691 | * * |
1702 | * If "side" has a pawn, then either the pawn had better * |
1692 | * If "side" has a pawn, then either the pawn had better * |
1703 | * not be a rook pawn, or else |
1693 | * not be a rook pawn, or else side had better have the * |
1704 | * right color bishop or any other piece, otherwise it is * |
1694 | * right color bishop or any other piece, otherwise it is * |
1705 | * not winnable if the enemy king can get to the queening * |
1695 | * not winnable if the enemy king can get to the queening * |
1706 | * square first. * |
1696 | * square first. * |
1707 | * * |
1697 | * * |
1708 | ************************************************************ |
1698 | ************************************************************ |
1709 | */ |
1699 | */ |
1710 |
|
1700 | if (!(Pawns(side) & not_rook_pawns)) |
1711 | do { |
1701 | do { |
1712 | if (TotalPieces(side, occupied) > 3 || (TotalPieces(side, occupied) == 3 |
1702 | if (TotalPieces(side, occupied) > 3 || (TotalPieces(side, occupied) == 3 |
1713 | && Knights(side))) |
1703 | && Knights(side))) |
1714 | continue; |
1704 | continue; |
1715 | if (file_mask[FILEA] & Pawns(side) && file_mask[FILEH] & Pawns(side)) |
1705 | if (file_mask[FILEA] & Pawns(side) && file_mask[FILEH] & Pawns(side)) |
Line 1730... | Line 1720... | ||
1730 | return 0; |
1720 | return 0; |
1731 | } while (0); |
1721 | } while (0); |
1732 | /* |
1722 | /* |
1733 | ************************************************************ |
1723 | ************************************************************ |
1734 | * * |
1724 | * * |
1735 | * Check to see if this is a KRP vs KR |
1725 | * Check to see if this is a KRP vs KR ending. If so, and * |
1736 | * |
1726 | * the losing king is in front of the passer, then this is * |
1737 | * |
1727 | * a drawish ending. * |
1738 | * * |
1728 | * * |
1739 | ************************************************************ |
1729 | ************************************************************ |
1740 | */ |
1730 | */ |
1741 | if (TotalPieces(side, pawn) == 1 && TotalPieces(enemy, pawn) == 0 && |
1731 | if (TotalPieces(side, pawn) == 1 && TotalPieces(enemy, pawn) == 0 && |
1742 |
|
1732 | TotalPieces(side, occupied) == 5 && TotalPieces(enemy, occupied) == 5) { |
1743 | || (TotalPieces(side, occupied) == 9 && |
- | |
1744 | TotalPieces(enemy, occupied) == 9))) { |
- | |
1745 | square = LSB(Pawns(side)); |
1733 | square = LSB(Pawns(side)); |
1746 | if (FileDistance(KingSQ(enemy), square) <= 1 && |
1734 | if (FileDistance(KingSQ(enemy), square) <= 1 && |
1747 | InFront(side, Rank(KingSQ(enemy)), Rank(square))) |
1735 | InFront(side, Rank(KingSQ(enemy)), Rank(square))) |
1748 | return 0; |
1736 | return 0; |
1749 | } |
1737 | } |
Line 1778... | Line 1766... | ||
1778 | ************************************************************ |
1766 | ************************************************************ |
1779 | */ |
1767 | */ |
1780 | if (TotalPieces(side, occupied) == 6 && !Bishops(side) |
1768 | if (TotalPieces(side, occupied) == 6 && !Bishops(side) |
1781 | && TotalPieces(enemy, occupied) + TotalPieces(enemy, pawn) == 0) |
1769 | && TotalPieces(enemy, occupied) + TotalPieces(enemy, pawn) == 0) |
1782 | return 0; |
1770 | return 0; |
- | 1771 | /* |
|
- | 1772 | ************************************************************ |
|
- | 1773 | * * |
|
- | 1774 | * If we make it through all the above tests, then "side" * |
|
- | 1775 | * can win so we return 1. * |
|
- | 1776 | * * |
|
- | 1777 | ************************************************************ |
|
- | 1778 | */ |
|
1783 | return 1; |
1779 | return 1; |
- | 1780 | } |
|
- | 1781 | ||
- | 1782 | /* |
|
- | 1783 | ******************************************************************************* |
|
- | 1784 | * * |
|
- | 1785 | * InitializeKingSafety() is used to initialize the king safety matrix. * |
|
- | 1786 | * This is set so that the matrix, indexed by king safety pawn structure * |
|
- | 1787 | * index and by king safety piece tropism, combines the two indices to * |
|
- | 1788 | * produce a single score. As either index rises, the king safety score * |
|
- | 1789 | * tracks along, but as both rise, the king safety score rises much more * |
|
- | 1790 | * quickly. * |
|
- | 1791 | * * |
|
- | 1792 | ******************************************************************************* |
|
- | 1793 | */ |
|
- | 1794 | void InitializeKingSafety() { |
|
- | 1795 | int safety, tropism; |
|
- | 1796 | ||
- | 1797 | for (safety = 0; safety < 16; safety++) { |
|
- | 1798 | for (tropism = 0; tropism < 16; tropism++) { |
|
- | 1799 | king_safety[safety][tropism] = |
|
- | 1800 | 180 * ((safety_vector[safety] + 100) * (tropism_vector[tropism] + |
|
- | 1801 | 100) / 100 - 100) / 100; |
|
- | 1802 | } |
|
- | 1803 | } |
|
1784 | } |
1804 | } |