Subversion Repositories Games.Chess Giants

Rev

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