Subversion Repositories Games.Chess Giants

Rev

Rev 169 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
96 pmbaty 1
/*
2
  Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
  Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
  Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
185 pmbaty 5
  Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
96 pmbaty 6
 
7
  Stockfish is free software: you can redistribute it and/or modify
8
  it under the terms of the GNU General Public License as published by
9
  the Free Software Foundation, either version 3 of the License, or
10
  (at your option) any later version.
11
 
12
  Stockfish is distributed in the hope that it will be useful,
13
  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
  GNU General Public License for more details.
16
 
17
  You should have received a copy of the GNU General Public License
18
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
*/
20
 
21
#include <algorithm>
22
#include <cassert>
23
#include <cstring>   // For std::memset
24
#include <iomanip>
25
#include <sstream>
26
 
154 pmbaty 27
#include "bitboard.h"
96 pmbaty 28
#include "evaluate.h"
29
#include "material.h"
30
#include "pawns.h"
185 pmbaty 31
#include "thread.h"
96 pmbaty 32
 
185 pmbaty 33
namespace Trace {
96 pmbaty 34
 
185 pmbaty 35
  enum Tracing { NO_TRACE, TRACE };
169 pmbaty 36
 
185 pmbaty 37
  enum Term { // The first 8 entries are reserved for PieceType
38
    MATERIAL = 8, IMBALANCE, MOBILITY, THREAT, PASSED, SPACE, INITIATIVE, TOTAL, TERM_NB
169 pmbaty 39
  };
40
 
185 pmbaty 41
  Score scores[TERM_NB][COLOR_NB];
96 pmbaty 42
 
185 pmbaty 43
  double to_cp(Value v) { return double(v) / PawnValueEg; }
169 pmbaty 44
 
185 pmbaty 45
  void add(int idx, Color c, Score s) {
46
    scores[idx][c] = s;
47
  }
96 pmbaty 48
 
185 pmbaty 49
  void add(int idx, Score w, Score b = SCORE_ZERO) {
50
    scores[idx][WHITE] = w;
51
    scores[idx][BLACK] = b;
52
  }
96 pmbaty 53
 
185 pmbaty 54
  std::ostream& operator<<(std::ostream& os, Score s) {
55
    os << std::setw(5) << to_cp(mg_value(s)) << " "
56
       << std::setw(5) << to_cp(eg_value(s));
57
    return os;
58
  }
96 pmbaty 59
 
185 pmbaty 60
  std::ostream& operator<<(std::ostream& os, Term t) {
96 pmbaty 61
 
185 pmbaty 62
    if (t == MATERIAL || t == IMBALANCE || t == INITIATIVE || t == TOTAL)
63
        os << " ----  ----"    << " | " << " ----  ----";
64
    else
65
        os << scores[t][WHITE] << " | " << scores[t][BLACK];
96 pmbaty 66
 
185 pmbaty 67
    os << " | " << scores[t][WHITE] - scores[t][BLACK] << "\n";
68
    return os;
96 pmbaty 69
  }
185 pmbaty 70
}
96 pmbaty 71
 
185 pmbaty 72
using namespace Trace;
96 pmbaty 73
 
185 pmbaty 74
namespace {
96 pmbaty 75
 
185 pmbaty 76
  constexpr Bitboard QueenSide   = FileABB | FileBBB | FileCBB | FileDBB;
77
  constexpr Bitboard CenterFiles = FileCBB | FileDBB | FileEBB | FileFBB;
78
  constexpr Bitboard KingSide    = FileEBB | FileFBB | FileGBB | FileHBB;
79
  constexpr Bitboard Center      = (FileDBB | FileEBB) & (Rank4BB | Rank5BB);
169 pmbaty 80
 
185 pmbaty 81
  constexpr Bitboard KingFlank[FILE_NB] = {
82
    QueenSide ^ FileDBB, QueenSide, QueenSide,
83
    CenterFiles, CenterFiles,
84
    KingSide, KingSide, KingSide ^ FileEBB
85
  };
169 pmbaty 86
 
185 pmbaty 87
  // Threshold for lazy and space evaluation
88
  constexpr Value LazyThreshold  = Value(1500);
89
  constexpr Value SpaceThreshold = Value(12222);
169 pmbaty 90
 
185 pmbaty 91
  // KingAttackWeights[PieceType] contains king attack weights by piece type
92
  constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 77, 55, 44, 10 };
169 pmbaty 93
 
185 pmbaty 94
  // Penalties for enemy's safe checks
95
  constexpr int QueenSafeCheck  = 780;
96
  constexpr int RookSafeCheck   = 880;
97
  constexpr int BishopSafeCheck = 435;
98
  constexpr int KnightSafeCheck = 790;
96 pmbaty 99
 
185 pmbaty 100
#define S(mg, eg) make_score(mg, eg)
154 pmbaty 101
 
169 pmbaty 102
  // MobilityBonus[PieceType-2][attacked] contains bonuses for middle and end game,
103
  // indexed by piece type and number of attacked squares in the mobility area.
185 pmbaty 104
  constexpr Score MobilityBonus[][32] = {
105
    { S(-62,-81), S(-53,-56), S(-12,-30), S( -4,-14), S(  3,  8), S( 13, 15), // Knights
106
      S( 22, 23), S( 28, 27), S( 33, 33) },
169 pmbaty 107
    { S(-48,-59), S(-20,-23), S( 16, -3), S( 26, 13), S( 38, 24), S( 51, 42), // Bishops
108
      S( 55, 54), S( 63, 57), S( 63, 65), S( 68, 73), S( 81, 78), S( 81, 86),
109
      S( 91, 88), S( 98, 97) },
110
    { S(-58,-76), S(-27,-18), S(-15, 28), S(-10, 55), S( -5, 69), S( -2, 82), // Rooks
111
      S(  9,112), S( 16,118), S( 30,132), S( 29,142), S( 32,155), S( 38,165),
112
      S( 46,166), S( 48,169), S( 58,171) },
113
    { S(-39,-36), S(-21,-15), S(  3,  8), S(  3, 18), S( 14, 34), S( 22, 54), // Queens
114
      S( 28, 61), S( 41, 73), S( 43, 79), S( 48, 92), S( 56, 94), S( 60,104),
115
      S( 60,113), S( 66,120), S( 67,123), S( 70,126), S( 71,133), S( 73,136),
116
      S( 79,140), S( 88,143), S( 88,148), S( 99,166), S(102,170), S(102,175),
117
      S(106,184), S(109,191), S(113,206), S(116,212) }
96 pmbaty 118
  };
119
 
169 pmbaty 120
  // Outpost[knight/bishop][supported by pawn] contains bonuses for minor
185 pmbaty 121
  // pieces if they occupy or can reach an outpost square, bigger if that
122
  // square is supported by a pawn.
123
  constexpr Score Outpost[][2] = {
169 pmbaty 124
    { S(22, 6), S(36,12) }, // Knight
125
    { S( 9, 2), S(15, 5) }  // Bishop
96 pmbaty 126
  };
127
 
185 pmbaty 128
  // RookOnFile[semiopen/open] contains bonuses for each rook when there is
129
  // no (friendly) pawn on the rook file.
130
  constexpr Score RookOnFile[] = { S(18, 7), S(44, 20) };
96 pmbaty 131
 
169 pmbaty 132
  // ThreatByMinor/ByRook[attacked PieceType] contains bonuses according to
133
  // which piece type attacks which one. Attacks on lesser pieces which are
134
  // pawn-defended are not considered.
185 pmbaty 135
  constexpr Score ThreatByMinor[PIECE_TYPE_NB] = {
136
    S(0, 0), S(0, 31), S(39, 42), S(57, 44), S(68, 112), S(62, 120)
154 pmbaty 137
  };
96 pmbaty 138
 
185 pmbaty 139
  constexpr Score ThreatByRook[PIECE_TYPE_NB] = {
140
    S(0, 0), S(0, 24), S(38, 71), S(38, 61), S(0, 38), S(51, 38)
96 pmbaty 141
  };
142
 
185 pmbaty 143
  // PassedRank[Rank] contains a bonus according to the rank of a passed pawn
144
  constexpr Score PassedRank[RANK_NB] = {
145
    S(0, 0), S(5, 18), S(12, 23), S(10, 31), S(57, 62), S(163, 167), S(271, 250)
96 pmbaty 146
  };
147
 
148
  // PassedFile[File] contains a bonus according to the file of a passed pawn
185 pmbaty 149
  constexpr Score PassedFile[FILE_NB] = {
150
    S( -1,  7), S( 0,  9), S(-9, -8), S(-30,-14),
151
    S(-30,-14), S(-9, -8), S( 0,  9), S( -1,  7)
96 pmbaty 152
  };
153
 
185 pmbaty 154
  // Assorted bonuses and penalties
155
  constexpr Score BishopPawns        = S(  3,  8);
156
  constexpr Score CloseEnemies       = S(  7,  0);
157
  constexpr Score CorneredBishop     = S( 50, 50);
158
  constexpr Score Hanging            = S( 62, 34);
159
  constexpr Score KingProtector      = S(  6,  7);
160
  constexpr Score KnightOnQueen      = S( 20, 12);
161
  constexpr Score LongDiagonalBishop = S( 44,  0);
162
  constexpr Score MinorBehindPawn    = S( 16,  0);
163
  constexpr Score Overload           = S( 12,  6);
164
  constexpr Score PawnlessFlank      = S( 18, 94);
165
  constexpr Score RestrictedPiece    = S(  7,  6);
166
  constexpr Score RookOnPawn         = S( 10, 28);
167
  constexpr Score SliderOnQueen      = S( 49, 21);
168
  constexpr Score ThreatByKing       = S( 21, 84);
169
  constexpr Score ThreatByPawnPush   = S( 48, 42);
170
  constexpr Score ThreatByRank       = S( 14,  3);
171
  constexpr Score ThreatBySafePawn   = S(169, 99);
172
  constexpr Score TrappedRook        = S( 98,  5);
173
  constexpr Score WeakQueen          = S( 51, 10);
174
  constexpr Score WeakUnopposedPawn  = S( 14, 20);
169 pmbaty 175
 
185 pmbaty 176
#undef S
169 pmbaty 177
 
185 pmbaty 178
  // Evaluation class computes and stores attacks tables and other working data
179
  template<Tracing T>
180
  class Evaluation {
96 pmbaty 181
 
185 pmbaty 182
  public:
183
    Evaluation() = delete;
184
    explicit Evaluation(const Position& p) : pos(p) {}
185
    Evaluation& operator=(const Evaluation&) = delete;
186
    Value value();
96 pmbaty 187
 
185 pmbaty 188
  private:
189
    template<Color Us> void initialize();
190
    template<Color Us, PieceType Pt> Score pieces();
191
    template<Color Us> Score king() const;
192
    template<Color Us> Score threats() const;
193
    template<Color Us> Score passed() const;
194
    template<Color Us> Score space() const;
195
    ScaleFactor scale_factor(Value eg) const;
196
    Score initiative(Value eg) const;
96 pmbaty 197
 
185 pmbaty 198
    const Position& pos;
199
    Material::Entry* me;
200
    Pawns::Entry* pe;
201
    Bitboard mobilityArea[COLOR_NB];
202
    Score mobility[COLOR_NB] = { SCORE_ZERO, SCORE_ZERO };
96 pmbaty 203
 
185 pmbaty 204
    // attackedBy[color][piece type] is a bitboard representing all squares
205
    // attacked by a given color and piece type. Special "piece types" which
206
    // is also calculated is ALL_PIECES.
207
    Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB];
96 pmbaty 208
 
185 pmbaty 209
    // attackedBy2[color] are the squares attacked by 2 pieces of a given color,
210
    // possibly via x-ray or by one pawn and one piece. Diagonal x-ray through
211
    // pawn or squares attacked by 2 pawns are not explicitly added.
212
    Bitboard attackedBy2[COLOR_NB];
96 pmbaty 213
 
185 pmbaty 214
    // kingRing[color] are the squares adjacent to the king, plus (only for a
215
    // king on its first rank) the squares two ranks in front. For instance,
216
    // if black's king is on g8, kingRing[BLACK] is f8, h8, f7, g7, h7, f6, g6
217
    // and h6. It is set to 0 when king safety evaluation is skipped.
218
    Bitboard kingRing[COLOR_NB];
96 pmbaty 219
 
185 pmbaty 220
    // kingAttackersCount[color] is the number of pieces of the given color
221
    // which attack a square in the kingRing of the enemy king.
222
    int kingAttackersCount[COLOR_NB];
223
 
224
    // kingAttackersWeight[color] is the sum of the "weights" of the pieces of
225
    // the given color which attack a square in the kingRing of the enemy king.
226
    // The weights of the individual piece types are given by the elements in
227
    // the KingAttackWeights array.
228
    int kingAttackersWeight[COLOR_NB];
229
 
230
    // kingAttacksCount[color] is the number of attacks by the given color to
231
    // squares directly adjacent to the enemy king. Pieces which attack more
232
    // than one square are counted multiple times. For instance, if there is
233
    // a white knight on g5 and black's king is on g8, this white knight adds 2
234
    // to kingAttacksCount[WHITE].
235
    int kingAttacksCount[COLOR_NB];
236
  };
237
 
238
 
239
  // Evaluation::initialize() computes king and pawn attacks, and the king ring
240
  // bitboard for a given color. This is done at the beginning of the evaluation.
169 pmbaty 241
  template<Tracing T> template<Color Us>
242
  void Evaluation<T>::initialize() {
96 pmbaty 243
 
185 pmbaty 244
    constexpr Color     Them = (Us == WHITE ? BLACK : WHITE);
245
    constexpr Direction Up   = (Us == WHITE ? NORTH : SOUTH);
246
    constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH);
247
    constexpr Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB: Rank7BB | Rank6BB);
96 pmbaty 248
 
185 pmbaty 249
    // Find our pawns that are blocked or on the first two ranks
169 pmbaty 250
    Bitboard b = pos.pieces(Us, PAWN) & (shift<Down>(pos.pieces()) | LowRanks);
251
 
185 pmbaty 252
    // Squares occupied by those pawns, by our king or queen, or controlled by enemy pawns
169 pmbaty 253
    // are excluded from the mobility area.
185 pmbaty 254
    mobilityArea[Us] = ~(b | pos.pieces(Us, KING, QUEEN) | pe->pawn_attacks(Them));
169 pmbaty 255
 
185 pmbaty 256
    // Initialise attackedBy bitboards for kings and pawns
257
    attackedBy[Us][KING] = pos.attacks_from<KING>(pos.square<KING>(Us));
169 pmbaty 258
    attackedBy[Us][PAWN] = pe->pawn_attacks(Us);
185 pmbaty 259
    attackedBy[Us][ALL_PIECES] = attackedBy[Us][KING] | attackedBy[Us][PAWN];
260
    attackedBy2[Us]            = attackedBy[Us][KING] & attackedBy[Us][PAWN];
169 pmbaty 261
 
185 pmbaty 262
    kingRing[Us] = kingAttackersCount[Them] = 0;
169 pmbaty 263
 
264
    // Init our king safety tables only if we are going to use them
265
    if (pos.non_pawn_material(Them) >= RookValueMg + KnightValueMg)
96 pmbaty 266
    {
185 pmbaty 267
        kingRing[Us] = attackedBy[Us][KING];
169 pmbaty 268
        if (relative_rank(Us, pos.square<KING>(Us)) == RANK_1)
185 pmbaty 269
            kingRing[Us] |= shift<Up>(kingRing[Us]);
169 pmbaty 270
 
185 pmbaty 271
        if (file_of(pos.square<KING>(Us)) == FILE_H)
272
            kingRing[Us] |= shift<WEST>(kingRing[Us]);
273
 
274
        else if (file_of(pos.square<KING>(Us)) == FILE_A)
275
            kingRing[Us] |= shift<EAST>(kingRing[Us]);
276
 
277
        kingAttackersCount[Them] = popcount(kingRing[Us] & pe->pawn_attacks(Them));
278
        kingAttacksCount[Them] = kingAttackersWeight[Them] = 0;
96 pmbaty 279
    }
280
  }
281
 
282
 
185 pmbaty 283
  // Evaluation::pieces() scores pieces of a given color and type
284
  template<Tracing T> template<Color Us, PieceType Pt>
285
  Score Evaluation<T>::pieces() {
96 pmbaty 286
 
185 pmbaty 287
    constexpr Color     Them = (Us == WHITE ? BLACK : WHITE);
288
    constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH);
289
    constexpr Bitboard OutpostRanks = (Us == WHITE ? Rank4BB | Rank5BB | Rank6BB
290
                                                   : Rank5BB | Rank4BB | Rank3BB);
96 pmbaty 291
    const Square* pl = pos.squares<Pt>(Us);
292
 
169 pmbaty 293
    Bitboard b, bb;
294
    Square s;
295
    Score score = SCORE_ZERO;
96 pmbaty 296
 
169 pmbaty 297
    attackedBy[Us][Pt] = 0;
298
 
96 pmbaty 299
    while ((s = *pl++) != SQ_NONE)
300
    {
301
        // Find attacked squares, including x-ray attacks for bishops and rooks
169 pmbaty 302
        b = Pt == BISHOP ? attacks_bb<BISHOP>(s, pos.pieces() ^ pos.pieces(QUEEN))
303
          : Pt ==   ROOK ? attacks_bb<  ROOK>(s, pos.pieces() ^ pos.pieces(QUEEN) ^ pos.pieces(Us, ROOK))
96 pmbaty 304
                         : pos.attacks_from<Pt>(s);
305
 
185 pmbaty 306
        if (pos.blockers_for_king(Us) & s)
96 pmbaty 307
            b &= LineBB[pos.square<KING>(Us)][s];
308
 
169 pmbaty 309
        attackedBy2[Us] |= attackedBy[Us][ALL_PIECES] & b;
185 pmbaty 310
        attackedBy[Us][Pt] |= b;
311
        attackedBy[Us][ALL_PIECES] |= b;
96 pmbaty 312
 
169 pmbaty 313
        if (b & kingRing[Them])
96 pmbaty 314
        {
169 pmbaty 315
            kingAttackersCount[Us]++;
316
            kingAttackersWeight[Us] += KingAttackWeights[Pt];
185 pmbaty 317
            kingAttacksCount[Us] += popcount(b & attackedBy[Them][KING]);
96 pmbaty 318
        }
319
 
154 pmbaty 320
        int mob = popcount(b & mobilityArea[Us]);
96 pmbaty 321
 
169 pmbaty 322
        mobility[Us] += MobilityBonus[Pt - 2][mob];
96 pmbaty 323
 
324
        if (Pt == BISHOP || Pt == KNIGHT)
325
        {
185 pmbaty 326
            // Bonus if piece is on an outpost square or can reach one
169 pmbaty 327
            bb = OutpostRanks & ~pe->pawn_attacks_span(Them);
96 pmbaty 328
            if (bb & s)
169 pmbaty 329
                score += Outpost[Pt == BISHOP][bool(attackedBy[Us][PAWN] & s)] * 2;
96 pmbaty 330
 
185 pmbaty 331
            else if (bb &= b & ~pos.pieces(Us))
332
                score += Outpost[Pt == BISHOP][bool(attackedBy[Us][PAWN] & bb)];
333
 
334
            // Knight and Bishop bonus for being right behind a pawn
335
            if (shift<Down>(pos.pieces(PAWN)) & s)
96 pmbaty 336
                score += MinorBehindPawn;
337
 
185 pmbaty 338
            // Penalty if the piece is far from the king
339
            score -= KingProtector * distance(s, pos.square<KING>(Us));
340
 
96 pmbaty 341
            if (Pt == BISHOP)
169 pmbaty 342
            {
185 pmbaty 343
                // Penalty according to number of pawns on the same color square as the
344
                // bishop, bigger when the center files are blocked with pawns.
345
                Bitboard blocked = pos.pieces(Us, PAWN) & shift<Down>(pos.pieces());
96 pmbaty 346
 
185 pmbaty 347
                score -= BishopPawns * pe->pawns_on_same_color_squares(Us, s)
348
                                     * (1 + popcount(blocked & CenterFiles));
349
 
169 pmbaty 350
                // Bonus for bishop on a long diagonal which can "see" both center squares
185 pmbaty 351
                if (more_than_one(attacks_bb<BISHOP>(s, pos.pieces(PAWN)) & Center))
352
                    score += LongDiagonalBishop;
169 pmbaty 353
            }
354
 
96 pmbaty 355
            // An important Chess960 pattern: A cornered bishop blocked by a friendly
356
            // pawn diagonally in front of it is a very serious problem, especially
357
            // when that pawn is also blocked.
358
            if (   Pt == BISHOP
359
                && pos.is_chess960()
360
                && (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1)))
361
            {
169 pmbaty 362
                Direction d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST);
96 pmbaty 363
                if (pos.piece_on(s + d) == make_piece(Us, PAWN))
185 pmbaty 364
                    score -= !pos.empty(s + d + pawn_push(Us))                ? CorneredBishop * 4
365
                            : pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? CorneredBishop * 2
366
                                                                              : CorneredBishop;
96 pmbaty 367
            }
368
        }
369
 
370
        if (Pt == ROOK)
371
        {
185 pmbaty 372
            // Bonus for aligning rook with enemy pawns on the same rank/file
96 pmbaty 373
            if (relative_rank(Us, s) >= RANK_5)
154 pmbaty 374
                score += RookOnPawn * popcount(pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s]);
96 pmbaty 375
 
185 pmbaty 376
            // Bonus for rook on an open or semi-open file
169 pmbaty 377
            if (pe->semiopen_file(Us, file_of(s)))
378
                score += RookOnFile[bool(pe->semiopen_file(Them, file_of(s)))];
96 pmbaty 379
 
169 pmbaty 380
            // Penalty when trapped by the king, even more if the king cannot castle
96 pmbaty 381
            else if (mob <= 3)
382
            {
185 pmbaty 383
                File kf = file_of(pos.square<KING>(Us));
384
                if ((kf < FILE_E) == (file_of(s) < kf))
96 pmbaty 385
                    score -= (TrappedRook - make_score(mob * 22, 0)) * (1 + !pos.can_castle(Us));
386
            }
387
        }
154 pmbaty 388
 
389
        if (Pt == QUEEN)
390
        {
391
            // Penalty if any relative pin or discovered attack against the queen
185 pmbaty 392
            Bitboard queenPinners;
393
            if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, queenPinners))
154 pmbaty 394
                score -= WeakQueen;
395
        }
96 pmbaty 396
    }
169 pmbaty 397
    if (T)
96 pmbaty 398
        Trace::add(Pt, Us, score);
399
 
169 pmbaty 400
    return score;
96 pmbaty 401
  }
402
 
403
 
185 pmbaty 404
  // Evaluation::king() assigns bonuses and penalties to a king of a given color
405
  template<Tracing T> template<Color Us>
406
  Score Evaluation<T>::king() const {
96 pmbaty 407
 
185 pmbaty 408
    constexpr Color    Them = (Us == WHITE ? BLACK : WHITE);
409
    constexpr Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB
410
                                           : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
154 pmbaty 411
 
96 pmbaty 412
    const Square ksq = pos.square<KING>(Us);
185 pmbaty 413
    Bitboard kingFlank, weak, b, b1, b2, safe, unsafeChecks;
96 pmbaty 414
 
415
    // King shelter and enemy pawns storm
185 pmbaty 416
    Score score = pe->king_safety<Us>(pos);
96 pmbaty 417
 
185 pmbaty 418
    // Find the squares that opponent attacks in our king flank, and the squares
419
    // which are attacked twice in that flank.
420
    kingFlank = KingFlank[file_of(ksq)];
421
    b1 = attackedBy[Them][ALL_PIECES] & kingFlank & Camp;
422
    b2 = b1 & attackedBy2[Them];
423
 
424
    int tropism = popcount(b1) + popcount(b2);
425
 
96 pmbaty 426
    // Main king safety evaluation
185 pmbaty 427
    if (kingAttackersCount[Them] > 1 - pos.count<QUEEN>(Them))
96 pmbaty 428
    {
185 pmbaty 429
        int kingDanger = 0;
430
        unsafeChecks = 0;
431
 
169 pmbaty 432
        // Attacked squares defended at most once by our queen or king
433
        weak =  attackedBy[Them][ALL_PIECES]
434
              & ~attackedBy2[Us]
185 pmbaty 435
              & (~attackedBy[Us][ALL_PIECES] | attackedBy[Us][KING] | attackedBy[Us][QUEEN]);
96 pmbaty 436
 
169 pmbaty 437
        // Analyse the safe enemy's checks which are possible on next move
438
        safe  = ~pos.pieces(Them);
439
        safe &= ~attackedBy[Us][ALL_PIECES] | (weak & attackedBy2[Them]);
154 pmbaty 440
 
169 pmbaty 441
        b1 = attacks_bb<ROOK  >(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
442
        b2 = attacks_bb<BISHOP>(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
96 pmbaty 443
 
444
        // Enemy queen safe checks
169 pmbaty 445
        if ((b1 | b2) & attackedBy[Them][QUEEN] & safe & ~attackedBy[Us][QUEEN])
446
            kingDanger += QueenSafeCheck;
96 pmbaty 447
 
169 pmbaty 448
        b1 &= attackedBy[Them][ROOK];
449
        b2 &= attackedBy[Them][BISHOP];
96 pmbaty 450
 
169 pmbaty 451
        // Enemy rooks checks
452
        if (b1 & safe)
453
            kingDanger += RookSafeCheck;
454
        else
455
            unsafeChecks |= b1;
96 pmbaty 456
 
169 pmbaty 457
        // Enemy bishops checks
458
        if (b2 & safe)
459
            kingDanger += BishopSafeCheck;
460
        else
461
            unsafeChecks |= b2;
96 pmbaty 462
 
169 pmbaty 463
        // Enemy knights checks
464
        b = pos.attacks_from<KNIGHT>(ksq) & attackedBy[Them][KNIGHT];
465
        if (b & safe)
466
            kingDanger += KnightSafeCheck;
467
        else
468
            unsafeChecks |= b;
154 pmbaty 469
 
169 pmbaty 470
        // Unsafe or occupied checking squares will also be considered, as long as
471
        // the square is in the attacker's mobility area.
472
        unsafeChecks &= mobilityArea[Them];
154 pmbaty 473
 
169 pmbaty 474
        kingDanger +=        kingAttackersCount[Them] * kingAttackersWeight[Them]
185 pmbaty 475
                     +  69 * kingAttacksCount[Them]
476
                     + 185 * popcount(kingRing[Us] & weak)
477
                     + 150 * popcount(pos.blockers_for_king(Us) | unsafeChecks)
478
                     +       tropism * tropism / 4
479
                     - 873 * !pos.count<QUEEN>(Them)
480
                     -   6 * mg_value(score) / 8
481
                     +       mg_value(mobility[Them] - mobility[Us])
482
                     -   30;
154 pmbaty 483
 
169 pmbaty 484
        // Transform the kingDanger units into a Score, and subtract it from the evaluation
154 pmbaty 485
        if (kingDanger > 0)
169 pmbaty 486
            score -= make_score(kingDanger * kingDanger / 4096, kingDanger / 16);
96 pmbaty 487
    }
488
 
154 pmbaty 489
    // Penalty when our king is on a pawnless flank
185 pmbaty 490
    if (!(pos.pieces(PAWN) & kingFlank))
154 pmbaty 491
        score -= PawnlessFlank;
492
 
185 pmbaty 493
    // King tropism bonus, to anticipate slow motion attacks on our king
494
    score -= CloseEnemies * tropism;
495
 
169 pmbaty 496
    if (T)
96 pmbaty 497
        Trace::add(KING, Us, score);
498
 
499
    return score;
500
  }
501
 
502
 
185 pmbaty 503
  // Evaluation::threats() assigns bonuses according to the types of the
504
  // attacking and the attacked pieces.
505
  template<Tracing T> template<Color Us>
506
  Score Evaluation<T>::threats() const {
96 pmbaty 507
 
185 pmbaty 508
    constexpr Color     Them     = (Us == WHITE ? BLACK   : WHITE);
509
    constexpr Direction Up       = (Us == WHITE ? NORTH   : SOUTH);
510
    constexpr Bitboard  TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
96 pmbaty 511
 
185 pmbaty 512
    Bitboard b, weak, defended, nonPawnEnemies, stronglyProtected, safe, restricted;
96 pmbaty 513
    Score score = SCORE_ZERO;
514
 
185 pmbaty 515
    // Non-pawn enemies
516
    nonPawnEnemies = pos.pieces(Them) ^ pos.pieces(Them, PAWN);
96 pmbaty 517
 
185 pmbaty 518
    // Squares strongly protected by the enemy, either because they defend the
519
    // square with a pawn, or because they defend the square twice and we don't.
169 pmbaty 520
    stronglyProtected =  attackedBy[Them][PAWN]
521
                       | (attackedBy2[Them] & ~attackedBy2[Us]);
96 pmbaty 522
 
169 pmbaty 523
    // Non-pawn enemies, strongly protected
185 pmbaty 524
    defended = nonPawnEnemies & stronglyProtected;
169 pmbaty 525
 
526
    // Enemies not strongly protected and under our attack
185 pmbaty 527
    weak = pos.pieces(Them) & ~stronglyProtected & attackedBy[Us][ALL_PIECES];
96 pmbaty 528
 
185 pmbaty 529
    // Safe or protected squares
530
    safe = ~attackedBy[Them][ALL_PIECES] | attackedBy[Us][ALL_PIECES];
531
 
532
    // Bonus according to the kind of attacking pieces
96 pmbaty 533
    if (defended | weak)
534
    {
169 pmbaty 535
        b = (defended | weak) & (attackedBy[Us][KNIGHT] | attackedBy[Us][BISHOP]);
96 pmbaty 536
        while (b)
169 pmbaty 537
        {
538
            Square s = pop_lsb(&b);
539
            score += ThreatByMinor[type_of(pos.piece_on(s))];
540
            if (type_of(pos.piece_on(s)) != PAWN)
541
                score += ThreatByRank * (int)relative_rank(Them, s);
542
        }
96 pmbaty 543
 
185 pmbaty 544
        b = weak & attackedBy[Us][ROOK];
96 pmbaty 545
        while (b)
169 pmbaty 546
        {
547
            Square s = pop_lsb(&b);
548
            score += ThreatByRook[type_of(pos.piece_on(s))];
549
            if (type_of(pos.piece_on(s)) != PAWN)
550
                score += ThreatByRank * (int)relative_rank(Them, s);
551
        }
96 pmbaty 552
 
185 pmbaty 553
        if (weak & attackedBy[Us][KING])
554
            score += ThreatByKing;
555
 
169 pmbaty 556
        score += Hanging * popcount(weak & ~attackedBy[Them][ALL_PIECES]);
96 pmbaty 557
 
185 pmbaty 558
        b = weak & nonPawnEnemies & attackedBy[Them][ALL_PIECES];
559
        score += Overload * popcount(b);
96 pmbaty 560
    }
561
 
185 pmbaty 562
    // Bonus for restricting their piece moves
563
    restricted =   attackedBy[Them][ALL_PIECES]
564
                & ~attackedBy[Them][PAWN]
565
                & ~attackedBy2[Them]
566
                &  attackedBy[Us][ALL_PIECES];
567
    score += RestrictedPiece * popcount(restricted);
568
 
569
    // Bonus for enemy unopposed weak pawns
169 pmbaty 570
    if (pos.pieces(Us, ROOK, QUEEN))
571
        score += WeakUnopposedPawn * pe->weak_unopposed(Them);
96 pmbaty 572
 
169 pmbaty 573
    // Find squares where our pawns can push on the next move
574
    b  = shift<Up>(pos.pieces(Us, PAWN)) & ~pos.pieces();
575
    b |= shift<Up>(b & TRank3BB) & ~pos.pieces();
96 pmbaty 576
 
185 pmbaty 577
    // Keep only the squares which are relatively safe
578
    b &= ~attackedBy[Them][PAWN] & safe;
169 pmbaty 579
 
185 pmbaty 580
    // Bonus for safe pawn threats on the next move
581
    b = pawn_attacks_bb<Us>(b) & pos.pieces(Them);
154 pmbaty 582
    score += ThreatByPawnPush * popcount(b);
96 pmbaty 583
 
185 pmbaty 584
    // Our safe or protected pawns
585
    b = pos.pieces(Us, PAWN) & safe;
169 pmbaty 586
 
185 pmbaty 587
    b = pawn_attacks_bb<Us>(b) & nonPawnEnemies;
588
    score += ThreatBySafePawn * popcount(b);
169 pmbaty 589
 
185 pmbaty 590
    // Bonus for threats on the next moves against enemy queen
591
    if (pos.count<QUEEN>(Them) == 1)
592
    {
593
        Square s = pos.square<QUEEN>(Them);
594
        safe = mobilityArea[Us] & ~stronglyProtected;
595
 
596
        b = attackedBy[Us][KNIGHT] & pos.attacks_from<KNIGHT>(s);
597
 
598
        score += KnightOnQueen * popcount(b & safe);
599
 
600
        b =  (attackedBy[Us][BISHOP] & pos.attacks_from<BISHOP>(s))
601
           | (attackedBy[Us][ROOK  ] & pos.attacks_from<ROOK  >(s));
602
 
603
        score += SliderOnQueen * popcount(b & safe & attackedBy2[Us]);
604
    }
605
 
169 pmbaty 606
    if (T)
96 pmbaty 607
        Trace::add(THREAT, Us, score);
608
 
609
    return score;
610
  }
611
 
185 pmbaty 612
  // Evaluation::passed() evaluates the passed pawns and candidate passed
169 pmbaty 613
  // pawns of the given color.
96 pmbaty 614
 
185 pmbaty 615
  template<Tracing T> template<Color Us>
616
  Score Evaluation<T>::passed() const {
96 pmbaty 617
 
185 pmbaty 618
    constexpr Color     Them = (Us == WHITE ? BLACK : WHITE);
619
    constexpr Direction Up   = (Us == WHITE ? NORTH : SOUTH);
96 pmbaty 620
 
185 pmbaty 621
    auto king_proximity = [&](Color c, Square s) {
622
      return std::min(distance(pos.square<KING>(c), s), 5);
623
    };
624
 
154 pmbaty 625
    Bitboard b, bb, squaresToQueen, defendedSquares, unsafeSquares;
96 pmbaty 626
    Score score = SCORE_ZERO;
627
 
169 pmbaty 628
    b = pe->passed_pawns(Us);
96 pmbaty 629
 
630
    while (b)
631
    {
632
        Square s = pop_lsb(&b);
633
 
169 pmbaty 634
        assert(!(pos.pieces(Them, PAWN) & forward_file_bb(Us, s + Up)));
96 pmbaty 635
 
169 pmbaty 636
        int r = relative_rank(Us, s);
96 pmbaty 637
 
185 pmbaty 638
        Score bonus = PassedRank[r];
96 pmbaty 639
 
185 pmbaty 640
        if (r > RANK_3)
96 pmbaty 641
        {
185 pmbaty 642
            int w = (r-2) * (r-2) + 2;
169 pmbaty 643
            Square blockSq = s + Up;
96 pmbaty 644
 
645
            // Adjust bonus based on the king's proximity
185 pmbaty 646
            bonus += make_score(0, (  king_proximity(Them, blockSq) * 5
647
                                    - king_proximity(Us,   blockSq) * 2) * w);
96 pmbaty 648
 
649
            // If blockSq is not the queening square then consider also a second push
169 pmbaty 650
            if (r != RANK_7)
185 pmbaty 651
                bonus -= make_score(0, king_proximity(Us, blockSq + Up) * w);
96 pmbaty 652
 
653
            // If the pawn is free to advance, then increase the bonus
654
            if (pos.empty(blockSq))
655
            {
656
                // If there is a rook or queen attacking/defending the pawn from behind,
657
                // consider all the squaresToQueen. Otherwise consider only the squares
658
                // in the pawn's path attacked or occupied by the enemy.
169 pmbaty 659
                defendedSquares = unsafeSquares = squaresToQueen = forward_file_bb(Us, s);
96 pmbaty 660
 
169 pmbaty 661
                bb = forward_file_bb(Them, s) & pos.pieces(ROOK, QUEEN) & pos.attacks_from<ROOK>(s);
96 pmbaty 662
 
663
                if (!(pos.pieces(Us) & bb))
169 pmbaty 664
                    defendedSquares &= attackedBy[Us][ALL_PIECES];
96 pmbaty 665
 
666
                if (!(pos.pieces(Them) & bb))
169 pmbaty 667
                    unsafeSquares &= attackedBy[Them][ALL_PIECES] | pos.pieces(Them);
96 pmbaty 668
 
669
                // If there aren't any enemy attacks, assign a big bonus. Otherwise
670
                // assign a smaller bonus if the block square isn't attacked.
185 pmbaty 671
                int k = !unsafeSquares ? 20 : !(unsafeSquares & blockSq) ? 9 : 0;
96 pmbaty 672
 
673
                // If the path to the queen is fully defended, assign a big bonus.
674
                // Otherwise assign a smaller bonus if the block square is defended.
675
                if (defendedSquares == squaresToQueen)
676
                    k += 6;
677
 
678
                else if (defendedSquares & blockSq)
679
                    k += 4;
680
 
185 pmbaty 681
                bonus += make_score(k * w, k * w);
96 pmbaty 682
            }
185 pmbaty 683
        } // rank > RANK_3
96 pmbaty 684
 
169 pmbaty 685
        // Scale down bonus for candidate passers which need more than one
185 pmbaty 686
        // pawn push to become passed, or have a pawn in front of them.
687
        if (   !pos.pawn_passed(Us, s + Up)
688
            || (pos.pieces(PAWN) & forward_file_bb(Us, s)))
689
            bonus = bonus / 2;
169 pmbaty 690
 
185 pmbaty 691
        score += bonus + PassedFile[file_of(s)];
96 pmbaty 692
    }
693
 
169 pmbaty 694
    if (T)
96 pmbaty 695
        Trace::add(PASSED, Us, score);
696
 
697
    return score;
698
  }
699
 
700
 
185 pmbaty 701
  // Evaluation::space() computes the space evaluation for a given side. The
96 pmbaty 702
  // space evaluation is a simple bonus based on the number of safe squares
703
  // available for minor pieces on the central four files on ranks 2--4. Safe
704
  // squares one, two or three squares behind a friendly pawn are counted
705
  // twice. Finally, the space bonus is multiplied by a weight. The aim is to
706
  // improve play on game opening.
707
 
185 pmbaty 708
  template<Tracing T> template<Color Us>
709
  Score Evaluation<T>::space() const {
169 pmbaty 710
 
185 pmbaty 711
    if (pos.non_pawn_material() < SpaceThreshold)
712
        return SCORE_ZERO;
713
 
714
    constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
715
    constexpr Bitboard SpaceMask =
169 pmbaty 716
      Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB)
717
                  : CenterFiles & (Rank7BB | Rank6BB | Rank5BB);
96 pmbaty 718
 
185 pmbaty 719
    // Find the available squares for our pieces inside the area defined by SpaceMask
96 pmbaty 720
    Bitboard safe =   SpaceMask
721
                   & ~pos.pieces(Us, PAWN)
185 pmbaty 722
                   & ~attackedBy[Them][PAWN];
96 pmbaty 723
 
724
    // Find all squares which are at most three squares behind some friendly pawn
725
    Bitboard behind = pos.pieces(Us, PAWN);
726
    behind |= (Us == WHITE ? behind >>  8 : behind <<  8);
727
    behind |= (Us == WHITE ? behind >> 16 : behind << 16);
728
 
185 pmbaty 729
    int bonus = popcount(safe) + popcount(behind & safe);
169 pmbaty 730
    int weight = pos.count<ALL_PIECES>(Us) - 2 * pe->open_files();
96 pmbaty 731
 
185 pmbaty 732
    Score score = make_score(bonus * weight * weight / 16, 0);
733
 
734
    if (T)
735
        Trace::add(SPACE, Us, score);
736
 
737
    return score;
96 pmbaty 738
  }
739
 
740
 
185 pmbaty 741
  // Evaluation::initiative() computes the initiative correction value
742
  // for the position. It is a second order bonus/malus based on the
743
  // known attacking/defending status of the players.
96 pmbaty 744
 
169 pmbaty 745
  template<Tracing T>
185 pmbaty 746
  Score Evaluation<T>::initiative(Value eg) const {
169 pmbaty 747
 
185 pmbaty 748
    int outflanking =  distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK))
749
                     - distance<Rank>(pos.square<KING>(WHITE), pos.square<KING>(BLACK));
96 pmbaty 750
 
185 pmbaty 751
    bool pawnsOnBothFlanks =   (pos.pieces(PAWN) & QueenSide)
752
                            && (pos.pieces(PAWN) & KingSide);
753
 
96 pmbaty 754
    // Compute the initiative bonus for the attacking side
185 pmbaty 755
    int complexity =   8 * pe->pawn_asymmetry()
756
                    + 12 * pos.count<PAWN>()
757
                    + 12 * outflanking
758
                    + 16 * pawnsOnBothFlanks
759
                    + 48 * !pos.non_pawn_material()
760
                    -118 ;
96 pmbaty 761
 
762
    // Now apply the bonus: note that we find the attacking side by extracting
763
    // the sign of the endgame value, and that we carefully cap the bonus so
169 pmbaty 764
    // that the endgame score will never change sign after the bonus.
185 pmbaty 765
    int v = ((eg > 0) - (eg < 0)) * std::max(complexity, -abs(eg));
96 pmbaty 766
 
169 pmbaty 767
    if (T)
768
        Trace::add(INITIATIVE, make_score(0, v));
769
 
770
    return make_score(0, v);
96 pmbaty 771
  }
772
 
773
 
185 pmbaty 774
  // Evaluation::scale_factor() computes the scale factor for the winning side
96 pmbaty 775
 
169 pmbaty 776
  template<Tracing T>
185 pmbaty 777
  ScaleFactor Evaluation<T>::scale_factor(Value eg) const {
169 pmbaty 778
 
154 pmbaty 779
    Color strongSide = eg > VALUE_DRAW ? WHITE : BLACK;
185 pmbaty 780
    int sf = me->scale_factor(pos, strongSide);
96 pmbaty 781
 
185 pmbaty 782
    // If scale is not already specific, scale down the endgame via general heuristics
783
    if (sf == SCALE_FACTOR_NORMAL)
96 pmbaty 784
    {
185 pmbaty 785
        if (   pos.opposite_bishops()
786
            && pos.non_pawn_material(WHITE) == BishopValueMg
787
            && pos.non_pawn_material(BLACK) == BishopValueMg)
788
            sf = 8 + 4 * pe->pawn_asymmetry();
789
        else
790
            sf = std::min(40 + (pos.opposite_bishops() ? 2 : 7) * pos.count<PAWN>(strongSide), sf);
96 pmbaty 791
 
792
    }
793
 
185 pmbaty 794
    return ScaleFactor(sf);
96 pmbaty 795
  }
796
 
797
 
185 pmbaty 798
  // Evaluation::value() is the main function of the class. It computes the various
799
  // parts of the evaluation and returns the value of the position from the point
800
  // of view of the side to move.
96 pmbaty 801
 
169 pmbaty 802
  template<Tracing T>
803
  Value Evaluation<T>::value() {
96 pmbaty 804
 
169 pmbaty 805
    assert(!pos.checkers());
96 pmbaty 806
 
169 pmbaty 807
    // Probe the material hash table
808
    me = Material::probe(pos);
96 pmbaty 809
 
169 pmbaty 810
    // If we have a specialized evaluation function for the current material
811
    // configuration, call it and return.
812
    if (me->specialized_eval_exists())
813
        return me->evaluate(pos);
96 pmbaty 814
 
169 pmbaty 815
    // Initialize score by reading the incrementally updated scores included in
816
    // the position object (material + piece square tables) and the material
817
    // imbalance. Score is computed internally from the white point of view.
185 pmbaty 818
    Score score = pos.psq_score() + me->imbalance() + pos.this_thread()->contempt;
96 pmbaty 819
 
169 pmbaty 820
    // Probe the pawn hash table
821
    pe = Pawns::probe(pos);
185 pmbaty 822
    score += pe->pawn_score(WHITE) - pe->pawn_score(BLACK);
96 pmbaty 823
 
169 pmbaty 824
    // Early exit if score is high
825
    Value v = (mg_value(score) + eg_value(score)) / 2;
826
    if (abs(v) > LazyThreshold)
827
       return pos.side_to_move() == WHITE ? v : -v;
154 pmbaty 828
 
169 pmbaty 829
    // Main evaluation begins here
96 pmbaty 830
 
169 pmbaty 831
    initialize<WHITE>();
832
    initialize<BLACK>();
96 pmbaty 833
 
185 pmbaty 834
    // Pieces should be evaluated first (populate attack tables)
835
    score +=  pieces<WHITE, KNIGHT>() - pieces<BLACK, KNIGHT>()
836
            + pieces<WHITE, BISHOP>() - pieces<BLACK, BISHOP>()
837
            + pieces<WHITE, ROOK  >() - pieces<BLACK, ROOK  >()
838
            + pieces<WHITE, QUEEN >() - pieces<BLACK, QUEEN >();
96 pmbaty 839
 
169 pmbaty 840
    score += mobility[WHITE] - mobility[BLACK];
96 pmbaty 841
 
185 pmbaty 842
    score +=  king<   WHITE>() - king<   BLACK>()
843
            + threats<WHITE>() - threats<BLACK>()
844
            + passed< WHITE>() - passed< BLACK>()
845
            + space<  WHITE>() - space<  BLACK>();
96 pmbaty 846
 
185 pmbaty 847
    score += initiative(eg_value(score));
96 pmbaty 848
 
169 pmbaty 849
    // Interpolate between a middlegame and a (scaled by 'sf') endgame score
185 pmbaty 850
    ScaleFactor sf = scale_factor(eg_value(score));
169 pmbaty 851
    v =  mg_value(score) * int(me->game_phase())
852
       + eg_value(score) * int(PHASE_MIDGAME - me->game_phase()) * sf / SCALE_FACTOR_NORMAL;
96 pmbaty 853
 
169 pmbaty 854
    v /= int(PHASE_MIDGAME);
96 pmbaty 855
 
169 pmbaty 856
    // In case of tracing add all remaining individual evaluation terms
857
    if (T)
858
    {
859
        Trace::add(MATERIAL, pos.psq_score());
860
        Trace::add(IMBALANCE, me->imbalance());
185 pmbaty 861
        Trace::add(PAWN, pe->pawn_score(WHITE), pe->pawn_score(BLACK));
169 pmbaty 862
        Trace::add(MOBILITY, mobility[WHITE], mobility[BLACK]);
863
        Trace::add(TOTAL, score);
864
    }
96 pmbaty 865
 
185 pmbaty 866
    return  (pos.side_to_move() == WHITE ? v : -v) // Side to move point of view
867
           + Eval::Tempo;
169 pmbaty 868
  }
96 pmbaty 869
 
169 pmbaty 870
} // namespace
96 pmbaty 871
 
872
 
185 pmbaty 873
/// evaluate() is the evaluator for the outer world. It returns a static
874
/// evaluation of the position from the point of view of the side to move.
96 pmbaty 875
 
185 pmbaty 876
Value Eval::evaluate(const Position& pos) {
877
  return Evaluation<NO_TRACE>(pos).value();
96 pmbaty 878
}
879
 
185 pmbaty 880
 
96 pmbaty 881
/// trace() is like evaluate(), but instead of returning a value, it returns
882
/// a string (suitable for outputting to stdout) that contains the detailed
883
/// descriptions and values of each evaluation term. Useful for debugging.
884
 
885
std::string Eval::trace(const Position& pos) {
886
 
887
  std::memset(scores, 0, sizeof(scores));
888
 
185 pmbaty 889
  pos.this_thread()->contempt = SCORE_ZERO; // Reset any dynamic contempt
96 pmbaty 890
 
185 pmbaty 891
  Value v = Evaluation<TRACE>(pos).value();
892
 
893
  v = pos.side_to_move() == WHITE ? v : -v; // Trace scores are from white's point of view
894
 
96 pmbaty 895
  std::stringstream ss;
896
  ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2)
185 pmbaty 897
     << "     Term    |    White    |    Black    |    Total   \n"
898
     << "             |   MG    EG  |   MG    EG  |   MG    EG \n"
899
     << " ------------+-------------+-------------+------------\n"
900
     << "    Material | " << Term(MATERIAL)
901
     << "   Imbalance | " << Term(IMBALANCE)
902
     << "  Initiative | " << Term(INITIATIVE)
903
     << "       Pawns | " << Term(PAWN)
904
     << "     Knights | " << Term(KNIGHT)
905
     << "     Bishops | " << Term(BISHOP)
906
     << "       Rooks | " << Term(ROOK)
907
     << "      Queens | " << Term(QUEEN)
908
     << "    Mobility | " << Term(MOBILITY)
909
     << " King safety | " << Term(KING)
910
     << "     Threats | " << Term(THREAT)
911
     << "      Passed | " << Term(PASSED)
912
     << "       Space | " << Term(SPACE)
913
     << " ------------+-------------+-------------+------------\n"
914
     << "       Total | " << Term(TOTAL);
96 pmbaty 915
 
185 pmbaty 916
  ss << "\nTotal evaluation: " << to_cp(v) << " (white side)\n";
96 pmbaty 917
 
918
  return ss.str();
919
}