Subversion Repositories Games.Chess Giants

Rev

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
}