Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
112 pmbaty 1
/*
2
    Protector -- a UCI chess engine
3
 
4
    Copyright (C) 2009-2010 Raimund Heid (Raimund_Heid@yahoo.com)
5
 
6
    This program is free software: you can redistribute it and/or modify
7
    it under the terms of the GNU General Public License as published by
8
    the Free Software Foundation, either version 3 of the License, or
9
    (at your option) any later version.
10
 
11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU General Public License for more details.
15
 
16
    You should have received a copy of the GNU General Public License
17
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 
19
*/
20
 
21
#define dumpPos dumpPosition(position);
22
 
23
#include <assert.h>
24
#include <stdlib.h>
25
#include <math.h>
26
#include "position.h"
27
#include "fen.h"
28
#include "io.h"
29
#include "evaluation.h"
30
#include "tools.h"
31
#ifdef INCLUDE_TABLEBASE_ACCESS
32
#include "tablebase.h"
33
#endif
34
 
35
#ifndef NDEBUG
36
PawnHashInfo localPawnHashtable[PAWN_HASHTABLE_SIZE];
37
KingSafetyHashInfo localKingSafetyHashtable[KINGSAFETY_HASHTABLE_SIZE];
38
#endif
39
 
40
KingSafetyHashInfo
41
   kingSafetyHashtable[MAX_THREADS][KINGSAFETY_HASHTABLE_SIZE];
42
 
43
#define MAX_MOVES_KNIGHT 8
44
#define MAX_MOVES_BISHOP 13
45
#define MAX_MOVES_ROOK 14
46
#define MAX_MOVES_QUEEN 27
47
 
48
INT32 KnightMobilityBonus[MAX_MOVES_KNIGHT + 1];
49
INT32 BishopMobilityBonus[MAX_MOVES_BISHOP + 1];
50
INT32 RookMobilityBonus[MAX_MOVES_ROOK + 1];
51
INT32 QueenMobilityBonus[MAX_MOVES_QUEEN + 1];
52
 
53
const INT32 PstPawn[64] = {
54
   V(0, 0), V(0, 0), V(0, 0), V(0, 0), V(0, 0), V(0, 0), V(0, 0), V(0, 0),      /* rank 1 */
55
   V(-10, -3), V(-2, -3), V(1, -3), V(5, -3), V(5, -3), V(1, -3), V(-2, -3), V(-10, -3),        /* rank 2 */
56
   V(-10, -3), V(-2, -3), V(3, -3), V(14, -3), V(14, -3), V(3, -3), V(-2, -3), V(-10, -3),      /* rank 3 */
57
   V(-10, -3), V(-2, -3), V(6, -3), V(22, -3), V(22, -3), V(6, -3), V(-2, -3), V(-10, -3),      /* rank 4 */
58
   V(-10, -3), V(-2, -3), V(6, -3), V(14, -3), V(14, -3), V(6, -3), V(-2, -3), V(-10, -3),      /* rank 5 */
59
   V(-10, -3), V(-2, -3), V(3, -3), V(5, -3), V(5, -3), V(3, -3), V(-2, -3), V(-10, -3),        /* rank 6 */
60
   V(-10, -3), V(-2, -3), V(1, -3), V(5, -3), V(5, -3), V(1, -3), V(-2, -3), V(-10, -3),        /* rank 7 */
61
   V(0, 0), V(0, 0), V(0, 0), V(0, 0), V(0, 0), V(0, 0), V(0, 0), V(0, 0),      /* rank 8 */
62
};
63
 
64
const INT32 PstKnight[64] = {
65
   V(-48, -42), V(-37, -32), V(-28, -22), V(-24, -17), V(-24, -17), V(-28, -22), V(-37, -32), V(-48, -42),      /* rank 1 */
66
   V(-33, -32), V(-24, -22), V(-13, -11), V(-8, -6), V(-8, -6), V(-13, -11), V(-24, -22), V(-33, -32),  /* rank 2 */
67
   V(-18, -22), V(-8, -11), V(0, -2), V(4, 1), V(4, 1), V(0, -2), V(-8, -11), V(-18, -22),      /* rank 3 */
68
   V(-8, -17), V(0, -6), V(9, 1), V(14, 7), V(14, 7), V(9, 1), V(0, -6), V(-8, -17),    /* rank 4 */
69
   V(-3, -17), V(4, -6), V(14, 1), V(19, 7), V(19, 7), V(14, 1), V(4, -6), V(-3, -17),  /* rank 5 */
70
   V(-3, -22), V(4, -11), V(14, -2), V(19, 1), V(19, 1), V(14, -2), V(4, -11), V(-3, -22),      /* rank 6 */
71
   V(-18, -32), V(-8, -22), V(0, -11), V(4, -6), V(4, -6), V(0, -11), V(-8, -22), V(-18, -32),  /* rank 7 */
72
   V(-70, -42), V(-24, -32), V(-13, -22), V(-8, -17), V(-8, -17), V(-13, -22), V(-24, -32), V(-70, -42) /* rank 8 */
73
};
74
 
75
const INT32 PstBishop[64] = {
76
   V(-15, -21), V(-15, -15), V(-13, -12), V(-11, -9), V(-11, -9), V(-13, -12), V(-15, -15), V(-15, -21),        /* rank 1 */
77
   V(-6, -15), V(0, -9), V(-1, -6), V(0, -3), V(0, -3), V(-1, -6), V(0, -9), V(-6, -15),        /* rank 2 */
78
   V(-5, -12), V(-1, -6), V(3, -3), V(1, 0), V(1, 0), V(3, -3), V(-1, -6), V(-5, -12),  /* rank 3 */
79
   V(-3, -9), V(0, -3), V(1, 0), V(6, 0), V(6, 0), V(1, 0), V(0, -3), V(-3, -9),        /* rank 4 */
80
   V(-3, -9), V(0, -3), V(1, 0), V(6, 0), V(6, 0), V(1, 0), V(0, -3), V(-3, -9),        /* rank 5 */
81
   V(-5, -12), V(-1, -6), V(3, -3), V(1, 0), V(1, 0), V(3, -3), V(-1, -6), V(-5, -12),  /* rank 6 */
82
   V(-6, -15), V(0, -9), V(-1, -6), V(0, -3), V(0, -3), V(-1, -6), V(0, -9), V(-6, -15),        /* rank 7 */
83
   V(-6, -21), V(-6, -15), V(-5, -12), V(-3, -9), V(-3, -9), V(-5, -12), V(-6, -15), V(-6, -21) /* rank 8 */
84
};
85
 
86
const INT32 PstRook[64] = {
87
   V(-4, 1), V(-2, 1), V(0, 1), V(0, 1), V(0, 1), V(0, 1), V(-2, 1), V(-4, 1),  /* rank 1 */
88
   V(-4, 1), V(-2, 1), V(0, 1), V(0, 1), V(0, 1), V(0, 1), V(-2, 1), V(-4, 1),  /* rank 2 */
89
   V(-4, 1), V(-2, 1), V(0, 1), V(0, 1), V(0, 1), V(0, 1), V(-2, 1), V(-4, 1),  /* rank 3 */
90
   V(-4, 1), V(-2, 1), V(0, 1), V(0, 1), V(0, 1), V(0, 1), V(-2, 1), V(-4, 1),  /* rank 4 */
91
   V(-4, 1), V(-2, 1), V(0, 1), V(0, 1), V(0, 1), V(0, 1), V(-2, 1), V(-4, 1),  /* rank 5 */
92
   V(-4, 1), V(-2, 1), V(0, 1), V(0, 1), V(0, 1), V(0, 1), V(-2, 1), V(-4, 1),  /* rank 6 */
93
   V(-4, 1), V(-2, 1), V(0, 1), V(0, 1), V(0, 1), V(0, 1), V(-2, 1), V(-4, 1),  /* rank 7 */
94
   V(-4, 1), V(-2, 1), V(0, 1), V(0, 1), V(0, 1), V(0, 1), V(-2, 1), V(-4, 1)   /* rank 8 */
95
};
96
 
97
const INT32 PstQueen[64] = {
98
   V(3, -31), V(3, -21), V(3, -16), V(3, -11), V(3, -11), V(3, -16), V(3, -21), V(3, -31),      /* rank 1 */
99
   V(3, -21), V(3, -11), V(3, -7), V(3, -2), V(3, -2), V(3, -7), V(3, -11), V(3, -21),  /* rank 2 */
100
   V(3, -16), V(3, -7), V(3, -2), V(3, 2), V(3, 2), V(3, -2), V(3, -7), V(3, -16),      /* rank 3 */
101
   V(3, -11), V(3, -2), V(3, 2), V(3, 7), V(3, 7), V(3, 2), V(3, -2), V(3, -11),        /* rank 4 */
102
   V(3, -11), V(3, -2), V(3, 2), V(3, 7), V(3, 7), V(3, 2), V(3, -2), V(3, -11),        /* rank 5 */
103
   V(3, -16), V(3, -7), V(3, -2), V(3, 2), V(3, 2), V(3, -2), V(3, -7), V(3, -16),      /* rank 6 */
104
   V(3, -21), V(3, -11), V(3, -7), V(3, -2), V(3, -2), V(3, -7), V(3, -11), V(3, -21),  /* rank 7 */
105
   V(3, -31), V(3, -21), V(3, -16), V(3, -11), V(3, -11), V(3, -16), V(3, -21), V(3, -31)       /* rank 8 */
106
};
107
 
108
const INT32 PstKing[64] = {
109
   V(106, 0), V(115, 23), V(96, 34), V(76, 46), V(76, 46), V(96, 34), V(115, 23), V(106, 0),    /* rank 1 */
110
   V(96, 23), V(106, 46), V(85, 58), V(67, 69), V(67, 69), V(85, 58), V(106, 46), V(96, 23),    /* rank 2 */
111
   V(76, 34), V(85, 58), V(67, 69), V(48, 81), V(48, 81), V(67, 69), V(85, 58), V(76, 34),      /* rank 3 */
112
   V(67, 46), V(76, 69), V(58, 81), V(38, 93), V(38, 93), V(58, 81), V(76, 69), V(67, 46),      /* rank 4 */
113
   V(58, 46), V(67, 69), V(48, 81), V(28, 93), V(28, 93), V(48, 81), V(67, 69), V(58, 46),      /* rank 5 */
114
   V(48, 34), V(58, 58), V(38, 69), V(18, 81), V(18, 81), V(38, 69), V(58, 58), V(48, 34),      /* rank 6 */
115
   V(38, 23), V(48, 46), V(28, 58), V(9, 69), V(9, 69), V(28, 58), V(48, 46), V(38, 23),        /* rank 7 */
116
   V(28, 0), V(38, 23), V(18, 34), V(0, 46), V(0, 46), V(18, 34), V(38, 23), V(28, 0)   /* rank 8 */
117
};
118
 
119
/* -------------------------------------------------------------------------- */
120
 
121
static const int KNIGHT_BONUS_ATTACK = 17;
122
static const int BISHOP_BONUS_ATTACK = 16;
123
static const int ROOK_BONUS_ATTACK = 26;
124
static const int QUEEN_BONUS_ATTACK = 40;
125
 
126
static const int BISHOP_MALUS_BLOCKED = 51;
127
static const int BISHOP_MALUS_TRAPPED = 124;
128
 
129
INT32 mvImpact[16];
130
 
131
const int KINGSAFETY_PAWN_MALUS_DEFENDER[3][8] = {
132
   {30, 0, 5, 15, 20, 25, 25, 25},      /* towards nearest border */
133
   {55, 0, 15, 40, 50, 55, 55, 55},
134
   {30, 0, 10, 20, 25, 30, 30, 30}      /* towards center */
135
};
136
 
137
const int KINGSAFETY_PAWN_BONUS_DEFENDER_DIAG[4][8] = {
138
   {10, 0, 2, 4, 6, 8, 10, 10},
139
   {8, 0, 2, 4, 6, 7, 8, 8},
140
   {6, 0, 2, 3, 4, 5, 6, 6},
141
   {4, 0, 1, 2, 3, 4, 4, 4}
142
};
143
 
144
const int KINGSAFETY_PAWN_BONUS_ATTACKER[3][8] = {
145
   {5, 0, 40, 15, 5, 0, 0, 0},  /* towards nearest border */
146
   {10, 0, 50, 20, 10, 0, 0, 0},
147
   {10, 0, 50, 20, 10, 0, 0, 0} /* towards center */
148
};
149
 
150
#define OWN_COLOR_WEIGHT_DIV 256
151
#define OWN_COLOR_WEIGHT_KINGSAFETY 296
152
 
153
#define PAWN_EVAL_WEIGHT_OP 256
154
#define PAWN_EVAL_WEIGHT_EG 258
155
#define PASSED_PAWN_WEIGHT_OP 98
156
#define PASSED_PAWN_WEIGHT_EG 132
157
#define CHAIN_BONUS_WEIGHT_OP 86
158
#define CHAIN_BONUS_WEIGHT_EG 85
159
#define KS_PAWNSTRUCTURE_ATTACK_WEIGHT 14
160
#define KS_PAWNSTRUCTURE_WEIGHT 59
161
#define HOMELAND_SECURITY_WEIGHT 19
162
#define KING_SAFETY_MALUS_DIM (500)
163
 
164
#define BISHOP_PIN_OP_VAL 23
165
#define BISHOP_PIN_EG_VAL 5
166
 
167
int KING_SAFETY_MALUS[KING_SAFETY_MALUS_DIM];
168
 
169
/* -------------------------------------------------------------------------- */
170
 
171
int centerDistance[_64_], centerTaxiDistance[_64_];
172
int attackPoints[16];
173
Bitboard butterflySquares[_64_];
174
Bitboard lateralSquares[_64_];
175
Bitboard companionFiles[_64_];
176
Bitboard passedPawnRectangle[2][_64_];
177
Bitboard passedPawnCorridor[2][_64_];
178
Bitboard candidateDefenders[2][_64_];   /* excludes squares of rank */
179
Bitboard candidateSupporters[2][_64_];  /* includes squares of rank */
180
Bitboard pawnOpponents[2][_64_];
181
Bitboard kingTrapsRook[2][64];
182
Bitboard rookBlockers[_64_];
183
Bitboard centralFiles;
184
Bitboard kingRealm[2][_64_][_64_];
185
Bitboard attackingRealm[2];
186
Bitboard homeland[2];
187
Bitboard troitzkyArea[2];
188
Bitboard krprkDrawFiles;
189
Bitboard A1C1, F1H1, A1B1, G1H1;
190
Bitboard filesBCFG;
191
KingAttacks kingAttacks[_64_];
192
int kingChaseMalus[3][_64_];
193
INT32 piecePieceAttackBonus[16][16];
194
MaterialInfo materialInfo[MATERIALINFO_TABLE_SIZE];
195
 
196
/* *INDENT-OFF* */
197
static const int BONUS_KNIGHT_OUTPOST_HR[64] = {
198
    0,  0,  0,  0,  0,  0,  0,  0,
199
    0,  0,  0,  0,  0,  0,  0,  0,
200
    0,  2,  7,  7,  7,  7,  2,  0,
201
    0,  3, 10, 14, 14, 10,  3,  0,
202
    0,  2,  7, 10, 10,  7,  2,  0,
203
    0,  0,  2,  3,  3,  2,  0,  0,
204
    0,  0,  0,  0,  0,  0,  0,  0,
205
    0,  0,  0,  0,  0,  0,  0,  0,
206
};
207
 
208
static const int BONUS_BISHOP_OUTPOST_HR[64] = {
209
    0,  0,  0,  0,  0,  0,  0,  0,
210
    0,  0,  0,  0,  0,  0,  0,  0,
211
    0,  2,  3,  3,  3,  3,  2,  0,
212
    0,  4,  8,  8,  8,  8,  4,  0,
213
    0,  2,  4,  4,  4,  4,  2,  0,
214
    0,  0,  2,  2,  2,  2,  0,  0,
215
    0,  0,  0,  0,  0,  0,  0,  0,
216
    0,  0,  0,  0,  0,  0,  0,  0,
217
};
218
/* *INDENT-ON* */
219
 
220
static int BONUS_KNIGHT_OUTPOST[_64_];
221
static int BONUS_BISHOP_OUTPOST[_64_];
222
static INT32 PAWN_CHAIN_BONUS[_64_];
223
 
224
#ifndef NDEBUG
225
bool debugEval = FALSE;
226
#endif
227
 
228
int quad(int y_min, int y_max, int rank);
229
bool squareIsPawnSafe(const EvaluationBase * base,
230
                      const Color color, const Square square);
231
bool hasAttackingBishop(const Position * position,
232
                        const Color attackingColor, const Square square);
233
void getPawnInfo(const Position * position, EvaluationBase * base);
234
bool passerWalks(const Position * position,
235
                 const Square passerSquare, const Color passerColor);
236
Piece getDiaBatteryPiece(const Position * position,
237
                         const Bitboard moves,
238
                         const Square attackerSquare, const Color kingColor);
239
Square getPinningPiece(const Position * position,
240
                       const EvaluationBase * base,
241
                       const Square pieceSquare, const Color pieceColor);
242
 
243
void addEvalBonusForColor(EvaluationBase * base, const Color color,
244
                          const INT32 bonus)
245
{
246
   if (color == WHITE)
247
   {
248
      base->balance += bonus;
249
   }
250
   else
251
   {
252
      base->balance -= bonus;
253
   }
254
}
255
 
256
void addEvalMalusForColor(EvaluationBase * base, const Color color,
257
                          const INT32 bonus)
258
{
259
   if (color == WHITE)
260
   {
261
      base->balance -= bonus;
262
   }
263
   else
264
   {
265
      base->balance += bonus;
266
   }
267
}
268
 
269
Color getWinningColor(const Position * position, const int value)
270
{
271
   if (position->activeColor == WHITE)
272
   {
273
      return (value >= 0 ? WHITE : BLACK);
274
   }
275
   else
276
   {
277
      return (value <= 0 ? WHITE : BLACK);
278
   }
279
}
280
 
281
int getWhiteBishopBlockingIndex(const Position * position,
282
                                const Bitboard bishopSquares)
283
{
284
   const Bitboard ownPawns =
285
      position->piecesOfType[WHITE_PAWN] & bishopSquares;
286
   const Bitboard blockingPieces = position->piecesOfColor[BLACK] | ownPawns;
287
   const Bitboard blockedPawns = (blockingPieces >> 8) & ownPawns;
288
 
289
   return getNumberOfSetSquares(ownPawns) +
290
      getNumberOfSetSquares(ownPawns & extendedCenter) +
291
      getNumberOfSetSquares(blockedPawns);
292
}
293
 
294
int getBlackBishopBlockingIndex(const Position * position,
295
                                const Bitboard bishopSquares)
296
{
297
   const Bitboard ownPawns =
298
      position->piecesOfType[BLACK_PAWN] & bishopSquares;
299
   const Bitboard blockingPieces = position->piecesOfColor[WHITE] | ownPawns;
300
   const Bitboard blockedPawns = (blockingPieces << 8) & ownPawns;
301
 
302
   return getNumberOfSetSquares(ownPawns) +
303
      getNumberOfSetSquares(ownPawns & extendedCenter) +
304
      getNumberOfSetSquares(blockedPawns);
305
}
306
 
307
Bitboard getPromotablePawns(const Position * position, const Color color)
308
{
309
   const Color oppColor = opponent(color);
310
   const Square oppKing = position->king[oppColor];
311
   const bool lightSquaredBishop = (bool)
312
      (EMPTY_BITBOARD !=
313
       (lightSquares & position->piecesOfType[BISHOP | color]));
314
   const Bitboard pawns = position->piecesOfType[PAWN | color];
315
   Bitboard supporters;
316
   File excludeFile;
317
   Rank promotionRank;
318
   Square promotionSquare;
319
 
320
   if (color == WHITE)
321
   {
322
      excludeFile = (lightSquaredBishop ? FILE_H : FILE_A);
323
      promotionRank = RANK_8;
324
   }
325
   else
326
   {
327
      excludeFile = (lightSquaredBishop ? FILE_A : FILE_H);
328
      promotionRank = RANK_1;
329
   }
330
 
331
   promotionSquare = getSquare(excludeFile, promotionRank);
332
   supporters = companionFiles[promotionSquare] & pawns;
333
 
334
   if (distance(oppKing, promotionSquare) <= 1 &&
335
       supporters == EMPTY_BITBOARD)
336
   {
337
      return pawns & ~squaresOfFile[excludeFile];
338
   }
339
   else
340
   {
341
      return pawns;
342
   }
343
}
344
 
345
bool oppositeColoredBishops(const Position * position)
346
{
347
   if (getPieceCount(position, (Piece) WHITE_BISHOP_DARK) +
348
       getPieceCount(position, (Piece) WHITE_BISHOP_LIGHT) == 1 &&
349
       getPieceCount(position, (Piece) BLACK_BISHOP_DARK) +
350
       getPieceCount(position, (Piece) BLACK_BISHOP_LIGHT) == 1)
351
   {
352
      const Bitboard bishops =
353
         position->piecesOfType[WHITE_BISHOP] |
354
         position->piecesOfType[BLACK_BISHOP];
355
 
356
      return (bool) ((lightSquares & bishops) != EMPTY_BITBOARD &&
357
                     (darkSquares & bishops) != EMPTY_BITBOARD);
358
   }
359
   else
360
   {
361
      return FALSE;
362
   }
363
}
364
 
365
bool passiveKingStopsPawn(const Square kingSquare,
366
                          const Square pawnSquare, const Color pawnColor)
367
{
368
   return testSquare(pawnOpponents[pawnColor][pawnSquare], kingSquare);
369
}
370
 
371
bool passiveKingOnFileStopsPawn(const Square kingSquare,
372
                                const Square pawnSquare,
373
                                const Color pawnColor)
374
{
375
   return file(kingSquare) == file(pawnSquare) &&
376
      testSquare(pawnOpponents[pawnColor][pawnSquare], kingSquare);
377
}
378
 
379
int getKnnkpChances(const Position * position, const Color color)
380
{
381
   Bitboard oppPawns = position->piecesOfType[PAWN | opponent(color)];
382
 
383
   return ((oppPawns & troitzkyArea[color]) == EMPTY_BITBOARD ? 0 : 8);
384
}
385
 
386
int getKppxKxChances(const Position * position, const Color color)
387
{
388
   Bitboard ownPawns = position->piecesOfType[PAWN | color];
389
   File file;
390
   int fileCount = 0;
391
 
392
   for (file = FILE_A; file <= FILE_H; file++)
393
   {
394
      if ((squaresOfFile[file] & ownPawns) != EMPTY_BITBOARD)
395
      {
396
         if (++fileCount > 1)
397
         {
398
            return 16;
399
         }
400
      }
401
   }
402
 
403
   if (fileCount == 1)
404
   {
405
      const Square oppKing = position->king[opponent(color)];
406
      Square square;
407
 
408
      ITERATE_BITBOARD(&ownPawns, square)
409
      {
410
         if (passiveKingOnFileStopsPawn(oppKing, square, color) == FALSE)
411
         {
412
            return (distance(oppKing, square) <= 2 ? 14 : 16);
413
         }
414
      }
415
 
416
      return (position->piecesOfType[KNIGHT | color] !=
417
              EMPTY_BITBOARD ? 8 : 4);
418
   }
419
 
420
   return 16;
421
}
422
 
423
int getKpxKpxChances(const Position * position, const EvaluationBase * base,
424
                     const Color color)
425
{
426
   if (base->passedPawns[WHITE] != EMPTY_BITBOARD ||
427
       base->passedPawns[BLACK] != EMPTY_BITBOARD)
428
   {
429
      return 16;
430
   }
431
   else
432
   {
433
      const int chancesByPawnWidth[8] = { 0, 5, 9, 13, 15, 16, 16, 16 };
434
      const int width = getWidth(position->piecesOfType[PAWN | color]);
435
      const int chances = chancesByPawnWidth[width];
436
 
437
      if (chances < 16)
438
      {
439
         const Color oppColor = opponent(color);
440
         const int kingDistance =
441
            getMinimumDistance(position->piecesOfType[PAWN | oppColor],
442
                               position->king[oppColor]);
443
 
444
         return min(16, chances + 2 * (kingDistance - 1));
445
      }
446
 
447
      return chances;
448
   }
449
}
450
 
451
int getKrppkrChances(const Position * position, const Color color)
452
{
453
   const Color oppColor = opponent(color);
454
   Bitboard pawns = position->piecesOfType[(Piece) (PAWN | color)];
455
   const Square oppKing = position->king[oppColor];
456
   Square square;
457
   Bitboard files = EMPTY_BITBOARD;
458
 
459
   assert(getNumberOfSetSquares(pawns) == 2);
460
 
461
   if (colorRank(color, oppKing) == RANK_8)
462
   {
463
      return 16;
464
   }
465
 
466
   ITERATE_BITBOARD(&pawns, square)
467
   {
468
      const File pawnFile = file(square);
469
 
470
      files |= minValue[getSquare(pawnFile, RANK_1)];
471
 
472
      if (passiveKingStopsPawn(oppKing, square, color) == FALSE)
473
      {
474
         const int fileDiff = abs(file(oppKing) - pawnFile);
475
         const int rankDiff =
476
            colorRank(color, square) - colorRank(color, oppKing);
477
 
478
         if ((fileDiff > 2) || (fileDiff == 2 && rankDiff >= 0))
479
         {
480
            return 16;
481
         }
482
      }
483
   }
484
 
485
   if (files == A1C1 || files == F1H1 || getNumberOfSetSquares(files) == 1)
486
   {
487
      return 4;
488
   }
489
 
490
   return 16;
491
}
492
 
493
int getKrpkrChances(const Position * position, const Color color)
494
{
495
   const Color oppColor = opponent(color);
496
   Bitboard pawns = position->piecesOfType[(Piece) (PAWN | color)];
497
   const Square oppKing = position->king[oppColor];
498
   Square square = getLastSquare(&pawns);
499
 
500
   assert(getNumberOfSetSquares(pawns) == 0);
501
 
502
   if (passiveKingStopsPawn(oppKing, square, color))
503
   {
504
      if (testSquare(krprkDrawFiles, square))
505
      {
506
         return 2;
507
      }
508
      else
509
      {
510
         const Square king = position->king[color];
511
         const Rank kingRank = colorRank(color, king);
512
         const Rank pawnRank = colorRank(color, square);
513
 
514
         if (kingRank < RANK_6 || pawnRank < RANK_6)
515
         {
516
            return 2;
517
         }
518
      }
519
   }
520
 
521
   return 16;
522
}
523
 
524
int getKqppkqChances(const Position * position, const Color color)
525
{
526
   const Color oppColor = opponent(color);
527
   Bitboard pawns = position->piecesOfType[(Piece) (PAWN | color)];
528
   const Square oppKing = position->king[oppColor];
529
   Square square;
530
   Bitboard files = EMPTY_BITBOARD;
531
 
532
   assert(getNumberOfSetSquares(pawns) == 2);
533
 
534
   ITERATE_BITBOARD(&pawns, square)
535
   {
536
      if (passiveKingStopsPawn(oppKing, square, color) == FALSE)
537
      {
538
         return 16;
539
      }
540
 
541
      files |= minValue[getSquare(file(square), RANK_1)];
542
   }
543
 
544
   if (files == A1B1 || files == G1H1 || getNumberOfSetSquares(files) == 1)
545
   {
546
      return 4;
547
   }
548
 
549
   return 16;
550
}
551
 
552
int getKqpkqChances(const Position * position, const Color color)
553
{
554
   const Color oppColor = opponent(color);
555
   Bitboard pawns = position->piecesOfType[(Piece) (PAWN | color)];
556
   const Square oppKing = position->king[oppColor];
557
   Square square = getLastSquare(&pawns);
558
   const File pawnFile = file(square);
559
   const Rank pawnRank = colorRank(color, square);
560
   const int distDiff = distance(oppKing, square) -
561
      distance(position->king[color], square);
562
   const int distDiv = (distDiff <= 0 ? 2 : 1);
563
 
564
   assert(getNumberOfSetSquares(pawns) == 0);
565
 
566
   if (pawnRank <= RANK_6 && (pawnFile <= FILE_B || pawnFile >= FILE_G))
567
   {
568
      return (passiveKingStopsPawn(oppKing, square, color) ? 1 : 4 / distDiv);
569
   }
570
   else
571
   {
572
      return (passiveKingStopsPawn(oppKing, square, color) ?
573
              4 : 16 / distDiv);
574
   }
575
}
576
 
577
int getKpkChances(const Position * position, const Color color)
578
{
579
   const Color oppColor = opponent(color);
580
   Bitboard pawns = position->piecesOfType[(Piece) (PAWN | color)];
581
 
582
   if ((pawns & nonA & nonH) != EMPTY_BITBOARD)
583
   {
584
      return 16;
585
   }
586
   else
587
   {
588
      const Square oppKing = position->king[oppColor];
589
      Square square;
590
 
591
      ITERATE_BITBOARD(&pawns, square)
592
      {
593
         if (passiveKingStopsPawn(oppKing, square, color) == FALSE)
594
         {
595
            return 16;
596
         }
597
      }
598
 
599
      return 0;                 /* king holds pawn(s) */
600
   }
601
}
602
 
603
int getKbpkChances(const Position * position, const Color color)
604
{
605
   const Color oppColor = opponent(color);
606
   const bool oppColors = oppositeColoredBishops(position);
607
   const int max = (oppColors ? 8 : 16);
608
   const Bitboard promotablePawns = getPromotablePawns(position, color);
609
   const int numPromotablePawns = getNumberOfSetSquares(promotablePawns);
610
   const int numDefenders =
611
      (oppColors ?
612
       getNumberOfSetSquares(position->piecesOfType[BISHOP | oppColor]) : 0);
613
 
614
   return (numPromotablePawns > numDefenders ? max : 0);
615
}
616
 
617
int specialPositionChances(const Position * position,
618
                           const EvaluationBase * base,
619
                           const SpecialEvalType type, const Color color)
620
{
621
   switch (type)
622
   {
623
   case Se_KpK:
624
      return getKpkChances(position, color);
625
 
626
   case Se_KbpK:
627
      return getKbpkChances(position, color);
628
 
629
   case Se_KrpKr:
630
      return getKrpkrChances(position, color);
631
 
632
   case Se_KrppKr:
633
      return getKrppkrChances(position, color);
634
 
635
   case Se_KqpKq:
636
      return getKqpkqChances(position, color);
637
 
638
   case Se_KqppKq:
639
      return getKqppkqChances(position, color);
640
 
641
   case Se_KnnKp:
642
      return getKnnkpChances(position, color);
643
 
644
   case Se_KppxKx:
645
      return getKppxKxChances(position, color);
646
 
647
   case Se_KpxKpx:
648
      return getKpxKpxChances(position, base, color);
649
 
650
   default:
651
      return 16;
652
   }
653
}
654
 
655
int getChances(const Position * position,
656
               const EvaluationBase * base, const Color winningColor)
657
{
658
   const MaterialInfo *mi = base->materialInfo;
659
   int chances = 16;
660
 
661
   if (numberOfNonPawnPieces(position, winningColor) <= 4 &&
662
       getPieceCount(position, WHITE_QUEEN) <= 1 &&
663
       getPieceCount(position, BLACK_QUEEN) <= 1)
664
   {
665
      if (winningColor == WHITE)
666
      {
667
         if (mi->specialEvalWhite != Se_None)
668
         {
669
            const int specialChances =
670
               specialPositionChances(position, base, mi->specialEvalWhite,
671
                                      WHITE);
672
 
673
            chances = min(specialChances, mi->chancesWhite);
674
         }
675
         else
676
         {
677
            chances = mi->chancesWhite;
678
         }
679
      }
680
      else
681
      {
682
         if (mi->specialEvalBlack != Se_None)
683
         {
684
            const int specialChances =
685
               specialPositionChances(position, base, mi->specialEvalBlack,
686
                                      BLACK);
687
 
688
            chances = min(specialChances, mi->chancesBlack);
689
         }
690
         else
691
         {
692
            chances = mi->chancesBlack;
693
         }
694
      }
695
   }
696
 
697
   return chances;
698
}
699
 
700
bool hasBishopPair(const Position * position, const Color color)
701
{
702
   const Bitboard *bishops =
703
      &position->piecesOfType[(Piece) (BISHOP | color)];
704
 
705
   return (bool) ((lightSquares & *bishops) != EMPTY_BITBOARD &&
706
                  (darkSquares & *bishops) != EMPTY_BITBOARD);
707
}
708
 
709
int phaseValue(const INT32 value, const Position * position,
710
               EvaluationBase * base)
711
{
712
   const INT32 materialValue = base->materialBalance +
713
      base->materialInfo->materialBalance;
714
   const int materialOpeningValue = getOpeningValue(materialValue);
715
   const int materialEndgameValue = getEndgameValue(materialValue);
716
   const int chancesWhite = getChances(position, base, WHITE);
717
   const int chancesBlack = getChances(position, base, BLACK);
718
   const int chances = max(chancesWhite, chancesBlack);
719
   const int openingValue = materialOpeningValue + getOpeningValue(value);
720
   const int endgameValue = (materialEndgameValue * chances) / 16 +
721
      (getEndgameValue(value) * (16 + chances)) / 32;
722
 
723
   return (openingValue * (256 - base->materialInfo->phaseIndex) +
724
           endgameValue * base->materialInfo->phaseIndex) / 256;
725
}
726
 
727
INT32 materialBalance(const Position * position)
728
{
729
   const INT32 bishopPairBonus =
730
      V(VALUE_BISHOP_PAIR_OPENING, VALUE_BISHOP_PAIR_ENDGAME);
731
   static const INT32 knightBonus = V(0, 5);
732
   static const INT32 rookMalus = V(5, 0);
733
   static const INT32 rookPairMalus = V(17, 25);
734
   static const INT32 rookQueenMalus = V(8, 12);
735
   static const INT32 pieceUpBonus =
736
      V(DEFAULTVALUE_PIECE_UP_OPENING, DEFAULTVALUE_PIECE_UP_ENDGAME);
737
 
738
   INT32 balance = 0;
739
   const int pawnCountWhite = position->numberOfPawns[WHITE] - 5;
740
   const int pawnCountBlack = position->numberOfPawns[BLACK] - 5;
741
   const int numWhiteKnights = getPieceCount(position, WHITE_KNIGHT);
742
   const int numBlackKnights = getPieceCount(position, BLACK_KNIGHT);
743
   const int knightSaldo = pawnCountWhite * numWhiteKnights -
744
      pawnCountBlack * numBlackKnights;
745
   const int numWhiteRooks = getPieceCount(position, WHITE_ROOK);
746
   const int numBlackRooks = getPieceCount(position, BLACK_ROOK);
747
   const int rookSaldo = pawnCountWhite * numWhiteRooks -
748
      pawnCountBlack * numBlackRooks;
749
   const int pieceCountSaldo =
750
      (numberOfNonPawnPieces(position, WHITE) - numWhiteRooks -
751
       getPieceCount(position, WHITE_QUEEN)) -
752
      (numberOfNonPawnPieces(position, BLACK) - numBlackRooks -
753
       getPieceCount(position, BLACK_QUEEN));
754
 
755
   if (hasBishopPair(position, WHITE))
756
   {
757
      balance += bishopPairBonus;
758
   }
759
 
760
   if (hasBishopPair(position, BLACK))
761
   {
762
      balance -= bishopPairBonus;
763
   }
764
 
765
   balance += knightSaldo * knightBonus - rookSaldo * rookMalus;
766
 
767
   if (numWhiteRooks >= 2)
768
   {
769
      balance -= rookPairMalus + rookQueenMalus;
770
   }
771
   else if (numWhiteRooks + getPieceCount(position, WHITE_QUEEN) >= 2)
772
   {
773
      balance -= rookQueenMalus;
774
   }
775
 
776
   if (numBlackRooks >= 2)
777
   {
778
      balance += rookPairMalus + rookQueenMalus;
779
   }
780
   else if (numBlackRooks + getPieceCount(position, BLACK_QUEEN) >= 2)
781
   {
782
      balance += rookQueenMalus;
783
   }
784
 
785
   if (pieceCountSaldo > 0)
786
   {
787
      balance += pieceUpBonus;
788
   }
789
   else if (pieceCountSaldo < 0)
790
   {
791
      balance -= pieceUpBonus;
792
   }
793
 
794
   return balance;
795
}
796
 
797
/**
798
 * Calculate a rough value of the specified position,
799
 * based on the current pst-values and the specified evaluation base.
800
 *
801
 * @return the value of the specified position
802
 */
803
INT32 positionalBalance(const Position * position, EvaluationBase * base)
804
{
805
   static const INT32 tempoBonus[2] = {
806
      V(VALUE_TEMPO_OPENING, VALUE_TEMPO_ENDGAME),
807
      V(-VALUE_TEMPO_OPENING, -VALUE_TEMPO_ENDGAME)
808
   };
809
   const INT32 balance = position->balance + base->balance +
810
      tempoBonus[position->activeColor];
811
   const int value = phaseValue(balance, position, base);
812
 
813
   return (position->activeColor == WHITE ? value : -value);
814
}
815
 
816
/**
817
 * Check if the specified color can win the specified position.
818
 *
819
 * @return FALSE if the specified color doesn't have sufficient material
820
 *         left to win the position
821
 */
822
bool hasWinningPotential(Position * position, Color color)
823
{
824
   return (bool) (position->numberOfPieces[color] > 1);
825
}
826
 
827
/**
828
 * Get the king safety hash value for the given king square.
829
 */
830
Bitboard calculateKingPawnSafetyHashKey(const Position * position,
831
                                        const Color color)
832
{
833
   const int mask[2] =
834
      { WHITE_00 | WHITE_000 | 16, BLACK_00 | BLACK_000 | 32 };
835
   const int index = (position->castlingRights | 48) & mask[color];
836
 
837
   return position->pawnHashKey ^
838
      GENERATED_KEYTABLE[color][position->king[color]] ^
839
      GENERATED_KEYTABLE[2][index];
840
}
841
 
842
int getPawnWidth(const Position * position, const Color color)
843
{
844
   const Bitboard tmp = position->piecesOfType[(Piece) (PAWN | color)] |
845
      minValue[position->king[opponent(color)]];
846
 
847
   return getWidth(tmp);
848
}
849
 
850
int getPassedPawnWidth(const Position * position,
851
                       const EvaluationBase * base, const Color color)
852
{
853
   const Bitboard tmp = base->passedPawns[color] |
854
      minValue[position->king[opponent(color)]];
855
 
856
   return getWidth(tmp);
857
}
858
 
859
int quad(int y_min, int y_max, int rank)
860
{
861
   const int bonusPerRank[8] = { 0, 0, 0, 26, 77, 154, 256, 0 };
862
 
863
   return y_min + ((y_max - y_min) * bonusPerRank[rank] + 128) / 256;
864
}
865
 
866
static int getHomeSecurityWeight(const Position * position)
867
{
868
   const int count = getPieceCount(position, WHITE_KNIGHT) +
869
      getPieceCount(position, (Piece) WHITE_BISHOP_DARK) +
870
      getPieceCount(position, (Piece) WHITE_BISHOP_LIGHT) +
871
      getPieceCount(position, BLACK_KNIGHT) +
872
      getPieceCount(position, (Piece) BLACK_BISHOP_DARK) +
873
      getPieceCount(position, (Piece) BLACK_BISHOP_LIGHT);
874
 
875
   return count * count;
876
}
877
 
878
bool squareIsPawnSafe(const EvaluationBase * base,
879
                      const Color color, const Square square)
880
{
881
   return testSquare(base->pawnAttackableSquares[opponent(color)],
882
                     square) == FALSE;
883
}
884
 
885
bool hasAttackingBishop(const Position * position,
886
                        const Color attackingColor, const Square square)
887
{
888
   const Bitboard attackers =
889
      ((lightSquares & minValue[square]) != EMPTY_BITBOARD ?
890
       lightSquares : darkSquares);
891
 
892
   return (bool)
893
      ((attackers & position->piecesOfType[BISHOP | attackingColor]) !=
894
       EMPTY_BITBOARD);
895
}
896
 
897
void getPawnInfo(const Position * position, EvaluationBase * base)
898
{
899
   const Bitboard white = position->piecesOfType[WHITE_PAWN];
900
   const Bitboard black = position->piecesOfType[BLACK_PAWN];
901
   Bitboard whiteLateralSquares, blackLateralSquares;
902
   Bitboard whiteSwamp, blackSwamp;
903
   Bitboard pawnAttackableSquaresWhite, pawnAttackableSquaresBlack;
904
   register Bitboard tmp1, tmp2;
905
 
906
   /* Calculate upward and downward realms */
907
   tmp1 = (white << 8) | (white << 16) | (white << 24);
908
   tmp1 |= (tmp1 << 24);
909
   tmp2 = (white >> 8) | (white >> 16) | (white >> 24);
910
   tmp2 |= (tmp2 >> 24);
911
 
912
   base->doubledPawns[WHITE] = white & tmp2;
913
   base->upwardRealm[WHITE] = (tmp1 = tmp1 | white);
914
   pawnAttackableSquaresWhite = ((tmp1 & nonA) << 7) | ((tmp1 & nonH) << 9);
915
   base->downwardRealm[WHITE] = tmp2;
916
 
917
   /* Calculate upward and downward realms */
918
   tmp1 = (black >> 8) | (black >> 16) | (black >> 24);
919
   tmp1 |= (tmp1 >> 24);
920
   tmp2 = (black << 8) | (black << 16) | (black << 24);
921
   tmp2 |= (tmp2 << 24);
922
 
923
   base->doubledPawns[BLACK] = black & tmp2;
924
   base->upwardRealm[BLACK] = (tmp1 = tmp1 | black);
925
   pawnAttackableSquaresBlack = ((tmp1 & nonA) >> 9) | ((tmp1 & nonH) >> 7);
926
   base->downwardRealm[BLACK] = tmp2;
927
 
928
   /* Calculate the squares protected by a pawn */
929
   whiteLateralSquares = ((white & nonA) >> 1) | ((white & nonH) << 1);
930
   base->pawnProtectedSquares[WHITE] = whiteLateralSquares << 8;
931
   blackLateralSquares = ((black & nonA) >> 1) | ((black & nonH) << 1);
932
   base->pawnProtectedSquares[BLACK] = blackLateralSquares >> 8;
933
 
934
   /* Identify the passed pawns */
935
   whiteSwamp = base->downwardRealm[BLACK] | base->upwardRealm[WHITE] |
936
      pawnAttackableSquaresWhite;
937
   blackSwamp = base->downwardRealm[WHITE] | base->upwardRealm[BLACK] |
938
      pawnAttackableSquaresBlack;
939
 
940
   base->passedPawns[WHITE] = white & ~blackSwamp;
941
   base->passedPawns[BLACK] = black & ~whiteSwamp;
942
 
943
   /* Calculate the weak pawns */
944
   tmp2 = ~(white | black | base->pawnProtectedSquares[BLACK]);
945
   tmp1 = (whiteLateralSquares & tmp2) >> 8;
946
   tmp1 |= (tmp1 & squaresOfRank[RANK_3] & tmp2) >> 8;
947
   base->weakPawns[WHITE] =
948
      (white & ~(pawnAttackableSquaresWhite | whiteLateralSquares | tmp1));
949
 
950
   tmp2 = ~(white | black | base->pawnProtectedSquares[WHITE]);
951
   tmp1 = (blackLateralSquares & tmp2) << 8;
952
   tmp1 |= (tmp1 & squaresOfRank[RANK_6] & tmp2) << 8;
953
   base->weakPawns[BLACK] =
954
      (black & ~(pawnAttackableSquaresBlack | blackLateralSquares | tmp1));
955
 
956
   /* Calculate the candidates */
957
   base->candidatePawns[WHITE] = white & ~base->passedPawns[WHITE] &
958
      (pawnAttackableSquaresWhite | whiteLateralSquares) &
959
      ~(base->upwardRealm[BLACK] | base->downwardRealm[WHITE]);
960
 
961
   base->candidatePawns[BLACK] = black & ~base->passedPawns[BLACK] &
962
      (pawnAttackableSquaresBlack | blackLateralSquares) &
963
      ~(base->upwardRealm[WHITE] | base->downwardRealm[BLACK]);
964
 
965
#ifdef BONUS_HIDDEN_PASSER
966
   /* Calculate the hidden candidates */
967
   base->hiddenCandidatePawns[WHITE] = white & (black >> 8) &
968
      ~pawnAttackableSquaresBlack & ~(blackLateralSquares) &
969
      (squaresOfRank[RANK_5] | squaresOfRank[RANK_6]) &
970
      base->pawnProtectedSquares[WHITE];
971
 
972
   base->hiddenCandidatePawns[BLACK] = black & (white << 8) &
973
      ~pawnAttackableSquaresWhite & ~(whiteLateralSquares) &
974
      (squaresOfRank[RANK_4] | squaresOfRank[RANK_3]) &
975
      base->pawnProtectedSquares[BLACK];
976
#endif
977
 
978
   tmp1 = black & base->pawnProtectedSquares[BLACK];
979
   tmp2 = ((tmp1 & nonA) >> 9) & ((tmp1 & nonH) >> 7);
980
   tmp2 &= ~pawnAttackableSquaresWhite;
981
   tmp1 = tmp2 | (tmp2 >> 8);
982
   base->fixedPawns[WHITE] = tmp1 | (tmp1 >> 16) | (tmp1 >> 32);
983
 
984
   tmp1 = white & base->pawnProtectedSquares[WHITE];
985
   tmp2 = ((tmp1 & nonA) << 7) & ((tmp1 & nonH) << 9);
986
   tmp2 &= ~pawnAttackableSquaresBlack;
987
   tmp1 = tmp2 | (tmp2 << 8);
988
   base->fixedPawns[BLACK] = tmp1 | (tmp1 << 16) | (tmp1 << 32);
989
 
990
#ifdef BONUS_HIDDEN_PASSER
991
   base->hasPassersOrCandidates[WHITE] = (bool)
992
      (base->passedPawns[WHITE] != EMPTY_BITBOARD ||
993
       base->candidatePawns[WHITE] != EMPTY_BITBOARD ||
994
       base->hiddenCandidatePawns[WHITE] != EMPTY_BITBOARD);
995
 
996
   base->hasPassersOrCandidates[BLACK] = (bool)
997
      (base->passedPawns[BLACK] != EMPTY_BITBOARD ||
998
       base->candidatePawns[BLACK] != EMPTY_BITBOARD ||
999
       base->hiddenCandidatePawns[BLACK] != EMPTY_BITBOARD);
1000
#endif
1001
 
1002
   tmp1 = (white << 8) & ~(white | black);
1003
   tmp2 = white | (tmp1 & ~base->pawnProtectedSquares[BLACK]);
1004
   tmp2 |= tmp1 & base->pawnProtectedSquares[WHITE];
1005
   tmp1 &= squaresOfRank[RANK_3] & ~base->pawnProtectedSquares[BLACK];
1006
   tmp1 = (tmp1 << 8) & ~(white | black);
1007
   tmp2 |= tmp1 & ~base->pawnProtectedSquares[BLACK];
1008
   tmp2 |= tmp1 & base->pawnProtectedSquares[WHITE];
1009
   base->pawnAttackableSquares[WHITE] =
1010
      ((tmp2 & nonA) << 7) | ((tmp2 & nonH) << 9);
1011
 
1012
   /*dumpBitboard(base->pawnAttackableSquares[WHITE], "pawnAttackable white");
1013
      dumpPosition(position); */
1014
 
1015
   tmp1 = (black >> 8) & ~(white | black);
1016
   tmp2 = black | (tmp1 & ~base->pawnProtectedSquares[WHITE]);
1017
   tmp2 |= tmp1 & base->pawnProtectedSquares[BLACK];
1018
   tmp1 &= squaresOfRank[RANK_6] & ~base->pawnProtectedSquares[WHITE];
1019
   tmp1 = (tmp1 >> 8) & ~(white | black);
1020
   tmp2 |= tmp1 & ~base->pawnProtectedSquares[WHITE];
1021
   tmp2 |= tmp1 & base->pawnProtectedSquares[BLACK];
1022
   base->pawnAttackableSquares[BLACK] =
1023
      ((tmp2 & nonA) >> 9) | ((tmp2 & nonH) >> 7);
1024
 
1025
   base->chainPawns[WHITE] = white &
1026
      (base->pawnProtectedSquares[WHITE] | whiteLateralSquares);
1027
   base->chainPawns[BLACK] = black &
1028
      (base->pawnProtectedSquares[BLACK] | blackLateralSquares);
1029
}
1030
 
1031
#define KP_DISTANCE_WEIGHT 6
1032
#define KP_REDUCED_DISTANCE_WEIGHT 3
1033
 
1034
static int getKingWhitePawnDistance(const Square pawnSquare,
1035
                                    const Square kingSquare)
1036
{
1037
   const int rankDiff = rank(pawnSquare) - rank(kingSquare);
1038
   const int fileDistance = abs(file(pawnSquare) - file(kingSquare));
1039
 
1040
   return (rankDiff < 0 ? KP_REDUCED_DISTANCE_WEIGHT :
1041
           KP_DISTANCE_WEIGHT) * abs(rankDiff) +
1042
      KP_DISTANCE_WEIGHT * fileDistance;
1043
}
1044
 
1045
static int getKingBlackPawnDistance(const Square pawnSquare,
1046
                                    const Square kingSquare)
1047
{
1048
   const int rankDiff = rank(pawnSquare) - rank(kingSquare);
1049
   const int fileDistance = abs(file(pawnSquare) - file(kingSquare));
1050
 
1051
   return (rankDiff > 0 ? KP_REDUCED_DISTANCE_WEIGHT :
1052
           KP_DISTANCE_WEIGHT) * abs(rankDiff) +
1053
      KP_DISTANCE_WEIGHT * fileDistance;
1054
}
1055
 
1056
static int getKingPawnDistanceValue(const Position * position,
1057
                                    const Square kingSquare, Bitboard pawns)
1058
{
1059
   Square square;
1060
   int value = 1024;
1061
 
1062
   ITERATE_BITBOARD(&pawns, square)
1063
   {
1064
      int currentValue;
1065
 
1066
      if (position->piece[square] == WHITE_PAWN)
1067
      {
1068
         currentValue = getKingWhitePawnDistance(square, kingSquare);
1069
      }
1070
      else
1071
      {
1072
         currentValue = getKingBlackPawnDistance(square, kingSquare);
1073
      }
1074
 
1075
      if (currentValue < value)
1076
      {
1077
         value = currentValue;
1078
      }
1079
   }
1080
 
1081
   return value;
1082
}
1083
 
1084
static int getKingPawnDistance(const Position * position, const Color color)
1085
{
1086
   const Bitboard pawns = position->piecesOfType[WHITE_PAWN] |
1087
      position->piecesOfType[BLACK_PAWN];
1088
   const Square kingSquare = position->king[color];
1089
 
1090
   if (pawns != EMPTY_BITBOARD)
1091
   {
1092
      int distance = 1;
1093
 
1094
      while (1)
1095
      {
1096
         Bitboard pid = pawns & squaresInDistance[distance][kingSquare];
1097
 
1098
         if (pid != EMPTY_BITBOARD)
1099
         {
1100
            return getKingPawnDistanceValue(position, kingSquare, pid);
1101
         }
1102
         else
1103
         {
1104
            distance++;
1105
         }
1106
      }
1107
   }
1108
 
1109
   return 0;
1110
}
1111
 
1112
bool pawnIsPassed(const Position * position, const Square pawnSquare,
1113
                  const Color pawnColor)
1114
{
1115
   const Color defenderColor = opponent(pawnColor);
1116
   const Bitboard corridor = passedPawnCorridor[pawnColor][pawnSquare];
1117
   const Bitboard defenders = position->piecesOfType[PAWN | defenderColor] &
1118
      (candidateDefenders[pawnColor][pawnSquare] | corridor);
1119
 
1120
   if (defenders == EMPTY_BITBOARD)
1121
   {
1122
      const Bitboard blockers = position->piecesOfType[PAWN | pawnColor] &
1123
         corridor;
1124
 
1125
      return (bool) (blockers == EMPTY_BITBOARD);
1126
   }
1127
 
1128
   return FALSE;
1129
}
1130
 
1131
bool captureCreatesPasser(Position * position, const Square captureSquare,
1132
                          const Piece capturingPiece)
1133
{
1134
   const Piece captured = position->piece[captureSquare];
1135
   const Color capturedColor = pieceColor(captured);
1136
   const Color passerColor = opponent(capturedColor);
1137
   Bitboard candidates = (passedPawnCorridor[capturedColor][captureSquare] |
1138
                          candidateDefenders[capturedColor][captureSquare]) &
1139
      position->piecesOfType[PAWN | passerColor];
1140
   bool result = FALSE;
1141
 
1142
   if (pieceType(capturingPiece) == PAWN &&
1143
       pawnIsPassed(position, captureSquare, passerColor))
1144
   {
1145
      /* dumpSquare(captureSquare);
1146
         dumpPosition(position); */
1147
 
1148
      return TRUE;
1149
   }
1150
 
1151
   if (candidates != EMPTY_BITBOARD)
1152
   {
1153
      const Bitboard pawnsOriginal =
1154
         position->piecesOfType[PAWN | capturedColor];
1155
      Square square;
1156
 
1157
      clearSquare(position->piecesOfType[PAWN | capturedColor],
1158
                  captureSquare);
1159
 
1160
      ITERATE_BITBOARD(&candidates, square)
1161
      {
1162
         if (pawnIsPassed(position, square, passerColor))
1163
         {
1164
            /*dumpSquare(captureSquare);
1165
               dumpSquare(square);
1166
               dumpBitboard(cc, "cd");
1167
               dumpPosition(position); */
1168
 
1169
            result = TRUE;
1170
            candidates = EMPTY_BITBOARD;        /* force loop exit */
1171
         }
1172
      }
1173
 
1174
      position->piecesOfType[PAWN | capturedColor] = pawnsOriginal;
1175
   }
1176
 
1177
   return result;
1178
}
1179
 
1180
bool passerWalks(const Position * position,
1181
                 const Square passerSquare, const Color passerColor)
1182
{
1183
   const Square attackerKingSquare = position->king[passerColor];
1184
   const Square defenderKingSquare = position->king[opponent(passerColor)];
1185
   const int attackerDistance = distance(attackerKingSquare, passerSquare);
1186
   const Rank kingRank = colorRank(passerColor, attackerKingSquare);
1187
   const File passerFile = file(passerSquare);
1188
 
1189
   if (passerFile >= FILE_B && passerFile <= FILE_G)
1190
   {
1191
      if ((kingRank == RANK_6 || kingRank == RANK_7) &&
1192
          kingRank > colorRank(passerColor, passerSquare) &&
1193
          abs(file(attackerKingSquare) - passerFile) <= 1 &&
1194
          attackerDistance <= 2)
1195
      {
1196
         if (position->activeColor == passerColor ||
1197
             attackerDistance == 1 ||
1198
             distance(defenderKingSquare, passerSquare) > 1)
1199
         {
1200
            return TRUE;
1201
         }
1202
      }
1203
 
1204
      /*
1205
         if (kingRank == colorRank(passerColor, passerSquare) + 2 &&
1206
         abs(file(attackerKingSquare) - passerFile) <= 1 &&
1207
         attackerDistance <= 2)
1208
         {
1209
         if (position->activeColor == passerColor ||
1210
         attackerDistance == 1 ||
1211
         distance(defenderKingSquare, passerSquare) > 1)
1212
         {
1213
         return TRUE;
1214
         }
1215
         }
1216
       */
1217
   }
1218
   else if ((kingRank == RANK_7 || kingRank == RANK_8) &&
1219
            abs(file(attackerKingSquare) - passerFile) == 1 &&
1220
            attackerDistance <= 2)
1221
   {
1222
      if (position->activeColor == passerColor ||
1223
          attackerDistance == 1 ||
1224
          distance(defenderKingSquare, passerSquare) > 1)
1225
      {
1226
         return TRUE;
1227
      }
1228
   }
1229
 
1230
   return FALSE;
1231
}
1232
 
1233
#ifdef USE_ORTHO_BATTERY_PIECE
1234
static Piece getOrthoBatteryPiece(const Position * position,
1235
                                  const Bitboard moves,
1236
                                  const Square attackerSquare,
1237
                                  const Color kingColor)
1238
{
1239
   const Square kingSquare = position->king[kingColor];
1240
   Bitboard middlePiece = EMPTY_BITBOARD;
1241
 
1242
   if (testSquare(generalMoves[ROOK][kingSquare], attackerSquare))
1243
   {
1244
      middlePiece = generalMoves[ROOK][attackerSquare] &
1245
         moves & getMagicRookMoves(kingSquare, position->allPieces);
1246
 
1247
      if (middlePiece != EMPTY_BITBOARD)
1248
      {
1249
         const Square pieceSquare = getLastSquare(&middlePiece);
1250
 
1251
         return position->piece[pieceSquare];
1252
      }
1253
   }
1254
 
1255
   return NO_PIECE;
1256
}
1257
#endif
1258
 
1259
Piece getDiaBatteryPiece(const Position * position,
1260
                         const Bitboard moves,
1261
                         const Square attackerSquare, const Color kingColor)
1262
{
1263
   const Square kingSquare = position->king[kingColor];
1264
   Bitboard middlePiece = EMPTY_BITBOARD;
1265
 
1266
   if (testSquare(generalMoves[BISHOP][kingSquare], attackerSquare))
1267
   {
1268
      middlePiece = generalMoves[BISHOP][attackerSquare] &
1269
         moves & getMagicBishopMoves(kingSquare, position->allPieces);
1270
 
1271
      if (middlePiece != EMPTY_BITBOARD)
1272
      {
1273
         const Square pieceSquare = getLastSquare(&middlePiece);
1274
 
1275
         return position->piece[pieceSquare];
1276
      }
1277
   }
1278
 
1279
   return NO_PIECE;
1280
}
1281
 
1282
Square getPinningPiece(const Position * position,
1283
                       const EvaluationBase * base,
1284
                       const Square pieceSquare, const Color pieceColor)
1285
{
1286
   if (testSquare(base->pinnedCandidatesDia[pieceColor], pieceSquare))
1287
   {
1288
      const Color oppColor = opponent(pieceColor);
1289
      Bitboard pinningCandidates = position->piecesOfType[BISHOP | oppColor] |
1290
         position->piecesOfType[QUEEN | oppColor];
1291
 
1292
      if (pinningCandidates != EMPTY_BITBOARD)
1293
      {
1294
         pinningCandidates &=
1295
            generalMoves[BISHOP][position->king[pieceColor]];
1296
 
1297
         if (pinningCandidates != EMPTY_BITBOARD)
1298
         {
1299
            pinningCandidates &=
1300
               getMagicBishopMoves(pieceSquare, position->allPieces);
1301
 
1302
            if (pinningCandidates != EMPTY_BITBOARD)
1303
            {
1304
               return getFirstSquare(&pinningCandidates);
1305
            }
1306
         }
1307
      }
1308
   }
1309
 
1310
   if (testSquare(base->pinnedCandidatesOrtho[pieceColor], pieceSquare))
1311
   {
1312
      const Color oppColor = opponent(pieceColor);
1313
      Bitboard pinningCandidates = position->piecesOfType[ROOK | oppColor] |
1314
         position->piecesOfType[QUEEN | oppColor];
1315
 
1316
      if (pinningCandidates != EMPTY_BITBOARD)
1317
      {
1318
         pinningCandidates &= generalMoves[ROOK][position->king[pieceColor]];
1319
 
1320
         if (pinningCandidates != EMPTY_BITBOARD)
1321
         {
1322
            pinningCandidates &=
1323
               getMagicRookMoves(pieceSquare, position->allPieces);
1324
 
1325
            if (pinningCandidates != EMPTY_BITBOARD)
1326
            {
1327
               return getFirstSquare(&pinningCandidates);
1328
            }
1329
         }
1330
      }
1331
   }
1332
 
1333
   return NO_SQUARE;
1334
}
1335
 
1336
#ifdef USE_CAN_CASTLE
1337
static bool canCastle(const Position * position, const Color color)
1338
{
1339
   BYTE castlingRights[2] = { WHITE_00 | WHITE_000, BLACK_00 | BLACK_000 };
1340
 
1341
   return (castlingRights[color] & position->castlingRights) != 0;
1342
}
1343
#endif
1344
 
1345
#define PERSPECTIVE_WHITE
1346
#include "evaluationc.c"
1347
#undef PERSPECTIVE_WHITE
1348
#include "evaluationc.c"
1349
 
1350
static void evaluatePawns(const Position * position, EvaluationBase * base)
1351
{
1352
   int opValue, egValue;
1353
 
1354
   static const INT32 isolatedMalusPerFile[8] = {
1355
      V(9, 9), V(13, 11), V(14, 11), V(14, 11),
1356
      V(14, 11), V(14, 11), V(13, 11), V(9, 9)
1357
   };
1358
   static const INT32 isolatedMalusPerOpenFile[8] = {
1359
      V(13, 14), V(19, 16), V(21, 16), V(21, 16),
1360
      V(21, 16), V(21, 16), V(19, 16), V(13, 14)
1361
   };
1362
   static const INT32 backwardMalusPerFile[8] = {
1363
      V(7, 9), V(10, 10), V(12, 10), V(12, 10),
1364
      V(12, 10), V(12, 10), V(10, 10), V(7, 9)
1365
   };
1366
   static const INT32 backwardMalusPerOpenFile[8] = {
1367
      V(11, 13), V(15, 14), V(18, 14), V(18, 14),
1368
      V(18, 14), V(18, 14), V(15, 14), V(11, 13)
1369
   };
1370
   static const INT32 candidateBonusPerRank[8] = {
1371
      V(0, 0), V(2, 5), V(2, 5), V(5, 11),
1372
      V(13, 26), V(32, 64), V(0, 0), V(0, 0)
1373
   };
1374
 
1375
   Square square;
1376
   Bitboard pieces = (base->weakPawns[WHITE] | base->weakPawns[BLACK]);
1377
 
1378
   ITERATE_BITBOARD(&pieces, square)
1379
   {
1380
      const Color pawnColor = pieceColor(position->piece[square]);
1381
      const Color oppColor = opponent(pawnColor);
1382
      const File pawnfile = file(square);
1383
      const bool isolated = (bool)
1384
         ((companionFiles[square] &
1385
           position->piecesOfType[position->piece[square]]) ==
1386
          EMPTY_BITBOARD);
1387
      const bool onOpenFile = (bool)
1388
         (testSquare(base->upwardRealm[oppColor], square) == FALSE &&
1389
          testSquare(base->doubledPawns[pawnColor], square) == FALSE);
1390
 
1391
      if (isolated)
1392
      {
1393
         if (onOpenFile)
1394
         {
1395
            addEvalMalusForColor(base, pawnColor,
1396
                                 isolatedMalusPerOpenFile[pawnfile]);
1397
         }
1398
         else
1399
         {
1400
            addEvalMalusForColor(base, pawnColor,
1401
                                 isolatedMalusPerFile[pawnfile]);
1402
         }
1403
 
1404
         if (testSquare(base->fixedPawns[pawnColor], square))
1405
         {
1406
            addEvalMalusForColor(base, pawnColor, V(2, 3));
1407
         }
1408
      }
1409
      else                      /* backward */
1410
      {
1411
         if (onOpenFile)
1412
         {
1413
            addEvalMalusForColor(base, pawnColor,
1414
                                 backwardMalusPerOpenFile[pawnfile]);
1415
         }
1416
         else
1417
         {
1418
            addEvalMalusForColor(base, pawnColor,
1419
                                 backwardMalusPerFile[pawnfile]);
1420
         }
1421
 
1422
         if (testSquare(base->fixedPawns[pawnColor], square))
1423
         {
1424
            addEvalMalusForColor(base, pawnColor, V(2, 3));
1425
         }
1426
      }
1427
   }
1428
 
1429
   pieces = (base->candidatePawns[WHITE] | base->candidatePawns[BLACK]);
1430
 
1431
   ITERATE_BITBOARD(&pieces, square)
1432
   {
1433
      const Color pawnColor = pieceColor(position->piece[square]);
1434
      const Bitboard supporters = candidateSupporters[pawnColor][square] &
1435
         position->piecesOfType[PAWN | pawnColor];
1436
      const Bitboard defenders = candidateDefenders[pawnColor][square] &
1437
         position->piecesOfType[PAWN | opponent(pawnColor)];
1438
 
1439
      if (getNumberOfSetSquares(supporters) >=
1440
          getNumberOfSetSquares(defenders))
1441
      {
1442
         const Bitboard ownDefenders =
1443
            generalMoves[PAWN | opponent(pawnColor)][square] &
1444
            position->piecesOfType[PAWN | pawnColor];
1445
         const Bitboard attackers =
1446
            generalMoves[PAWN | pawnColor][square] &
1447
            position->piecesOfType[PAWN | opponent(pawnColor)];
1448
 
1449
         if (getNumberOfSetSquares(ownDefenders) >=
1450
             getNumberOfSetSquares(attackers))
1451
         {
1452
            const Rank pawnRank = colorRank(pawnColor, square);
1453
 
1454
            addEvalBonusForColor(base, pawnColor,
1455
                                 candidateBonusPerRank[pawnRank]);
1456
         }
1457
      }
1458
   }
1459
 
1460
   base->balance += V(0, 5 *
1461
                      (getWidth(position->piecesOfType[WHITE_PAWN]) -
1462
                       getWidth(position->piecesOfType[BLACK_PAWN])));
1463
 
1464
   evaluateWhitePawns(base);
1465
   evaluateBlackPawns(base);
1466
 
1467
   opValue = getOpeningValue(base->balance);
1468
   egValue = getEndgameValue(base->balance);
1469
   base->balance = V((opValue * PAWN_EVAL_WEIGHT_OP) / 256,
1470
                     (egValue * PAWN_EVAL_WEIGHT_EG) / 256);
1471
}
1472
 
1473
static void evaluatePassedPawns(const Position * position,
1474
                                EvaluationBase * base)
1475
{
1476
   Square square;
1477
   Bitboard pieces = base->passedPawns[WHITE];
1478
 
1479
   ITERATE_BITBOARD(&pieces, square)
1480
   {
1481
      evaluateWhitePasser(position, base, square);
1482
   }
1483
 
1484
   pieces = base->passedPawns[BLACK];
1485
 
1486
   ITERATE_BITBOARD(&pieces, square)
1487
   {
1488
      evaluateBlackPasser(position, base, square);
1489
   }
1490
}
1491
 
1492
static void evaluateWhiteTrappedBishops(const Position * position,
1493
                                        EvaluationBase * base)
1494
{
1495
   if ((position->piece[A7] == WHITE_BISHOP &&
1496
        position->piece[B6] == BLACK_PAWN) ||
1497
       (position->piece[B8] == WHITE_BISHOP &&
1498
        position->piece[C7] == BLACK_PAWN) ||
1499
       (position->piece[H7] == WHITE_BISHOP &&
1500
        position->piece[G6] == BLACK_PAWN) ||
1501
       (position->piece[G8] == WHITE_BISHOP &&
1502
        position->piece[F7] == BLACK_PAWN))
1503
   {
1504
      base->balance -= V(BISHOP_MALUS_TRAPPED, BISHOP_MALUS_TRAPPED);
1505
   }
1506
 
1507
   if ((position->piece[A6] == WHITE_BISHOP &&
1508
        position->piece[B5] == BLACK_PAWN) ||
1509
       (position->piece[H6] == WHITE_BISHOP &&
1510
        position->piece[G5] == BLACK_PAWN))
1511
   {
1512
      base->balance -= V(BISHOP_MALUS_TRAPPED / 2, BISHOP_MALUS_TRAPPED / 2);
1513
   }
1514
 
1515
   if ((position->piece[C1] == WHITE_BISHOP &&
1516
        position->piece[D2] == WHITE_PAWN &&
1517
        position->piece[D3] != NO_PIECE) ||
1518
       (position->piece[F1] == WHITE_BISHOP &&
1519
        position->piece[E2] == WHITE_PAWN && position->piece[E3] != NO_PIECE))
1520
   {
1521
      base->balance -= V(BISHOP_MALUS_BLOCKED, BISHOP_MALUS_BLOCKED);
1522
   }
1523
}
1524
 
1525
static void evaluateBlackTrappedBishops(const Position * position,
1526
                                        EvaluationBase * base)
1527
{
1528
   if ((position->piece[A2] == BLACK_BISHOP &&
1529
        position->piece[B3] == WHITE_PAWN) ||
1530
       (position->piece[B1] == BLACK_BISHOP &&
1531
        position->piece[C2] == WHITE_PAWN) ||
1532
       (position->piece[H2] == BLACK_BISHOP &&
1533
        position->piece[G3] == WHITE_PAWN) ||
1534
       (position->piece[G1] == BLACK_BISHOP &&
1535
        position->piece[F2] == WHITE_PAWN))
1536
   {
1537
      base->balance += V(BISHOP_MALUS_TRAPPED, BISHOP_MALUS_TRAPPED);
1538
   }
1539
 
1540
   if ((position->piece[A3] == BLACK_BISHOP &&
1541
        position->piece[B4] == WHITE_PAWN) ||
1542
       (position->piece[H3] == BLACK_BISHOP &&
1543
        position->piece[G4] == WHITE_PAWN))
1544
   {
1545
      base->balance += V(BISHOP_MALUS_TRAPPED / 2, BISHOP_MALUS_TRAPPED / 2);
1546
   }
1547
 
1548
   if ((position->piece[C8] == BLACK_BISHOP &&
1549
        position->piece[D7] == BLACK_PAWN &&
1550
        position->piece[D6] != NO_PIECE) ||
1551
       (position->piece[F8] == BLACK_BISHOP &&
1552
        position->piece[E7] == BLACK_PAWN && position->piece[E6] != NO_PIECE))
1553
   {
1554
      base->balance += V(BISHOP_MALUS_BLOCKED, BISHOP_MALUS_BLOCKED);
1555
   }
1556
}
1557
 
1558
static int getSafetyMalusOfKingFile(const Position * position,
1559
                                    const int file,
1560
                                    const Square kingSquare,
1561
                                    const int fileType, const Color color)
1562
{
1563
   return (color == WHITE ?
1564
           getPawnSafetyMalusOfWhiteKingFile(position, file, kingSquare,
1565
                                             fileType) :
1566
           getPawnSafetyMalusOfBlackKingFile(position, file, kingSquare,
1567
                                             fileType));
1568
}
1569
 
1570
static int getSafetyMalusOfKingSquare(const Position * position,
1571
                                      const Square kingSquare,
1572
                                      const Color color)
1573
{
1574
   const int kingFile = file(kingSquare);
1575
   int malus =
1576
      getSafetyMalusOfKingFile(position, kingFile, kingSquare, 1, color);
1577
 
1578
   if (kingFile > FILE_A)
1579
   {
1580
      const int fileType = (kingFile <= FILE_D ? 0 : 2);
1581
 
1582
      malus += getSafetyMalusOfKingFile(position, kingFile - 1, kingSquare,
1583
                                        fileType, color);
1584
   }
1585
 
1586
   if (kingFile < FILE_H)
1587
   {
1588
      const int fileType = (kingFile <= FILE_D ? 2 : 0);
1589
 
1590
      malus += getSafetyMalusOfKingFile(position, kingFile + 1, kingSquare,
1591
                                        fileType, color);
1592
   }
1593
 
1594
   if (malus == 0)
1595
   {
1596
      malus = 8;                /* malus for weak back rank */
1597
   }
1598
 
1599
   return malus;
1600
}
1601
 
1602
static INT32 getPawnShelterMalus(const Position * position, const Color color,
1603
                                 KingSafetyHashInfo * kingSafetyHashtable)
1604
{
1605
   const Bitboard hashKey = calculateKingPawnSafetyHashKey(position, color);
1606
   KingSafetyHashInfo *kingSafetyHashInfo =
1607
      &kingSafetyHashtable[hashKey & KINGSAFETY_HASHTABLE_MASK];
1608
 
1609
   if (kingSafetyHashInfo->hashKey == hashKey &&
1610
       kingSafetyHashInfo->hashKey != 0)
1611
   {
1612
      return kingSafetyHashInfo->safetyMalus;
1613
   }
1614
   else
1615
   {
1616
      static const int rankByColor[2] = { RANK_1, RANK_8 };
1617
      int cr00, cr000;
1618
      const Square kingSquare = position->king[color];
1619
      int pawnShelterMalus = 0, castlingShelterMalus = 0;
1620
      INT32 malus;
1621
 
1622
      if (color == WHITE)
1623
      {
1624
         cr00 = WHITE_00, cr000 = WHITE_000;
1625
      }
1626
      else
1627
      {
1628
         cr00 = BLACK_00, cr000 = BLACK_000;
1629
      }
1630
 
1631
      pawnShelterMalus = castlingShelterMalus =
1632
         getSafetyMalusOfKingSquare(position, kingSquare, color);
1633
 
1634
      if (position->castlingRights & cr00)
1635
      {
1636
         const Square kingSquare = getSquare(FILE_G, rankByColor[color]);
1637
         const int malus00 =
1638
            getSafetyMalusOfKingSquare(position, kingSquare, color);
1639
 
1640
         castlingShelterMalus = min(malus00, castlingShelterMalus);
1641
      }
1642
 
1643
      if (position->castlingRights & cr000)
1644
      {
1645
         const Square kingSquare = getSquare(FILE_B, rankByColor[color]);
1646
         const int malus000 =
1647
            getSafetyMalusOfKingSquare(position, kingSquare, color);
1648
 
1649
         castlingShelterMalus = min(malus000, castlingShelterMalus);
1650
      }
1651
 
1652
      pawnShelterMalus = (pawnShelterMalus + castlingShelterMalus) / 2;
1653
      malus = V(pawnShelterMalus, getKingPawnDistance(position, color));
1654
      kingSafetyHashInfo->hashKey = hashKey;
1655
      kingSafetyHashInfo->safetyMalus = malus;
1656
 
1657
      return malus;
1658
   }
1659
}
1660
 
1661
static Bitboard getWellDefendedSquares(EvaluationBase * base,
1662
                                       const Color color)
1663
{
1664
   return base->pawnProtectedSquares[color] |
1665
      base->knightAttackedSquares[color] | base->bishopAttackedSquares[color];
1666
}
1667
 
1668
static INT32 getKingSafetyMalus(const Position * position,
1669
                                EvaluationBase * base, const Color color)
1670
{
1671
   const Color oppColor = opponent(color);
1672
   const INT32 pawnShelterMalus =
1673
      getPawnShelterMalus(position, color, base->kingsafetyHashtable);
1674
   const int openingShelterMalus = getOpeningValue(pawnShelterMalus);
1675
   const Square kingSquare = position->king[color];
1676
   const Bitboard corona = getKingMoves(kingSquare);
1677
   const Bitboard protectingPawn = corona &
1678
      passedPawnCorridor[color][kingSquare];
1679
   const Bitboard pawnAttackers =
1680
      position->piecesOfType[PAWN | oppColor] &
1681
      kingAttacks[kingSquare].pawnAttackers[oppColor] & ~protectingPawn;
1682
   const int numAttackers = getEndgameValue(base->attackInfo[oppColor]) +
1683
      getNumberOfSetSquares(pawnAttackers) / 2;
1684
   int opMalus = (KS_PAWNSTRUCTURE_WEIGHT * openingShelterMalus) / 64;
1685
 
1686
   if (numAttackers > 0)
1687
   {
1688
      int attackUnits = 0;
1689
      const int attackersWeight = getOpeningValue(base->attackInfo[oppColor]);
1690
      const Bitboard oppQueenAttacks = base->queenAttackedSquares[oppColor];
1691
      const Bitboard oppAttacks = base->attackedSquares[oppColor] |
1692
         getKingMoves(position->king[oppColor]);
1693
      const Bitboard attackedSquares = corona & oppAttacks;
1694
      const Bitboard undefendedSquares =
1695
         attackedSquares & ~base->attackedSquares[color];
1696
      const Bitboard safeChecks =
1697
         ~(position->piecesOfColor[oppColor] | base->attackedSquares[color]);
1698
      const Bitboard safeQueenChecks =
1699
         oppQueenAttacks & undefendedSquares & safeChecks &
1700
         (getWellDefendedSquares(base, oppColor) |
1701
          base->rookAttackedSquares[oppColor] |
1702
          base->queenSupportedSquares[oppColor] |
1703
          getKingMoves(position->king[oppColor]));
1704
      const Bitboard safeRookChecks =
1705
         base->rookAttackedSquares[oppColor] &
1706
         undefendedSquares & safeChecks &
1707
         generalMoves[ROOK][kingSquare] &
1708
         (getWellDefendedSquares(base, oppColor) |
1709
          base->rookDoubleAttackedSquares[oppColor] |
1710
          base->queenAttackedSquares[oppColor] |
1711
          base->queenSupportedSquares[oppColor]);
1712
      const Bitboard safeDistantChecks = safeChecks & ~corona;
1713
      const Bitboard safeOrthoChecks =
1714
         safeDistantChecks &
1715
         getMagicRookMoves(kingSquare, position->allPieces);
1716
      const Bitboard safeDiaChecks =
1717
         safeDistantChecks &
1718
         getMagicBishopMoves(kingSquare, position->allPieces);
1719
      const Bitboard safeKnightChecks =
1720
         safeDistantChecks & getKnightMoves(kingSquare);
1721
 
1722
      attackUnits =
1723
         min(25, (numAttackers * attackersWeight) / 16) +
1724
         2 * base->kingSquaresAttackCount[oppColor] +
1725
         4 * getNumberOfSetSquares(undefendedSquares) +
1726
         (openingShelterMalus * KS_PAWNSTRUCTURE_ATTACK_WEIGHT) / 256;
1727
 
1728
      if (base->pinnedPieces[color] != EMPTY_BITBOARD)
1729
      {
1730
         attackUnits += 2;
1731
      }
1732
 
1733
      if (position->piecesOfType[QUEEN | oppColor] == EMPTY_BITBOARD)
1734
      {
1735
         attackUnits -= 19;
1736
      }
1737
 
1738
      if (safeQueenChecks != EMPTY_BITBOARD)
1739
      {
1740
         const int numChecks = getNumberOfSetSquares(safeQueenChecks);
1741
 
1742
         attackUnits += 23 * numChecks;
1743
      }
1744
 
1745
      if (safeRookChecks != EMPTY_BITBOARD)
1746
      {
1747
         const int numChecks = getNumberOfSetSquares(safeRookChecks);
1748
 
1749
         attackUnits += 12 * numChecks;
1750
      }
1751
 
1752
      if (safeOrthoChecks != EMPTY_BITBOARD)
1753
      {
1754
         const Bitboard queenChecks =
1755
            safeOrthoChecks & base->queenAttackedSquares[oppColor];
1756
         const Bitboard rookChecks =
1757
            safeOrthoChecks & base->rookAttackedSquares[oppColor];
1758
 
1759
         if (queenChecks != EMPTY_BITBOARD)
1760
         {
1761
            attackUnits += 12 * getNumberOfSetSquares(queenChecks);
1762
         }
1763
 
1764
         if (rookChecks != EMPTY_BITBOARD)
1765
         {
1766
            attackUnits += 8 * getNumberOfSetSquares(rookChecks);
1767
         }
1768
      }
1769
 
1770
      if (safeDiaChecks != EMPTY_BITBOARD)
1771
      {
1772
         const Bitboard queenChecks =
1773
            safeDiaChecks & base->queenAttackedSquares[oppColor];
1774
         const Bitboard bishopChecks =
1775
            safeDiaChecks & base->bishopAttackedSquares[oppColor];
1776
 
1777
         if (queenChecks != EMPTY_BITBOARD)
1778
         {
1779
            attackUnits += 12 * getNumberOfSetSquares(queenChecks);
1780
         }
1781
 
1782
         if (bishopChecks != EMPTY_BITBOARD)
1783
         {
1784
            attackUnits += 2 * getNumberOfSetSquares(bishopChecks);
1785
         }
1786
      }
1787
 
1788
      if (safeKnightChecks != EMPTY_BITBOARD)
1789
      {
1790
         const Bitboard knightChecks =
1791
            safeKnightChecks & base->knightAttackedSquares[oppColor];
1792
 
1793
         if (knightChecks != EMPTY_BITBOARD)
1794
         {
1795
            attackUnits += 3 * getNumberOfSetSquares(knightChecks);
1796
         }
1797
      }
1798
 
1799
      if (attackUnits > 0)
1800
      {
1801
         const int numUnits =
1802
            min(KING_SAFETY_MALUS_DIM - 1, (715 * attackUnits) / 256);
1803
 
1804
         opMalus += KING_SAFETY_MALUS[numUnits];
1805
      }
1806
   }
1807
 
1808
   return V(opMalus, getEndgameValue(pawnShelterMalus));
1809
}
1810
 
1811
static bool kingSafetyEvalRequired(const Position * position,
1812
                                   const Color color)
1813
{
1814
   const Color oppColor = opponent(color);
1815
 
1816
   return (bool)
1817
      (getPieceCount(position, (Piece) (QUEEN | oppColor)) > 0 &&
1818
       getPieceWeight(position,
1819
                      oppColor) >= MIN_PIECE_WEIGHT_FOR_KING_ATTACK);
1820
}
1821
 
1822
#ifndef NDEBUG
1823
static Bitboard randomBitboard()
1824
{
1825
   Bitboard tmp1 = rand();
1826
   Bitboard tmp2 = rand();
1827
   Bitboard tmp3 = rand();
1828
   Bitboard tmp4 = rand();
1829
 
1830
   return tmp1 + (tmp2 << 16) + (tmp3 << 32) + (tmp4 << 48);
1831
}
1832
#endif
1833
 
1834
static void initializeEvaluationBase(EvaluationBase * base,
1835
                                     KingSafetyHashInfo *
1836
                                     kingsafetyHashtable,
1837
                                     const Position * position)
1838
{
1839
#ifndef NDEBUG
1840
   base->attackedSquares[WHITE] = randomBitboard();
1841
   base->attackedSquares[BLACK] = randomBitboard();
1842
   base->queenAttackedSquares[WHITE] = randomBitboard();
1843
   base->queenAttackedSquares[BLACK] = randomBitboard();
1844
   base->queenSupportedSquares[WHITE] = randomBitboard();
1845
   base->queenSupportedSquares[BLACK] = randomBitboard();
1846
   base->rookAttackedSquares[WHITE] = randomBitboard();
1847
   base->rookAttackedSquares[BLACK] = randomBitboard();
1848
   base->rookDoubleAttackedSquares[WHITE] = randomBitboard();
1849
   base->rookDoubleAttackedSquares[BLACK] = randomBitboard();
1850
   base->bishopAttackedSquares[WHITE] = randomBitboard();
1851
   base->bishopAttackedSquares[BLACK] = randomBitboard();
1852
   base->knightAttackedSquares[WHITE] = randomBitboard();
1853
   base->knightAttackedSquares[BLACK] = randomBitboard();
1854
   base->balance = rand();
1855
   base->candidatePawns[WHITE] = randomBitboard();
1856
   base->candidatePawns[BLACK] = randomBitboard();
1857
   base->countedSquares[WHITE] = randomBitboard();
1858
   base->countedSquares[BLACK] = randomBitboard();
1859
   base->doubledPawns[WHITE] = randomBitboard();
1860
   base->doubledPawns[BLACK] = randomBitboard();
1861
   base->downwardRealm[WHITE] = randomBitboard();
1862
   base->downwardRealm[BLACK] = randomBitboard();
1863
   base->evaluateKingSafety[WHITE] = (bool) rand();
1864
   base->evaluateKingSafety[BLACK] = (bool) rand();
1865
   base->fixedPawns[WHITE] = randomBitboard();
1866
   base->fixedPawns[BLACK] = randomBitboard();
1867
   base->hasPassersOrCandidates[WHITE] = (bool) rand();
1868
   base->hasPassersOrCandidates[BLACK] = (bool) rand();
1869
   base->hiddenCandidatePawns[WHITE] = randomBitboard();
1870
   base->hiddenCandidatePawns[BLACK] = randomBitboard();
1871
   base->kingAttackSquares[WHITE] = randomBitboard();
1872
   base->kingAttackSquares[BLACK] = randomBitboard();
1873
   base->passedPawns[WHITE] = randomBitboard();
1874
   base->passedPawns[BLACK] = randomBitboard();
1875
   base->pinnedCandidatesDia[WHITE] = randomBitboard();
1876
   base->pinnedCandidatesDia[BLACK] = randomBitboard();
1877
   base->pinnedCandidatesOrtho[WHITE] = randomBitboard();
1878
   base->pinnedCandidatesOrtho[BLACK] = randomBitboard();
1879
   base->pinnedPieces[WHITE] = randomBitboard();
1880
   base->pinnedPieces[BLACK] = randomBitboard();
1881
   base->pawnAttackableSquares[WHITE] = randomBitboard();
1882
   base->pawnAttackableSquares[BLACK] = randomBitboard();
1883
   base->pawnProtectedSquares[WHITE] = randomBitboard();
1884
   base->pawnProtectedSquares[BLACK] = randomBitboard();
1885
   base->spaceAttackPoints[WHITE] = rand();
1886
   base->spaceAttackPoints[BLACK] = rand();
1887
   base->unprotectedPieces[WHITE] = randomBitboard();
1888
   base->unprotectedPieces[BLACK] = randomBitboard();
1889
   base->upwardRealm[WHITE] = randomBitboard();
1890
   base->upwardRealm[BLACK] = randomBitboard();
1891
   base->weakPawns[WHITE] = randomBitboard();
1892
   base->weakPawns[BLACK] = randomBitboard();
1893
   base->kingSquaresAttackCount[WHITE] = rand();
1894
   base->kingSquaresAttackCount[BLACK] = rand();
1895
   base->attackInfo[WHITE] = rand();
1896
   base->attackInfo[BLACK] = rand();
1897
#endif
1898
   base->balance = 0;
1899
   base->kingsafetyHashtable = kingsafetyHashtable;
1900
   base->materialInfo = &materialInfo[calculateMaterialSignature(position)];
1901
}
1902
 
1903
static void evaluatePieces(const Position * position, EvaluationBase * base)
1904
{
1905
   Bitboard queens = position->piecesOfType[WHITE_QUEEN] |
1906
      position->piecesOfType[BLACK_QUEEN];
1907
   const Bitboard exclude = position->piecesOfType[WHITE_PAWN] |
1908
      position->piecesOfType[BLACK_PAWN] | queens |
1909
      minValue[position->king[WHITE]] | minValue[position->king[BLACK]];
1910
   Bitboard pieces = position->allPieces & (~exclude);
1911
   Square square;
1912
 
1913
#ifndef NDEBUG
1914
   if (debugEval)
1915
   {
1916
      logDebug("\nStart of piece evaluation\n");
1917
   }
1918
#endif
1919
 
1920
   ITERATE_BITBOARD(&pieces, square)
1921
   {
1922
#ifndef NDEBUG
1923
      if (debugEval)
1924
      {
1925
         dumpSquare(square);
1926
         logDebug("op=%d eg=%d\n", getOpeningValue(base->balance),
1927
                  getEndgameValue(base->balance));
1928
      }
1929
#endif
1930
      base->materialBalance += mvImpact[position->piece[square]];
1931
 
1932
      switch (position->piece[square])
1933
      {
1934
      case WHITE_ROOK:
1935
         evaluateWhiteRook(position, base, square);
1936
         break;
1937
 
1938
      case BLACK_ROOK:
1939
         evaluateBlackRook(position, base, square);
1940
         break;
1941
 
1942
      case WHITE_BISHOP:
1943
         evaluateWhiteBishop(position, base, square);
1944
         break;
1945
 
1946
      case BLACK_BISHOP:
1947
         evaluateBlackBishop(position, base, square);
1948
         break;
1949
 
1950
      case WHITE_KNIGHT:
1951
         evaluateWhiteKnight(position, base, square);
1952
         break;
1953
 
1954
      case BLACK_KNIGHT:
1955
         evaluateBlackKnight(position, base, square);
1956
         break;
1957
 
1958
      default:
1959
         break;
1960
      }
1961
 
1962
#ifndef NDEBUG
1963
      if (debugEval)
1964
      {
1965
         logDebug("op=%d eg=%d\n", getOpeningValue(base->balance),
1966
                  getEndgameValue(base->balance));
1967
      }
1968
#endif
1969
   }
1970
 
1971
   ITERATE_BITBOARD(&queens, square)
1972
   {
1973
#ifndef NDEBUG
1974
      if (debugEval)
1975
      {
1976
         dumpSquare(square);
1977
         logDebug("op=%d eg=%d\n", getOpeningValue(base->balance),
1978
                  getEndgameValue(base->balance));
1979
      }
1980
#endif
1981
      base->materialBalance += mvImpact[position->piece[square]];
1982
 
1983
      switch (position->piece[square])
1984
      {
1985
      case WHITE_QUEEN:
1986
         evaluateWhiteQueen(position, base, square);
1987
         break;
1988
 
1989
      case BLACK_QUEEN:
1990
         evaluateBlackQueen(position, base, square);
1991
         break;
1992
 
1993
      default:
1994
         break;
1995
      }
1996
 
1997
#ifndef NDEBUG
1998
      if (debugEval)
1999
      {
2000
         logDebug("op=%d eg=%d\n", getOpeningValue(base->balance),
2001
                  getEndgameValue(base->balance));
2002
      }
2003
#endif
2004
   }
2005
 
2006
   if (position->piecesOfType[WHITE_BISHOP] != EMPTY_BITBOARD)
2007
   {
2008
      evaluateWhiteTrappedBishops(position, base);
2009
   }
2010
 
2011
   if (position->piecesOfType[BLACK_BISHOP] != EMPTY_BITBOARD)
2012
   {
2013
      evaluateBlackTrappedBishops(position, base);
2014
   }
2015
 
2016
#ifndef NDEBUG
2017
   if (debugEval)
2018
   {
2019
      logDebug("Values after piece evaluation\n");
2020
      logDebug("op=%d eg=%d\n", getOpeningValue(base->balance),
2021
               getEndgameValue(base->balance));
2022
      logDebug("End of piece evaluation\n");
2023
   }
2024
#endif
2025
}
2026
 
2027
static bool evaluateKingChase(const Position * position,
2028
                              const Color kingColor)
2029
{
2030
   if (position->numberOfPawns[WHITE] == 0 &&
2031
       position->numberOfPawns[BLACK] == 0 &&
2032
       numberOfNonPawnPieces(position, kingColor) <= 2)
2033
   {
2034
      return (bool) (getPieceWeight(position, kingColor) <
2035
                     getPieceWeight(position, opponent(kingColor)));
2036
   }
2037
 
2038
   return FALSE;
2039
}
2040
 
2041
static int getKingChaseMalus(const Position * position,
2042
                             const Color huntedKingColor)
2043
{
2044
   const Color attackingColor = opponent(huntedKingColor);
2045
   const Square huntedKingSquare = position->king[huntedKingColor];
2046
   const Square attackingKingSquare = position->king[attackingColor];
2047
   const int mutualDistance =
2048
      distance(huntedKingSquare, attackingKingSquare) - 2;
2049
   int cornerDistanceMalus = kingChaseMalus[ALL][huntedKingSquare];
2050
 
2051
   if (hasOrthoPieces(position, attackingColor) == FALSE &&
2052
       position->piecesOfType[(Piece) (BISHOP | attackingColor)] !=
2053
       EMPTY_BITBOARD)
2054
   {
2055
      const Bitboard attackingBishops =
2056
         position->piecesOfType[BISHOP | attackingColor];
2057
 
2058
      if ((lightSquares & attackingBishops) == EMPTY_BITBOARD)
2059
      {
2060
         cornerDistanceMalus = kingChaseMalus[DARK][huntedKingSquare];
2061
      }
2062
 
2063
      if ((darkSquares & attackingBishops) == EMPTY_BITBOARD)
2064
      {
2065
         cornerDistanceMalus = kingChaseMalus[LIGHT][huntedKingSquare];
2066
      }
2067
   }
2068
 
2069
   return 5 * (5 - mutualDistance) + 15 * cornerDistanceMalus;
2070
}
2071
 
2072
static int getHomelandSecurityCount(const Position * position,
2073
                                    EvaluationBase * base, const Color color)
2074
{
2075
   const Color oppColor = opponent(color);
2076
   const Bitboard ownPawns = position->piecesOfType[PAWN | color];
2077
   const Bitboard exclude = ownPawns |
2078
      base->pawnProtectedSquares[oppColor] |
2079
      (base->attackedSquares[oppColor] & ~base->attackedSquares[color]);
2080
   const Bitboard safeSquares = homeland[color] & ~exclude;
2081
   const Bitboard superSafeSquares =
2082
      safeSquares & (color == WHITE ? (ownPawns >> 8) | (ownPawns >> 16) :
2083
                     (ownPawns << 8) | (ownPawns << 16));
2084
 
2085
   return getNumberOfSetSquares(safeSquares) +
2086
      getNumberOfSetSquares(superSafeSquares);
2087
}
2088
 
2089
static void setPinnedCandidates(const Position * position,
2090
                                EvaluationBase * base, const Color color)
2091
{
2092
   const Bitboard candidatePieces = getNonPawnPieces(position, color);
2093
   const Square kingSquare = position->king[color];
2094
 
2095
   base->pinnedCandidatesDia[color] =
2096
      candidatePieces & getMagicBishopMoves(kingSquare, position->allPieces);
2097
   base->pinnedCandidatesOrtho[color] =
2098
      candidatePieces & getMagicRookMoves(kingSquare, position->allPieces);
2099
}
2100
 
2101
static int getNumberOfUnprotectedMinors(const Position * position,
2102
                                        EvaluationBase * base,
2103
                                        const Color color)
2104
{
2105
   const Bitboard candidatePieces = position->piecesOfType[KNIGHT | color] |
2106
      position->piecesOfType[BISHOP | color];
2107
   const Bitboard unprotectedMinors =
2108
      candidatePieces & ~base->attackedSquares[color];
2109
 
2110
   return (unprotectedMinors == EMPTY_BITBOARD ? 0 :
2111
           getNumberOfSetSquares(unprotectedMinors));
2112
}
2113
 
2114
static void getPositionalValue(const Position * position,
2115
                               EvaluationBase * base)
2116
{
2117
   const Bitboard whiteCorona = getKingMoves(position->king[WHITE]);
2118
   const Bitboard blackCorona = getKingMoves(position->king[BLACK]);
2119
 
2120
   base->countedSquares[WHITE] = ~(minValue[position->king[WHITE]] |
2121
                                   position->piecesOfType[WHITE_PAWN] |
2122
                                   base->pawnProtectedSquares[BLACK]);
2123
   base->unprotectedPieces[WHITE] = position->piecesOfColor[WHITE] &
2124
      ~base->pawnProtectedSquares[WHITE];
2125
   base->countedSquares[BLACK] = ~(minValue[position->king[BLACK]] |
2126
                                   position->piecesOfType[BLACK_PAWN] |
2127
                                   base->pawnProtectedSquares[WHITE]);
2128
   base->unprotectedPieces[BLACK] = position->piecesOfColor[BLACK] &
2129
      ~base->pawnProtectedSquares[BLACK];
2130
   base->spaceAttackPoints[WHITE] = base->spaceAttackPoints[BLACK] = 0;
2131
   base->attackedSquares[WHITE] = base->pawnProtectedSquares[WHITE];
2132
   base->attackedSquares[BLACK] = base->pawnProtectedSquares[BLACK];
2133
   base->knightAttackedSquares[WHITE] = EMPTY_BITBOARD;
2134
   base->knightAttackedSquares[BLACK] = EMPTY_BITBOARD;
2135
   base->bishopAttackedSquares[WHITE] = EMPTY_BITBOARD;
2136
   base->bishopAttackedSquares[BLACK] = EMPTY_BITBOARD;
2137
   base->rookAttackedSquares[WHITE] = EMPTY_BITBOARD;
2138
   base->rookAttackedSquares[BLACK] = EMPTY_BITBOARD;
2139
   base->rookDoubleAttackedSquares[WHITE] = EMPTY_BITBOARD;
2140
   base->rookDoubleAttackedSquares[BLACK] = EMPTY_BITBOARD;
2141
   base->queenAttackedSquares[WHITE] = EMPTY_BITBOARD;
2142
   base->queenAttackedSquares[BLACK] = EMPTY_BITBOARD;
2143
   base->queenSupportedSquares[WHITE] = EMPTY_BITBOARD;
2144
   base->queenSupportedSquares[BLACK] = EMPTY_BITBOARD;
2145
   base->pinnedPieces[WHITE] = EMPTY_BITBOARD;
2146
   base->pinnedPieces[BLACK] = EMPTY_BITBOARD;
2147
   base->kingAttackSquares[WHITE] = whiteCorona | (whiteCorona << 8);
2148
   base->kingAttackSquares[BLACK] = blackCorona | (blackCorona >> 8);
2149
   base->evaluateKingSafety[WHITE] = kingSafetyEvalRequired(position, WHITE);
2150
   base->evaluateKingSafety[BLACK] = kingSafetyEvalRequired(position, BLACK);
2151
   base->kingSquaresAttackCount[WHITE] =
2152
      base->kingSquaresAttackCount[BLACK] = 0;
2153
   base->attackInfo[WHITE] = base->attackInfo[BLACK] = 0;
2154
   base->materialBalance =
2155
      position->numberOfPawns[WHITE] * mvImpact[WHITE_PAWN] +
2156
      position->numberOfPawns[BLACK] * mvImpact[BLACK_PAWN];
2157
   setPinnedCandidates(position, base, WHITE);
2158
   setPinnedCandidates(position, base, BLACK);
2159
 
2160
   evaluatePieces(position, base);
2161
   base->attackedSquares[WHITE] |= base->knightAttackedSquares[WHITE] |
2162
      base->bishopAttackedSquares[WHITE] | base->rookAttackedSquares[WHITE] |
2163
      base->queenAttackedSquares[WHITE];
2164
   base->attackedSquares[BLACK] |= base->knightAttackedSquares[BLACK] |
2165
      base->bishopAttackedSquares[BLACK] | base->rookAttackedSquares[BLACK] |
2166
      base->queenAttackedSquares[BLACK];
2167
 
2168
#ifndef NDEBUG
2169
   if (debugEval)
2170
   {
2171
      logDebug("\nEval values before king safety eval:\n");
2172
      logDebug("op=%d eg=%d\n", getOpeningValue(base->balance),
2173
               getEndgameValue(base->balance));
2174
   }
2175
 
2176
   {
2177
      Color color;
2178
 
2179
      for (color = WHITE; color <= BLACK; color++)
2180
      {
2181
         Bitboard pawns = position->piecesOfType[PAWN | color];
2182
         Square pawnSquare;
2183
 
2184
         ITERATE_BITBOARD(&pawns, pawnSquare)
2185
         {
2186
            if (testSquare(base->passedPawns[color], pawnSquare))
2187
            {
2188
               assert(pawnIsPassed(position, pawnSquare, color));
2189
            }
2190
            else
2191
            {
2192
               assert(pawnIsPassed(position, pawnSquare, color) == FALSE);
2193
            }
2194
         }
2195
      }
2196
   }
2197
#endif
2198
 
2199
   {
2200
      INT32 malus = getKingSafetyMalus(position, base, WHITE);
2201
 
2202
#ifdef NDEBUG
2203
      if (base->ownColor == WHITE)
2204
      {
2205
         const int opValue =
2206
            (OWN_COLOR_WEIGHT_KINGSAFETY * getOpeningValue(malus)) /
2207
            OWN_COLOR_WEIGHT_DIV;
2208
 
2209
         malus = V(opValue, getEndgameValue(malus));
2210
      }
2211
#endif
2212
 
2213
      base->balance -= malus;
2214
   }
2215
 
2216
   {
2217
      INT32 malus = getKingSafetyMalus(position, base, BLACK);
2218
 
2219
#ifdef NDEBUG
2220
      if (base->ownColor == BLACK)
2221
      {
2222
         const int opValue =
2223
            (OWN_COLOR_WEIGHT_KINGSAFETY * getOpeningValue(malus)) /
2224
            OWN_COLOR_WEIGHT_DIV;
2225
 
2226
         malus = V(opValue, getEndgameValue(malus));
2227
      }
2228
#endif
2229
 
2230
      base->balance += malus;
2231
   }
2232
 
2233
#ifndef NDEBUG
2234
   if (debugEval)
2235
   {
2236
      logDebug("\nEval values before passed pawn eval:\n");
2237
      logDebug("op=%d eg=%d\n", getOpeningValue(base->balance),
2238
               getEndgameValue(base->balance));
2239
   }
2240
#endif
2241
 
2242
   if (base->passedPawns[WHITE] != EMPTY_BITBOARD ||
2243
       base->passedPawns[BLACK] != EMPTY_BITBOARD)
2244
   {
2245
#ifndef NDEBUG
2246
      if (debugEval)
2247
      {
2248
         dumpBitboard(base->passedPawns[WHITE], "white passers");
2249
         dumpBitboard(base->passedPawns[BLACK], "black passers");
2250
      }
2251
#endif
2252
 
2253
      evaluatePassedPawns(position, base);
2254
   }
2255
 
2256
   if (evaluateKingChase(position, WHITE))
2257
   {
2258
      const int kingChaseMalus = getKingChaseMalus(position, WHITE);
2259
 
2260
      base->balance -= V(kingChaseMalus, kingChaseMalus);
2261
   }
2262
   else if (evaluateKingChase(position, BLACK))
2263
   {
2264
      const int kingChaseMalus = getKingChaseMalus(position, BLACK);
2265
 
2266
      base->balance += V(kingChaseMalus, kingChaseMalus);
2267
   }
2268
 
2269
#ifndef NDEBUG
2270
   if (debugEval)
2271
   {
2272
      logDebug("\nEval values before space attack eval:\n");
2273
      logDebug("op=%d eg=%d\n", getOpeningValue(base->balance),
2274
               getEndgameValue(base->balance));
2275
   }
2276
#endif
2277
 
2278
   base->attackedSquares[WHITE] |= getKingMoves(position->king[WHITE]);
2279
   base->attackedSquares[BLACK] |= getKingMoves(position->king[BLACK]);
2280
 
2281
   {
2282
      const INT32 malus = V(15, 2);
2283
      const int unprotectedWhiteMinors =
2284
         getNumberOfUnprotectedMinors(position, base, WHITE);
2285
      const int unprotectedBlackMinors =
2286
         getNumberOfUnprotectedMinors(position, base, BLACK);
2287
 
2288
      base->balance -=
2289
         malus * (unprotectedWhiteMinors - unprotectedBlackMinors);
2290
   }
2291
 
2292
   {
2293
      const INT32 bonusPerMinor = V(4, 0);
2294
      const Bitboard whiteMinors = (position->piecesOfType[WHITE_PAWN] >> 8) &
2295
         (position->piecesOfType[WHITE_BISHOP] |
2296
          position->piecesOfType[WHITE_KNIGHT]) &
2297
         squaresOfRankRange[RANK_1][RANK_4];
2298
      const Bitboard blackMinors = (position->piecesOfType[BLACK_PAWN] << 8) &
2299
         (position->piecesOfType[BLACK_BISHOP] |
2300
          position->piecesOfType[BLACK_KNIGHT]) &
2301
         squaresOfRankRange[RANK_8][RANK_5];
2302
      const int delta = getNumberOfSetSquares(whiteMinors) -
2303
         getNumberOfSetSquares(blackMinors);
2304
 
2305
      base->balance += delta * bonusPerMinor;
2306
   }
2307
 
2308
   if (base->materialInfo->phaseIndex < PHASE_INDEX_MAX)
2309
   {
2310
      const int weight = getHomeSecurityWeight(position);
2311
 
2312
      if (weight > 0)
2313
      {
2314
         const int countWhite =
2315
            getHomelandSecurityCount(position, base, WHITE);
2316
         const int countBlack =
2317
            getHomelandSecurityCount(position, base, BLACK);
2318
         const int baseValue = (countWhite - countBlack) * weight;
2319
 
2320
         base->balance += V((baseValue * HOMELAND_SECURITY_WEIGHT) / 256, 0);
2321
      }
2322
   }
2323
 
2324
#ifndef NDEBUG
2325
   if (debugEval)
2326
   {
2327
      logDebug("\nFinal eval values:\n");
2328
      logDebug("op=%d eg=%d\n", getOpeningValue(base->balance),
2329
               getEndgameValue(base->balance));
2330
   }
2331
#endif
2332
}
2333
 
2334
int getValue(const Position * position,
2335
             EvaluationBase * base,
2336
             PawnHashInfo * pawnHashtable,
2337
             KingSafetyHashInfo * kingsafetyHashtable)
2338
{
2339
   PawnHashInfo *pawnHashInfo =
2340
      &pawnHashtable[position->pawnHashKey & PAWN_HASHTABLE_MASK];
2341
 
2342
   initializeEvaluationBase(base, kingsafetyHashtable, position);
2343
 
2344
   if (pawnHashInfo->hashKey == position->pawnHashKey &&
2345
       pawnHashInfo->hashKey != 0)
2346
   {
2347
#ifndef NDEBUG
2348
      getPawnInfo(position, base);
2349
      evaluatePawns(position, base);
2350
 
2351
      assert(base->balance == pawnHashInfo->balance);
2352
      assert(base->pawnProtectedSquares[WHITE] ==
2353
             pawnHashInfo->pawnProtectedSquares[WHITE]);
2354
      assert(base->pawnProtectedSquares[BLACK] ==
2355
             pawnHashInfo->pawnProtectedSquares[BLACK]);
2356
      assert(base->passedPawns[WHITE] == pawnHashInfo->passedPawns[WHITE]);
2357
      assert(base->passedPawns[BLACK] == pawnHashInfo->passedPawns[BLACK]);
2358
#endif
2359
 
2360
      base->balance = pawnHashInfo->balance;
2361
      base->passedPawns[WHITE] = pawnHashInfo->passedPawns[WHITE];
2362
      base->passedPawns[BLACK] = pawnHashInfo->passedPawns[BLACK];
2363
      base->pawnProtectedSquares[WHITE] =
2364
         pawnHashInfo->pawnProtectedSquares[WHITE];
2365
      base->pawnProtectedSquares[BLACK] =
2366
         pawnHashInfo->pawnProtectedSquares[BLACK];
2367
      base->pawnAttackableSquares[WHITE] =
2368
         pawnHashInfo->pawnAttackableSquares[WHITE];
2369
      base->pawnAttackableSquares[BLACK] =
2370
         pawnHashInfo->pawnAttackableSquares[BLACK];
2371
#ifdef BONUS_HIDDEN_PASSER
2372
      base->hasPassersOrCandidates[WHITE] =
2373
         pawnHashInfo->hasPassersOrCandidates[WHITE];
2374
      base->hasPassersOrCandidates[BLACK] =
2375
         pawnHashInfo->hasPassersOrCandidates[BLACK];
2376
#endif
2377
   }
2378
   else
2379
   {
2380
      getPawnInfo(position, base);
2381
      evaluatePawns(position, base);
2382
 
2383
      pawnHashInfo->hashKey = position->pawnHashKey;
2384
      pawnHashInfo->balance = base->balance;
2385
      pawnHashInfo->pawnProtectedSquares[WHITE] =
2386
         base->pawnProtectedSquares[WHITE];
2387
      pawnHashInfo->pawnProtectedSquares[BLACK] =
2388
         base->pawnProtectedSquares[BLACK];
2389
      pawnHashInfo->passedPawns[WHITE] = base->passedPawns[WHITE];
2390
      pawnHashInfo->passedPawns[BLACK] = base->passedPawns[BLACK];
2391
      pawnHashInfo->pawnAttackableSquares[WHITE] =
2392
         base->pawnAttackableSquares[WHITE];
2393
      pawnHashInfo->pawnAttackableSquares[BLACK] =
2394
         base->pawnAttackableSquares[BLACK];
2395
#ifdef BONUS_HIDDEN_PASSER
2396
      pawnHashInfo->hasPassersOrCandidates[WHITE] =
2397
         base->hasPassersOrCandidates[WHITE];
2398
      pawnHashInfo->hasPassersOrCandidates[BLACK] =
2399
         base->hasPassersOrCandidates[BLACK];
2400
#endif
2401
   }
2402
 
2403
#ifdef TRACE_EVAL
2404
   logDebug("\nStarting evaluation.\n");
2405
   logDebug("phaseIndex = %d\n", phaseIndex(position));
2406
   logDebug("opvWhite = %d egvWhite = %d\n",
2407
            position->openingValue[WHITE], position->endgameValue[WHITE]);
2408
   logDebug("opvBlack = %d egvBlack = %d\n",
2409
            position->openingValue[BLACK], position->endgameValue[BLACK]);
2410
   logDebug("basicValue = %d\n\n", basicValue);
2411
   logPosition(position);
2412
   logDebug("\n");
2413
#endif
2414
 
2415
   getPositionalValue(position, base);
2416
 
2417
   return positionalBalance(position, base);
2418
}
2419
 
2420
static void transposeMatrix(const int human[], int machine[])
2421
{
2422
   int file, rank, i = 0;
2423
 
2424
   for (rank = RANK_8; rank >= RANK_1; rank--)
2425
   {
2426
      for (file = FILE_A; file <= FILE_H; file++)
2427
      {
2428
         const Square machineSquare = getSquare(file, rank);
2429
 
2430
         machine[machineSquare] = human[i++];
2431
      }
2432
   }
2433
}
2434
 
2435
static int pstOpeningValue(INT32 value, const int weight)
2436
{
2437
   return applyWeight(weight, getOpeningValue(value));
2438
}
2439
 
2440
static int pstEndgameValue(INT32 value, const int weight)
2441
{
2442
   return applyWeight(weight, getEndgameValue(value));
2443
}
2444
 
2445
static void initializePieceSquareValues()
2446
{
2447
   Square sq;
2448
 
2449
   mvImpact[WHITE_QUEEN] = V(VALUE_QUEEN_OPENING, VALUE_QUEEN_ENDGAME);
2450
   mvImpact[BLACK_QUEEN] = V(-VALUE_QUEEN_OPENING, -VALUE_QUEEN_ENDGAME);
2451
   mvImpact[WHITE_ROOK] = V(VALUE_ROOK_OPENING, VALUE_ROOK_ENDGAME);
2452
   mvImpact[BLACK_ROOK] = V(-VALUE_ROOK_OPENING, -VALUE_ROOK_ENDGAME);
2453
   mvImpact[WHITE_BISHOP] = V(VALUE_BISHOP_OPENING, VALUE_BISHOP_ENDGAME);
2454
   mvImpact[BLACK_BISHOP] = V(-VALUE_BISHOP_OPENING, -VALUE_BISHOP_ENDGAME);
2455
   mvImpact[WHITE_KNIGHT] = V(VALUE_KNIGHT_OPENING, VALUE_KNIGHT_ENDGAME);
2456
   mvImpact[BLACK_KNIGHT] = V(-VALUE_KNIGHT_OPENING, -VALUE_KNIGHT_ENDGAME);
2457
   mvImpact[WHITE_PAWN] = V(VALUE_PAWN_OPENING, VALUE_PAWN_ENDGAME);
2458
   mvImpact[BLACK_PAWN] = V(-VALUE_PAWN_OPENING, -VALUE_PAWN_ENDGAME);
2459
 
2460
   ITERATE(sq)
2461
   {
2462
      int ov, ev;
2463
 
2464
      ov = pstOpeningValue(PstPawn[sq], 256);
2465
      ev = pstEndgameValue(PstPawn[sq], 250);
2466
      pieceSquareBonus[WHITE_PAWN][sq] =
2467
         pieceSquareBonus[BLACK_PAWN][getFlippedSquare(sq)] = V(ov, ev);
2468
 
2469
      ov = pstOpeningValue(PstKnight[sq], 256);
2470
      ev = pstEndgameValue(PstKnight[sq], 256);
2471
      pieceSquareBonus[WHITE_KNIGHT][sq] =
2472
         pieceSquareBonus[BLACK_KNIGHT][getFlippedSquare(sq)] = V(ov, ev);
2473
 
2474
      ov = pstOpeningValue(PstBishop[sq], 256);
2475
      ev = pstEndgameValue(PstBishop[sq], 256);
2476
      pieceSquareBonus[WHITE_BISHOP][sq] =
2477
         pieceSquareBonus[BLACK_BISHOP][getFlippedSquare(sq)] = V(ov, ev);
2478
 
2479
      ov = pstOpeningValue(PstRook[sq], 256);
2480
      ev = pstEndgameValue(PstRook[sq], 256);
2481
      pieceSquareBonus[WHITE_ROOK][sq] =
2482
         pieceSquareBonus[BLACK_ROOK][getFlippedSquare(sq)] = V(ov, ev);
2483
 
2484
      ov = pstOpeningValue(PstQueen[sq], 256);
2485
      ev = pstEndgameValue(PstQueen[sq], 322);
2486
      pieceSquareBonus[WHITE_QUEEN][sq] =
2487
         pieceSquareBonus[BLACK_QUEEN][getFlippedSquare(sq)] = V(ov, ev);
2488
 
2489
      ov = pstOpeningValue(PstKing[sq], 247);
2490
      ev = pstEndgameValue(PstKing[sq], 244);
2491
      pieceSquareBonus[WHITE_KING][sq] =
2492
         pieceSquareBonus[BLACK_KING][getFlippedSquare(sq)] = V(ov, ev);
2493
 
2494
#ifdef LOG_ARRAY
2495
      logDebug("V(%d,%d),", ov, ev);
2496
 
2497
      if ((sq + 1) % 8 == 0)
2498
      {
2499
         logDebug(" /* rank %d */\n", (sq + 1) / 8);
2500
      }
2501
#endif
2502
   }
2503
 
2504
#ifdef LOG_ARRAY
2505
   getKeyStroke();
2506
#endif
2507
}
2508
 
2509
static void initializeKingAttacks()
2510
{
2511
   Square square;
2512
 
2513
   ITERATE(square)
2514
   {
2515
      const Bitboard corona = getKingMoves(square);
2516
      KingAttacks *attackInfo = &kingAttacks[square];
2517
      Square attackerSquare;
2518
 
2519
      attackInfo->diaAttackers = attackInfo->orthoAttackers =
2520
         attackInfo->knightAttackers = attackInfo->pawnAttackers[WHITE] =
2521
         attackInfo->pawnAttackers[BLACK] = EMPTY_BITBOARD;
2522
 
2523
      ITERATE(attackerSquare)
2524
      {
2525
         attackInfo->attackedByDia[attackerSquare] =
2526
            attackInfo->attackedByOrtho[attackerSquare] = NO_SQUARE;
2527
      }
2528
 
2529
      ITERATE(attackerSquare)
2530
      {
2531
         Bitboard dia, ortho;
2532
         const Bitboard knight =
2533
            corona & generalMoves[WHITE_KNIGHT][attackerSquare];
2534
         const Bitboard whitePawn =
2535
            corona & generalMoves[WHITE_PAWN][attackerSquare];
2536
         const Bitboard blackPawn =
2537
            corona & generalMoves[BLACK_PAWN][attackerSquare];
2538
 
2539
         dia = corona & generalMoves[WHITE_BISHOP][attackerSquare];
2540
         ortho = corona & generalMoves[WHITE_ROOK][attackerSquare];
2541
 
2542
         if (dia != EMPTY_BITBOARD)
2543
         {
2544
            Square attackedSquare;
2545
            int dist = 8;
2546
 
2547
            setSquare(attackInfo->diaAttackers, attackerSquare);
2548
 
2549
            ITERATE_BITBOARD(&dia, attackedSquare)
2550
            {
2551
               const int currentDistance =
2552
                  distance(attackerSquare, attackedSquare);
2553
 
2554
               if (currentDistance < dist)
2555
               {
2556
                  attackInfo->attackedByDia[attackerSquare] = attackedSquare;
2557
                  dist = currentDistance;
2558
               }
2559
            }
2560
         }
2561
 
2562
         if (ortho != EMPTY_BITBOARD)
2563
         {
2564
            Square attackedSquare;
2565
            int dist = 8;
2566
 
2567
            setSquare(attackInfo->orthoAttackers, attackerSquare);
2568
 
2569
            ITERATE_BITBOARD(&ortho, attackedSquare)
2570
            {
2571
               const int currentDistance =
2572
                  distance(attackerSquare, attackedSquare);
2573
 
2574
               if (currentDistance < dist)
2575
               {
2576
                  attackInfo->attackedByOrtho[attackerSquare] =
2577
                     attackedSquare;
2578
                  dist = currentDistance;
2579
               }
2580
            }
2581
         }
2582
 
2583
         if (knight != EMPTY_BITBOARD)
2584
         {
2585
            setSquare(attackInfo->knightAttackers, attackerSquare);
2586
         }
2587
 
2588
         if (whitePawn != EMPTY_BITBOARD)
2589
         {
2590
            setSquare(attackInfo->pawnAttackers[WHITE], attackerSquare);
2591
         }
2592
 
2593
         if (blackPawn != EMPTY_BITBOARD)
2594
         {
2595
            setSquare(attackInfo->pawnAttackers[BLACK], attackerSquare);
2596
         }
2597
      }
2598
   }
2599
}
2600
 
2601
#define AVOID_TRADES_WITH_TWO_KNIGHTS   /* */
2602
 
2603
static void getPieceTradeSignatures(UINT32 * materialSignatureWhite,
2604
                                    UINT32 * materialSignatureBlack)
2605
{
2606
   int numWhiteQueens, numWhiteRooks, numWhiteLightSquareBishops;
2607
   int numWhiteDarkSquareBishops, numWhiteKnights, numWhitePawns;
2608
   int numBlackQueens, numBlackRooks, numBlackLightSquareBishops;
2609
   int numBlackDarkSquareBishops, numBlackKnights, numBlackPawns;
2610
   bool finished = TRUE;
2611
   bool whiteKnightTradesOnly = FALSE, blackKnightTradesOnly = FALSE;
2612
   bool knightTradesOnly = FALSE;
2613
   const UINT32 signature =
2614
      bilateralSignature(*materialSignatureWhite, *materialSignatureBlack);
2615
 
2616
#ifdef AVOID_TRADES_WITH_TWO_KNIGHTS
2617
   int numWhiteNonPawns, numBlackNonPawns;
2618
#endif
2619
 
2620
   getPieceCounters(signature, &numWhiteQueens, &numWhiteRooks,
2621
                    &numWhiteLightSquareBishops,
2622
                    &numWhiteDarkSquareBishops, &numWhiteKnights,
2623
                    &numWhitePawns, &numBlackQueens, &numBlackRooks,
2624
                    &numBlackLightSquareBishops,
2625
                    &numBlackDarkSquareBishops, &numBlackKnights,
2626
                    &numBlackPawns);
2627
 
2628
#ifdef AVOID_TRADES_WITH_TWO_KNIGHTS
2629
   numWhiteNonPawns =
2630
      numWhiteQueens + numWhiteRooks + numWhiteLightSquareBishops +
2631
      numWhiteDarkSquareBishops + numWhiteKnights;
2632
   numBlackNonPawns =
2633
      numBlackQueens + numBlackRooks + numBlackLightSquareBishops +
2634
      numBlackDarkSquareBishops + numBlackKnights;
2635
 
2636
   if (numWhitePawns + numBlackPawns == 0 && numWhiteKnights == 2 &&
2637
       numWhiteNonPawns == 3 && numWhiteNonPawns - numBlackNonPawns >= 2)
2638
   {
2639
      whiteKnightTradesOnly = TRUE;     /* white will avoid to trade pieces */
2640
   }
2641
 
2642
   if (numBlackPawns + numWhitePawns == 0 && numBlackKnights == 2 &&
2643
       numBlackNonPawns == 3 && numBlackNonPawns - numWhiteNonPawns >= 2)
2644
   {
2645
      blackKnightTradesOnly = TRUE;     /* black will avoid to trade pieces */
2646
   }
2647
 
2648
   knightTradesOnly = whiteKnightTradesOnly || blackKnightTradesOnly;
2649
#endif
2650
 
2651
   if (knightTradesOnly == FALSE && numWhiteQueens > 0 && numBlackQueens > 0)
2652
   {
2653
      numWhiteQueens--;
2654
      numBlackQueens--;
2655
      finished = FALSE;
2656
      goto calculateSignature;
2657
   }
2658
 
2659
   if (knightTradesOnly == FALSE && numWhiteRooks > 0 && numBlackRooks > 0)
2660
   {
2661
      numWhiteRooks--;
2662
      numBlackRooks--;
2663
      finished = FALSE;
2664
      goto calculateSignature;
2665
   }
2666
 
2667
   if (knightTradesOnly == FALSE &&
2668
       numWhiteLightSquareBishops > 0 && numBlackLightSquareBishops > 0)
2669
   {
2670
      numWhiteLightSquareBishops--;
2671
      numBlackLightSquareBishops--;
2672
      finished = FALSE;
2673
      goto calculateSignature;
2674
   }
2675
 
2676
   if (knightTradesOnly == FALSE &&
2677
       numWhiteDarkSquareBishops > 0 && numBlackDarkSquareBishops > 0)
2678
   {
2679
      numWhiteDarkSquareBishops--;
2680
      numBlackDarkSquareBishops--;
2681
      finished = FALSE;
2682
      goto calculateSignature;
2683
   }
2684
 
2685
   if (knightTradesOnly == FALSE &&
2686
       numWhiteLightSquareBishops > 0 && numBlackDarkSquareBishops > 0)
2687
   {
2688
      numWhiteLightSquareBishops--;
2689
      numBlackDarkSquareBishops--;
2690
      finished = FALSE;
2691
      goto calculateSignature;
2692
   }
2693
 
2694
   if (knightTradesOnly == FALSE &&
2695
       numWhiteDarkSquareBishops > 0 && numBlackLightSquareBishops > 0)
2696
   {
2697
      numWhiteDarkSquareBishops--;
2698
      numBlackLightSquareBishops--;
2699
      finished = FALSE;
2700
      goto calculateSignature;
2701
   }
2702
 
2703
   if (numWhiteKnights > 0 && numBlackKnights > 0)
2704
   {
2705
      numWhiteKnights--;
2706
      numBlackKnights--;
2707
      finished = FALSE;
2708
      goto calculateSignature;
2709
   }
2710
 
2711
   if (whiteKnightTradesOnly == FALSE &&
2712
       numWhiteLightSquareBishops > 0 && numBlackKnights > 0 &&
2713
       numWhiteDarkSquareBishops == 0)
2714
   {
2715
      numWhiteLightSquareBishops--;
2716
      numBlackKnights--;
2717
      finished = FALSE;
2718
      goto calculateSignature;
2719
   }
2720
 
2721
   if (whiteKnightTradesOnly == FALSE &&
2722
       numWhiteDarkSquareBishops > 0 && numBlackKnights > 0 &&
2723
       numWhiteLightSquareBishops == 0)
2724
   {
2725
      numWhiteDarkSquareBishops--;
2726
      numBlackKnights--;
2727
      finished = FALSE;
2728
      goto calculateSignature;
2729
   }
2730
 
2731
   if (blackKnightTradesOnly == FALSE &&
2732
       numWhiteKnights > 0 && numBlackLightSquareBishops > 0 &&
2733
       numBlackDarkSquareBishops == 0)
2734
   {
2735
      numWhiteKnights--;
2736
      numBlackLightSquareBishops--;
2737
      finished = FALSE;
2738
      goto calculateSignature;
2739
   }
2740
 
2741
   if (blackKnightTradesOnly == FALSE &&
2742
       numWhiteKnights > 0 && numBlackDarkSquareBishops > 0 &&
2743
       numBlackLightSquareBishops == 0)
2744
   {
2745
      numWhiteKnights--;
2746
      numBlackDarkSquareBishops--;
2747
      finished = FALSE;
2748
      goto calculateSignature;
2749
   }
2750
 
2751
 calculateSignature:
2752
 
2753
   *materialSignatureWhite =
2754
      getSingleMaterialSignature(numWhiteQueens, numWhiteRooks,
2755
                                 numWhiteLightSquareBishops,
2756
                                 numWhiteDarkSquareBishops, numWhiteKnights,
2757
                                 numWhitePawns);
2758
   *materialSignatureBlack =
2759
      getSingleMaterialSignature(numBlackQueens, numBlackRooks,
2760
                                 numBlackLightSquareBishops,
2761
                                 numBlackDarkSquareBishops, numBlackKnights,
2762
                                 numBlackPawns);
2763
 
2764
   if (finished == FALSE)
2765
   {
2766
      getPieceTradeSignatures(materialSignatureWhite, materialSignatureBlack);
2767
   }
2768
}
2769
 
2770
static bool hasMaterialForMate(const UINT32 materialSignature,
2771
                               const UINT32 oppMaterialSignature,
2772
                               SpecialEvalType * specialEval,
2773
                               const bool tradePieces,
2774
                               const bool evaluateOppMaterial)
2775
{
2776
   int numQueens, numRooks, numLightSquareBishops, numDarkSquareBishops;
2777
   int numKnights, numPawns;
2778
   int numOppQueens, numOppRooks, numOppLightSquareBishops;
2779
   int numOppDarkSquareBishops, numOppKnights, numOppPawns;
2780
   int numBishops, numOppBishops;
2781
   int numPieces, numOppPieces;
2782
   const UINT32 signature =
2783
      bilateralSignature(materialSignature, oppMaterialSignature);
2784
 
2785
   if (tradePieces)
2786
   {
2787
      UINT32 ms = materialSignature, mso = oppMaterialSignature;
2788
      SpecialEvalType dummy;
2789
 
2790
      getPieceTradeSignatures(&ms, &mso);
2791
 
2792
      return hasMaterialForMate(ms, mso, &dummy, FALSE, evaluateOppMaterial);
2793
   }
2794
 
2795
   getPieceCounters(signature, &numQueens, &numRooks,
2796
                    &numLightSquareBishops, &numDarkSquareBishops,
2797
                    &numKnights, &numPawns, &numOppQueens, &numOppRooks,
2798
                    &numOppLightSquareBishops, &numOppDarkSquareBishops,
2799
                    &numOppKnights, &numOppPawns);
2800
 
2801
   numBishops = numLightSquareBishops + numDarkSquareBishops;
2802
   numOppBishops = numOppLightSquareBishops + numOppDarkSquareBishops;
2803
   numPieces = numQueens + numRooks + numBishops + numKnights;
2804
   numOppPieces = numOppQueens + numOppRooks + numOppBishops + numOppKnights;
2805
 
2806
   if (evaluateOppMaterial && numPawns == 0)
2807
   {
2808
      if (numPieces == 1)
2809
      {
2810
         if (numRooks == 1 && numOppPieces > 0)
2811
         {
2812
            return FALSE;
2813
         }
2814
 
2815
         if (numQueens == 1)
2816
         {
2817
            if (numOppQueens >= 1 || numOppKnights >= 2)
2818
            {
2819
               return FALSE;
2820
            }
2821
 
2822
            if (numOppPieces >= 2 && numOppRooks >= 1)
2823
            {
2824
               return FALSE;
2825
            }
2826
         }
2827
      }
2828
      else if (numPieces == 2)
2829
      {
2830
         if (numBishops == 2 &&
2831
             numOppQueens + numOppRooks + numOppBishops > 0)
2832
         {
2833
            return FALSE;
2834
         }
2835
 
2836
         if (numBishops == 1 && numKnights == 1 && numOppPieces > 0)
2837
         {
2838
            return FALSE;
2839
         }
2840
      }
2841
   }
2842
 
2843
   if (numQueens + numRooks + numLightSquareBishops + numDarkSquareBishops +
2844
       numKnights == 0 && numPawns > 0)
2845
   {
2846
      *specialEval = Se_KpK;
2847
 
2848
      return TRUE;
2849
   }
2850
 
2851
   if (numQueens + numRooks + numLightSquareBishops + numDarkSquareBishops +
2852
       numPawns == 0 && numKnights == 2)
2853
   {
2854
      if (numOppQueens + numOppRooks + numOppLightSquareBishops +
2855
          numOppDarkSquareBishops + numOppKnights == 0 && numOppPawns > 0)
2856
      {
2857
         *specialEval = Se_KnnKp;
2858
 
2859
         return TRUE;
2860
      }
2861
   }
2862
 
2863
   if (numPawns <= 3 && numPawns >= numOppPawns &&
2864
       numOppPawns >= numPawns - 1 && numQueens == 0 &&
2865
       numPieces == 1 && numPieces == numOppPieces &&
2866
       (numBishops + numKnights == numOppBishops + numOppKnights ||
2867
        numRooks == numOppRooks))
2868
   {
2869
      *specialEval = Se_KpxKpx;
2870
 
2871
      return TRUE;
2872
   }
2873
 
2874
   if (numPawns >= 2 && numOppPawns == 0 &&
2875
       numQueens == 0 && numOppQueens == 0 &&
2876
       numPieces == 1 && numPieces == numOppPieces)
2877
   {
2878
      if (numBishops == 1 ||
2879
          (numKnights == 1 && numOppBishops == 1) ||
2880
          (numRooks == 1 && numRooks == numOppRooks))
2881
      {
2882
         *specialEval = Se_KppxKx;
2883
      }
2884
 
2885
      return TRUE;
2886
   }
2887
 
2888
   if (numQueens + numRooks + numKnights == 0 &&
2889
       numLightSquareBishops + numDarkSquareBishops == 1 && numPawns > 0)
2890
   {
2891
      *specialEval = Se_KbpK;
2892
 
2893
      return TRUE;
2894
   }
2895
 
2896
   if (numQueens + numBishops + numKnights == 0 && numRooks == 1 &&
2897
       numPawns == 1 && numOppBishops >= 1)
2898
   {
2899
      *specialEval = Se_KrpKb;
2900
 
2901
      return TRUE;
2902
   }
2903
 
2904
   if (numQueens + numBishops + numKnights == 0 && numRooks == 1 &&
2905
       numPawns == 1 && numOppRooks >= 1)
2906
   {
2907
      *specialEval = Se_KrpKr;
2908
 
2909
      return TRUE;
2910
   }
2911
 
2912
   if (numQueens + numBishops + numKnights == 0 && numRooks == 1 &&
2913
       numPawns == 2 && numOppRooks >= 1)
2914
   {
2915
      *specialEval = Se_KrppKr;
2916
 
2917
      return TRUE;
2918
   }
2919
 
2920
   if (numRooks + numBishops + numKnights == 0 && numQueens == 1 &&
2921
       numPawns == 1 && numOppQueens >= 1)
2922
   {
2923
      *specialEval = Se_KqpKq;
2924
 
2925
      return TRUE;
2926
   }
2927
 
2928
   if (numRooks + numBishops + numKnights == 0 && numQueens == 1 &&
2929
       numPawns == 2 && numOppQueens >= 1)
2930
   {
2931
      *specialEval = Se_KqppKq;
2932
 
2933
      return TRUE;
2934
   }
2935
 
2936
   if (numQueens + numRooks + numPawns > 0 || numKnights >= 3)
2937
   {
2938
      return TRUE;
2939
   }
2940
 
2941
   if (numLightSquareBishops > 0 && numDarkSquareBishops > 0)
2942
   {
2943
      return TRUE;
2944
   }
2945
 
2946
   if (numKnights > 0 && numLightSquareBishops + numDarkSquareBishops > 0)
2947
   {
2948
      return TRUE;
2949
   }
2950
 
2951
   return FALSE;
2952
}
2953
 
2954
static PieceType getKamikazePiece(const UINT32 ownMaterialSignature,
2955
                                  const UINT32 oppMaterialSignature)
2956
{
2957
   int numQueens, numRooks, numLightSquareBishops;
2958
   int numDarkSquareBishops, numKnights, numPawns;
2959
   int numOppQueens, numOppRooks, numOppLightSquareBishops;
2960
   int numOppDarkSquareBishops, numOppKnights, numOppPawns;
2961
   int ownSignature;
2962
   const UINT32 signature =
2963
      bilateralSignature(ownMaterialSignature, oppMaterialSignature);
2964
 
2965
   getPieceCounters(signature, &numQueens, &numRooks,
2966
                    &numLightSquareBishops, &numDarkSquareBishops,
2967
                    &numKnights, &numPawns, &numOppQueens, &numOppRooks,
2968
                    &numOppLightSquareBishops, &numOppDarkSquareBishops,
2969
                    &numOppKnights, &numOppPawns);
2970
 
2971
   ownSignature =
2972
      getSingleMaterialSignature(numQueens, numRooks,
2973
                                 numLightSquareBishops,
2974
                                 numDarkSquareBishops, numKnights,
2975
                                 numPawns - 1);
2976
 
2977
   if (numOppRooks > 0)
2978
   {
2979
      const int oppSignature =
2980
         getSingleMaterialSignature(numOppQueens, numOppRooks - 1,
2981
                                    numOppLightSquareBishops,
2982
                                    numOppDarkSquareBishops,
2983
                                    numOppKnights, numOppPawns);
2984
 
2985
      if (hasMaterialForMate(ownSignature, oppSignature, 0, TRUE, FALSE) ==
2986
          FALSE)
2987
      {
2988
         return ROOK;
2989
      }
2990
   }
2991
 
2992
   if (numOppLightSquareBishops > 0)
2993
   {
2994
      const int oppSignature =
2995
         getSingleMaterialSignature(numOppQueens, numOppRooks,
2996
                                    numOppLightSquareBishops - 1,
2997
                                    numOppDarkSquareBishops,
2998
                                    numOppKnights, numOppPawns);
2999
 
3000
      if (hasMaterialForMate(ownSignature, oppSignature, 0, TRUE, FALSE) ==
3001
          FALSE)
3002
      {
3003
         return BISHOP;
3004
      }
3005
   }
3006
 
3007
   if (numOppDarkSquareBishops > 0)
3008
   {
3009
      const int oppSignature =
3010
         getSingleMaterialSignature(numOppQueens, numOppRooks,
3011
                                    numOppLightSquareBishops,
3012
                                    numOppDarkSquareBishops - 1,
3013
                                    numOppKnights, numOppPawns);
3014
 
3015
      if (hasMaterialForMate(ownSignature, oppSignature, 0, TRUE, FALSE) ==
3016
          FALSE)
3017
      {
3018
         return BISHOP;
3019
      }
3020
   }
3021
 
3022
   if (numOppKnights > 0)
3023
   {
3024
      const int oppSignature =
3025
         getSingleMaterialSignature(numOppQueens, numOppRooks,
3026
                                    numOppLightSquareBishops,
3027
                                    numOppDarkSquareBishops,
3028
                                    numOppKnights - 1,
3029
                                    numOppPawns);
3030
 
3031
      if (hasMaterialForMate(ownSignature, oppSignature, 0, TRUE, FALSE) ==
3032
          FALSE)
3033
      {
3034
         return KNIGHT;
3035
      }
3036
   }
3037
 
3038
   return NO_PIECETYPE;
3039
}
3040
 
3041
static UINT8 getWinningChances(const UINT32 materialSignature,
3042
                               const UINT32 oppMaterialSignature)
3043
{
3044
   int numQueens, numRooks, numLightSquareBishops;
3045
   int numDarkSquareBishops, numKnights, numPawns;
3046
   int numOppQueens, numOppRooks, numOppLightSquareBishops;
3047
   int numOppDarkSquareBishops, numOppKnights, numOppPawns;
3048
   int numPieces;
3049
   int numOppBishops, numOppMinors, numOppSliders;
3050
   bool oppositeColoredBishops;
3051
   const UINT32 signature =
3052
      bilateralSignature(materialSignature, oppMaterialSignature);
3053
   PieceType kamikazePiece = getKamikazePiece(materialSignature,
3054
                                              oppMaterialSignature);
3055
 
3056
   getPieceCounters(signature, &numQueens, &numRooks,
3057
                    &numLightSquareBishops, &numDarkSquareBishops,
3058
                    &numKnights, &numPawns, &numOppQueens, &numOppRooks,
3059
                    &numOppLightSquareBishops, &numOppDarkSquareBishops,
3060
                    &numOppKnights, &numOppPawns);
3061
   numPieces = numQueens + numRooks + numLightSquareBishops +
3062
      numDarkSquareBishops + numKnights;
3063
   numOppBishops = numOppLightSquareBishops + numOppDarkSquareBishops;
3064
   numOppMinors = numOppBishops + numOppKnights;
3065
   numOppSliders = numOppQueens + numOppRooks + numOppBishops;
3066
   oppositeColoredBishops = (bool)
3067
      (numLightSquareBishops + numDarkSquareBishops > 0 &&
3068
       ((numOppLightSquareBishops > 0 && numLightSquareBishops == 0) ||
3069
        (numOppDarkSquareBishops > 0 && numDarkSquareBishops == 0)));
3070
 
3071
   if (numPieces == 0)
3072
   {
3073
      if (numPawns <= 1 && numOppSliders > 0)
3074
      {
3075
         return 0;
3076
      }
3077
 
3078
      if (numPawns <= 1 && numOppKnights > 0)
3079
      {
3080
         return 4;
3081
      }
3082
 
3083
      if (numPawns == 2)
3084
      {
3085
         return (numOppSliders >= 2 ? 2 : 8);
3086
      }
3087
   }
3088
 
3089
   if (numPieces == 1)
3090
   {
3091
      if (oppositeColoredBishops)
3092
      {
3093
         const int pawnDiff = min(3, abs(numPawns - numOppPawns));
3094
 
3095
         return (UINT8) (numPawns > 1 ? 8 + 2 * pawnDiff : 0);
3096
      }
3097
 
3098
      if (numPawns == 1)        /* One piece, one pawn: */
3099
      {
3100
         if (numQueens > 0 && numOppRooks >= 2)
3101
         {
3102
            return 1;
3103
         }
3104
 
3105
         if (numQueens > 0 && numOppRooks + numOppMinors >= 2)
3106
         {
3107
            return 12;          /* usually won, but difficult */
3108
         }
3109
 
3110
         if (kamikazePiece != NO_PIECETYPE)
3111
         {
3112
            switch (kamikazePiece)
3113
            {
3114
            case ROOK:
3115
               return 1;
3116
            case BISHOP:
3117
               return 2;
3118
            case KNIGHT:
3119
               return 4;
3120
            default:
3121
               break;
3122
            }
3123
         }
3124
      }
3125
   }
3126
   else if (numPieces == 2)     /* has more than one piece: */
3127
   {
3128
      if (numPawns <= 1)
3129
      {
3130
         if (numRooks == 2 && numOppQueens > 0)
3131
         {
3132
            return (numPawns == 0 ? 1 : 2);
3133
         }
3134
 
3135
         if (kamikazePiece != NO_PIECETYPE)
3136
         {
3137
            switch (kamikazePiece)
3138
            {
3139
            case ROOK:
3140
               return 1;
3141
            case BISHOP:
3142
               return 2;
3143
            case KNIGHT:
3144
               return 4;
3145
            default:
3146
               break;
3147
            }
3148
         }
3149
      }
3150
 
3151
      if (numQueens == 0 && numRooks <= 1 && numRooks == numOppRooks &&
3152
          oppositeColoredBishops)
3153
      {
3154
         const int pawnDiff = min(3, abs(numPawns - numOppPawns));
3155
 
3156
         return (UINT8) (12 + pawnDiff);
3157
      }
3158
   }
3159
 
3160
   return 16;
3161
}
3162
 
3163
static UINT8 getWinningChancesWithoutPawn(UINT32 materialSignature,
3164
                                          UINT32 oppMaterialSignature)
3165
{
3166
   int numQueens, numRooks, numLightSquareBishops;
3167
   int numDarkSquareBishops, numKnights, numPawns;
3168
   int numOppQueens, numOppRooks, numOppLightSquareBishops;
3169
   int numOppDarkSquareBishops, numOppKnights, numOppPawns;
3170
   int numPieces, numOppPieces;
3171
   int numOppBishops, numOppMinors, numOppSliders;
3172
   const UINT32 signature =
3173
      bilateralSignature(materialSignature, oppMaterialSignature);
3174
   int pieceCountDiff;
3175
 
3176
   getPieceCounters(signature, &numQueens, &numRooks,
3177
                    &numLightSquareBishops, &numDarkSquareBishops,
3178
                    &numKnights, &numPawns, &numOppQueens, &numOppRooks,
3179
                    &numOppLightSquareBishops, &numOppDarkSquareBishops,
3180
                    &numOppKnights, &numOppPawns);
3181
   numPieces = numQueens + numRooks + numLightSquareBishops +
3182
      numDarkSquareBishops + numKnights;
3183
   numOppBishops = numOppLightSquareBishops + numOppDarkSquareBishops;
3184
   numOppMinors = numOppBishops + numOppKnights;
3185
   numOppSliders = numOppQueens + numOppRooks + numOppBishops;
3186
   numOppPieces = numOppSliders + numOppKnights;
3187
   pieceCountDiff = numPieces - numOppPieces;
3188
 
3189
   if (numPieces == 0)
3190
   {
3191
      return 0;
3192
   }
3193
 
3194
   if (numPieces == 1)
3195
   {
3196
      if (numQueens > 0 && numOppRooks > 0 && numOppRooks + numOppMinors >= 2)
3197
      {
3198
         return 1;
3199
      }
3200
 
3201
      if (numQueens > 0 && numOppKnights >= 2)
3202
      {
3203
         return 1;
3204
      }
3205
 
3206
      if (numRooks > 0 && numOppQueens + numOppRooks > 0)
3207
      {
3208
         return 1;
3209
      }
3210
 
3211
      if (numRooks > 0 && numOppMinors > 0)
3212
      {
3213
         return (numOppMinors == 1 ? 2 : 1);
3214
      }
3215
 
3216
      if (numLightSquareBishops + numDarkSquareBishops + numKnights > 0)
3217
      {
3218
         return 0;
3219
      }
3220
   }
3221
   else if (numPieces == 2)
3222
   {
3223
      if (pieceCountDiff <= 1)
3224
      {
3225
         if (numOppRooks > 0 && numOppRooks >= numRooks)
3226
         {
3227
            return 0;
3228
         }
3229
      }
3230
   }
3231
   else if (numPieces <= 3)
3232
   {
3233
      if (numQueens == 0 && numOppQueens > 0)
3234
      {
3235
         if (numRooks <= 1)
3236
         {
3237
            return 1;
3238
         }
3239
         else
3240
         {
3241
            return 8;           /* hard to win */
3242
         }
3243
      }
3244
 
3245
      if (numRooks + numQueens == 0 &&
3246
          numLightSquareBishops + numDarkSquareBishops <= 1 &&
3247
          numOppRooks + numOppQueens >= 1)
3248
      {
3249
         return (numOppQueens >= 1 ? 1 : 2);
3250
      }
3251
   }
3252
 
3253
   if (numLightSquareBishops == 1 && numDarkSquareBishops == 1)
3254
   {
3255
      if (numOppPieces == 1 && numOppRooks == 1)
3256
      {
3257
         return (numPieces == 2 ? 1 : 12);
3258
      }
3259
 
3260
      if (numOppKnights > 0)
3261
      {
3262
         return 8;              /* hard to win sometimes */
3263
      }
3264
   }
3265
 
3266
   return 16;
3267
}
3268
 
3269
static void testMaterialSignatureNew(const int numWhiteQueens,
3270
                                     const int numWhiteRooks,
3271
                                     const int numWhiteLightSquareBishops,
3272
                                     const int numWhiteDarkSquareBishops,
3273
                                     const int numWhiteKnights,
3274
                                     const int numWhitePawns,
3275
                                     const int numBlackQueens,
3276
                                     const int numBlackRooks,
3277
                                     const int numBlackLightSquareBishops,
3278
                                     const int numBlackDarkSquareBishops,
3279
                                     const int numBlackKnights,
3280
                                     const int numBlackPawns)
3281
{
3282
   int calculatedNumWhiteQueens;
3283
   int calculatedNumWhiteRooks;
3284
   int calculatedNumWhiteLightSquareBishops;
3285
   int calculatedNumWhiteDarkSquareBishops;
3286
   int calculatedNumWhiteKnights;
3287
   int calculatedNumWhitePawns;
3288
   int calculatedNumBlackQueens;
3289
   int calculatedNumBlackRooks;
3290
   int calculatedNumBlackLightSquareBishops;
3291
   int calculatedNumBlackDarkSquareBishops;
3292
   int calculatedNumBlackKnights;
3293
   int calculatedNumBlackPawns;
3294
 
3295
   if (numWhiteRooks <= 2 && numWhiteKnights <= 2 &&
3296
       numBlackRooks <= 2 && numBlackKnights <= 2)
3297
   {
3298
      const UINT32 signature = getMaterialSignature(numWhiteQueens,
3299
                                                    numWhiteRooks,
3300
                                                    numWhiteLightSquareBishops,
3301
                                                    numWhiteDarkSquareBishops,
3302
                                                    numWhiteKnights,
3303
                                                    numWhitePawns,
3304
                                                    numBlackQueens,
3305
                                                    numBlackRooks,
3306
                                                    numBlackLightSquareBishops,
3307
                                                    numBlackDarkSquareBishops,
3308
                                                    numBlackKnights,
3309
                                                    numBlackPawns);
3310
 
3311
      getPieceCounters(signature,
3312
                       &calculatedNumWhiteQueens, &calculatedNumWhiteRooks,
3313
                       &calculatedNumWhiteLightSquareBishops,
3314
                       &calculatedNumWhiteDarkSquareBishops,
3315
                       &calculatedNumWhiteKnights,
3316
                       &calculatedNumWhitePawns, &calculatedNumBlackQueens,
3317
                       &calculatedNumBlackRooks,
3318
                       &calculatedNumBlackLightSquareBishops,
3319
                       &calculatedNumBlackDarkSquareBishops,
3320
                       &calculatedNumBlackKnights, &calculatedNumBlackPawns);
3321
 
3322
      assert(calculatedNumWhiteQueens == numWhiteQueens);
3323
      assert(calculatedNumWhiteRooks == numWhiteRooks);
3324
      assert(calculatedNumWhiteLightSquareBishops ==
3325
             numWhiteLightSquareBishops);
3326
      assert(calculatedNumWhiteDarkSquareBishops ==
3327
             numWhiteDarkSquareBishops);
3328
      assert(calculatedNumWhiteKnights == numWhiteKnights);
3329
      assert(calculatedNumWhitePawns == numWhitePawns);
3330
      assert(calculatedNumBlackQueens == numBlackQueens);
3331
      assert(calculatedNumBlackRooks == numBlackRooks);
3332
      assert(calculatedNumBlackLightSquareBishops ==
3333
             numBlackLightSquareBishops);
3334
      assert(calculatedNumBlackDarkSquareBishops ==
3335
             numBlackDarkSquareBishops);
3336
      assert(calculatedNumBlackKnights == numBlackKnights);
3337
      assert(calculatedNumBlackPawns == numBlackPawns);
3338
   }
3339
}
3340
 
3341
static int calculatePhase(UINT32 signature)
3342
{
3343
   int numWhiteQueens;
3344
   int numWhiteRooks;
3345
   int numWhiteLightSquareBishops;
3346
   int numWhiteDarkSquareBishops;
3347
   int numWhiteKnights;
3348
   int numWhitePawns;
3349
   int numBlackQueens;
3350
   int numBlackRooks;
3351
   int numBlackLightSquareBishops;
3352
   int numBlackDarkSquareBishops;
3353
   int numBlackKnights;
3354
   int numBlackPawns;
3355
   int whiteWeight, blackWeight, basicPhase;
3356
 
3357
   getPieceCounters(signature,
3358
                    &numWhiteQueens, &numWhiteRooks,
3359
                    &numWhiteLightSquareBishops,
3360
                    &numWhiteDarkSquareBishops,
3361
                    &numWhiteKnights, &numWhitePawns,
3362
                    &numBlackQueens, &numBlackRooks,
3363
                    &numBlackLightSquareBishops,
3364
                    &numBlackDarkSquareBishops,
3365
                    &numBlackKnights, &numBlackPawns);
3366
 
3367
   whiteWeight =
3368
      9 * numWhiteQueens + 5 * numWhiteRooks +
3369
      3 * numWhiteLightSquareBishops + 3 * numWhiteDarkSquareBishops +
3370
      3 * numWhiteKnights;
3371
   blackWeight =
3372
      9 * numBlackQueens + 5 * numBlackRooks +
3373
      3 * numBlackLightSquareBishops + 3 * numBlackDarkSquareBishops +
3374
      3 * numBlackKnights;
3375
 
3376
   basicPhase = (whiteWeight + blackWeight <= PIECE_WEIGHT_ENDGAME ?
3377
                 PHASE_MAX : max(0, PHASE_MAX - whiteWeight - blackWeight));
3378
 
3379
   return (basicPhase * 256 + (PHASE_MAX / 2)) / PHASE_MAX;
3380
}
3381
 
3382
static INT32 calculateMaterialBalance(UINT32 signature)
3383
{
3384
   const INT32 bishopPairBonus =
3385
      V(VALUE_BISHOP_PAIR_OPENING, VALUE_BISHOP_PAIR_ENDGAME);
3386
   static const INT32 knightBonus = V(0, 5);
3387
   static const INT32 rookMalus = V(5, 0);
3388
   static const INT32 rookPairMalus = V(17, 25);
3389
   static const INT32 rookQueenMalus = V(8, 12);
3390
   static const INT32 pieceUpBonus =
3391
      V(DEFAULTVALUE_PIECE_UP_OPENING, DEFAULTVALUE_PIECE_UP_ENDGAME);
3392
 
3393
   int numWhiteQueens;
3394
   int numWhiteRooks;
3395
   int numWhiteLightSquareBishops;
3396
   int numWhiteDarkSquareBishops;
3397
   int numWhiteKnights;
3398
   int numWhitePawns;
3399
   int numBlackQueens;
3400
   int numBlackRooks;
3401
   int numBlackLightSquareBishops;
3402
   int numBlackDarkSquareBishops;
3403
   int numBlackKnights;
3404
   int numBlackPawns;
3405
   int pawnCountWhite, pawnCountBlack;
3406
   int knightSaldo, rookSaldo, pieceCountSaldo;
3407
   INT32 balance = 0;
3408
 
3409
   getPieceCounters(signature,
3410
                    &numWhiteQueens, &numWhiteRooks,
3411
                    &numWhiteLightSquareBishops,
3412
                    &numWhiteDarkSquareBishops,
3413
                    &numWhiteKnights,
3414
                    &numWhitePawns, &numBlackQueens,
3415
                    &numBlackRooks,
3416
                    &numBlackLightSquareBishops,
3417
                    &numBlackDarkSquareBishops,
3418
                    &numBlackKnights, &numBlackPawns);
3419
 
3420
   pawnCountWhite = numWhitePawns - 5;
3421
   pawnCountBlack = numBlackPawns - 5;
3422
   knightSaldo = pawnCountWhite * numWhiteKnights -
3423
      pawnCountBlack * numBlackKnights;
3424
   rookSaldo = pawnCountWhite * numWhiteRooks -
3425
      pawnCountBlack * numBlackRooks;
3426
   pieceCountSaldo =
3427
      (numWhiteLightSquareBishops +
3428
       numWhiteDarkSquareBishops + numWhiteKnights) -
3429
      (numBlackLightSquareBishops +
3430
       numBlackDarkSquareBishops + numBlackKnights);
3431
 
3432
   if (numWhiteLightSquareBishops > 0 && numWhiteDarkSquareBishops > 0)
3433
   {
3434
      balance += bishopPairBonus;
3435
   }
3436
 
3437
   if (numBlackLightSquareBishops > 0 && numBlackDarkSquareBishops > 0)
3438
   {
3439
      balance -= bishopPairBonus;
3440
   }
3441
 
3442
   balance += knightSaldo * knightBonus - rookSaldo * rookMalus;
3443
 
3444
   if (numWhiteRooks >= 2)
3445
   {
3446
      balance -= rookPairMalus + rookQueenMalus;
3447
   }
3448
   else if (numWhiteRooks + numWhiteQueens >= 2)
3449
   {
3450
      balance -= rookQueenMalus;
3451
   }
3452
 
3453
   if (numBlackRooks >= 2)
3454
   {
3455
      balance += rookPairMalus + rookQueenMalus;
3456
   }
3457
   else if (numBlackRooks + numBlackQueens >= 2)
3458
   {
3459
      balance += rookQueenMalus;
3460
   }
3461
 
3462
   if (pieceCountSaldo > 0)
3463
   {
3464
      balance += pieceUpBonus;
3465
   }
3466
   else if (pieceCountSaldo < 0)
3467
   {
3468
      balance -= pieceUpBonus;
3469
   }
3470
 
3471
   return balance;
3472
}
3473
 
3474
static void initializeMaterialInfoTableCore1(const UINT32 signatureWhite,
3475
                                             const UINT32 signatureBlack)
3476
{
3477
   const UINT32 signature =
3478
      bilateralSignature(signatureWhite, signatureBlack);
3479
   SpecialEvalType specialEvalWhite = Se_None;
3480
   SpecialEvalType specialEvalBlack = Se_None;
3481
   const bool whiteMateMat =
3482
      hasMaterialForMate(signatureWhite, signatureBlack, &specialEvalWhite,
3483
                         FALSE, FALSE);
3484
   const bool blackMateMat =
3485
      hasMaterialForMate(signatureBlack, signatureWhite, &specialEvalBlack,
3486
                         FALSE, FALSE);
3487
   int numWhiteQueens, numWhiteRooks, numWhiteLightSquareBishops;
3488
   int numWhiteDarkSquareBishops, numWhiteKnights, numWhitePawns;
3489
   int numBlackQueens, numBlackRooks, numBlackLightSquareBishops;
3490
   int numBlackDarkSquareBishops, numBlackKnights, numBlackPawns;
3491
 
3492
   /*int criticalCase = FALSE; */
3493
 
3494
   getPieceCounters(signature, &numWhiteQueens, &numWhiteRooks,
3495
                    &numWhiteLightSquareBishops,
3496
                    &numWhiteDarkSquareBishops, &numWhiteKnights,
3497
                    &numWhitePawns, &numBlackQueens, &numBlackRooks,
3498
                    &numBlackLightSquareBishops,
3499
                    &numBlackDarkSquareBishops, &numBlackKnights,
3500
                    &numBlackPawns);
3501
 
3502
   testMaterialSignatureNew(numWhiteQueens,
3503
                            numWhiteRooks,
3504
                            numWhiteLightSquareBishops,
3505
                            numWhiteDarkSquareBishops,
3506
                            numWhiteKnights,
3507
                            numWhitePawns,
3508
                            numBlackQueens,
3509
                            numBlackRooks,
3510
                            numBlackLightSquareBishops,
3511
                            numBlackDarkSquareBishops,
3512
                            numBlackKnights, numBlackPawns);
3513
 
3514
   materialInfo[signature].chancesWhite = (whiteMateMat == FALSE ? 0 : 16);
3515
   materialInfo[signature].chancesBlack = (blackMateMat == FALSE ? 0 : 16);
3516
   materialInfo[signature].specialEvalWhite = specialEvalWhite;
3517
   materialInfo[signature].specialEvalBlack = specialEvalBlack;
3518
 
3519
   /*if (numWhiteQueens == 0 && numWhiteRooks == 0 &&
3520
      numWhiteLightSquareBishops == 0 &&
3521
      numWhiteDarkSquareBishops == 0 &&
3522
      numWhiteKnights == 0 && numWhitePawns == 1 &&
3523
      numBlackQueens == 0 && numBlackRooks == 0 &&
3524
      numBlackLightSquareBishops == 0 &&
3525
      numBlackDarkSquareBishops == 1 &&
3526
      numBlackKnights == 0 && numBlackPawns == 0)
3527
      {
3528
      criticalCase = TRUE;
3529
      } */
3530
 
3531
   if (whiteMateMat != FALSE)
3532
   {
3533
      if (numWhitePawns == 0)
3534
      {
3535
         if (hasMaterialForMate(signatureWhite, signatureBlack, 0,
3536
                                TRUE, TRUE) == FALSE)
3537
         {
3538
            materialInfo[signature].chancesWhite = 1;
3539
         }
3540
         else
3541
         {
3542
            materialInfo[signature].chancesWhite =
3543
               getWinningChancesWithoutPawn(signatureWhite, signatureBlack);
3544
         }
3545
      }
3546
      else
3547
      {
3548
         materialInfo[signature].chancesWhite =
3549
            getWinningChances(signatureWhite, signatureBlack);
3550
      }
3551
   }
3552
 
3553
   if (blackMateMat != FALSE)
3554
   {
3555
      if (numBlackPawns == 0)
3556
      {
3557
         if (hasMaterialForMate(signatureBlack, signatureWhite, 0,
3558
                                TRUE, TRUE) == FALSE)
3559
         {
3560
            materialInfo[signature].chancesBlack = 1;
3561
         }
3562
         else
3563
         {
3564
            materialInfo[signature].chancesBlack =
3565
               getWinningChancesWithoutPawn(signatureBlack, signatureWhite);
3566
         }
3567
      }
3568
      else
3569
      {
3570
         materialInfo[signature].chancesBlack =
3571
            getWinningChances(signatureBlack, signatureWhite);
3572
      }
3573
 
3574
      /*if (criticalCase){
3575
         logDebug("wc=%d",materialInfo[signature].chancesBlack);
3576
         getKeyStroke();
3577
 
3578
         materialInfo[signature].chancesBlack=0;
3579
         } */
3580
   }
3581
 
3582
   materialInfo[signature].materialBalance =
3583
      calculateMaterialBalance(signature);
3584
   materialInfo[signature].phaseIndex = calculatePhase(signature);
3585
}
3586
 
3587
static void initializeMaterialInfoTable()
3588
{
3589
   int whiteSignature, blackSignature;
3590
 
3591
   for (whiteSignature = 0; whiteSignature < 648; whiteSignature++)
3592
   {
3593
      for (blackSignature = 0; blackSignature < 648; blackSignature++)
3594
      {
3595
         initializeMaterialInfoTableCore1(whiteSignature, blackSignature);
3596
      }
3597
   }
3598
}
3599
 
3600
/* #define DEBUG_KSTABLE 1 */
3601
 
3602
static int initializeKingSafetyTable()
3603
{
3604
   const double MIN_SLOPE = 1.0;
3605
   const double MAX_SLOPE = 7.0;
3606
   const double MAX_VALUE = 1347.0;
3607
   double t = 0.0 - MIN_SLOPE;
3608
   int i;
3609
 
3610
   for (i = 0; i < KING_SAFETY_MALUS_DIM; i++)
3611
   {
3612
      t = max(t + MIN_SLOPE,
3613
              min(MAX_VALUE, min(0.025 * i * i, t + MAX_SLOPE)));
3614
      KING_SAFETY_MALUS[i] = (int)((156 * t) / 256); // Pierre-Marie Baty -- added type cast
3615
 
3616
#ifdef DEBUG_KSTABLE
3617
      logDebug("ksm(%d)=%d\n", i, KING_SAFETY_MALUS[i]);
3618
#endif
3619
   }
3620
 
3621
#ifdef DEBUG_KSTABLE
3622
   getKeyStroke();
3623
#endif
3624
 
3625
   return 0;
3626
}
3627
 
3628
int getLogarithmicValue(const double minValue, const double maxValue,
3629
                        const double numValues, const double valueCount)
3630
{
3631
   const double offset = 1.0;
3632
   const double factor = (maxValue - minValue) / log(numValues + offset);
3633
   const double value = factor * log(valueCount + offset) + minValue;
3634
 
3635
   return (int) value;
3636
}
3637
 
3638
double wmbv(const double baseValue)
3639
{
3640
   return baseValue * 1.075;
3641
}
3642
 
3643
/* #define LOG_MOBILILITY_VALUES */
3644
static void initializeMoveBonusValue()
3645
{
3646
   int i, limit;
3647
 
3648
   limit = MAX_MOVES_QUEEN;
3649
   for (i = 0; i <= limit; i++)
3650
   {
3651
      const int opValue =
3652
         getLogarithmicValue(wmbv(-21.0), wmbv(13.0), limit, i);
3653
      const int egValue =
3654
         getLogarithmicValue(wmbv(-20.0), wmbv(21.0), limit, i);
3655
 
3656
      QueenMobilityBonus[i] = V(opValue, egValue);
3657
 
3658
#ifdef LOG_MOBILILITY_VALUES
3659
      logDebug("mQ(%d)=(%d/%d)\n", i, getOpeningValue(QueenMobilityBonus[i]),
3660
               getEndgameValue(QueenMobilityBonus[i]));
3661
#endif
3662
   }
3663
 
3664
#ifdef LOG_MOBILILITY_VALUES
3665
   logDebug("\n");
3666
#endif
3667
 
3668
   limit = MAX_MOVES_ROOK;
3669
   for (i = 0; i <= limit; i++)
3670
   {
3671
      const int opValue =
3672
         getLogarithmicValue(wmbv(-24.0), wmbv(19.0), limit, i);
3673
      const int egValue =
3674
         getLogarithmicValue(wmbv(-27.0), wmbv(62.0), limit, i);
3675
 
3676
      RookMobilityBonus[i] = V(opValue, egValue);
3677
 
3678
#ifdef LOG_MOBILILITY_VALUES
3679
      logDebug("mR(%d)=(%d/%d)\n", i, getOpeningValue(RookMobilityBonus[i]),
3680
               getEndgameValue(RookMobilityBonus[i]));
3681
#endif
3682
   }
3683
 
3684
#ifdef LOG_MOBILILITY_VALUES
3685
   logDebug("\n");
3686
#endif
3687
 
3688
   limit = MAX_MOVES_BISHOP;
3689
   for (i = 0; i <= limit; i++)
3690
   {
3691
      const int opValue =
3692
         getLogarithmicValue(wmbv(-26.0), wmbv(43.0), limit, i);
3693
      const int egValue =
3694
         getLogarithmicValue(wmbv(-24.0), wmbv(40.0), limit, i);
3695
 
3696
      BishopMobilityBonus[i] = V(opValue, egValue);
3697
 
3698
#ifdef LOG_MOBILILITY_VALUES
3699
      logDebug("mB(%d)=(%d/%d)\n", i, getOpeningValue(BishopMobilityBonus[i]),
3700
               getEndgameValue(BishopMobilityBonus[i]));
3701
#endif
3702
   }
3703
 
3704
#ifdef LOG_MOBILILITY_VALUES
3705
   logDebug("\n");
3706
#endif
3707
 
3708
   limit = MAX_MOVES_KNIGHT;
3709
   for (i = 0; i <= limit; i++)
3710
   {
3711
      const int opValue =
3712
         getLogarithmicValue(wmbv(-33.0), wmbv(22.0), limit, i);
3713
      const int egValue =
3714
         getLogarithmicValue(wmbv(-25.0), wmbv(17.0), limit, i);
3715
 
3716
      KnightMobilityBonus[i] = V(opValue, egValue);
3717
 
3718
#ifdef LOG_MOBILILITY_VALUES
3719
      logDebug("mN(%d)=(%d/%d)\n", i, getOpeningValue(KnightMobilityBonus[i]),
3720
               getEndgameValue(KnightMobilityBonus[i]));
3721
#endif
3722
   }
3723
 
3724
#ifdef LOG_MOBILILITY_VALUES
3725
   getKeyStroke();
3726
#endif
3727
}
3728
 
3729
static INT32 PPAB(const int opv, const int egv)
3730
{
3731
   const int wopv = (opv * 125) / 256;
3732
   const int wegv = (egv * 133) / 256;
3733
 
3734
   return V(wopv, wegv);
3735
}
3736
 
3737
static void initializePawnChainBonus()
3738
{
3739
   const int bonusPerFile[8] = { 1, 3, 3, 4, 4, 3, 3, 1 };
3740
   Square square;
3741
 
3742
   ITERATE(square)
3743
   {
3744
      const File squarefile = file(square);
3745
      const Rank squarerank = rank(square);
3746
      const int bonus = squarerank * (squarerank - 1) * (squarerank - 2) +
3747
         bonusPerFile[squarefile] * (squarerank / 2 + 1);
3748
 
3749
      PAWN_CHAIN_BONUS[square] = V((bonus * CHAIN_BONUS_WEIGHT_OP) / 256,
3750
                                   (bonus * CHAIN_BONUS_WEIGHT_EG) / 256);
3751
   }
3752
}
3753
 
3754
int initializeModuleEvaluation()
3755
{
3756
   int i;
3757
   Square square, kingsquare, catchersquare;
3758
 
3759
   centralFiles = squaresOfFile[FILE_D] | squaresOfFile[FILE_E];
3760
   attackingRealm[WHITE] = squaresOfRank[RANK_5] | squaresOfRank[RANK_6] |
3761
      squaresOfRank[RANK_7] | squaresOfRank[RANK_8];
3762
   attackingRealm[BLACK] = squaresOfRank[RANK_4] | squaresOfRank[RANK_3] |
3763
      squaresOfRank[RANK_2] | squaresOfRank[RANK_1];
3764
   filesBCFG = squaresOfFileRange[FILE_B][FILE_C] |
3765
      squaresOfFileRange[FILE_F][FILE_G];
3766
 
3767
   ITERATE(square)
3768
   {
3769
      Color color;
3770
      Square kingSquare;
3771
 
3772
      for (color = WHITE; color <= BLACK; color++)
3773
      {
3774
         passedPawnRectangle[color][square] =
3775
            passedPawnCorridor[color][square] =
3776
            candidateDefenders[color][square] =
3777
            candidateSupporters[color][square] =
3778
            pawnOpponents[color][square] = EMPTY_BITBOARD;
3779
      }
3780
 
3781
      ITERATE(kingSquare)
3782
      {
3783
         kingRealm[WHITE][square][kingSquare] =
3784
            kingRealm[BLACK][square][kingSquare] = EMPTY_BITBOARD;
3785
      }
3786
 
3787
      kingTrapsRook[WHITE][square] = kingTrapsRook[BLACK][square] =
3788
         EMPTY_BITBOARD;
3789
   }
3790
 
3791
   setSquare(kingTrapsRook[WHITE][F1], H1);     /* a king on f1 traps a rook on h1 ... */
3792
   setSquare(kingTrapsRook[WHITE][F1], G1);
3793
   setSquare(kingTrapsRook[WHITE][F1], H2);
3794
   setSquare(kingTrapsRook[WHITE][F1], G2);
3795
   setSquare(kingTrapsRook[WHITE][G1], H1);
3796
   setSquare(kingTrapsRook[WHITE][G1], H2);
3797
   setSquare(kingTrapsRook[WHITE][G1], G2);
3798
   setSquare(kingTrapsRook[WHITE][G2], H2);
3799
 
3800
   setSquare(kingTrapsRook[WHITE][C1], A1);
3801
   setSquare(kingTrapsRook[WHITE][C1], B1);
3802
   setSquare(kingTrapsRook[WHITE][C1], A2);
3803
   setSquare(kingTrapsRook[WHITE][C1], B2);
3804
   setSquare(kingTrapsRook[WHITE][B1], A1);
3805
   setSquare(kingTrapsRook[WHITE][B1], A2);
3806
   setSquare(kingTrapsRook[WHITE][B1], B2);
3807
   setSquare(kingTrapsRook[WHITE][B2], A2);
3808
 
3809
   setSquare(kingTrapsRook[BLACK][F8], H8);
3810
   setSquare(kingTrapsRook[BLACK][F8], G8);
3811
   setSquare(kingTrapsRook[BLACK][F8], H7);
3812
   setSquare(kingTrapsRook[BLACK][F8], G7);
3813
   setSquare(kingTrapsRook[BLACK][G8], H8);
3814
   setSquare(kingTrapsRook[BLACK][G8], H7);
3815
   setSquare(kingTrapsRook[BLACK][G8], G7);
3816
   setSquare(kingTrapsRook[BLACK][G7], H7);
3817
 
3818
   setSquare(kingTrapsRook[BLACK][C8], A8);
3819
   setSquare(kingTrapsRook[BLACK][C8], B8);
3820
   setSquare(kingTrapsRook[BLACK][C8], A7);
3821
   setSquare(kingTrapsRook[BLACK][C8], B7);
3822
   setSquare(kingTrapsRook[BLACK][B8], A8);
3823
   setSquare(kingTrapsRook[BLACK][B8], A7);
3824
   setSquare(kingTrapsRook[BLACK][B8], B7);
3825
   setSquare(kingTrapsRook[BLACK][B7], A7);
3826
 
3827
   ITERATE(square)
3828
   {
3829
      const File squarefile = file(square);
3830
      const Rank squarerank = rank(square);
3831
      int d1 = min(distance(square, D4), distance(square, E4));
3832
      int d2 = min(distance(square, D5), distance(square, E5));
3833
      int td1 = min(taxiDistance(square, D4), taxiDistance(square, E4));
3834
      int td2 = min(taxiDistance(square, D5), taxiDistance(square, E5));
3835
 
3836
      centerDistance[square] = min(d1, d2);
3837
      centerTaxiDistance[square] = min(td1, td2);
3838
      butterflySquares[square] =
3839
         generalMoves[KING][square] & ~squaresOfFile[squarefile];
3840
      lateralSquares[square] =
3841
         generalMoves[KING][square] & squaresOfRank[squarerank];
3842
      companionFiles[square] =
3843
         ((squaresOfFile[squarefile] & nonA) >> 1) |
3844
         ((squaresOfFile[squarefile] & nonH) << 1);
3845
      rookBlockers[square] = EMPTY_BITBOARD;
3846
 
3847
      ITERATE(kingsquare)
3848
      {
3849
         const File kingsquarefile = file(kingsquare);
3850
         const Rank kingsquarerank = rank(kingsquare);
3851
         Square targetSquare;
3852
 
3853
         if (kingsquarerank >= squarerank &&
3854
             distance(square, kingsquare) <= (int) (7 - squarerank))
3855
         {
3856
            setSquare(passedPawnRectangle[WHITE][square], kingsquare);
3857
         }
3858
 
3859
         if (kingsquarerank <= squarerank &&
3860
             distance(square, kingsquare) <= (int) squarerank)
3861
         {
3862
            setSquare(passedPawnRectangle[BLACK][square], kingsquare);
3863
         }
3864
 
3865
         if (kingsquarefile == squarefile)
3866
         {
3867
            if (kingsquarerank > squarerank)
3868
            {
3869
               setSquare(passedPawnCorridor[WHITE][square], kingsquare);
3870
            }
3871
 
3872
            if (kingsquarerank < squarerank)
3873
            {
3874
               setSquare(passedPawnCorridor[BLACK][square], kingsquare);
3875
            }
3876
         }
3877
 
3878
         if (squarerank == kingsquarerank)
3879
         {
3880
            if (squarefile <= FILE_C && kingsquarefile <= FILE_C &&
3881
                kingsquarefile > squarefile)
3882
            {
3883
               setSquare(rookBlockers[square], kingsquare);
3884
            }
3885
 
3886
            if (squarefile >= FILE_F && kingsquarefile >= FILE_F &&
3887
                kingsquarefile < squarefile)
3888
            {
3889
               setSquare(rookBlockers[square], kingsquare);
3890
            }
3891
         }
3892
 
3893
         ITERATE(targetSquare)
3894
         {
3895
            if (distance(square, targetSquare) <
3896
                distance(kingsquare, targetSquare))
3897
            {
3898
               const Rank targetrank = rank(targetSquare);
3899
 
3900
               if (targetrank <= (Rank) (squarerank + 1))
3901
               {
3902
                  setSquare(kingRealm[WHITE][square][kingsquare],
3903
                            targetSquare);
3904
               }
3905
 
3906
               if (targetrank >= (Rank) (squarerank - 1))
3907
               {
3908
                  setSquare(kingRealm[BLACK][square][kingsquare],
3909
                            targetSquare);
3910
               }
3911
            }
3912
         }
3913
      }
3914
 
3915
      ITERATE(catchersquare)
3916
      {
3917
         if (abs(file(catchersquare) - squarefile) == 1)
3918
         {
3919
            if (rank(catchersquare) > squarerank)
3920
            {
3921
               setSquare(candidateDefenders[WHITE][square], catchersquare);
3922
            }
3923
 
3924
            if (rank(catchersquare) <= squarerank)
3925
            {
3926
               setSquare(candidateSupporters[WHITE][square], catchersquare);
3927
            }
3928
 
3929
            if (rank(catchersquare) < squarerank)
3930
            {
3931
               setSquare(candidateDefenders[BLACK][square], catchersquare);
3932
            }
3933
 
3934
            if (rank(catchersquare) >= squarerank)
3935
            {
3936
               setSquare(candidateSupporters[BLACK][square], catchersquare);
3937
            }
3938
         }
3939
 
3940
         if (abs(file(catchersquare) - squarefile) <= 1)
3941
         {
3942
            if (rank(catchersquare) >= squarerank)
3943
            {
3944
               setSquare(pawnOpponents[WHITE][square], catchersquare);
3945
            }
3946
 
3947
            if (rank(catchersquare) <= squarerank)
3948
            {
3949
               setSquare(pawnOpponents[BLACK][square], catchersquare);
3950
            }
3951
         }
3952
      }
3953
   }
3954
 
3955
   ITERATE(square)
3956
   {
3957
      const int dDark =
3958
         min(taxiDistance(square, A1), taxiDistance(square, H8));
3959
      const int dLight =
3960
         min(taxiDistance(square, A8), taxiDistance(square, H1));
3961
      const int dStandard = centerDistance[square];
3962
 
3963
      kingChaseMalus[DARK][square] = 3 * (7 - dDark) + dStandard;
3964
      kingChaseMalus[LIGHT][square] = 3 * (7 - dLight) + dStandard;
3965
      kingChaseMalus[ALL][square] = 6 - min(dDark, dLight) +
3966
         centerDistance[square];
3967
   }
3968
 
3969
   /*
3970
      dumpBoardValues(kingChaseMalus[DARK]);
3971
      dumpBoardValues(kingChaseMalus[LIGHT]);
3972
      dumpBoardValues(kingChaseMalus[ALL]);
3973
      getKeyStroke();
3974
    */
3975
 
3976
   transposeMatrix(BONUS_KNIGHT_OUTPOST_HR, BONUS_KNIGHT_OUTPOST);
3977
   transposeMatrix(BONUS_BISHOP_OUTPOST_HR, BONUS_BISHOP_OUTPOST);
3978
 
3979
   initializePieceSquareValues();
3980
   initializeKingAttacks();
3981
   initializeKingSafetyTable();
3982
 
3983
   attackPoints[WHITE_KING] = 0;
3984
   attackPoints[WHITE_QUEEN] = QUEEN_BONUS_ATTACK;
3985
   attackPoints[WHITE_ROOK] = ROOK_BONUS_ATTACK;
3986
   attackPoints[WHITE_BISHOP] = BISHOP_BONUS_ATTACK;
3987
   attackPoints[WHITE_KNIGHT] = KNIGHT_BONUS_ATTACK;
3988
   attackPoints[WHITE_PAWN] = 0;
3989
   attackPoints[BLACK_KING] = 0;
3990
   attackPoints[BLACK_QUEEN] = QUEEN_BONUS_ATTACK;
3991
   attackPoints[BLACK_ROOK] = ROOK_BONUS_ATTACK;
3992
   attackPoints[BLACK_BISHOP] = BISHOP_BONUS_ATTACK;
3993
   attackPoints[BLACK_KNIGHT] = KNIGHT_BONUS_ATTACK;
3994
   attackPoints[BLACK_PAWN] = 0;
3995
 
3996
   homeland[WHITE] = (squaresOfRank[RANK_2] | squaresOfRank[RANK_3] |
3997
                      squaresOfRank[RANK_4]) &
3998
      (squaresOfFile[FILE_C] | squaresOfFile[FILE_D] |
3999
       squaresOfFile[FILE_E] | squaresOfFile[FILE_F]);
4000
 
4001
   homeland[BLACK] = getFlippedBitboard(homeland[WHITE]);
4002
 
4003
   for (i = 0; i < 16; i++)
4004
   {
4005
      int j;
4006
 
4007
      for (j = 0; j < 16; j++)
4008
      {
4009
         piecePieceAttackBonus[i][j] = 0;
4010
      }
4011
   }
4012
 
4013
   piecePieceAttackBonus[WHITE_PAWN][BLACK_KNIGHT] = PPAB(56, 70);
4014
   piecePieceAttackBonus[WHITE_PAWN][BLACK_BISHOP] = PPAB(56, 70);
4015
   piecePieceAttackBonus[WHITE_PAWN][BLACK_ROOK] = PPAB(76, 99);
4016
   piecePieceAttackBonus[WHITE_PAWN][BLACK_QUEEN] = PPAB(86, 118);
4017
 
4018
   piecePieceAttackBonus[WHITE_KNIGHT][BLACK_PAWN] = PPAB(7, 39);
4019
   piecePieceAttackBonus[WHITE_KNIGHT][BLACK_BISHOP] = PPAB(24, 49);
4020
   piecePieceAttackBonus[WHITE_KNIGHT][BLACK_ROOK] = PPAB(41, 100);
4021
   piecePieceAttackBonus[WHITE_KNIGHT][BLACK_QUEEN] = PPAB(41, 100);
4022
 
4023
   piecePieceAttackBonus[WHITE_BISHOP][BLACK_PAWN] = PPAB(7, 39);
4024
   piecePieceAttackBonus[WHITE_BISHOP][BLACK_KNIGHT] = PPAB(24, 49);
4025
   piecePieceAttackBonus[WHITE_BISHOP][BLACK_ROOK] = PPAB(41, 100);
4026
   piecePieceAttackBonus[WHITE_BISHOP][BLACK_QUEEN] = PPAB(41, 100);
4027
 
4028
   piecePieceAttackBonus[WHITE_ROOK][BLACK_PAWN] = PPAB(0, 22);
4029
   piecePieceAttackBonus[WHITE_ROOK][BLACK_KNIGHT] = PPAB(15, 49);
4030
   piecePieceAttackBonus[WHITE_ROOK][BLACK_BISHOP] = PPAB(15, 49);
4031
   piecePieceAttackBonus[WHITE_ROOK][BLACK_QUEEN] = PPAB(24, 49);
4032
 
4033
   piecePieceAttackBonus[WHITE_QUEEN][BLACK_PAWN] = PPAB(15, 39);
4034
   piecePieceAttackBonus[WHITE_QUEEN][BLACK_KNIGHT] = PPAB(15, 39);
4035
   piecePieceAttackBonus[WHITE_QUEEN][BLACK_BISHOP] = PPAB(15, 39);
4036
   piecePieceAttackBonus[WHITE_QUEEN][BLACK_ROOK] = PPAB(15, 39);
4037
 
4038
   for (i = 0; i < 16; i++)
4039
   {
4040
      int j;
4041
 
4042
      for (j = 0; j < 16; j++)
4043
      {
4044
         if (pieceColor(i) == BLACK)
4045
         {
4046
            const Color reversedColor = opponent(pieceColor(j));
4047
            PieceType attacker = (PieceType) (pieceType(i) | WHITE);
4048
            PieceType attackedPiece =
4049
               (PieceType) (pieceType(j) | reversedColor);
4050
 
4051
            piecePieceAttackBonus[i][j] =
4052
               piecePieceAttackBonus[attacker][attackedPiece];
4053
         }
4054
      }
4055
   }
4056
 
4057
   troitzkyArea[WHITE] =
4058
      passedPawnCorridor[WHITE][A3] | passedPawnCorridor[WHITE][B5] |
4059
      passedPawnCorridor[WHITE][C3] | passedPawnCorridor[WHITE][D3] |
4060
      passedPawnCorridor[WHITE][E3] | passedPawnCorridor[WHITE][F3] |
4061
      passedPawnCorridor[WHITE][G5] | passedPawnCorridor[WHITE][H3];
4062
   troitzkyArea[BLACK] = getFlippedBitboard(troitzkyArea[WHITE]);
4063
 
4064
   krprkDrawFiles = squaresOfFile[FILE_A] | squaresOfFile[FILE_B] |
4065
      squaresOfFile[FILE_G] | squaresOfFile[FILE_H];
4066
   A1C1 = minValue[A1] | minValue[C1], F1H1 = minValue[F1] | minValue[H1];
4067
   A1B1 = minValue[A1] | minValue[B1], G1H1 = minValue[G1] | minValue[H1];
4068
 
4069
   initializeMaterialInfoTable();
4070
   initializeMoveBonusValue();
4071
   initializePawnChainBonus();
4072
 
4073
   return 0;
4074
}
4075
 
4076
#ifndef NDEBUG
4077
bool flipTest(Position * position,
4078
              PawnHashInfo * pawnHashtable,
4079
              KingSafetyHashInfo * kingsafetyHashtable)
4080
{
4081
   int v1, v2;
4082
   EvaluationBase base;
4083
 
4084
   initializePosition(position);
4085
   v1 = getValue(position, &base, pawnHashtable, kingsafetyHashtable);
4086
 
4087
   flipPosition(position);
4088
   initializePosition(position);
4089
   v2 = getValue(position, &base, pawnHashtable, kingsafetyHashtable);
4090
 
4091
   flipPosition(position);
4092
   initializePosition(position);
4093
 
4094
   if (v1 != v2)
4095
   {
4096
      const int debugFlag = debugOutput;
4097
      const bool debugEvalFlag = debugEval;
4098
 
4099
      debugOutput = TRUE;
4100
      debugEval = TRUE;
4101
 
4102
      logDebug("flip test failed: v1=%d v2=%d\n", v1, v2);
4103
      logPosition(position);
4104
      logDebug("hash: %llu\n", position->hashKey);
4105
      getValue(position, &base, pawnHashtable, kingsafetyHashtable);
4106
      flipPosition(position);
4107
      initializePosition(position);
4108
      logPosition(position);
4109
      getValue(position, &base, pawnHashtable, kingsafetyHashtable);
4110
      flipPosition(position);
4111
      initializePosition(position);
4112
 
4113
      debugEval = debugEvalFlag;
4114
      debugOutput = debugFlag;
4115
   }
4116
 
4117
   return (bool) (v1 == v2);
4118
}
4119
#endif
4120
 
4121
static int testPawnInfoGeneration()
4122
{
4123
   Variation variation;
4124
   EvaluationBase base;
4125
 
4126
   initializeVariation(&variation,
4127
                       "8/7p/5k2/5p2/p1p2P2/Pr1pPK2/1P1R3P/8 b - - 0 1");
4128
   getPawnInfo(&variation.singlePosition, &base);
4129
 
4130
   assert(getNumberOfSetSquares(base.pawnProtectedSquares[WHITE]) == 8);
4131
   assert(testSquare(base.pawnProtectedSquares[WHITE], B4));
4132
   assert(testSquare(base.pawnProtectedSquares[WHITE], A3));
4133
   assert(testSquare(base.pawnProtectedSquares[WHITE], C3));
4134
   assert(testSquare(base.pawnProtectedSquares[WHITE], D4));
4135
   assert(testSquare(base.pawnProtectedSquares[WHITE], F4));
4136
   assert(testSquare(base.pawnProtectedSquares[WHITE], E5));
4137
   assert(testSquare(base.pawnProtectedSquares[WHITE], G5));
4138
   assert(testSquare(base.pawnProtectedSquares[WHITE], G3));
4139
 
4140
   assert(getNumberOfSetSquares(base.pawnProtectedSquares[BLACK]) == 7);
4141
   assert(testSquare(base.pawnProtectedSquares[BLACK], B3));
4142
   assert(testSquare(base.pawnProtectedSquares[BLACK], D3));
4143
   assert(testSquare(base.pawnProtectedSquares[BLACK], C2));
4144
   assert(testSquare(base.pawnProtectedSquares[BLACK], E2));
4145
   assert(testSquare(base.pawnProtectedSquares[BLACK], E4));
4146
   assert(testSquare(base.pawnProtectedSquares[BLACK], G4));
4147
   assert(testSquare(base.pawnProtectedSquares[BLACK], G6));
4148
 
4149
   assert(getNumberOfSetSquares(base.passedPawns[WHITE]) == 0);
4150
   assert(getNumberOfSetSquares(base.passedPawns[BLACK]) == 1);
4151
   assert(testSquare(base.passedPawns[BLACK], D3));
4152
 
4153
   assert(getNumberOfSetSquares(base.weakPawns[WHITE]) == 3);
4154
   assert(testSquare(base.weakPawns[WHITE], B2));
4155
   assert(testSquare(base.weakPawns[WHITE], E3));
4156
   assert(testSquare(base.weakPawns[WHITE], H2));
4157
 
4158
   assert(getNumberOfSetSquares(base.weakPawns[BLACK]) == 4);
4159
   assert(testSquare(base.weakPawns[BLACK], A4));
4160
   assert(testSquare(base.weakPawns[BLACK], C4));
4161
   assert(testSquare(base.weakPawns[BLACK], F5));
4162
   assert(testSquare(base.weakPawns[BLACK], H7));
4163
 
4164
   initializeVariation(&variation,
4165
                       "4k3/2p5/p2p4/P2P4/1PP3p1/7p/7P/4K3 w - - 0 1");
4166
   getPawnInfo(&variation.singlePosition, &base);
4167
 
4168
   assert(getNumberOfSetSquares(base.passedPawns[WHITE]) == 0);
4169
   assert(getNumberOfSetSquares(base.passedPawns[BLACK]) == 0);
4170
   assert(getNumberOfSetSquares(base.weakPawns[WHITE]) == 1);
4171
   assert(testSquare(base.weakPawns[WHITE], H2));
4172
 
4173
   assert(getNumberOfSetSquares(base.weakPawns[BLACK]) == 3);
4174
   assert(testSquare(base.weakPawns[BLACK], A6));
4175
   assert(testSquare(base.weakPawns[BLACK], C7));
4176
   assert(testSquare(base.weakPawns[BLACK], G4));
4177
 
4178
   return 0;
4179
}
4180
 
4181
static int testWeakPawnDetection()
4182
{
4183
   Position position;
4184
   Bitboard expectedResult = EMPTY_BITBOARD;
4185
   EvaluationBase base;
4186
 
4187
   clearPosition(&position);
4188
   position.piece[E1] = WHITE_KING;
4189
   position.piece[E8] = BLACK_KING;
4190
   position.piece[A3] = WHITE_PAWN;
4191
   position.piece[B5] = WHITE_PAWN;
4192
   position.piece[B6] = WHITE_PAWN;
4193
   position.piece[C4] = WHITE_PAWN;
4194
   position.piece[E4] = WHITE_PAWN;
4195
   position.piece[G4] = WHITE_PAWN;
4196
   position.piece[H2] = WHITE_PAWN;
4197
   position.piece[A4] = BLACK_PAWN;
4198
   position.piece[B7] = BLACK_PAWN;
4199
   setSquare(expectedResult, A3);
4200
   setSquare(expectedResult, E4);
4201
   initializePosition(&position);
4202
   getPawnInfo(&position, &base);
4203
   assert(base.weakPawns[WHITE] == expectedResult);
4204
   expectedResult = EMPTY_BITBOARD;
4205
   setSquare(expectedResult, B7);
4206
   assert(base.weakPawns[BLACK] == expectedResult);
4207
   assert(base.candidatePawns[BLACK] == EMPTY_BITBOARD);
4208
 
4209
   position.piece[C4] = NO_PIECE;
4210
   position.piece[C5] = WHITE_PAWN;
4211
   initializePosition(&position);
4212
   getPawnInfo(&position, &base);
4213
   expectedResult = EMPTY_BITBOARD;
4214
   setSquare(expectedResult, C5);
4215
   assert(base.candidatePawns[WHITE] == expectedResult);
4216
 
4217
   clearPosition(&position);
4218
   position.piece[E1] = WHITE_KING;
4219
   position.piece[E8] = BLACK_KING;
4220
   position.piece[A3] = WHITE_PAWN;
4221
   position.piece[B5] = WHITE_PAWN;
4222
   position.piece[B6] = WHITE_PAWN;
4223
   position.piece[C4] = WHITE_PAWN;
4224
   position.piece[E4] = WHITE_PAWN;
4225
   position.piece[G4] = WHITE_PAWN;
4226
   position.piece[H2] = WHITE_PAWN;
4227
   position.piece[A4] = BLACK_PAWN;
4228
   position.piece[B7] = BLACK_PAWN;
4229
   position.piece[D6] = BLACK_PAWN;
4230
   expectedResult = EMPTY_BITBOARD;
4231
   setSquare(expectedResult, A3);
4232
   setSquare(expectedResult, E4);
4233
   setSquare(expectedResult, C4);
4234
   initializePosition(&position);
4235
   getPawnInfo(&position, &base);
4236
   assert(base.weakPawns[WHITE] == expectedResult);
4237
   assert(base.candidatePawns[WHITE] == EMPTY_BITBOARD);
4238
   expectedResult = EMPTY_BITBOARD;
4239
   setSquare(expectedResult, B7);
4240
   setSquare(expectedResult, D6);
4241
   assert(base.weakPawns[BLACK] == expectedResult);
4242
   assert(base.candidatePawns[BLACK] == EMPTY_BITBOARD);
4243
 
4244
   position.piece[G5] = BLACK_PAWN;
4245
   expectedResult = EMPTY_BITBOARD;
4246
   setSquare(expectedResult, A3);
4247
   setSquare(expectedResult, E4);
4248
   setSquare(expectedResult, C4);
4249
   setSquare(expectedResult, H2);
4250
   initializePosition(&position);
4251
   getPawnInfo(&position, &base);
4252
   assert(base.weakPawns[WHITE] == expectedResult);
4253
   assert(base.candidatePawns[WHITE] == EMPTY_BITBOARD);
4254
   expectedResult = EMPTY_BITBOARD;
4255
   setSquare(expectedResult, B7);
4256
   setSquare(expectedResult, D6);
4257
   setSquare(expectedResult, G5);
4258
   assert(base.weakPawns[BLACK] == expectedResult);
4259
   assert(base.candidatePawns[BLACK] == EMPTY_BITBOARD);
4260
 
4261
   return 0;
4262
}
4263
 
4264
static int testBaseInitialization()
4265
{
4266
   Variation variation;
4267
 
4268
   initializeVariation(&variation, FEN_GAMESTART);
4269
 
4270
   assert(testSquare(passedPawnCorridor[WHITE][B4], B6));
4271
   assert(testSquare(passedPawnCorridor[BLACK][B4], B6) == FALSE);
4272
   assert(testSquare(passedPawnCorridor[WHITE][C2], H7) == FALSE);
4273
   assert(testSquare(passedPawnCorridor[BLACK][G6], G2));
4274
 
4275
#ifndef NDEBUG
4276
   {
4277
      INT32 testBonus = evalBonus(-1, -1);
4278
 
4279
      assert(getOpeningValue(testBonus) == -1);
4280
      assert(getEndgameValue(testBonus) == -1);
4281
   }
4282
#endif
4283
 
4284
   return 0;
4285
}
4286
 
4287
static int testKingPawnDistanceCalculation()
4288
{
4289
#ifndef NDEBUG
4290
   Bitboard whitePawns = minValue[B4] | minValue[G7], blackPawns =
4291
      minValue[E3];
4292
   Position position;
4293
 
4294
   position.king[WHITE] = B2;
4295
   position.king[BLACK] = G6;
4296
   position.piecesOfType[WHITE_PAWN] = whitePawns;
4297
   position.piecesOfType[BLACK_PAWN] = blackPawns;
4298
   position.piece[B4] = position.piece[G7] = WHITE_PAWN;
4299
   position.piece[E3] = BLACK_PAWN;
4300
 
4301
   assert(getKingPawnDistance(&position, WHITE) == 2 * KP_DISTANCE_WEIGHT);
4302
   assert(getKingPawnDistance(&position, BLACK) == KP_DISTANCE_WEIGHT);
4303
 
4304
   position.king[WHITE] = B7;
4305
   assert(getKingPawnDistance(&position, WHITE) ==
4306
          3 * KP_REDUCED_DISTANCE_WEIGHT);
4307
 
4308
   position.king[WHITE] = E1;
4309
   assert(getKingPawnDistance(&position, WHITE) ==
4310
          2 * KP_REDUCED_DISTANCE_WEIGHT);
4311
 
4312
   position.king[BLACK] = E5;
4313
   assert(getKingPawnDistance(&position, BLACK) == 2 * KP_DISTANCE_WEIGHT);
4314
#endif
4315
 
4316
   return 0;
4317
}
4318
 
4319
#ifndef NDEBUG
4320
static void initializePawnHashtable(PawnHashInfo * pawnHashtable)
4321
{
4322
   int i;
4323
 
4324
   for (i = 0; i < PAWN_HASHTABLE_SIZE; i++)
4325
   {
4326
      pawnHashtable[i].hashKey = 0;
4327
   }
4328
}
4329
 
4330
static void initializeKingsafetyHashtable(KingSafetyHashInfo *
4331
                                          kingsafetyHashtable)
4332
{
4333
   int i;
4334
 
4335
   for (i = 0; i < KINGSAFETY_HASHTABLE_SIZE; i++)
4336
   {
4337
      kingsafetyHashtable[i].hashKey = 0;
4338
   }
4339
}
4340
 
4341
static int testFlippings()
4342
{
4343
   const char fen1[] =
4344
      "2rr2k1/1b3ppp/pb2p3/1p2P3/1P2BPnq/P1N3P1/1B2Q2P/R4R1K b - - 0 1";
4345
   const char fen2[] = "4k3/2p5/p2p4/P2P4/1PP3p1/7p/7P/4K3 w - - 0 1";
4346
   const char fen3[] = "8/7p/5k2/5p2/p1p2P2/Pr1pPK2/1P1R3P/8 b - - 0 1";
4347
   const char fen4[] =
4348
      "6r1/Q2Pn2k/p1p1P2p/5p2/2PqR1r1/1P6/P6P/5R1K b - - 5 4";
4349
   const char fen5[] =
4350
      "Q4rk1/2bb1ppp/4pn2/pQ5q/3P4/N4N2/5PPP/R1B2RK1 w - a6 0 4";
4351
   Variation variation;
4352
 
4353
   initializeVariation(&variation, fen1);
4354
   variation.pawnHashtable = localPawnHashtable;
4355
   variation.kingsafetyHashtable = localKingSafetyHashtable;
4356
   initializePawnHashtable(variation.pawnHashtable);
4357
   initializeKingsafetyHashtable(variation.kingsafetyHashtable);
4358
   assert(flipTest(&variation.singlePosition, variation.pawnHashtable,
4359
                   variation.kingsafetyHashtable) != FALSE);
4360
 
4361
   initializeVariation(&variation, fen2);
4362
   assert(flipTest(&variation.singlePosition, variation.pawnHashtable,
4363
                   variation.kingsafetyHashtable) != FALSE);
4364
 
4365
   initializeVariation(&variation, fen3);
4366
   assert(flipTest(&variation.singlePosition, variation.pawnHashtable,
4367
                   variation.kingsafetyHashtable) != FALSE);
4368
 
4369
   initializeVariation(&variation, fen4);
4370
   assert(flipTest(&variation.singlePosition, variation.pawnHashtable,
4371
                   variation.kingsafetyHashtable) != FALSE);
4372
 
4373
   initializeVariation(&variation, fen5);
4374
   assert(flipTest(&variation.singlePosition, variation.pawnHashtable,
4375
                   variation.kingsafetyHashtable) != FALSE);
4376
 
4377
   return 0;
4378
}
4379
#endif
4380
 
4381
int testModuleEvaluation()
4382
{
4383
   int result;
4384
 
4385
   if ((result = testPawnInfoGeneration()) != 0)
4386
   {
4387
      return result;
4388
   }
4389
 
4390
   if ((result = testWeakPawnDetection()) != 0)
4391
   {
4392
      return result;
4393
   }
4394
 
4395
   if ((result = testBaseInitialization()) != 0)
4396
   {
4397
      return result;
4398
   }
4399
 
4400
   if ((result = testKingPawnDistanceCalculation()) != 0)
4401
   {
4402
      return result;
4403
   }
4404
 
4405
#ifndef NDEBUG
4406
   if ((result = testFlippings()) != 0)
4407
   {
4408
      return result;
4409
   }
4410
#endif
4411
 
4412
   return 0;
4413
}