Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
99 pmbaty 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
}