Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
112 | pmbaty | 1 | #undef addBonus |
2 | #undef addMalus |
||
3 | #undef COLOR |
||
4 | #undef OPPCOLOR |
||
5 | |||
6 | #ifdef PERSPECTIVE_WHITE |
||
7 | #define COLOR WHITE |
||
8 | #define OPPCOLOR BLACK |
||
9 | #define addBonus(base, bonus) (base->balance += bonus); |
||
10 | #define addMalus(base, bonus) (base->balance -= bonus); |
||
11 | |||
12 | void evaluateWhiteKnight(const Position * position, |
||
13 | EvaluationBase * base, const Square square); |
||
14 | void evaluateWhiteBishop(const Position * position, |
||
15 | EvaluationBase * base, const Square square); |
||
16 | void evaluateWhiteRook(const Position * position, |
||
17 | EvaluationBase * base, const Square square); |
||
18 | void evaluateWhiteQueen(const Position * position, |
||
19 | EvaluationBase * base, const Square square); |
||
20 | void evaluateWhitePasser(const Position * position, |
||
21 | EvaluationBase * base, const Square square); |
||
22 | void evaluateWhitePawns(EvaluationBase * base); |
||
23 | int getPawnSafetyMalusOfWhiteKingFile(const Position * position, |
||
24 | const int file, |
||
25 | const Square kingSquare, |
||
26 | const int fileType); |
||
27 | |||
28 | #else |
||
29 | #define COLOR BLACK |
||
30 | #define OPPCOLOR WHITE |
||
31 | #define addBonus(base, bonus) (base->balance -= bonus); |
||
32 | #define addMalus(base, bonus) (base->balance += bonus); |
||
33 | |||
34 | void evaluateBlackKnight(const Position * position, |
||
35 | EvaluationBase * base, const Square square); |
||
36 | void evaluateBlackBishop(const Position * position, |
||
37 | EvaluationBase * base, const Square square); |
||
38 | void evaluateBlackRook(const Position * position, |
||
39 | EvaluationBase * base, const Square square); |
||
40 | void evaluateBlackQueen(const Position * position, |
||
41 | EvaluationBase * base, const Square square); |
||
42 | void evaluateBlackPasser(const Position * position, |
||
43 | EvaluationBase * base, const Square square); |
||
44 | void evaluateBlackPawns(EvaluationBase * base); |
||
45 | int getPawnSafetyMalusOfBlackKingFile(const Position * position, |
||
46 | const int file, |
||
47 | const Square kingSquare, |
||
48 | const int fileType); |
||
49 | |||
50 | #endif |
||
51 | |||
52 | #ifdef PERSPECTIVE_WHITE |
||
53 | static void addWhitePieceAttackBonus(const Position * position, |
||
54 | EvaluationBase * base, |
||
55 | const Bitboard moves, |
||
56 | const Bitboard candidateTargets, |
||
57 | const Piece attacker) |
||
58 | #else |
||
59 | static void addBlackPieceAttackBonus(const Position * position, |
||
60 | EvaluationBase * base, |
||
61 | const Bitboard moves, |
||
62 | const Bitboard candidateTargets, |
||
63 | const Piece attacker) |
||
64 | #endif |
||
65 | { |
||
66 | Bitboard targets = moves & candidateTargets; |
||
67 | Square targetSquare; |
||
68 | |||
69 | ITERATE_BITBOARD(&targets, targetSquare) |
||
70 | { |
||
71 | const Piece target = position->piece[targetSquare]; |
||
72 | |||
73 | addBonus(base, piecePieceAttackBonus[attacker][target]); |
||
74 | } |
||
75 | } |
||
76 | |||
77 | #ifdef PERSPECTIVE_WHITE |
||
78 | void evaluateWhiteKnight(const Position * position, |
||
79 | EvaluationBase * base, const Square square) |
||
80 | #else |
||
81 | void evaluateBlackKnight(const Position * position, |
||
82 | EvaluationBase * base, const Square square) |
||
83 | #endif |
||
84 | { |
||
85 | const Square pinningPiece = getPinningPiece(position, base, square, COLOR); |
||
86 | const Bitboard moves = |
||
87 | (pinningPiece == NO_SQUARE ? getKnightMoves(square) : EMPTY_BITBOARD); |
||
88 | const Bitboard ctm = position->piecesOfType[PAWN | OPPCOLOR] | |
||
89 | position->piecesOfType[BISHOP | OPPCOLOR]; |
||
90 | const Bitboard cth = position->piecesOfType[ROOK | OPPCOLOR] | |
||
91 | position->piecesOfType[QUEEN | OPPCOLOR]; |
||
92 | const Bitboard candidateTargets = cth | |
||
93 | (ctm & base->unprotectedPieces[OPPCOLOR]); |
||
94 | |||
95 | #ifdef PERSPECTIVE_WHITE |
||
96 | const Square relativeSquare = square; |
||
97 | #else |
||
98 | const Square relativeSquare = getFlippedSquare(square); |
||
99 | #endif |
||
100 | |||
101 | if (pinningPiece == NO_SQUARE) |
||
102 | { |
||
103 | const Bitboard mobSquares = base->countedSquares[COLOR] | |
||
104 | getNonPawnPieces(position, OPPCOLOR); |
||
105 | const int mobilityCount = getNumberOfSetSquares(moves & mobSquares); |
||
106 | |||
107 | assert(mobilityCount <= MAX_MOVES_KNIGHT); |
||
108 | |||
109 | addBonus(base, KnightMobilityBonus[mobilityCount]); |
||
110 | } |
||
111 | else |
||
112 | { |
||
113 | setSquare(base->pinnedPieces[COLOR], square); |
||
114 | } |
||
115 | |||
116 | base->knightAttackedSquares[COLOR] |= moves; |
||
117 | |||
118 | if (position->piecesOfType[KNIGHT | OPPCOLOR] == EMPTY_BITBOARD && |
||
119 | position->piecesOfType[BISHOP | OPPCOLOR] != EMPTY_BITBOARD && |
||
120 | hasAttackingBishop(position, OPPCOLOR, square) == FALSE) |
||
121 | { |
||
122 | addBonus(base, V(2, 2)); |
||
123 | } |
||
124 | |||
125 | if (squareIsPawnSafe(base, COLOR, square) && |
||
126 | BONUS_KNIGHT_OUTPOST[relativeSquare] > 0) |
||
127 | { |
||
128 | int bonusValue = BONUS_KNIGHT_OUTPOST[relativeSquare]; |
||
129 | |||
130 | if (testSquare(base->pawnProtectedSquares[COLOR], square)) |
||
131 | { |
||
132 | if (position->piecesOfType[KNIGHT | OPPCOLOR] == EMPTY_BITBOARD && |
||
133 | hasAttackingBishop(position, OPPCOLOR, square) == FALSE) |
||
134 | { |
||
135 | bonusValue += bonusValue + bonusValue / 2; |
||
136 | } |
||
137 | else |
||
138 | { |
||
139 | bonusValue += bonusValue; |
||
140 | } |
||
141 | } |
||
142 | |||
143 | addBonus(base, V(bonusValue, bonusValue)); |
||
144 | } |
||
145 | |||
146 | if (base->evaluateKingSafety[OPPCOLOR] && |
||
147 | (moves & base->kingAttackSquares[OPPCOLOR]) != EMPTY_BITBOARD) |
||
148 | { |
||
149 | const Bitboard coronaAttacks = |
||
150 | moves & getKingMoves(position->king[OPPCOLOR]); |
||
151 | |||
152 | base->kingSquaresAttackCount[COLOR] += |
||
153 | getNumberOfSetSquares(coronaAttacks); |
||
154 | base->attackInfo[COLOR] += V(KNIGHT_BONUS_ATTACK, 1); |
||
155 | } |
||
156 | |||
157 | #ifdef PERSPECTIVE_WHITE |
||
158 | addWhitePieceAttackBonus(position, base, moves, candidateTargets, |
||
159 | WHITE_KNIGHT); |
||
160 | #else |
||
161 | addBlackPieceAttackBonus(position, base, moves, candidateTargets, |
||
162 | BLACK_KNIGHT); |
||
163 | #endif |
||
164 | |||
165 | if (testSquare(base->pawnProtectedSquares[OPPCOLOR], square)) |
||
166 | { |
||
167 | addMalus(base, piecePieceAttackBonus[PAWN | OPPCOLOR][KNIGHT | COLOR]); |
||
168 | } |
||
169 | } |
||
170 | |||
171 | #ifdef PERSPECTIVE_WHITE |
||
172 | void evaluateWhiteBishop(const Position * position, |
||
173 | EvaluationBase * base, const Square square) |
||
174 | #else |
||
175 | void evaluateBlackBishop(const Position * position, |
||
176 | EvaluationBase * base, const Square square) |
||
177 | #endif |
||
178 | { |
||
179 | const Square pinningPiece = getPinningPiece(position, base, square, COLOR); |
||
180 | const Bitboard xrayPieces = position->piecesOfType[QUEEN | COLOR]; |
||
181 | const Bitboard moves = |
||
182 | (pinningPiece == NO_SQUARE ? |
||
183 | getMagicBishopMoves(square, position->allPieces & ~xrayPieces) : |
||
184 | getMagicBishopMoves(square, position->allPieces & ~xrayPieces) & |
||
185 | (squaresBetween[pinningPiece][position->king[COLOR]] | |
||
186 | minValue[pinningPiece])); |
||
187 | const Bitboard mobSquares = base->countedSquares[COLOR] | |
||
188 | getNonPawnPieces(position, OPPCOLOR); |
||
189 | const Bitboard bishopSquares = |
||
190 | (testSquare(lightSquares, square) ? lightSquares : darkSquares); |
||
191 | const Bitboard squareColorTargets = |
||
192 | position->piecesOfType[PAWN | OPPCOLOR] & squaresBelow[COLOR][square] & |
||
193 | base->unprotectedPieces[OPPCOLOR] & bishopSquares; |
||
194 | const Bitboard ctm = position->piecesOfType[PAWN | OPPCOLOR] | |
||
195 | position->piecesOfType[KNIGHT | OPPCOLOR]; |
||
196 | const Bitboard cth = position->piecesOfType[ROOK | OPPCOLOR] | |
||
197 | position->piecesOfType[QUEEN | OPPCOLOR]; |
||
198 | const Bitboard candidateTargets = |
||
199 | cth | (ctm & base->unprotectedPieces[OPPCOLOR]); |
||
200 | const Piece batteryPiece = |
||
201 | getDiaBatteryPiece(position, moves, square, OPPCOLOR); |
||
202 | const int mobilityCount = getNumberOfSetSquares(moves & mobSquares); |
||
203 | |||
204 | #ifdef PERSPECTIVE_WHITE |
||
205 | const int pawnIndex = getWhiteBishopBlockingIndex(position, bishopSquares); |
||
206 | #else |
||
207 | const int pawnIndex = getBlackBishopBlockingIndex(position, bishopSquares); |
||
208 | #endif |
||
209 | |||
210 | #ifdef PERSPECTIVE_WHITE |
||
211 | const Square relativeSquare = square; |
||
212 | #else |
||
213 | const Square relativeSquare = getFlippedSquare(square); |
||
214 | #endif |
||
215 | |||
216 | assert(mobilityCount <= MAX_MOVES_BISHOP); |
||
217 | |||
218 | addBonus(base, BishopMobilityBonus[mobilityCount]); |
||
219 | |||
220 | addMalus(base, V(wV(pawnIndex, 650), wV(pawnIndex, 750))); |
||
221 | addBonus(base, getNumberOfSetSquares(squareColorTargets) * V(0, 2)); |
||
222 | |||
223 | base->bishopAttackedSquares[COLOR] |= moves; |
||
224 | |||
225 | if (squareIsPawnSafe(base, COLOR, square) && |
||
226 | BONUS_BISHOP_OUTPOST[relativeSquare] > 0) |
||
227 | { |
||
228 | int bonusValue = BONUS_BISHOP_OUTPOST[relativeSquare]; |
||
229 | |||
230 | if (testSquare(base->pawnProtectedSquares[COLOR], square)) |
||
231 | { |
||
232 | if (position->piecesOfType[KNIGHT | OPPCOLOR] == EMPTY_BITBOARD && |
||
233 | hasAttackingBishop(position, OPPCOLOR, square) == FALSE) |
||
234 | { |
||
235 | bonusValue += bonusValue + bonusValue / 2; |
||
236 | } |
||
237 | else |
||
238 | { |
||
239 | bonusValue += bonusValue; |
||
240 | } |
||
241 | } |
||
242 | |||
243 | addBonus(base, V(bonusValue, bonusValue)); |
||
244 | } |
||
245 | |||
246 | if (pinningPiece != NO_SQUARE) |
||
247 | { |
||
248 | setSquare(base->pinnedPieces[COLOR], square); |
||
249 | } |
||
250 | |||
251 | #ifdef PERSPECTIVE_WHITE |
||
252 | addWhitePieceAttackBonus(position, base, moves, candidateTargets, |
||
253 | WHITE_BISHOP); |
||
254 | #else |
||
255 | addBlackPieceAttackBonus(position, base, moves, candidateTargets, |
||
256 | BLACK_BISHOP); |
||
257 | #endif |
||
258 | |||
259 | if (testSquare(base->pawnProtectedSquares[OPPCOLOR], square)) |
||
260 | { |
||
261 | addMalus(base, piecePieceAttackBonus[PAWN | OPPCOLOR][BISHOP | COLOR]); |
||
262 | } |
||
263 | |||
264 | if (base->evaluateKingSafety[OPPCOLOR]) |
||
265 | { |
||
266 | if ((moves & base->kingAttackSquares[OPPCOLOR]) != EMPTY_BITBOARD) |
||
267 | { |
||
268 | const Bitboard coronaAttacks = |
||
269 | moves & getKingMoves(position->king[OPPCOLOR]); |
||
270 | |||
271 | base->kingSquaresAttackCount[COLOR] += |
||
272 | getNumberOfSetSquares(coronaAttacks); |
||
273 | base->attackInfo[COLOR] += V(BISHOP_BONUS_ATTACK, 1); |
||
274 | } |
||
275 | } |
||
276 | |||
277 | if (batteryPiece != NO_PIECE) |
||
278 | { |
||
279 | addBonus(base, V(BISHOP_PIN_OP_VAL, BISHOP_PIN_EG_VAL)); |
||
280 | } |
||
281 | } |
||
282 | |||
283 | #ifdef PERSPECTIVE_WHITE |
||
284 | void evaluateWhiteRook(const Position * position, |
||
285 | EvaluationBase * base, const Square square) |
||
286 | #else |
||
287 | void evaluateBlackRook(const Position * position, |
||
288 | EvaluationBase * base, const Square square) |
||
289 | #endif |
||
290 | { |
||
291 | const Piece piece = position->piece[square]; |
||
292 | const Square pinningPiece = getPinningPiece(position, base, square, COLOR); |
||
293 | const Bitboard xrayPieces = position->piecesOfType[QUEEN | COLOR] | |
||
294 | position->piecesOfType[piece]; |
||
295 | const Bitboard moves = |
||
296 | (pinningPiece == NO_SQUARE ? |
||
297 | getMagicRookMoves(square, position->allPieces & ~xrayPieces) : |
||
298 | getMagicRookMoves(square, position->allPieces & ~xrayPieces) & |
||
299 | (squaresBetween[pinningPiece][position->king[COLOR]] | |
||
300 | minValue[pinningPiece])); |
||
301 | const Bitboard mobSquares = base->countedSquares[COLOR]; |
||
302 | const Bitboard fileSquares = squaresOfFile[file(square)]; |
||
303 | const Bitboard ownPawns = position->piecesOfType[PAWN | COLOR]; |
||
304 | const Rank relativeRank = colorRank(COLOR, square); |
||
305 | const Bitboard ctm = position->piecesOfType[PAWN | OPPCOLOR] | |
||
306 | position->piecesOfType[KNIGHT | OPPCOLOR] | |
||
307 | position->piecesOfType[BISHOP | OPPCOLOR]; |
||
308 | const Bitboard cth = position->piecesOfType[QUEEN | OPPCOLOR]; |
||
309 | const Bitboard candidateTargets = cth | |
||
310 | (ctm & base->unprotectedPieces[OPPCOLOR]); |
||
311 | const int mobilityCount = getNumberOfSetSquares(moves & mobSquares); |
||
312 | |||
313 | assert(mobilityCount <= MAX_MOVES_ROOK); |
||
314 | |||
315 | addBonus(base, RookMobilityBonus[mobilityCount]); |
||
316 | base->rookDoubleAttackedSquares[COLOR] |= |
||
317 | base->rookAttackedSquares[COLOR] & moves; |
||
318 | base->rookAttackedSquares[COLOR] |= moves; |
||
319 | |||
320 | if (pinningPiece != NO_SQUARE) |
||
321 | { |
||
322 | setSquare(base->pinnedPieces[COLOR], square); |
||
323 | } |
||
324 | |||
325 | #ifdef PERSPECTIVE_WHITE |
||
326 | addWhitePieceAttackBonus(position, base, moves, candidateTargets, |
||
327 | WHITE_ROOK); |
||
328 | #else |
||
329 | addBlackPieceAttackBonus(position, base, moves, candidateTargets, |
||
330 | BLACK_ROOK); |
||
331 | #endif |
||
332 | |||
333 | if (testSquare(base->pawnProtectedSquares[OPPCOLOR], square)) |
||
334 | { |
||
335 | addMalus(base, piecePieceAttackBonus[PAWN | OPPCOLOR][ROOK | COLOR]); |
||
336 | } |
||
337 | |||
338 | /* Add a bonus if this rook is located on an open file. */ |
||
339 | if ((ownPawns & fileSquares) == EMPTY_BITBOARD) |
||
340 | { |
||
341 | const Bitboard oppPawns = position->piecesOfType[PAWN | OPPCOLOR]; |
||
342 | const Bitboard frontSquares = fileSquares & squaresAbove[COLOR][square]; |
||
343 | Bitboard protectedBlockers = frontSquares & |
||
344 | base->pawnProtectedSquares[OPPCOLOR] & |
||
345 | (oppPawns | position->piecesOfType[OPPCOLOR | KNIGHT] | |
||
346 | position->piecesOfType[OPPCOLOR | BISHOP]); |
||
347 | |||
348 | if (protectedBlockers == EMPTY_BITBOARD) |
||
349 | { |
||
350 | if ((frontSquares & oppPawns) == EMPTY_BITBOARD) |
||
351 | { |
||
352 | addBonus(base, V(20, 19)); |
||
353 | } |
||
354 | else /* semi-open file */ |
||
355 | { |
||
356 | addBonus(base, V(9, 11)); |
||
357 | } |
||
358 | } |
||
359 | else /* file is blocked by a protected pawn, knight of bishop */ |
||
360 | { |
||
361 | if ((protectedBlockers & oppPawns) != EMPTY_BITBOARD) |
||
362 | { |
||
363 | addBonus(base, V(8, 0)); |
||
364 | } |
||
365 | else |
||
366 | { |
||
367 | #ifdef PERSPECTIVE_WHITE |
||
368 | const Square minorSquare = getFirstSquare(&protectedBlockers); |
||
369 | #else |
||
370 | const Square minorSquare = getLastSquare(&protectedBlockers); |
||
371 | #endif |
||
372 | if (squareIsPawnSafe(base, OPPCOLOR, minorSquare)) |
||
373 | { |
||
374 | addBonus(base, V(8, 1)); |
||
375 | } |
||
376 | else |
||
377 | { |
||
378 | addBonus(base, V(15, 5)); |
||
379 | } |
||
380 | } |
||
381 | } |
||
382 | } |
||
383 | else if (testSquare(kingTrapsRook[COLOR][position->king[COLOR]], square) && |
||
384 | (moves & centralFiles) == EMPTY_BITBOARD |
||
385 | /* && mobilityCount < 4 */ ) |
||
386 | { |
||
387 | const int basicMalus = max(0, 51 - 9 * mobilityCount); |
||
388 | |||
389 | addMalus(base, V(basicMalus, 0)); |
||
390 | } |
||
391 | |||
392 | if (relativeRank >= RANK_5) |
||
393 | { |
||
394 | const Bitboard pawnTargets = position->piecesOfType[PAWN | OPPCOLOR] & |
||
395 | generalMoves[ROOK][square]; |
||
396 | |||
397 | if (relativeRank == RANK_7 && |
||
398 | colorRank(COLOR, position->king[OPPCOLOR]) == RANK_8) |
||
399 | { |
||
400 | Bitboard companions = position->piecesOfType[ROOK | COLOR] | |
||
401 | position->piecesOfType[QUEEN | COLOR]; |
||
402 | |||
403 | addBonus(base, V(5, 16)); |
||
404 | |||
405 | if ((moves & companions & squaresOfRank[rank(square)]) != |
||
406 | EMPTY_BITBOARD) |
||
407 | { |
||
408 | addBonus(base, V(5, 10)); |
||
409 | } |
||
410 | } |
||
411 | |||
412 | if (pawnTargets != EMPTY_BITBOARD) |
||
413 | { |
||
414 | const int numTargets = getNumberOfSetSquares(pawnTargets); |
||
415 | |||
416 | addBonus(base, numTargets * V(5, 14)); |
||
417 | } |
||
418 | |||
419 | if (squareIsPawnSafe(base, COLOR, square) && |
||
420 | testSquare(border, square) == FALSE && |
||
421 | testSquare(base->pawnProtectedSquares[COLOR], square)) |
||
422 | { |
||
423 | addBonus(base, V(3, 5)); |
||
424 | } |
||
425 | } |
||
426 | |||
427 | if (base->evaluateKingSafety[OPPCOLOR]) |
||
428 | { |
||
429 | if ((moves & base->kingAttackSquares[OPPCOLOR]) != EMPTY_BITBOARD) |
||
430 | { |
||
431 | const Bitboard coronaAttacks = |
||
432 | moves & getKingMoves(position->king[OPPCOLOR]); |
||
433 | |||
434 | base->kingSquaresAttackCount[COLOR] += |
||
435 | getNumberOfSetSquares(coronaAttacks); |
||
436 | base->attackInfo[COLOR] += V(ROOK_BONUS_ATTACK, 1); |
||
437 | } |
||
438 | } |
||
439 | |||
440 | /* Give a malus for a rook blocking his own passer on the 7th rank */ |
||
441 | if (numberOfNonPawnPieces(position, COLOR) == 2 && |
||
442 | colorRank(COLOR, square) == RANK_8 && |
||
443 | testSquare(base->passedPawns[COLOR], |
||
444 | (Square) downward(COLOR, square)) && |
||
445 | (fileSquares & squaresBelow[COLOR][square] & |
||
446 | position->piecesOfType[ROOK | OPPCOLOR]) != EMPTY_BITBOARD && |
||
447 | (companionFiles[square] & |
||
448 | (position->piecesOfType[WHITE_PAWN] | |
||
449 | position->piecesOfType[BLACK_PAWN])) == EMPTY_BITBOARD) |
||
450 | { |
||
451 | addMalus(base, V(0, 90)); |
||
452 | } |
||
453 | } |
||
454 | |||
455 | #ifdef PERSPECTIVE_WHITE |
||
456 | void evaluateWhiteQueen(const Position * position, |
||
457 | EvaluationBase * base, const Square square) |
||
458 | #else |
||
459 | void evaluateBlackQueen(const Position * position, |
||
460 | EvaluationBase * base, const Square square) |
||
461 | #endif |
||
462 | { |
||
463 | const Square pinningPiece = getPinningPiece(position, base, square, COLOR); |
||
464 | const Bitboard moves = |
||
465 | (pinningPiece == NO_SQUARE ? |
||
466 | getMagicQueenMoves(square, position->allPieces) : |
||
467 | getMagicQueenMoves(square, position->allPieces) & |
||
468 | (squaresBetween[pinningPiece][position->king[COLOR]] | |
||
469 | minValue[pinningPiece])); |
||
470 | const Bitboard xrayOrthoPieces = position->piecesOfType[ROOK | COLOR] | |
||
471 | position->piecesOfType[QUEEN | COLOR]; |
||
472 | const Bitboard xrayOrthoMoves = |
||
473 | (pinningPiece == NO_SQUARE ? |
||
474 | getMagicRookMoves(square, position->allPieces & ~xrayOrthoPieces) : |
||
475 | getMagicRookMoves(square, position->allPieces & ~xrayOrthoPieces) & |
||
476 | squaresBetween[pinningPiece][position->king[COLOR]]); |
||
477 | const Bitboard candidateTargets = base->unprotectedPieces[OPPCOLOR]; |
||
478 | const Bitboard countedQueenSquares = base->countedSquares[COLOR] & |
||
479 | ~(base->knightAttackedSquares[OPPCOLOR] | |
||
480 | base->bishopAttackedSquares[OPPCOLOR] | |
||
481 | base->rookAttackedSquares[OPPCOLOR]); |
||
482 | const int mobilityCount = |
||
483 | getNumberOfSetSquares(moves & countedQueenSquares); |
||
484 | |||
485 | assert(mobilityCount <= MAX_MOVES_QUEEN); |
||
486 | |||
487 | addBonus(base, QueenMobilityBonus[mobilityCount]); |
||
488 | base->queenAttackedSquares[COLOR] |= moves; |
||
489 | base->queenSupportedSquares[COLOR] |= xrayOrthoMoves & ~moves; |
||
490 | |||
491 | if (colorRank(COLOR, square) >= RANK_5) |
||
492 | { |
||
493 | const Bitboard pawnTargets = position->piecesOfType[PAWN | OPPCOLOR] & |
||
494 | generalMoves[ROOK][square]; |
||
495 | |||
496 | if (colorRank(COLOR, square) == RANK_7 && |
||
497 | colorRank(COLOR, position->king[OPPCOLOR]) == RANK_8) |
||
498 | { |
||
499 | addBonus(base, V(3, 15)); |
||
500 | } |
||
501 | |||
502 | if (pawnTargets != EMPTY_BITBOARD) |
||
503 | { |
||
504 | const int numTargets = getNumberOfSetSquares(pawnTargets); |
||
505 | |||
506 | addBonus(base, numTargets * V(2, 10)); |
||
507 | } |
||
508 | } |
||
509 | |||
510 | if (base->evaluateKingSafety[OPPCOLOR]) |
||
511 | { |
||
512 | if ((moves & base->kingAttackSquares[OPPCOLOR]) != EMPTY_BITBOARD) |
||
513 | { |
||
514 | const Bitboard coronaAttacks = |
||
515 | moves & getKingMoves(position->king[OPPCOLOR]); |
||
516 | |||
517 | base->kingSquaresAttackCount[COLOR] += |
||
518 | getNumberOfSetSquares(coronaAttacks); |
||
519 | base->attackInfo[COLOR] += V(QUEEN_BONUS_ATTACK, 1); |
||
520 | } |
||
521 | } |
||
522 | |||
523 | if (pinningPiece != NO_SQUARE) |
||
524 | { |
||
525 | setSquare(base->pinnedPieces[COLOR], square); |
||
526 | } |
||
527 | |||
528 | #ifdef PERSPECTIVE_WHITE |
||
529 | addWhitePieceAttackBonus(position, base, moves, candidateTargets, |
||
530 | WHITE_QUEEN); |
||
531 | #else |
||
532 | addBlackPieceAttackBonus(position, base, moves, candidateTargets, |
||
533 | BLACK_QUEEN); |
||
534 | #endif |
||
535 | |||
536 | if (testSquare(base->pawnProtectedSquares[OPPCOLOR], square)) |
||
537 | { |
||
538 | addMalus(base, piecePieceAttackBonus[PAWN | OPPCOLOR][QUEEN | COLOR]); |
||
539 | } |
||
540 | } |
||
541 | |||
542 | #ifdef PERSPECTIVE_WHITE |
||
543 | void evaluateWhitePasser(const Position * position, |
||
544 | EvaluationBase * base, const Square square) |
||
545 | #else |
||
546 | void evaluateBlackPasser(const Position * position, |
||
547 | EvaluationBase * base, const Square square) |
||
548 | #endif |
||
549 | { |
||
550 | const Rank pawnRank = colorRank(COLOR, square); |
||
551 | const int pawnDirection = (COLOR == WHITE ? 8 : -8); |
||
552 | const Square stopSquare = (Square) (square + pawnDirection); |
||
553 | const int numDefenders = position->numberOfPieces[OPPCOLOR] - |
||
554 | position->numberOfPawns[OPPCOLOR]; |
||
555 | bool unStoppable = FALSE; |
||
556 | const int rank = pawnRank - RANK_2; |
||
557 | const int rankFactor = rank * (rank - 1); |
||
558 | int openingBonus = 17 * rankFactor; |
||
559 | int endgameBonus = 7 * (rankFactor + rank + 1); |
||
560 | int opValue, egValue; |
||
561 | |||
562 | assert(pawnIsPassed(position, square, COLOR)); |
||
563 | |||
564 | if (numDefenders == 1) |
||
565 | { |
||
566 | const int egBonus = quad(0, 800, pawnRank); |
||
567 | const int kingDistance = distance(square, position->king[COLOR]); |
||
568 | const Square rectangleSquare = |
||
569 | (COLOR == position->activeColor ? |
||
570 | square : (Square) (square - pawnDirection)); |
||
571 | const bool kingInRectangle = |
||
572 | testSquare(passedPawnRectangle[COLOR][rectangleSquare], |
||
573 | position->king[OPPCOLOR]); |
||
574 | |||
575 | if ((kingInRectangle == FALSE && |
||
576 | (passedPawnCorridor[COLOR][square] & |
||
577 | position->piecesOfColor[COLOR]) == EMPTY_BITBOARD)) |
||
578 | { |
||
579 | addBonus(base, V(0, egBonus)); |
||
580 | unStoppable = TRUE; |
||
581 | } |
||
582 | else if (kingDistance == 1) |
||
583 | { |
||
584 | const File pawnFile = file(square); |
||
585 | const File kingFile = file(position->king[COLOR]); |
||
586 | const Square promotionSquare = |
||
587 | (COLOR == WHITE ? getSquare(pawnFile, RANK_8) : |
||
588 | getSquare(pawnFile, RANK_1)); |
||
589 | const bool clearPath = (bool) |
||
590 | (kingFile != pawnFile || |
||
591 | (kingFile != FILE_A && kingFile != FILE_H)); |
||
592 | |||
593 | if (clearPath && |
||
594 | distance(promotionSquare, position->king[COLOR]) <= 1) |
||
595 | { |
||
596 | addBonus(base, V(0, egBonus)); |
||
597 | unStoppable = TRUE; |
||
598 | } |
||
599 | } |
||
600 | |||
601 | if (unStoppable == FALSE && |
||
602 | base->hasPassersOrCandidates[OPPCOLOR] == FALSE && |
||
603 | passerWalks(position, square, COLOR)) |
||
604 | { |
||
605 | addBonus(base, V(0, egBonus)); |
||
606 | unStoppable = TRUE; |
||
607 | } |
||
608 | } |
||
609 | |||
610 | if (rankFactor > 0 && unStoppable == FALSE) |
||
611 | { |
||
612 | const Square attKing = position->king[COLOR]; |
||
613 | const Square defKing = position->king[OPPCOLOR]; |
||
614 | const int attackerDistance = distance(attKing, stopSquare); |
||
615 | const int defenderDistance = distance(defKing, stopSquare); |
||
616 | |||
617 | endgameBonus -= 3 * rankFactor * attackerDistance; |
||
618 | endgameBonus += 5 * rankFactor * defenderDistance; |
||
619 | |||
620 | if (position->piece[stopSquare] == NO_PIECE) |
||
621 | { |
||
622 | Bitboard ownAttacks = base->attackedSquares[COLOR] | |
||
623 | getKingMoves(attKing); |
||
624 | const Bitboard oppAttacks = base->attackedSquares[OPPCOLOR] | |
||
625 | getKingMoves(defKing); |
||
626 | const Bitboard path = passedPawnCorridor[COLOR][square]; |
||
627 | const Bitboard oppBlockers = |
||
628 | path & position->piecesOfColor[OPPCOLOR]; |
||
629 | const Bitboard blockingSquare = minValue[stopSquare]; |
||
630 | int bonus = 0; |
||
631 | Bitboard obstacles = path & oppAttacks; |
||
632 | |||
633 | if (testSquare(base->attackedSquares[OPPCOLOR], square)) |
||
634 | { |
||
635 | const Bitboard candidates = |
||
636 | (position->piecesOfType[ROOK | OPPCOLOR] | |
||
637 | position->piecesOfType[QUEEN | OPPCOLOR]) & |
||
638 | passedPawnCorridor[OPPCOLOR][square] & |
||
639 | getMagicRookMoves(square, position->allPieces); |
||
640 | |||
641 | if (candidates != EMPTY_BITBOARD) |
||
642 | { |
||
643 | obstacles = path; |
||
644 | } |
||
645 | } |
||
646 | |||
647 | if (testSquare(base->attackedSquares[COLOR], square)) |
||
648 | { |
||
649 | const Bitboard candidates = |
||
650 | (position->piecesOfType[ROOK | COLOR] | |
||
651 | position->piecesOfType[QUEEN | COLOR]) & |
||
652 | passedPawnCorridor[OPPCOLOR][square] & |
||
653 | getMagicRookMoves(square, position->allPieces); |
||
654 | |||
655 | if (candidates != EMPTY_BITBOARD) |
||
656 | { |
||
657 | ownAttacks = path; |
||
658 | } |
||
659 | } |
||
660 | |||
661 | obstacles |= oppBlockers; |
||
662 | |||
663 | if (obstacles == EMPTY_BITBOARD) |
||
664 | { |
||
665 | bonus += 16; |
||
666 | } |
||
667 | else if ((obstacles & blockingSquare) == EMPTY_BITBOARD) |
||
668 | { |
||
669 | bonus += 9; |
||
670 | } |
||
671 | |||
672 | if (ownAttacks == path) |
||
673 | { |
||
674 | bonus += 6; |
||
675 | } |
||
676 | else if ((ownAttacks & blockingSquare) != EMPTY_BITBOARD) |
||
677 | { |
||
678 | bonus += ((obstacles & ~ownAttacks) == EMPTY_BITBOARD ? 4 : 2); |
||
679 | } |
||
680 | |||
681 | openingBonus += rankFactor * bonus; |
||
682 | endgameBonus += rankFactor * bonus; |
||
683 | } |
||
684 | } |
||
685 | |||
686 | if (position->numberOfPawns[COLOR] < position->numberOfPawns[OPPCOLOR]) |
||
687 | { |
||
688 | endgameBonus += endgameBonus / 4; |
||
689 | } |
||
690 | |||
691 | opValue = (openingBonus * PASSED_PAWN_WEIGHT_OP) / 256; |
||
692 | egValue = (endgameBonus * PASSED_PAWN_WEIGHT_EG) / 256; |
||
693 | |||
694 | addBonus(base, V(opValue, egValue)); |
||
695 | } |
||
696 | |||
697 | #ifdef PERSPECTIVE_WHITE |
||
698 | int getPawnSafetyMalusOfWhiteKingFile(const Position * position, |
||
699 | const int file, |
||
700 | const Square kingSquare, |
||
701 | const int fileType) |
||
702 | #else |
||
703 | int getPawnSafetyMalusOfBlackKingFile(const Position * position, |
||
704 | const int file, |
||
705 | const Square kingSquare, |
||
706 | const int fileType) |
||
707 | #endif |
||
708 | { |
||
709 | const int ATTACK_WEIGHT = 306; |
||
710 | const Square baseSquare = getSquare(file, rank(kingSquare)); |
||
711 | const Bitboard pawnRealm = squaresOfRank[rank(kingSquare)] | |
||
712 | squaresAbove[COLOR][kingSquare]; |
||
713 | const Bitboard fileRealm = squaresOfFile[file] & pawnRealm; |
||
714 | const Bitboard diagRealm = pawnRealm & |
||
715 | generalMoves[WHITE_BISHOP][baseSquare] & |
||
716 | (file(kingSquare) <= FILE_D ? |
||
717 | squaresRightOf[baseSquare] : squaresLeftOf[baseSquare]); |
||
718 | Bitboard fileDefenders = fileRealm & position->piecesOfType[PAWN | COLOR]; |
||
719 | Bitboard diagDefenders = diagRealm & position->piecesOfType[PAWN | COLOR]; |
||
720 | Bitboard attackers = fileRealm & position->piecesOfType[PAWN | OPPCOLOR]; |
||
721 | int fileDefenderIndex = 0, fileAttackerIndex = 0; |
||
722 | int fileAttackerDivisor = 256; |
||
723 | int diagonalDefenderMalus = 0; |
||
724 | |||
725 | #ifdef PERSPECTIVE_WHITE |
||
726 | const Square fileDefenderSquare = getFirstSquare(&fileDefenders); |
||
727 | const Square fileAttackerSquare = getFirstSquare(&attackers); |
||
728 | #else |
||
729 | const Square fileDefenderSquare = getLastSquare(&fileDefenders); |
||
730 | const Square fileAttackerSquare = getLastSquare(&attackers); |
||
731 | #endif |
||
732 | |||
733 | if (fileType == 1) |
||
734 | { |
||
735 | #ifdef PERSPECTIVE_WHITE |
||
736 | const Square diagDefenderSquare = getFirstSquare(&diagDefenders); |
||
737 | #else |
||
738 | const Square diagDefenderSquare = getLastSquare(&diagDefenders); |
||
739 | #endif |
||
740 | |||
741 | const File fileIndex = (File) (file <= FILE_D ? file : FILE_H - file); |
||
742 | const Rank rankIndex = (diagDefenderSquare != NO_SQUARE ? |
||
743 | colorRank(COLOR, diagDefenderSquare) : RANK_1); |
||
744 | |||
745 | assert(fileIndex >= FILE_A); |
||
746 | assert(fileIndex <= FILE_D); |
||
747 | assert(rankIndex >= RANK_1); |
||
748 | assert(rankIndex <= RANK_8); |
||
749 | |||
750 | diagonalDefenderMalus = |
||
751 | KINGSAFETY_PAWN_BONUS_DEFENDER_DIAG[fileIndex][rankIndex]; |
||
752 | } |
||
753 | |||
754 | if (fileDefenderSquare != NO_SQUARE) |
||
755 | { |
||
756 | fileDefenderIndex = colorRank(COLOR, fileDefenderSquare); |
||
757 | } |
||
758 | else |
||
759 | { |
||
760 | fileAttackerDivisor = 192; |
||
761 | } |
||
762 | |||
763 | if (fileAttackerSquare != NO_SQUARE) |
||
764 | { |
||
765 | fileAttackerIndex = colorRank(COLOR, fileAttackerSquare); |
||
766 | |||
767 | if (fileAttackerIndex == fileDefenderIndex + 1) |
||
768 | { |
||
769 | fileAttackerDivisor = (fileAttackerIndex == RANK_3 ? 160 : 390); |
||
770 | } |
||
771 | } |
||
772 | |||
773 | assert(fileType >= 0); |
||
774 | assert(fileType <= 2); |
||
775 | assert(fileDefenderIndex >= RANK_1); |
||
776 | assert(fileDefenderIndex <= RANK_8); |
||
777 | assert(fileAttackerIndex >= RANK_1); |
||
778 | assert(fileAttackerIndex <= RANK_8); |
||
779 | |||
780 | return KINGSAFETY_PAWN_MALUS_DEFENDER[fileType][fileDefenderIndex] + |
||
781 | (KINGSAFETY_PAWN_BONUS_ATTACKER[fileType][fileAttackerIndex] * |
||
782 | ATTACK_WEIGHT) / fileAttackerDivisor + diagonalDefenderMalus; |
||
783 | } |
||
784 | |||
785 | #ifdef PERSPECTIVE_WHITE |
||
786 | void evaluateWhitePawns(EvaluationBase * base) |
||
787 | #else |
||
788 | void evaluateBlackPawns(EvaluationBase * base) |
||
789 | #endif |
||
790 | { |
||
791 | static const INT32 doubledMalusPerFile[8] = { |
||
792 | V(5, 13), V(7, 15), V(8, 15), V(8, 15), |
||
793 | V(8, 15), V(8, 15), V(7, 15), V(5, 13) |
||
794 | }; |
||
795 | |||
796 | Bitboard chainPawns = base->chainPawns[COLOR]; |
||
797 | Bitboard doubledPawns = base->doubledPawns[COLOR]; |
||
798 | Square square; |
||
799 | |||
800 | ITERATE_BITBOARD(&chainPawns, square) |
||
801 | { |
||
802 | #ifdef PERSPECTIVE_WHITE |
||
803 | addBonus(base, PAWN_CHAIN_BONUS[square]); |
||
804 | #else |
||
805 | addBonus(base, PAWN_CHAIN_BONUS[getFlippedSquare(square)]); |
||
806 | #endif |
||
807 | } |
||
808 | |||
809 | ITERATE_BITBOARD(&doubledPawns, square) |
||
810 | { |
||
811 | addMalus(base, doubledMalusPerFile[file(square)]); |
||
812 | } |
||
813 | } |