Subversion Repositories Games.Chess Giants

Rev

Blame | Last modification | View Log | Download | RSS feed

  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. }
  814.