Subversion Repositories Games.Chess Giants

Rev

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

  1. /*
  2.     Texel - A UCI chess engine.
  3.     Copyright (C) 2012-2014  Peter Ă–sterlund, peterosterlund2@gmail.com
  4.  
  5.     This program is free software: you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation, either version 3 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17. */
  18.  
  19. /*
  20.  * evaluate.cpp
  21.  *
  22.  *  Created on: Feb 25, 2012
  23.  *      Author: petero
  24.  */
  25.  
  26. #include "evaluate.hpp"
  27. #include "endGameEval.hpp"
  28. #include <vector>
  29.  
  30. int Evaluate::pieceValueOrder[Piece::nPieceTypes] = {
  31.     0,
  32.     5, 4, 3, 2, 2, 1,
  33.     5, 4, 3, 2, 2, 1
  34. };
  35.  
  36.  
  37. static const int empty[64] = { 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  38.                                0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  39.                                0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  40.                                0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0};
  41.  
  42. int Evaluate::castleMaskFactor[256];
  43.  
  44. static StaticInitializer<Evaluate> evInit;
  45.  
  46.  
  47. /** Get bitboard mask for a square translated (dx,dy). Return 0 if square outside board. */
  48. static inline U64 getMask(int sq, int dx, int dy) {
  49.     int x = Position::getX(sq) + dx;
  50.     int y = Position::getY(sq) + dy;
  51.     if (x >= 0 && x < 8 && y >= 0 && y < 8)
  52.         return 1ULL << Position::getSquare(x, y);
  53.     else
  54.         return 0;
  55. }
  56.  
  57. void
  58. Evaluate::staticInitialize() {
  59.     psTab1[Piece::EMPTY]   = empty;
  60.     psTab1[Piece::WKING]   = kt1w.getTable();
  61.     psTab1[Piece::WQUEEN]  = qt1w.getTable();
  62.     psTab1[Piece::WROOK]   = rt1w.getTable();
  63.     psTab1[Piece::WBISHOP] = bt1w.getTable();
  64.     psTab1[Piece::WKNIGHT] = nt1w.getTable();
  65.     psTab1[Piece::WPAWN]   = pt1w.getTable();
  66.     psTab1[Piece::BKING]   = kt1b.getTable();
  67.     psTab1[Piece::BQUEEN]  = qt1b.getTable();
  68.     psTab1[Piece::BROOK]   = rt1b.getTable();
  69.     psTab1[Piece::BBISHOP] = bt1b.getTable();
  70.     psTab1[Piece::BKNIGHT] = nt1b.getTable();
  71.     psTab1[Piece::BPAWN]   = pt1b.getTable();
  72.  
  73.     psTab2[Piece::EMPTY]   = empty;
  74.     psTab2[Piece::WKING]   = kt2w.getTable();
  75.     psTab2[Piece::WQUEEN]  = qt2w.getTable();
  76.     psTab2[Piece::WROOK]   = rt1w.getTable();
  77.     psTab2[Piece::WBISHOP] = bt2w.getTable();
  78.     psTab2[Piece::WKNIGHT] = nt2w.getTable();
  79.     psTab2[Piece::WPAWN]   = pt2w.getTable();
  80.     psTab2[Piece::BKING]   = kt2b.getTable();
  81.     psTab2[Piece::BQUEEN]  = qt2b.getTable();
  82.     psTab2[Piece::BROOK]   = rt1b.getTable();
  83.     psTab2[Piece::BBISHOP] = bt2b.getTable();
  84.     psTab2[Piece::BKNIGHT] = nt2b.getTable();
  85.     psTab2[Piece::BPAWN]   = pt2b.getTable();
  86.  
  87.     // Initialize knight/bishop king safety patterns
  88.     for (int sq = 0; sq < 64; sq++) {
  89.         const int x = Position::getX(sq);
  90.         const int y = Position::getY(sq);
  91.         int dx = (x < 4) ? -1 : 1;
  92.         int dy = (y < 4) ? 1 : -1;
  93.         U64 n = getMask(sq, -dx, 0) | getMask(sq, dx, 0) | getMask(sq, 0, dy) | getMask(sq, 0, 2*dy) | getMask(sq, dx, 2*dy);
  94.         U64 b = getMask(sq, -dx, 0) | getMask(sq, 0, dy) | getMask(sq, dx, 2*dy);
  95.         knightKingProtectPattern[sq] = n;
  96.         bishopKingProtectPattern[sq] = b;
  97.     }
  98. }
  99.  
  100. void
  101. Evaluate::updateEvalParams() {
  102.     // Castle bonus
  103.     for (int i = 0; i < 256; i++) {
  104.         int h1Dist = 100;
  105.         bool h1Castle = (i & (1<<7)) != 0;
  106.         if (h1Castle)
  107.             h1Dist = BitBoard::bitCount(i & BitBoard::sqMask(F1,G1));
  108.         int a1Dist = 100;
  109.         bool a1Castle = (i & 1) != 0;
  110.         if (a1Castle)
  111.             a1Dist = BitBoard::bitCount(i & BitBoard::sqMask(B1,C1,D1));
  112.         int dist = std::min(a1Dist, h1Dist);
  113.         castleMaskFactor[i] = dist < 4 ? castleFactor[dist] : 0;
  114.     }
  115.  
  116.     // Knight mobility scores
  117.     for (int sq = 0; sq < 64; sq++) {
  118.         int x = Position::getX(sq);
  119.         int y = Position::getY(sq);
  120.         if (x >= 4) x = 7 - x;
  121.         if (y >= 4) y = 7 - y;
  122.         if (x < y) std::swap(x, y);
  123.         int maxMob = 0;
  124.         switch (y*8+x) {
  125.         case A1: maxMob = 2; break;
  126.         case B1: maxMob = 3; break;
  127.         case C1: maxMob = 4; break;
  128.         case D1: maxMob = 4; break;
  129.         case B2: maxMob = 4; break;
  130.         case C2: maxMob = 6; break;
  131.         case D2: maxMob = 6; break;
  132.         case C3: maxMob = 8; break;
  133.         case D3: maxMob = 8; break;
  134.         case D4: maxMob = 8; break;
  135.         default:
  136.             assert(false);
  137.         }
  138.         for (int m = 0; m <= 8; m++) {
  139.             int offs = 0;
  140.             switch (maxMob) {
  141.             case 2: offs = 0; break;
  142.             case 3: offs = 3; break;
  143.             case 4: offs = 7; break;
  144.             case 6: offs = 12; break;
  145.             case 8: offs = 19; break;
  146.             }
  147.             knightMobScoreA[sq][m] = knightMobScore[offs + std::min(m, maxMob)];
  148.         }
  149.     }
  150. }
  151.  
  152. const int* Evaluate::psTab1[Piece::nPieceTypes];
  153. const int* Evaluate::psTab2[Piece::nPieceTypes];
  154.  
  155. int Evaluate::knightMobScoreA[64][9];
  156. U64 Evaluate::knightKingProtectPattern[64];
  157. U64 Evaluate::bishopKingProtectPattern[64];
  158.  
  159. Evaluate::Evaluate(EvalHashTables& et)
  160.     : pawnHash(et.pawnHash),
  161.       materialHash(et.materialHash),
  162.       kingSafetyHash(et.kingSafetyHash),
  163.       wKingZone(0), bKingZone(0),
  164.       wKingAttacks(0), bKingAttacks(0),
  165.       wAttacksBB(0), bAttacksBB(0),
  166.       wPawnAttacks(0), bPawnAttacks(0) {
  167. }
  168.  
  169. int
  170. Evaluate::evalPos(const Position& pos) {
  171.     return evalPos<false>(pos);
  172. }
  173.  
  174. int
  175. Evaluate::evalPosPrint(const Position& pos) {
  176.     return evalPos<true>(pos);
  177. }
  178.  
  179. template <bool print>
  180. inline int
  181. Evaluate::evalPos(const Position& pos) {
  182.     int score = materialScore(pos, print);
  183.  
  184.     wKingAttacks = bKingAttacks = 0;
  185.     wKingZone = BitBoard::kingAttacks[pos.getKingSq(true)]; wKingZone |= wKingZone << 8;
  186.     bKingZone = BitBoard::kingAttacks[pos.getKingSq(false)]; bKingZone |= bKingZone >> 8;
  187.     wAttacksBB = bAttacksBB = 0L;
  188.  
  189.     U64 pawns = pos.pieceTypeBB(Piece::WPAWN);
  190.     wPawnAttacks = ((pawns & BitBoard::maskBToHFiles) << 7) |
  191.                    ((pawns & BitBoard::maskAToGFiles) << 9);
  192.     pawns = pos.pieceTypeBB(Piece::BPAWN);
  193.     bPawnAttacks = ((pawns & BitBoard::maskBToHFiles) >> 9) |
  194.                    ((pawns & BitBoard::maskAToGFiles) >> 7);
  195.  
  196.     score += pieceSquareEval(pos);
  197.     if (print) std::cout << "eval pst    :" << score << std::endl;
  198.     score += pawnBonus(pos);
  199.     if (print) std::cout << "eval pawn   :" << score << std::endl;
  200.     score += castleBonus(pos);
  201.     if (print) std::cout << "eval castle :" << score << std::endl;
  202.  
  203.     score += rookBonus(pos);
  204.     if (print) std::cout << "eval rook   :" << score << std::endl;
  205.     score += bishopEval(pos, score);
  206.     if (print) std::cout << "eval bishop :" << score << std::endl;
  207.     score += knightEval(pos);
  208.     if (print) std::cout << "eval knight :" << score << std::endl;
  209.     score += threatBonus(pos);
  210.     if (print) std::cout << "eval threat :" << score << std::endl;
  211.     score += protectBonus(pos);
  212.     if (print) std::cout << "eval protect:" << score << std::endl;
  213.     score += kingSafety(pos);
  214.     if (print) std::cout << "eval king   :" << score << std::endl;
  215.     if (mhd->endGame)
  216.         score = EndGameEval::endGameEval<true>(pos, phd->passedPawns, score);
  217.     if (print) std::cout << "eval endgame:" << score << std::endl;
  218.     if (pos.pieceTypeBB(Piece::WPAWN, Piece::BPAWN)) {
  219.         int hmc = clamp(pos.getHalfMoveClock() / 10, 0, 9);
  220.         score = score * halfMoveFactor[hmc] / 128;
  221.     }
  222.     if (print) std::cout << "eval halfmove:" << score << std::endl;
  223.     if (score > 0) {
  224.         int nStale = BitBoard::bitCount(BitBoard::southFill(phd->stalePawns & pos.pieceTypeBB(Piece::WPAWN)) & 0xff);
  225.         score = score * stalePawnFactor[nStale] / 128;
  226.     } else if (score < 0) {
  227.         int nStale = BitBoard::bitCount(BitBoard::southFill(phd->stalePawns & pos.pieceTypeBB(Piece::BPAWN)) & 0xff);
  228.         score = score * stalePawnFactor[nStale] / 128;
  229.     }
  230.     if (print) std::cout << "eval staleP :" << score << std::endl;
  231.  
  232.     if (!pos.isWhiteMove())
  233.         score = -score;
  234.     return score;
  235. }
  236.  
  237. /** Compensate for the fact that many knights are stronger compared to queens
  238.  * than what the default material scores would predict. */
  239. static inline int correctionNvsQ(int n, int q) {
  240.     if (n <= q+1)
  241.         return 0;
  242.     int knightBonus = 0;
  243.     if (q == 1)
  244.         knightBonus = knightVsQueenBonus1;
  245.     else if (q == 2)
  246.         knightBonus = knightVsQueenBonus2;
  247.     else if (q >= 3)
  248.         knightBonus = knightVsQueenBonus3;
  249.     int corr = knightBonus * (n - q - 1);
  250.     return corr;
  251. }
  252.  
  253. void
  254. Evaluate::computeMaterialScore(const Position& pos, MaterialHashData& mhd, bool print) const {
  255.     // Compute material part of score
  256.     int score = pos.wMtrl() - pos.bMtrl();
  257.     if (print) std::cout << "eval mtrlraw:" << score << std::endl;
  258.     const int nWQ = BitBoard::bitCount(pos.pieceTypeBB(Piece::WQUEEN));
  259.     const int nBQ = BitBoard::bitCount(pos.pieceTypeBB(Piece::BQUEEN));
  260.     const int nWN = BitBoard::bitCount(pos.pieceTypeBB(Piece::WKNIGHT));
  261.     const int nBN = BitBoard::bitCount(pos.pieceTypeBB(Piece::BKNIGHT));
  262.     int wCorr = correctionNvsQ(nWN, nBQ);
  263.     int bCorr = correctionNvsQ(nBN, nWQ);
  264.     score += wCorr - bCorr;
  265.     if (print) std::cout << "eval qncorr :" << score << std::endl;
  266.     score += tradeBonus(pos, wCorr, bCorr);
  267.     if (print) std::cout << "eval trade  :" << score << std::endl;
  268.  
  269.     const int nWR = BitBoard::bitCount(pos.pieceTypeBB(Piece::WROOK));
  270.     const int nBR = BitBoard::bitCount(pos.pieceTypeBB(Piece::BROOK));
  271.     { // Redundancy of major pieces
  272.         int wMajor = nWQ + nWR;
  273.         int bMajor = nBQ + nBR;
  274.         int w = std::min(wMajor, 3);
  275.         int b = std::min(bMajor, 3);
  276.         score += majorPieceRedundancy[w*4+b];
  277.     }
  278.     if (print) std::cout << "eval majred :" << score << std::endl;
  279.  
  280.     const int wMtrl = pos.wMtrl();
  281.     const int bMtrl = pos.bMtrl();
  282.     const int wMtrlPawns = pos.wMtrlPawns();
  283.     const int bMtrlPawns = pos.bMtrlPawns();
  284.     const int wMtrlNoPawns = wMtrl - wMtrlPawns;
  285.     const int bMtrlNoPawns = bMtrl - bMtrlPawns;
  286.  
  287.     // Handle imbalances
  288.     const int nWB = BitBoard::bitCount(pos.pieceTypeBB(Piece::WBISHOP));
  289.     const int nBB = BitBoard::bitCount(pos.pieceTypeBB(Piece::BBISHOP));
  290.     const int nWP = BitBoard::bitCount(pos.pieceTypeBB(Piece::WPAWN));
  291.     const int nBP = BitBoard::bitCount(pos.pieceTypeBB(Piece::BPAWN));
  292.     {
  293.         const int dQ = nWQ - nBQ;
  294.         const int dR = nWR - nBR;
  295.         const int dB = nWB - nBB;
  296.         const int dN = nWN - nBN;
  297.         int nMinor = nWB + nWN + nBB + nBN;
  298.         if ((dQ == 1) && (dR == -2)) {
  299.             score += QvsRRBonus[std::min(4, nMinor)];
  300.         } else if ((dQ == -1) && (dR == 2)) {
  301.             score -= QvsRRBonus[std::min(4, nMinor)];
  302.         }
  303.  
  304.         const int dP = nWP - nBP;
  305.         if ((dR == 1) && (dB + dN == -1)) {
  306.             score += RvsMBonus[clamp(dP, -3, 3)+3];
  307.             if (wMtrlNoPawns == rV && dB == -1 && dP == -1)
  308.                 score += RvsBPBonus;
  309.         } else if ((dR == -1) && (dB + dN == 1)) {
  310.             score -= RvsMBonus[clamp(-dP, -3, 3)+3];
  311.             if (bMtrlNoPawns == rV && dB == 1 && dP == 1)
  312.                 score -= RvsBPBonus;
  313.         }
  314.  
  315.         if ((dR == 1) && (dB + dN == -2)) {
  316.             score += RvsMMBonus[clamp(dP, -3, 3)+3];
  317.         } else if ((dR == -1) && (dB + dN == 2)) {
  318.             score -= RvsMMBonus[clamp(-dP, -3, 3)+3];
  319.         }
  320.  
  321.         if ((dQ == 1) && (dR == -1) && (dB + dN == -1)) {
  322.             score += (nWR == 0) ? (int)QvsRMBonus1 : (int)QvsRMBonus2; // Pierre-Marie Baty -- added type cast
  323.         } else if ((dQ == -1) && (dR == 1) && (dB + dN == 1)) {
  324.             score -= (nBR == 0) ? (int)QvsRMBonus1 : (int)QvsRMBonus2; // Pierre-Marie Baty -- added type cast
  325.         }
  326.     }
  327.     if (print) std::cout << "eval imbala :" << score << std::endl;
  328.     mhd.id = pos.materialId();
  329.     mhd.score = score;
  330.     mhd.endGame = EndGameEval::endGameEval<false>(pos, 0, 0);
  331.  
  332.     // Compute interpolation factors
  333.     { // Pawn
  334.         const int loMtrl = pawnLoMtrl;
  335.         const int hiMtrl = pawnHiMtrl;
  336.         mhd.wPawnIPF = interpolate(bMtrlNoPawns, loMtrl, 0, hiMtrl, IPOLMAX);
  337.         mhd.bPawnIPF = interpolate(wMtrlNoPawns, loMtrl, 0, hiMtrl, IPOLMAX);
  338.         if (wCorr > 100)
  339.             mhd.wPawnIPF = mhd.wPawnIPF * 100 / wCorr;
  340.         if (bCorr > 100)
  341.             mhd.bPawnIPF = mhd.bPawnIPF * 100 / bCorr;
  342.     }
  343.     { // Knight/bishop
  344.         const int loMtrl = minorLoMtrl;
  345.         const int hiMtrl = minorHiMtrl;
  346.         mhd.wKnightIPF = interpolate(bMtrl, loMtrl, 0, hiMtrl, IPOLMAX);
  347.         mhd.bKnightIPF = interpolate(wMtrl, loMtrl, 0, hiMtrl, IPOLMAX);
  348.     }
  349.     { // Castle
  350.         const int loMtrl = castleLoMtrl;
  351.         const int hiMtrl = castleHiMtrl;
  352.         const int m = wMtrlNoPawns + bMtrlNoPawns;
  353.         mhd.castleIPF = interpolate(m, loMtrl, 0, hiMtrl, IPOLMAX);
  354.     }
  355.     {
  356.         const int loMtrl = queenLoMtrl;
  357.         const int hiMtrl = queenHiMtrl;
  358.         const int m = wMtrlNoPawns + bMtrlNoPawns;
  359.         mhd.queenIPF = interpolate(m, loMtrl, 0, hiMtrl, IPOLMAX);
  360.     }
  361.     { // Passed pawn
  362.         const int loMtrl = passedPawnLoMtrl;
  363.         const int hiMtrl = passedPawnHiMtrl;
  364.         mhd.wPassedPawnIPF = interpolate(bMtrlNoPawns-nBN*(nV/2), loMtrl, 0, hiMtrl, IPOLMAX);
  365.         mhd.bPassedPawnIPF = interpolate(wMtrlNoPawns-nWN*(nV/2), loMtrl, 0, hiMtrl, IPOLMAX);
  366.     }
  367.     { // King safety
  368.         const int loMtrl = kingSafetyLoMtrl;
  369.         const int hiMtrl = kingSafetyHiMtrl;
  370.         const int m = (wMtrlNoPawns + bMtrlNoPawns) / 2;
  371.         mhd.kingSafetyIPF = interpolate(m, loMtrl, 0, hiMtrl, IPOLMAX);
  372.         if (wCorr + bCorr > 200)
  373.             mhd.kingSafetyIPF = mhd.kingSafetyIPF * 200 / (wCorr + bCorr);
  374.     }
  375.     { // Different color bishops
  376.         const int loMtrl = oppoBishopLoMtrl;
  377.         const int hiMtrl = oppoBishopHiMtrl;
  378.         const int m = wMtrlNoPawns + bMtrlNoPawns;
  379.         mhd.diffColorBishopIPF = interpolate(m, loMtrl, 0, hiMtrl, IPOLMAX);
  380.     }
  381.     { // Knight outpost
  382.         const int loMtrl = knightOutpostLoMtrl;
  383.         const int hiMtrl = knightOutpostHiMtrl;
  384.         mhd.wKnightOutPostIPF = interpolate(bMtrlPawns, loMtrl, 0, hiMtrl, IPOLMAX);
  385.         mhd.bKnightOutPostIPF = interpolate(wMtrlPawns, loMtrl, 0, hiMtrl, IPOLMAX);
  386.     }
  387. }
  388.  
  389. int
  390. Evaluate::tradeBonus(const Position& pos, int wCorr, int bCorr) const {
  391.     const int wM = pos.wMtrl() + wCorr;
  392.     const int bM = pos.bMtrl() + bCorr;
  393.     const int wPawn = pos.wMtrlPawns();
  394.     const int bPawn = pos.bMtrlPawns();
  395.     const int deltaScore = wM - bM;
  396.  
  397.     int pBonus = 0;
  398.     pBonus += interpolate((deltaScore > 0) ? wPawn : bPawn, 0, -pawnTradePenalty * deltaScore / 100, pawnTradeThreshold, 0);
  399.     pBonus += interpolate((deltaScore > 0) ? bM : wM, 0, pieceTradeBonus * deltaScore / 100, pieceTradeThreshold * 100, 0);
  400.  
  401.     return pBonus;
  402. }
  403.  
  404. int
  405. Evaluate::pieceSquareEval(const Position& pos) {
  406.     int score = 0;
  407.  
  408.     // Kings/pawns
  409.     if (pos.wMtrlPawns() + pos.bMtrlPawns() > 0) {
  410.         {
  411.             const int k1 = pos.psScore1(Piece::WKING) + pos.psScore1(Piece::WPAWN);
  412.             const int k2 = pos.psScore2(Piece::WKING) + pos.psScore2(Piece::WPAWN);
  413.             score += interpolate(k2, k1, mhd->wPawnIPF);
  414.         }
  415.         {
  416.             const int k1 = pos.psScore1(Piece::BKING) + pos.psScore1(Piece::BPAWN);
  417.             const int k2 = pos.psScore2(Piece::BKING) + pos.psScore2(Piece::BPAWN);
  418.             score -= interpolate(k2, k1, mhd->bPawnIPF);
  419.         }
  420.     } else { // Use symmetric tables if no pawns left
  421.         if (pos.wMtrl() > pos.bMtrl())
  422.             score += EndGameEval::mateEval(pos.getKingSq(true), pos.getKingSq(false));
  423.         else if (pos.wMtrl() < pos.bMtrl())
  424.             score -= EndGameEval::mateEval(pos.getKingSq(false), pos.getKingSq(true));
  425.         else
  426.             score += EndGameEval::winKingTable[pos.getKingSq(true)] -
  427.                      EndGameEval::winKingTable[pos.getKingSq(false)];
  428.     }
  429.  
  430.     // Knights/bishops
  431.     {
  432.         int n1 = pos.psScore1(Piece::WKNIGHT) + pos.psScore1(Piece::WBISHOP);
  433.         int n2 = pos.psScore2(Piece::WKNIGHT) + pos.psScore2(Piece::WBISHOP);
  434.         score += interpolate(n2, n1, mhd->wKnightIPF);
  435.         n1 = pos.psScore1(Piece::BKNIGHT) + pos.psScore1(Piece::BBISHOP);
  436.         n2 = pos.psScore2(Piece::BKNIGHT) + pos.psScore2(Piece::BBISHOP);
  437.         score -= interpolate(n2, n1, mhd->bKnightIPF);
  438.     }
  439.  
  440.     // Queens
  441.     {
  442.         const U64 occupied = pos.occupiedBB();
  443.         int q1 = pos.psScore1(Piece::WQUEEN);
  444.         int q2 = pos.psScore2(Piece::WQUEEN);
  445.         score += interpolate(q2, q1, mhd->queenIPF);
  446.         U64 m = pos.pieceTypeBB(Piece::WQUEEN);
  447.         while (m != 0) {
  448.             int sq = BitBoard::extractSquare(m);
  449.             U64 atk = BitBoard::rookAttacks(sq, occupied) | BitBoard::bishopAttacks(sq, occupied);
  450.             wAttacksBB |= atk;
  451.             score += queenMobScore[BitBoard::bitCount(atk & ~(pos.whiteBB() | bPawnAttacks))];
  452.             bKingAttacks += BitBoard::bitCount(atk & bKingZone) * 2;
  453.         }
  454.         q1 = pos.psScore1(Piece::BQUEEN);
  455.         q2 = pos.psScore2(Piece::BQUEEN);
  456.         score -= interpolate(q2, q1, mhd->queenIPF);
  457.         m = pos.pieceTypeBB(Piece::BQUEEN);
  458.         while (m != 0) {
  459.             int sq = BitBoard::extractSquare(m);
  460.             U64 atk = BitBoard::rookAttacks(sq, occupied) | BitBoard::bishopAttacks(sq, occupied);
  461.             bAttacksBB |= atk;
  462.             score -= queenMobScore[BitBoard::bitCount(atk & ~(pos.blackBB() | wPawnAttacks))];
  463.             wKingAttacks += BitBoard::bitCount(atk & wKingZone) * 2;
  464.         }
  465.     }
  466.  
  467.     // Rooks
  468.     {
  469.         int r1 = pos.psScore1(Piece::WROOK);
  470.         if (r1 != 0) {
  471.             const int nP = BitBoard::bitCount(pos.pieceTypeBB(Piece::BPAWN));
  472.             const int s = r1 * std::min(nP, 6) / 6;
  473.             score += s;
  474.         }
  475.         r1 = pos.psScore1(Piece::BROOK);
  476.         if (r1 != 0) {
  477.             const int nP = BitBoard::bitCount(pos.pieceTypeBB(Piece::WPAWN));
  478.             const int s = r1 * std::min(nP, 6) / 6;
  479.             score -= s;
  480.         }
  481.     }
  482.  
  483.     return score;
  484. }
  485.  
  486. int
  487. Evaluate::castleBonus(const Position& pos) {
  488.     if (pos.getCastleMask() == 0) return 0;
  489.  
  490.     const int k1 = kt1b[G8] - kt1b[E8];
  491.     const int k2 = kt2b[G8] - kt2b[E8];
  492.     const int ks = interpolate(k2, k1, mhd->castleIPF);
  493.  
  494.     const int castleValue = ks + rt1b[F8] - rt1b[H8];
  495.     if (castleValue <= 0)
  496.         return 0;
  497.  
  498.     U64 occupied = pos.occupiedBB();
  499.     int tmp = (int) (occupied & BitBoard::sqMask(B1,C1,D1,F1,G1));
  500.     if (pos.a1Castle()) tmp |= 1;
  501.     if (pos.h1Castle()) tmp |= (1 << 7);
  502.     const int wBonus = (castleValue * castleMaskFactor[tmp]) >> 7;
  503.  
  504.     tmp = (int) ((occupied >> 56) & BitBoard::sqMask(B1,C1,D1,F1,G1));
  505.     if (pos.a8Castle()) tmp |= 1;
  506.     if (pos.h8Castle()) tmp |= (1 << 7);
  507.     const int bBonus = (castleValue * castleMaskFactor[tmp]) >> 7;
  508.  
  509.     return wBonus - bBonus;
  510. }
  511.  
  512. int
  513. Evaluate::pawnBonus(const Position& pos) {
  514.     U64 key = pos.pawnZobristHash();
  515.     PawnHashData& phd = getPawnHashEntry(pawnHash, key);
  516.     if (phd.key != key)
  517.         computePawnHashData(pos, phd);
  518.     this->phd = &phd;
  519.     int score = phd.score;
  520.  
  521.     // Bonus for own king supporting passed pawns
  522.     int passedScore = phd.passedBonusW;
  523.     const U64 passedPawnsW = phd.passedPawns & pos.pieceTypeBB(Piece::WPAWN);
  524.     U64 m = passedPawnsW;
  525.     if (m != 0) {
  526.         U64 kMask = pos.pieceTypeBB(Piece::WKING);
  527.         int ky = Position::getY(pos.getKingSq(true));
  528.         if ((m << 8) & kMask)
  529.             passedScore += kingPPSupportK[0] * kingPPSupportP[ky-1] / 32;
  530.         else if ((m << 16) & kMask)
  531.             passedScore += kingPPSupportK[1] * kingPPSupportP[ky-2] / 32;
  532.         m = ((m & BitBoard::maskAToGFiles) << 1) | ((m & BitBoard::maskBToHFiles) >> 1);
  533.         if (m & kMask)
  534.             passedScore += kingPPSupportK[2] * kingPPSupportP[ky-0] / 32;
  535.         if ((m << 8) & kMask)
  536.             passedScore += kingPPSupportK[3] * kingPPSupportP[ky-1] / 32;
  537.         if ((m << 16) & kMask)
  538.             passedScore += kingPPSupportK[4] * kingPPSupportP[ky-2] / 32;
  539.  
  540.         // Penalty for opponent pieces blocking passed pawns
  541.         U64 ppBlockSquares = passedPawnsW << 8;
  542.         if (ppBlockSquares & pos.blackBB()) {
  543.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::BKNIGHT)) * ppBlockerBonus[0];
  544.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::BBISHOP)) * ppBlockerBonus[1];
  545.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::BROOK))   * ppBlockerBonus[2];
  546.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::BQUEEN))  * ppBlockerBonus[3];
  547.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::BKING))   * ppBlockerBonus[4];
  548.         }
  549.         ppBlockSquares = BitBoard::northFill(passedPawnsW << 16);
  550.         if (ppBlockSquares & pos.blackBB()) {
  551.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::BKNIGHT)) * ppBlockerBonus[5];
  552.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::BBISHOP)) * ppBlockerBonus[6];
  553.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::BROOK))   * ppBlockerBonus[7];
  554.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::BQUEEN))  * ppBlockerBonus[8];
  555.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::BKING))   * ppBlockerBonus[9];
  556.         }
  557.  
  558.         // Bonus for rook behind passed pawn
  559.         m = BitBoard::southFill(passedPawnsW);
  560.         passedScore += RBehindPP1 * BitBoard::bitCount(m & pos.pieceTypeBB(Piece::WROOK));
  561.         passedScore -= RBehindPP2 * BitBoard::bitCount(m & pos.pieceTypeBB(Piece::BROOK));
  562.     }
  563.     score += interpolate(passedScore * passedPawnEGFactor / 32, passedScore, mhd->wPassedPawnIPF);
  564.  
  565.     passedScore = phd.passedBonusB;
  566.     const U64 passedPawnsB = phd.passedPawns & pos.pieceTypeBB(Piece::BPAWN);
  567.     m = passedPawnsB;
  568.     if (m != 0) {
  569.         U64 kMask = pos.pieceTypeBB(Piece::BKING);
  570.         int ky = Position::getY(pos.getKingSq(false));
  571.         if ((m >> 8) & kMask)
  572.             passedScore += kingPPSupportK[0] * kingPPSupportP[6-ky] / 32;
  573.         else if ((m >> 16) & kMask)
  574.             passedScore += kingPPSupportK[1] * kingPPSupportP[5-ky] / 32;
  575.         m = ((m & BitBoard::maskAToGFiles) << 1) | ((m & BitBoard::maskBToHFiles) >> 1);
  576.         if (m & kMask)
  577.             passedScore += kingPPSupportK[2] * kingPPSupportP[7-ky] / 32;
  578.         if ((m >> 8) & kMask)
  579.             passedScore += kingPPSupportK[3] * kingPPSupportP[6-ky] / 32;
  580.         if ((m >> 16) & kMask)
  581.             passedScore += kingPPSupportK[4] * kingPPSupportP[5-ky] / 32;
  582.  
  583.         // Penalty for opponent pieces blocking passed pawns
  584.         U64 ppBlockSquares = passedPawnsB >> 8;
  585.         if (ppBlockSquares & pos.whiteBB()) {
  586.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::WKNIGHT)) * ppBlockerBonus[0];
  587.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::WBISHOP)) * ppBlockerBonus[1];
  588.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::WROOK))   * ppBlockerBonus[2];
  589.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::WQUEEN))  * ppBlockerBonus[3];
  590.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::WKING))   * ppBlockerBonus[4];
  591.         }
  592.         ppBlockSquares = BitBoard::southFill(passedPawnsB >> 16);
  593.         if (ppBlockSquares && pos.whiteBB()) {
  594.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::WKNIGHT)) * ppBlockerBonus[5];
  595.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::WBISHOP)) * ppBlockerBonus[6];
  596.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::WROOK))   * ppBlockerBonus[7];
  597.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::WQUEEN))  * ppBlockerBonus[8];
  598.             passedScore -= BitBoard::bitCount(ppBlockSquares & pos.pieceTypeBB(Piece::WKING))   * ppBlockerBonus[9];
  599.         }
  600.  
  601.         // Bonus for rook behind passed pawn
  602.         m = BitBoard::northFill(passedPawnsB);
  603.         passedScore += RBehindPP1 * BitBoard::bitCount(m & pos.pieceTypeBB(Piece::BROOK));
  604.         passedScore -= RBehindPP2 * BitBoard::bitCount(m & pos.pieceTypeBB(Piece::WROOK));
  605.     }
  606.     score -= interpolate(passedScore * passedPawnEGFactor / 32, passedScore, mhd->bPassedPawnIPF);
  607.  
  608.     // Passed pawns are more dangerous if enemy king is far away
  609.     const int hiMtrl = passedPawnHiMtrl;
  610.     m = passedPawnsW;
  611.     int bestWPawnDist = 8;
  612.     int bestWPromSq = -1;
  613.     if (m != 0) {
  614.         int mtrlNoPawns = pos.bMtrl() - pos.bMtrlPawns();
  615.         if (mtrlNoPawns < hiMtrl) {
  616.             int kingPos = pos.getKingSq(false);
  617.             while (m != 0) {
  618.                 int sq = BitBoard::extractSquare(m);
  619.                 int x = Position::getX(sq);
  620.                 int y = Position::getY(sq);
  621.                 int pawnDist = std::min(5, 7 - y);
  622.                 int kingDist = BitBoard::getKingDistance(kingPos, Position::getSquare(x, 7));
  623.                 int kScore = kingDist * 4;
  624.                 if (kingDist > pawnDist) kScore += (kingDist - pawnDist) * (kingDist - pawnDist);
  625.                 score += interpolate(kScore, 0, mhd->wPassedPawnIPF);
  626.                 if (!pos.isWhiteMove())
  627.                     kingDist--;
  628.                 if ((pawnDist < kingDist) && (mtrlNoPawns == 0)) {
  629.                     if (BitBoard::northFill(1ULL<<sq) & (1LL << pos.getKingSq(true)))
  630.                         pawnDist++; // Own king blocking pawn
  631.                     if (pawnDist < bestWPawnDist) {
  632.                         bestWPawnDist = pawnDist;
  633.                         bestWPromSq = Position::getSquare(x, 7);
  634.                     }
  635.                 }
  636.             }
  637.         }
  638.     }
  639.     int bestBPawnDist = 8;
  640.     int bestBPromSq = -1;
  641.     m = passedPawnsB;
  642.     if (m != 0) {
  643.         int mtrlNoPawns = pos.wMtrl() - pos.wMtrlPawns();
  644.         if (mtrlNoPawns < hiMtrl) {
  645.             int kingPos = pos.getKingSq(true);
  646.             while (m != 0) {
  647.                 int sq = BitBoard::extractSquare(m);
  648.                 int x = Position::getX(sq);
  649.                 int y = Position::getY(sq);
  650.                 int pawnDist = std::min(5, y);
  651.                 int kingDist = BitBoard::getKingDistance(kingPos, Position::getSquare(x, 0));
  652.                 int kScore = kingDist * 4;
  653.                 if (kingDist > pawnDist) kScore += (kingDist - pawnDist) * (kingDist - pawnDist);
  654.                 score -= interpolate(kScore, 0, mhd->bPassedPawnIPF);
  655.                 if (pos.isWhiteMove())
  656.                     kingDist--;
  657.                 if ((pawnDist < kingDist) && (mtrlNoPawns == 0)) {
  658.                     if (BitBoard::southFill(1ULL<<sq) & (1LL << pos.getKingSq(false)))
  659.                         pawnDist++; // Own king blocking pawn
  660.                     if (pawnDist < bestBPawnDist) {
  661.                         bestBPawnDist = pawnDist;
  662.                         bestBPromSq = Position::getSquare(x, 0);
  663.                     }
  664.                 }
  665.             }
  666.         }
  667.     }
  668.  
  669.     // Evaluate pawn races in pawn end games
  670.     const int prBonus = pawnRaceBonus;
  671.     if (bestWPromSq >= 0) {
  672.         if (bestBPromSq >= 0) {
  673.             int wPly = bestWPawnDist * 2; if (pos.isWhiteMove()) wPly--;
  674.             int bPly = bestBPawnDist * 2; if (!pos.isWhiteMove()) bPly--;
  675.             if (wPly < bPly - 1) {
  676.                 score += prBonus;
  677.             } else if (wPly == bPly - 1) {
  678.                 if (BitBoard::getDirection(bestWPromSq, pos.getKingSq(false)))
  679.                     score += prBonus;
  680.             } else if (wPly == bPly + 1) {
  681.                 if (BitBoard::getDirection(bestBPromSq, pos.getKingSq(true)))
  682.                     score -= prBonus;
  683.             } else {
  684.                 score -= prBonus;
  685.             }
  686.         } else
  687.             score += prBonus;
  688.     } else if (bestBPromSq >= 0)
  689.         score -= prBonus;
  690.  
  691.     return score;
  692. }
  693.  
  694. template <bool white>
  695. static inline int
  696. evalConnectedPP(int x, int y, U64 ppMask) {
  697.     if ((x >= 7) || !(BitBoard::maskFile[x+1] & ppMask))
  698.         return 0;
  699.  
  700.     int y2 = 0;
  701.     if (white) {
  702.         for (int i = 6; i >= 1; i--) {
  703.             int sq = Position::getSquare(x+1, i);
  704.             if (ppMask & (1ULL << sq)) {
  705.                 y2 = i;
  706.                 break;
  707.             }
  708.         }
  709.     } else {
  710.         for (int i = 1; i <= 6; i++) {
  711.             int sq = Position::getSquare(x+1, i);
  712.             if (ppMask & (1ULL << sq)) {
  713.                 y2 = i;
  714.                 break;
  715.             }
  716.         }
  717.     }
  718.     if (y2 == 0)
  719.         return 0;
  720.  
  721.     if (!white) {
  722.         y = 7 - y;
  723.         y2 = 7 - y2;
  724.     }
  725.     return connectedPPBonus[(y-1)*6 + (y2-1)];
  726. }
  727.  
  728. /** Compute subset of squares given by mask that white is in control over, ie
  729.  *  squares that have at least as many white pawn guards as black has pawn
  730.  *  attacks on the square. */
  731. static inline U64
  732. wPawnCtrlSquares(U64 mask, U64 wPawns, U64 bPawns) {
  733.     U64 wLAtks = (wPawns & BitBoard::maskBToHFiles) << 7;
  734.     U64 wRAtks = (wPawns & BitBoard::maskAToGFiles) << 9;
  735.     U64 bLAtks = (bPawns & BitBoard::maskBToHFiles) >> 9;
  736.     U64 bRAtks = (bPawns & BitBoard::maskAToGFiles) >> 7;
  737.     return ((mask & ~bLAtks & ~bRAtks) |
  738.             (mask & (bLAtks ^ bRAtks) & (wLAtks | wRAtks)) |
  739.             (mask & wLAtks & wRAtks));
  740. }
  741.  
  742. static inline U64
  743. bPawnCtrlSquares(U64 mask, U64 wPawns, U64 bPawns) {
  744.     U64 wLAtks = (wPawns & BitBoard::maskBToHFiles) << 7;
  745.     U64 wRAtks = (wPawns & BitBoard::maskAToGFiles) << 9;
  746.     U64 bLAtks = (bPawns & BitBoard::maskBToHFiles) >> 9;
  747.     U64 bRAtks = (bPawns & BitBoard::maskAToGFiles) >> 7;
  748.     return ((mask & ~wLAtks & ~wRAtks) |
  749.             (mask & (wLAtks ^ wRAtks) & (bLAtks | bRAtks)) |
  750.             (mask & bLAtks & bRAtks));
  751. }
  752.  
  753. U64
  754. Evaluate::computeStalePawns(const Position& pos) {
  755.     const U64 wPawns = pos.pieceTypeBB(Piece::WPAWN);
  756.     const U64 bPawns = pos.pieceTypeBB(Piece::BPAWN);
  757.  
  758.     // Compute stale white pawns
  759.     U64 wStale;
  760.     {
  761.         U64 wPawnCtrl = wPawnCtrlSquares(wPawns, wPawns, bPawns);
  762.         for (int i = 0; i < 4; i++)
  763.             wPawnCtrl |= wPawnCtrlSquares((wPawnCtrl << 8) & ~bPawns, wPawnCtrl, bPawns);
  764.         wPawnCtrl &= ~BitBoard::maskRow8;
  765.         U64 wPawnCtrlLAtk = (wPawnCtrl & BitBoard::maskBToHFiles) << 7;
  766.         U64 wPawnCtrlRAtk = (wPawnCtrl & BitBoard::maskAToGFiles) << 9;
  767.  
  768.         U64 bLAtks = (bPawns & BitBoard::maskBToHFiles) >> 9;
  769.         U64 bRAtks = (bPawns & BitBoard::maskAToGFiles) >> 7;
  770.         U64 wActive = ((bLAtks ^ bRAtks) |
  771.                        (bLAtks & bRAtks & (wPawnCtrlLAtk | wPawnCtrlRAtk)));
  772.         for (int i = 0; i < 4; i++)
  773.             wActive |= (wActive & ~(wPawns | bPawns)) >> 8;
  774.         wStale = wPawns & ~wActive;
  775.     }
  776.  
  777.     // Compute stale black pawns
  778.     U64 bStale;
  779.     {
  780.         U64 bPawnCtrl = bPawnCtrlSquares(bPawns, wPawns, bPawns);
  781.         for (int i = 0; i < 4; i++)
  782.             bPawnCtrl |= bPawnCtrlSquares((bPawnCtrl >> 8) & ~wPawns, wPawns, bPawnCtrl);
  783.         bPawnCtrl &= ~BitBoard::maskRow1;
  784.         U64 bPawnCtrlLAtk = (bPawnCtrl & BitBoard::maskBToHFiles) >> 9;
  785.         U64 bPawnCtrlRAtk = (bPawnCtrl & BitBoard::maskAToGFiles) >> 7;
  786.  
  787.         U64 wLAtks = (wPawns & BitBoard::maskBToHFiles) << 7;
  788.         U64 wRAtks = (wPawns & BitBoard::maskAToGFiles) << 9;
  789.         U64 bActive = ((wLAtks ^ wRAtks) |
  790.                        (wLAtks & wRAtks & (bPawnCtrlLAtk | bPawnCtrlRAtk)));
  791.         for (int i = 0; i < 4; i++)
  792.             bActive |= (bActive & ~(wPawns | bPawns)) << 8;
  793.         bStale = bPawns & ~bActive;
  794.     }
  795.  
  796.     return wStale | bStale;
  797. }
  798.  
  799. void
  800. Evaluate::computePawnHashData(const Position& pos, PawnHashData& ph) {
  801.     int score = 0;
  802.  
  803.     // Evaluate double pawns and pawn islands
  804.     const U64 wPawns = pos.pieceTypeBB(Piece::WPAWN);
  805.     const U64 wPawnFiles = BitBoard::southFill(wPawns) & 0xff;
  806.     const int wIslands = BitBoard::bitCount(((~wPawnFiles) >> 1) & wPawnFiles);
  807.  
  808.     const U64 bPawns = pos.pieceTypeBB(Piece::BPAWN);
  809.     const U64 bPawnFiles = BitBoard::southFill(bPawns) & 0xff;
  810.     const int bIslands = BitBoard::bitCount(((~bPawnFiles) >> 1) & bPawnFiles);
  811.     score -= (wIslands - bIslands) * pawnIslandPenalty;
  812.  
  813.     // Evaluate doubled pawns
  814.     const U64 wDoubled = BitBoard::northFill(wPawns << 8) & wPawns;
  815.     U64 m = wDoubled;
  816.     while (m != 0) {
  817.         int sq = BitBoard::extractSquare(m);
  818.         score -= pawnDoubledPenalty[Position::getX(sq)];
  819.     }
  820.     const U64 bDoubled = BitBoard::southFill(bPawns >> 8) & bPawns;
  821.     m = bDoubled;
  822.     while (m != 0) {
  823.         int sq = BitBoard::extractSquare(m);
  824.         score += pawnDoubledPenalty[Position::getX(sq)];
  825.     }
  826.  
  827.     // Evaluate isolated pawns
  828.     const U64 wIsolated = wPawns & ~BitBoard::northFill(BitBoard::southFill(
  829.             ((wPawns & BitBoard::maskAToGFiles) << 1) |
  830.             ((wPawns & BitBoard::maskBToHFiles) >> 1)));
  831.     m = wIsolated;
  832.     while (m != 0) {
  833.         int sq = BitBoard::extractSquare(m);
  834.         score -= pawnIsolatedPenalty[Position::getX(sq)];
  835.     }
  836.     const U64 bIsolated = bPawns & ~BitBoard::northFill(BitBoard::southFill(
  837.             ((bPawns & BitBoard::maskAToGFiles) << 1) |
  838.             ((bPawns & BitBoard::maskBToHFiles) >> 1)));
  839.     m = bIsolated;
  840.     while (m != 0) {
  841.         int sq = BitBoard::extractSquare(m);
  842.         score += pawnIsolatedPenalty[Position::getX(sq)];
  843.     }
  844.  
  845.     // Evaluate backward pawns, defined as a pawn that guards a friendly pawn,
  846.     // can't be guarded by friendly pawns, can advance, but can't advance without
  847.     // being captured by an enemy pawn.
  848.     const U64 bPawnNoAtks = ~BitBoard::southFill(bPawnAttacks);
  849.     const U64 wPawnNoAtks = ~BitBoard::northFill(wPawnAttacks);
  850.     ph.outPostsW = bPawnNoAtks & wPawnAttacks;
  851.     ph.outPostsB = wPawnNoAtks & bPawnAttacks;
  852.  
  853.     U64 wBackward = wPawns & ~((wPawns | bPawns) >> 8) & (bPawnAttacks >> 8) & wPawnNoAtks;
  854.     wBackward &= (((wPawns & BitBoard::maskBToHFiles) >> 9) |
  855.                   ((wPawns & BitBoard::maskAToGFiles) >> 7));
  856.     wBackward &= ~BitBoard::northFill(bPawnFiles);
  857.     U64 bBackward = bPawns & ~((wPawns | bPawns) << 8) & (wPawnAttacks << 8) & bPawnNoAtks;
  858.     bBackward &= (((bPawns & BitBoard::maskBToHFiles) << 7) |
  859.                   ((bPawns & BitBoard::maskAToGFiles) << 9));
  860.     bBackward &= ~BitBoard::northFill(wPawnFiles);
  861.     score -= (BitBoard::bitCount(wBackward) - BitBoard::bitCount(bBackward)) * pawnBackwardPenalty;
  862.  
  863.     // Evaluate "semi-backward pawns", defined as pawns on 2:nd or 3:rd rank that can advance,
  864.     // but the advanced pawn is attacked by an enemy pawn.
  865.     U64 wSemiBackward = wPawns & ~((wPawns | bPawns) >> 8) & (bPawnAttacks >> 8);
  866.     score -= BitBoard::bitCount(wSemiBackward & BitBoard::maskRow2) * pawnSemiBackwardPenalty1;
  867.     score -= BitBoard::bitCount(wSemiBackward & BitBoard::maskRow3) * pawnSemiBackwardPenalty2;
  868.     U64 bSemiBackward = bPawns & ~((wPawns | bPawns) << 8) & (wPawnAttacks << 8);
  869.     score += BitBoard::bitCount(bSemiBackward & BitBoard::maskRow7) * pawnSemiBackwardPenalty1;
  870.     score += BitBoard::bitCount(bSemiBackward & BitBoard::maskRow6) * pawnSemiBackwardPenalty2;
  871.  
  872.     // Evaluate passed pawn bonus, white
  873.     U64 passedPawnsW = wPawns & ~BitBoard::southFill(bPawns | bPawnAttacks | (wPawns >> 8));
  874.     int passedBonusW = 0;
  875.     if (passedPawnsW != 0) {
  876.         U64 m = passedPawnsW;
  877.         while (m != 0) {
  878.             int sq = BitBoard::extractSquare(m);
  879.             int x = Position::getX(sq);
  880.             int y = Position::getY(sq);
  881.             passedBonusW += passedPawnBonusX[x] + passedPawnBonusY[y];
  882.             passedBonusW += evalConnectedPP<true>(x, y, passedPawnsW);
  883.         }
  884.     }
  885.  
  886.     // Evaluate passed pawn bonus, black
  887.     U64 passedPawnsB = bPawns & ~BitBoard::northFill(wPawns | wPawnAttacks | (bPawns << 8));
  888.     int passedBonusB = 0;
  889.     if (passedPawnsB != 0) {
  890.         U64 m = passedPawnsB;
  891.         while (m != 0) {
  892.             int sq = BitBoard::extractSquare(m);
  893.             int x = Position::getX(sq);
  894.             int y = Position::getY(sq);
  895.             passedBonusB += passedPawnBonusX[x] + passedPawnBonusY[7-y];
  896.             passedBonusB += evalConnectedPP<false>(x, y, passedPawnsB);
  897.         }
  898.     }
  899.  
  900.     // Evaluate candidate passed pawn bonus
  901.     const U64 wLeftAtks  = (wPawns & BitBoard::maskBToHFiles) << 7;
  902.     const U64 wRightAtks = (wPawns & BitBoard::maskAToGFiles) << 9;
  903.     const U64 bLeftAtks  = (bPawns & BitBoard::maskBToHFiles) >> 9;
  904.     const U64 bRightAtks = (bPawns & BitBoard::maskAToGFiles) >> 7;
  905.     const U64 bBlockSquares = ((bLeftAtks | bRightAtks) & ~(wLeftAtks | wRightAtks)) |
  906.                               ((bLeftAtks & bRightAtks) & ~(wLeftAtks & wRightAtks));
  907.     const U64 wCandidates = wPawns & ~BitBoard::southFill(bPawns | (wPawns >> 8) | bBlockSquares) & ~passedPawnsW;
  908.  
  909.     const U64 wBlockSquares = ((wLeftAtks | wRightAtks) & ~(bLeftAtks | bRightAtks)) |
  910.                               ((wLeftAtks & wRightAtks) & ~(bLeftAtks & bRightAtks));
  911.     const U64 bCandidates = bPawns & ~BitBoard::northFill(wPawns | (bPawns << 8) | wBlockSquares) & ~passedPawnsB;
  912.  
  913.     {
  914.         U64 m = wCandidates;
  915.         while (m != 0) {
  916.             int sq = BitBoard::extractSquare(m);
  917.             int y = Position::getY(sq);
  918.             passedBonusW += candidatePassedBonus[y];
  919.         }
  920.     }
  921.     {
  922.         U64 m = bCandidates;
  923.         while (m != 0) {
  924.             int sq = BitBoard::extractSquare(m);
  925.             int y = Position::getY(sq);
  926.             passedBonusB += candidatePassedBonus[7-y];
  927.         }
  928.     }
  929.  
  930.     { // Bonus for pawns protected by pawns
  931.         U64 m = wPawnAttacks & wPawns;
  932.         while (m != 0) {
  933.             int sq = BitBoard::extractSquare(m);
  934.             score += protectedPawnBonus[63-sq];
  935.         }
  936.         m = bPawnAttacks & bPawns;
  937.         while (m != 0) {
  938.             int sq = BitBoard::extractSquare(m);
  939.             score -= protectedPawnBonus[sq];
  940.         }
  941.     }
  942.     { // Bonus for pawns attacked by pawns
  943.         U64 m = wPawnAttacks & bPawns;
  944.         while (m != 0) {
  945.             int sq = BitBoard::extractSquare(m);
  946.             score += attackedPawnBonus[63-sq];
  947.         }
  948.         m = bPawnAttacks & wPawns;
  949.         while (m != 0) {
  950.             int sq = BitBoard::extractSquare(m);
  951.             score -= attackedPawnBonus[sq];
  952.         }
  953.     }
  954.  
  955.     ph.key = pos.pawnZobristHash();
  956.     ph.score = score;
  957.     ph.passedBonusW = (S16)passedBonusW;
  958.     ph.passedBonusB = (S16)passedBonusB;
  959.     ph.passedPawns = passedPawnsW | passedPawnsB;
  960.     ph.stalePawns = computeStalePawns(pos) & ~passedPawnsW & ~passedPawnsB;
  961. }
  962.  
  963. int
  964. Evaluate::rookBonus(const Position& pos) {
  965.     int score = 0;
  966.     const U64 wPawns = pos.pieceTypeBB(Piece::WPAWN);
  967.     const U64 bPawns = pos.pieceTypeBB(Piece::BPAWN);
  968.     const U64 occupied = pos.occupiedBB();
  969.     U64 m = pos.pieceTypeBB(Piece::WROOK);
  970.     while (m != 0) {
  971.         int sq = BitBoard::extractSquare(m);
  972.         const int x = Position::getX(sq);
  973.         if ((wPawns & BitBoard::maskFile[x]) == 0) { // At least half-open file
  974.             score += (bPawns & BitBoard::maskFile[x]) == 0 ? (int)rookOpenBonus : (int)rookHalfOpenBonus; // Pierre-Marie Baty -- added type cast
  975.         } // Pierre-Marie Baty -- braces fix
  976.         U64 atk = BitBoard::rookAttacks(sq, occupied);
  977.         wAttacksBB |= atk;
  978.         score += rookMobScore[BitBoard::bitCount(atk & ~(pos.whiteBB() | bPawnAttacks))];
  979.         if ((atk & bKingZone) != 0)
  980.             bKingAttacks += BitBoard::bitCount(atk & bKingZone);
  981.     }
  982.     U64 r7 = pos.pieceTypeBB(Piece::WROOK) & BitBoard::maskRow7;
  983.     if (((r7 & (r7 - 1)) != 0) &&
  984.         ((pos.pieceTypeBB(Piece::BKING) & BitBoard::maskRow8) != 0))
  985.         score += rookDouble7thRowBonus; // Two rooks on 7:th row
  986.     m = pos.pieceTypeBB(Piece::BROOK);
  987.     while (m != 0) {
  988.         int sq = BitBoard::extractSquare(m);
  989.         const int x = Position::getX(sq);
  990.         if ((bPawns & BitBoard::maskFile[x]) == 0) {
  991.             score -= (wPawns & BitBoard::maskFile[x]) == 0 ? (int)rookOpenBonus : (int)rookHalfOpenBonus; // Pierre-Marie Baty -- added type cast
  992.         } // Pierre-Marie Baty -- braces fix
  993.         U64 atk = BitBoard::rookAttacks(sq, occupied);
  994.         bAttacksBB |= atk;
  995.         score -= rookMobScore[BitBoard::bitCount(atk & ~(pos.blackBB() | wPawnAttacks))];
  996.         if ((atk & wKingZone) != 0)
  997.             wKingAttacks += BitBoard::bitCount(atk & wKingZone);
  998.     }
  999.     r7 = pos.pieceTypeBB(Piece::BROOK) & BitBoard::maskRow2;
  1000.     if (((r7 & (r7 - 1)) != 0) &&
  1001.         ((pos.pieceTypeBB(Piece::WKING) & BitBoard::maskRow1) != 0))
  1002.       score -= rookDouble7thRowBonus; // Two rooks on 2:nd row
  1003.     return score;
  1004. }
  1005.  
  1006. int
  1007. Evaluate::bishopEval(const Position& pos, int oldScore) {
  1008.     int score = 0;
  1009.     const U64 occupied = pos.occupiedBB();
  1010.     const U64 wBishops = pos.pieceTypeBB(Piece::WBISHOP);
  1011.     const U64 bBishops = pos.pieceTypeBB(Piece::BBISHOP);
  1012.     if ((wBishops | bBishops) == 0)
  1013.         return 0;
  1014.     U64 m = wBishops;
  1015.     while (m != 0) {
  1016.         int sq = BitBoard::extractSquare(m);
  1017.         U64 atk = BitBoard::bishopAttacks(sq, occupied);
  1018.         wAttacksBB |= atk;
  1019.         score += bishMobScore[BitBoard::bitCount(atk & ~(pos.whiteBB() | bPawnAttacks))];
  1020.         if ((atk & bKingZone) != 0)
  1021.             bKingAttacks += BitBoard::bitCount(atk & bKingZone);
  1022.     }
  1023.     m = bBishops;
  1024.     while (m != 0) {
  1025.         int sq = BitBoard::extractSquare(m);
  1026.         U64 atk = BitBoard::bishopAttacks(sq, occupied);
  1027.         bAttacksBB |= atk;
  1028.         score -= bishMobScore[BitBoard::bitCount(atk & ~(pos.blackBB() | wPawnAttacks))];
  1029.         if ((atk & wKingZone) != 0)
  1030.             wKingAttacks += BitBoard::bitCount(atk & wKingZone);
  1031.     }
  1032.  
  1033.     bool whiteDark  = (wBishops & BitBoard::maskDarkSq ) != 0;
  1034.     bool whiteLight = (wBishops & BitBoard::maskLightSq) != 0;
  1035.     bool blackDark  = (bBishops & BitBoard::maskDarkSq ) != 0;
  1036.     bool blackLight = (bBishops & BitBoard::maskLightSq) != 0;
  1037.     int numWhite = (whiteDark ? 1 : 0) + (whiteLight ? 1 : 0);
  1038.     int numBlack = (blackDark ? 1 : 0) + (blackLight ? 1 : 0);
  1039.  
  1040.     // Bishop pair bonus
  1041.     if (numWhite == 2) {
  1042.         int numMinors = BitBoard::bitCount(pos.pieceTypeBB(Piece::BBISHOP, Piece::BKNIGHT));
  1043.         const int numPawns = BitBoard::bitCount(pos.pieceTypeBB(Piece::WPAWN));
  1044.         score += bishopPairValue[std::min(numMinors,3)] - numPawns * bishopPairPawnPenalty;
  1045.     }
  1046.     if (numBlack == 2) {
  1047.         int numMinors = BitBoard::bitCount(pos.pieceTypeBB(Piece::WBISHOP, Piece::WKNIGHT));
  1048.         const int numPawns = BitBoard::bitCount(pos.pieceTypeBB(Piece::BPAWN));
  1049.         score -= bishopPairValue[std::min(numMinors,3)] - numPawns * bishopPairPawnPenalty;
  1050.     }
  1051.  
  1052.     if ((numWhite == 1) && (numBlack == 1) && (whiteDark != blackDark) &&
  1053.         (pos.wMtrl() - pos.wMtrlPawns() == pos.bMtrl() - pos.bMtrlPawns())) {
  1054.         const int penalty = (oldScore + score) * oppoBishopPenalty / 128;
  1055.         score -= interpolate(penalty, 0, mhd->diffColorBishopIPF);
  1056.     } else {
  1057.         if (numWhite == 1) {
  1058.             U64 bishColorMask = whiteDark ? BitBoard::maskDarkSq : BitBoard::maskLightSq;
  1059.             U64 m = pos.pieceTypeBB(Piece::WPAWN) & bishColorMask;
  1060.             m |= (m << 8) & pos.pieceTypeBB(Piece::BPAWN);
  1061.             score -= 2 * BitBoard::bitCount(m);
  1062.         }
  1063.         if (numBlack == 1) {
  1064.             U64 bishColorMask = blackDark ? BitBoard::maskDarkSq : BitBoard::maskLightSq;
  1065.             U64 m = pos.pieceTypeBB(Piece::BPAWN) & bishColorMask;
  1066.             m |= (m >> 8) & pos.pieceTypeBB(Piece::WPAWN);
  1067.             score += 2 * BitBoard::bitCount(m);
  1068.         }
  1069.     }
  1070.  
  1071.     // Penalty for bishop trapped behind pawn at a2/h2/a7/h7
  1072.     if (((wBishops | bBishops) & BitBoard::sqMask(A2,H2,A7,H7)) != 0) {
  1073.         const int bTrapped = trappedBishopPenalty;
  1074.         if ((pos.getPiece(A7) == Piece::WBISHOP) &&
  1075.             (pos.getPiece(B6) == Piece::BPAWN) &&
  1076.             (pos.getPiece(C7) == Piece::BPAWN))
  1077.             score -= bTrapped;
  1078.         if ((pos.getPiece(H7) == Piece::WBISHOP) &&
  1079.             (pos.getPiece(G6) == Piece::BPAWN) &&
  1080.             (pos.getPiece(F7) == Piece::BPAWN))
  1081.             score -= bTrapped;
  1082.         if ((pos.getPiece(A2)  == Piece::BBISHOP) &&
  1083.             (pos.getPiece(B3) == Piece::WPAWN) &&
  1084.             (pos.getPiece(C2) == Piece::WPAWN))
  1085.             score += bTrapped;
  1086.         if ((pos.getPiece(H2) == Piece::BBISHOP) &&
  1087.             (pos.getPiece(G3) == Piece::WPAWN) &&
  1088.             (pos.getPiece(F2) == Piece::WPAWN))
  1089.             score += bTrapped;
  1090.     }
  1091.  
  1092.     return score;
  1093. }
  1094.  
  1095. int
  1096. Evaluate::knightEval(const Position& pos) {
  1097.     int score = 0;
  1098.     U64 wKnights = pos.pieceTypeBB(Piece::WKNIGHT);
  1099.     U64 bKnights = pos.pieceTypeBB(Piece::BKNIGHT);
  1100.     if ((wKnights | bKnights) == 0)
  1101.         return 0;
  1102.  
  1103.     // Knight mobility
  1104.     U64 m = wKnights;
  1105.     while (m != 0) {
  1106.         int sq = BitBoard::extractSquare(m);
  1107.         U64 atk = BitBoard::knightAttacks[sq];
  1108.         wAttacksBB |= atk;
  1109.         score += knightMobScoreA[sq][BitBoard::bitCount(atk & ~pos.whiteBB() & ~bPawnAttacks)];
  1110.     }
  1111.  
  1112.     m = bKnights;
  1113.     while (m != 0) {
  1114.         int sq = BitBoard::extractSquare(m);
  1115.         U64 atk = BitBoard::knightAttacks[sq];
  1116.         bAttacksBB |= atk;
  1117.         score -= knightMobScoreA[sq][BitBoard::bitCount(atk & ~pos.blackBB() & ~wPawnAttacks)];
  1118.     }
  1119.  
  1120.     m = wKnights & phd->outPostsW;
  1121.     if (m != 0) {
  1122.         int outPost = 0;
  1123.         while (m != 0) {
  1124.             int sq = BitBoard::extractSquare(m);
  1125.             outPost += knightOutpostBonus[63-sq];
  1126.         }
  1127.         score += interpolate(0, outPost, mhd->wKnightOutPostIPF);
  1128.     }
  1129.  
  1130.     m = bKnights & phd->outPostsB;
  1131.     if (m != 0) {
  1132.         int outPost = 0;
  1133.         while (m != 0) {
  1134.             int sq = BitBoard::extractSquare(m);
  1135.             outPost += knightOutpostBonus[sq];
  1136.         }
  1137.         score -= interpolate(0, outPost, mhd->bKnightOutPostIPF);
  1138.     }
  1139.  
  1140.     return score;
  1141. }
  1142.  
  1143. int
  1144. Evaluate::threatBonus(const Position& pos) {
  1145.     int score = 0;
  1146.  
  1147.     // Sum values for all black pieces under attack
  1148.     wAttacksBB &= pos.pieceTypeBB(Piece::BKNIGHT, Piece::BBISHOP, Piece::BROOK, Piece::BQUEEN);
  1149.     wAttacksBB |= wPawnAttacks;
  1150.     U64 m = wAttacksBB & pos.blackBB() & ~pos.pieceTypeBB(Piece::BKING);
  1151.     int tmp = 0;
  1152.     while (m != 0) {
  1153.         int sq = BitBoard::extractSquare(m);
  1154.         tmp += ::pieceValue[pos.getPiece(sq)];
  1155.     }
  1156.     score += tmp + tmp * tmp / threatBonus2;
  1157.  
  1158.     // Sum values for all white pieces under attack
  1159.     bAttacksBB &= pos.pieceTypeBB(Piece::WKNIGHT, Piece::WBISHOP, Piece::WROOK, Piece::WQUEEN);
  1160.     bAttacksBB |= bPawnAttacks;
  1161.     m = bAttacksBB & pos.whiteBB() & ~pos.pieceTypeBB(Piece::WKING);
  1162.     tmp = 0;
  1163.     while (m != 0) {
  1164.         int sq = BitBoard::extractSquare(m);
  1165.         tmp += ::pieceValue[pos.getPiece(sq)];
  1166.     }
  1167.     score -= tmp + tmp * tmp / threatBonus2;
  1168.     return score / threatBonus1;
  1169. }
  1170.  
  1171. int
  1172. Evaluate::protectBonus(const Position& pos) {
  1173.     int score = 0;
  1174.     score += BitBoard::bitCount(pos.pieceTypeBB(Piece::WKNIGHT) & wPawnAttacks) * ::protectBonus[0];
  1175.     score += BitBoard::bitCount(pos.pieceTypeBB(Piece::WBISHOP) & wPawnAttacks) * ::protectBonus[1];
  1176.     score += BitBoard::bitCount(pos.pieceTypeBB(Piece::WROOK  ) & wPawnAttacks) * ::protectBonus[2];
  1177.     score += BitBoard::bitCount(pos.pieceTypeBB(Piece::WQUEEN ) & wPawnAttacks) * ::protectBonus[3];
  1178.     score -= BitBoard::bitCount(pos.pieceTypeBB(Piece::BKNIGHT) & bPawnAttacks) * ::protectBonus[0];
  1179.     score -= BitBoard::bitCount(pos.pieceTypeBB(Piece::BBISHOP) & bPawnAttacks) * ::protectBonus[1];
  1180.     score -= BitBoard::bitCount(pos.pieceTypeBB(Piece::BROOK  ) & bPawnAttacks) * ::protectBonus[2];
  1181.     score -= BitBoard::bitCount(pos.pieceTypeBB(Piece::BQUEEN ) & bPawnAttacks) * ::protectBonus[3];
  1182.     return score;
  1183. }
  1184.  
  1185. /** Compute king safety for both kings. */
  1186. int
  1187. Evaluate::kingSafety(const Position& pos) {
  1188.     const int minM = (rV + bV) * 2;
  1189.     const int m = pos.wMtrl() - pos.wMtrlPawns() + pos.bMtrl() - pos.bMtrlPawns();
  1190.     if (m <= minM)
  1191.         return 0;
  1192.  
  1193.     const int wKing = pos.getKingSq(true);
  1194.     const int bKing = pos.getKingSq(false);
  1195.     int score = kingSafetyKPPart(pos);
  1196.     if (Position::getY(wKing) == 0) {
  1197.         if (((pos.pieceTypeBB(Piece::WKING) & BitBoard::sqMask(F1,G1)) != 0) &&
  1198.             ((pos.pieceTypeBB(Piece::WROOK) & BitBoard::sqMask(G1,H1)) != 0) &&
  1199.             ((pos.pieceTypeBB(Piece::WPAWN) & BitBoard::maskFile[6]) != 0)) {
  1200.             score -= ((pos.pieceTypeBB(Piece::WPAWN) & BitBoard::maskFile[7]) != 0) ?
  1201.                      (int)trappedRookPenalty1 : (int)trappedRookPenalty2; // Pierre-Marie Baty -- added type cast
  1202.         } else
  1203.         if (((pos.pieceTypeBB(Piece::WKING) & BitBoard::sqMask(B1,C1)) != 0) &&
  1204.             ((pos.pieceTypeBB(Piece::WROOK) & BitBoard::sqMask(A1,B1)) != 0) &&
  1205.             ((pos.pieceTypeBB(Piece::WPAWN) & BitBoard::maskFile[1]) != 0)) {
  1206.             score -= ((pos.pieceTypeBB(Piece::WPAWN) & BitBoard::maskFile[0]) != 0) ?
  1207.                      (int)trappedRookPenalty1 : (int)trappedRookPenalty2; // Pierre-Marie Baty -- added type cast
  1208.         }
  1209.     }
  1210.     if (Position::getY(bKing) == 7) {
  1211.         if (((pos.pieceTypeBB(Piece::BKING) & BitBoard::sqMask(F8,G8)) != 0) &&
  1212.             ((pos.pieceTypeBB(Piece::BROOK) & BitBoard::sqMask(G8,H8)) != 0) &&
  1213.             ((pos.pieceTypeBB(Piece::BPAWN) & BitBoard::maskFile[6]) != 0)) {
  1214.             score += ((pos.pieceTypeBB(Piece::BPAWN) & BitBoard::maskFile[7]) != 0) ?
  1215.                      (int)trappedRookPenalty1 : (int)trappedRookPenalty2; // Pierre-Marie Baty -- added type cast
  1216.         } else
  1217.         if (((pos.pieceTypeBB(Piece::BKING) & BitBoard::sqMask(B8,C8)) != 0) &&
  1218.             ((pos.pieceTypeBB(Piece::BROOK) & BitBoard::sqMask(A8,B8)) != 0) &&
  1219.             ((pos.pieceTypeBB(Piece::BPAWN) & BitBoard::maskFile[1]) != 0)) {
  1220.             score += ((pos.pieceTypeBB(Piece::BPAWN) & BitBoard::maskFile[0]) != 0) ?
  1221.                      (int)trappedRookPenalty1 : (int)trappedRookPenalty2; // Pierre-Marie Baty -- added type cast
  1222.         }
  1223.     }
  1224.  
  1225.     // Bonus for minor pieces protecting king
  1226.     score += BitBoard::bitCount(Evaluate::knightKingProtectPattern[wKing] & pos.pieceTypeBB(Piece::WKNIGHT)) * knightKingProtectBonus;
  1227.     score += BitBoard::bitCount(Evaluate::bishopKingProtectPattern[wKing] & pos.pieceTypeBB(Piece::WBISHOP)) * bishopKingProtectBonus;
  1228.     score -= BitBoard::bitCount(Evaluate::knightKingProtectPattern[bKing] & pos.pieceTypeBB(Piece::BKNIGHT)) * knightKingProtectBonus;
  1229.     score -= BitBoard::bitCount(Evaluate::bishopKingProtectPattern[bKing] & pos.pieceTypeBB(Piece::BBISHOP)) * bishopKingProtectBonus;
  1230.  
  1231.     score += kingAttackWeight[std::min(bKingAttacks, 13)] - kingAttackWeight[std::min(wKingAttacks, 13)];
  1232.     const int kSafety = interpolate(0, score, mhd->kingSafetyIPF);
  1233.     return kSafety;
  1234. }
  1235.  
  1236. template <bool white, bool right>
  1237. static inline int
  1238. evalKingPawnShelter(const Position& pos) {
  1239.     const int mPawn = white ? Piece::WPAWN : Piece::BPAWN;
  1240.     const int oPawn = white ? Piece::BPAWN : Piece::WPAWN;
  1241.  
  1242.     const int yBeg = white ? 1 :  6;
  1243.     const int yInc = white ? 1 : -1;
  1244.     const int yEnd = white ? 4 :  3;
  1245.     const int xBeg = right ? 5 :  2;
  1246.     const int xInc = right ? 1 : -1;
  1247.     const int xEnd = right ? 8 : -1;
  1248.     int idx = 0;
  1249.     int score = 0;
  1250.     for (int y = yBeg; y != yEnd; y += yInc) {
  1251.         for (int x = xBeg; x != xEnd; x += xInc) {
  1252.             int p = pos.getPiece(Position::getSquare(x, y));
  1253.             if (p == mPawn)
  1254.                 score += pawnShelterTable[idx];
  1255.             else if (p == oPawn)
  1256.                 score -= pawnStormTable[idx];
  1257.             idx++;
  1258.         }
  1259.     }
  1260.     return score;
  1261. }
  1262.  
  1263. int
  1264. Evaluate::kingSafetyKPPart(const Position& pos) {
  1265.     const U64 key = pos.pawnZobristHash() ^ pos.kingZobristHash();
  1266.     KingSafetyHashData& ksh = getKingSafetyHashEntry(kingSafetyHash, key);
  1267.     if (ksh.key != key) {
  1268.         int score = 0;
  1269.         const U64 wPawns = pos.pieceTypeBB(Piece::WPAWN);
  1270.         const U64 bPawns = pos.pieceTypeBB(Piece::BPAWN);
  1271.         { // White pawn shelter bonus
  1272.             int safety = 0;
  1273.             int halfOpenFiles = 0;
  1274.             if (Position::getY(pos.wKingSq()) < 2) {
  1275.                 U64 shelter = 1ULL << Position::getX(pos.wKingSq());
  1276.                 shelter |= ((shelter & BitBoard::maskBToHFiles) >> 1) |
  1277.                            ((shelter & BitBoard::maskAToGFiles) << 1);
  1278.                 shelter <<= 8;
  1279.                 safety += kingSafetyWeight1 * BitBoard::bitCount(wPawns & shelter);
  1280.                 safety -= kingSafetyWeight2 * BitBoard::bitCount(bPawns & (shelter | (shelter << 8)));
  1281.                 shelter <<= 8;
  1282.                 safety += kingSafetyWeight3 * BitBoard::bitCount(wPawns & shelter);
  1283.                 shelter <<= 8;
  1284.                 safety -= kingSafetyWeight4 * BitBoard::bitCount(bPawns & shelter);
  1285.  
  1286.                 U64 wOpen = BitBoard::southFill(shelter) & (~BitBoard::southFill(wPawns)) & 0xff;
  1287.                 if (wOpen != 0) {
  1288.                     halfOpenFiles += kingSafetyHalfOpenBCDEFG1 * BitBoard::bitCount(wOpen & 0xe7);
  1289.                     halfOpenFiles += kingSafetyHalfOpenAH1 * BitBoard::bitCount(wOpen & 0x18);
  1290.                 }
  1291.                 U64 bOpen = BitBoard::southFill(shelter) & (~BitBoard::southFill(bPawns)) & 0xff;
  1292.                 if (bOpen != 0) {
  1293.                     halfOpenFiles += kingSafetyHalfOpenBCDEFG2 * BitBoard::bitCount(bOpen & 0xe7);
  1294.                     halfOpenFiles += kingSafetyHalfOpenAH2 * BitBoard::bitCount(bOpen & 0x18);
  1295.                 }
  1296.                 const int th = kingSafetyThreshold;
  1297.                 safety = std::min(safety, th);
  1298.  
  1299.                 const int xKing = Position::getX(pos.wKingSq());
  1300.                 if (xKing >= 5)
  1301.                     score += evalKingPawnShelter<true, true>(pos);
  1302.                 else if (xKing <= 2)
  1303.                     score += evalKingPawnShelter<true, false>(pos);
  1304.             }
  1305.             const int kSafety = safety - halfOpenFiles;
  1306.             score += kSafety;
  1307.         }
  1308.         { // Black pawn shelter bonus
  1309.             int safety = 0;
  1310.             int halfOpenFiles = 0;
  1311.             if (Position::getY(pos.bKingSq()) >= 6) {
  1312.                 U64 shelter = 1ULL << (56 + Position::getX(pos.bKingSq()));
  1313.                 shelter |= ((shelter & BitBoard::maskBToHFiles) >> 1) |
  1314.                            ((shelter & BitBoard::maskAToGFiles) << 1);
  1315.                 shelter >>= 8;
  1316.                 safety += kingSafetyWeight1 * BitBoard::bitCount(bPawns & shelter);
  1317.                 safety -= kingSafetyWeight2 * BitBoard::bitCount(wPawns & (shelter | (shelter >> 8)));
  1318.                 shelter >>= 8;
  1319.                 safety += kingSafetyWeight3 * BitBoard::bitCount(bPawns & shelter);
  1320.                 shelter >>= 8;
  1321.                 safety -= kingSafetyWeight4 * BitBoard::bitCount(wPawns & shelter);
  1322.  
  1323.                 U64 bOpen = BitBoard::southFill(shelter) & (~BitBoard::southFill(bPawns)) & 0xff;
  1324.                 if (bOpen != 0) {
  1325.                     halfOpenFiles += kingSafetyHalfOpenBCDEFG1 * BitBoard::bitCount(bOpen & 0xe7);
  1326.                     halfOpenFiles += kingSafetyHalfOpenAH1 * BitBoard::bitCount(bOpen & 0x18);
  1327.                 }
  1328.                 U64 wOpen = BitBoard::southFill(shelter) & (~BitBoard::southFill(wPawns)) & 0xff;
  1329.                 if (wOpen != 0) {
  1330.                     halfOpenFiles += kingSafetyHalfOpenBCDEFG2 * BitBoard::bitCount(wOpen & 0xe7);
  1331.                     halfOpenFiles += kingSafetyHalfOpenAH2 * BitBoard::bitCount(wOpen & 0x18);
  1332.                 }
  1333.                 const int th = kingSafetyThreshold;
  1334.                 safety = std::min(safety, th);
  1335.  
  1336.                 const int xKing = Position::getX(pos.bKingSq());
  1337.                 if (xKing >= 5)
  1338.                     score -= evalKingPawnShelter<false, true>(pos);
  1339.                 else if (xKing <= 2)
  1340.                     score -= evalKingPawnShelter<false, false>(pos);
  1341.             }
  1342.             const int kSafety = safety - halfOpenFiles;
  1343.             score -= kSafety;
  1344.         }
  1345.         // Pawn storm bonus
  1346.         static const int kingZone[8] = {0,0,0, 1,1, 2,2,2};
  1347.         static const U64 pStormMask[3] = { 0x0707070707070707ULL, 0, 0xE0E0E0E0E0E0E0E0ULL };
  1348.         const int wKingZone = kingZone[Position::getX(pos.wKingSq())];
  1349.         const int bKingZone = kingZone[Position::getX(pos.bKingSq())];
  1350.         const int kingDiff = std::abs(wKingZone - bKingZone);
  1351.         if (kingDiff > 1) {
  1352.             U64 m = wPawns & pStormMask[bKingZone];
  1353.             while (m != 0) {
  1354.                 int sq = BitBoard::extractSquare(m);
  1355.                 score += pawnStormBonus * (Position::getY(sq)-5);
  1356.             }
  1357.             m = bPawns & pStormMask[wKingZone];
  1358.             while (m != 0) {
  1359.                 int sq = BitBoard::extractSquare(m);
  1360.                 score += pawnStormBonus * (Position::getY(sq)-2);
  1361.             }
  1362.         }
  1363.  
  1364.         ksh.key = key;
  1365.         ksh.score = score;
  1366.     }
  1367.     return ksh.score;
  1368. }
  1369.  
  1370. std::shared_ptr<Evaluate::EvalHashTables>
  1371. Evaluate::getEvalHashTables() {
  1372.     return std::make_shared<EvalHashTables>();
  1373. }
  1374.  
  1375. int
  1376. Evaluate::swindleScore(int evalScore) {
  1377.     int sgn = evalScore >= 0 ? 1 : -1;
  1378.     int score = std::abs(evalScore) + 4;
  1379.     int lg = floorLog2(score);
  1380.     score = (lg - 3) * 4 + (score >> (lg - 2));
  1381.     return sgn * score;
  1382. }
  1383.