2 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3 Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4 Copyright (C) 2008-2009 Marco Costalba
6 Stockfish 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.
11 Stockfish 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.
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/>.
34 //// Local definitions
39 /// Constants and variables
41 // Doubled pawn penalty by file, middle game
42 const Value DoubledPawnMidgamePenalty[8] = {
43 Value(13), Value(20), Value(23), Value(23),
44 Value(23), Value(23), Value(20), Value(13)
47 // Doubled pawn penalty by file, endgame
48 const Value DoubledPawnEndgamePenalty[8] = {
49 Value(43), Value(48), Value(48), Value(48),
50 Value(48), Value(48), Value(48), Value(43)
53 // Isolated pawn penalty by file, middle game
54 const Value IsolatedPawnMidgamePenalty[8] = {
55 Value(25), Value(36), Value(40), Value(40),
56 Value(40), Value(40), Value(36), Value(25)
59 // Isolated pawn penalty by file, endgame
60 const Value IsolatedPawnEndgamePenalty[8] = {
61 Value(30), Value(35), Value(35), Value(35),
62 Value(35), Value(35), Value(35), Value(30)
65 // Backward pawn penalty by file, middle game
66 const Value BackwardPawnMidgamePenalty[8] = {
67 Value(20), Value(29), Value(33), Value(33),
68 Value(33), Value(33), Value(29), Value(20)
71 // Backward pawn penalty by file, endgame
72 const Value BackwardPawnEndgamePenalty[8] = {
73 Value(28), Value(31), Value(31), Value(31),
74 Value(31), Value(31), Value(31), Value(28)
77 // Pawn chain membership bonus by file, middle game
78 const Value ChainMidgameBonus[8] = {
79 Value(11), Value(13), Value(13), Value(14),
80 Value(14), Value(13), Value(13), Value(11)
83 // Pawn chain membership bonus by file, endgame
84 const Value ChainEndgameBonus[8] = {
85 Value(-1), Value(-1), Value(-1), Value(-1),
86 Value(-1), Value(-1), Value(-1), Value(-1)
89 // Candidate passed pawn bonus by rank, middle game
90 const Value CandidateMidgameBonus[8] = {
91 Value( 0), Value( 6), Value(6), Value(14),
92 Value(34), Value(83), Value(0), Value( 0)
95 // Candidate passed pawn bonus by rank, endgame
96 const Value CandidateEndgameBonus[8] = {
97 Value( 0), Value( 13), Value(13), Value(29),
98 Value(68), Value(166), Value( 0), Value( 0)
101 // Pawn storm tables for positions with opposite castling
102 const int QStormTable[64] = {
103 0, 0, 0, 0, 0, 0, 0, 0,
104 -22,-22,-22,-14,-6, 0, 0, 0,
105 -6,-10,-10,-10,-6, 0, 0, 0,
106 4, 12, 16, 12, 4, 0, 0, 0,
107 16, 23, 23, 16, 0, 0, 0, 0,
108 23, 31, 31, 23, 0, 0, 0, 0,
109 23, 31, 31, 23, 0, 0, 0, 0,
110 0, 0, 0, 0, 0, 0, 0, 0
113 const int KStormTable[64] = {
114 0, 0, 0, 0, 0, 0, 0, 0,
115 0, 0, 0,-10,-19,-28,-33,-33,
116 0, 0, 0,-10,-15,-19,-24,-24,
117 0, 0, 0, 0, 1, 1, 1, 1,
118 0, 0, 0, 0, 1, 10, 19, 19,
119 0, 0, 0, 0, 1, 19, 31, 27,
120 0, 0, 0, 0, 0, 22, 31, 22,
121 0, 0, 0, 0, 0, 0, 0, 0
124 // Pawn storm open file bonuses by file
125 const int16_t KStormOpenFileBonus[8] = { 31, 31, 18, 0, 0, 0, 0, 0 };
126 const int16_t QStormOpenFileBonus[8] = { 0, 0, 0, 0, 0, 26, 42, 26 };
128 // Pawn storm lever bonuses by file
129 const int StormLeverBonus[8] = { -8, -8, -13, 0, 0, -13, -8, -8 };
140 PawnInfoTable::PawnInfoTable(unsigned numOfEntries) {
143 entries = new PawnInfo[size];
146 std::cerr << "Failed to allocate " << (numOfEntries * sizeof(PawnInfo))
147 << " bytes for pawn hash table." << std::endl;
148 Application::exit_with_failure();
155 PawnInfoTable::~PawnInfoTable() {
160 /// PawnInfo::clear() resets to zero the PawnInfo entry. Note that
161 /// kingSquares[] is initialized to SQ_NONE instead.
163 void PawnInfo::clear() {
165 memset(this, 0, sizeof(PawnInfo));
166 kingSquares[WHITE] = kingSquares[BLACK] = SQ_NONE;
170 /// PawnInfoTable::get_pawn_info() takes a position object as input, computes
171 /// a PawnInfo object, and returns a pointer to it. The result is also
172 /// stored in a hash table, so we don't have to recompute everything when
173 /// the same pawn structure occurs again.
175 PawnInfo* PawnInfoTable::get_pawn_info(const Position& pos) {
179 Key key = pos.get_pawn_key();
180 int index = int(key & (size - 1));
181 PawnInfo* pi = entries + index;
183 // If pi->key matches the position's pawn hash key, it means that we
184 // have analysed this pawn structure before, and we can simply return
185 // the information we found the last time instead of recomputing it.
189 // Clear the PawnInfo object, and set the key
193 // Calculate pawn attacks
194 Bitboard whitePawns = pos.pieces(PAWN, WHITE);
195 Bitboard blackPawns = pos.pieces(PAWN, BLACK);
196 pi->pawnAttacks[WHITE] = ((whitePawns << 9) & ~FileABB) | ((whitePawns << 7) & ~FileHBB);
197 pi->pawnAttacks[BLACK] = ((blackPawns >> 7) & ~FileABB) | ((blackPawns >> 9) & ~FileHBB);
199 // Evaluate pawns for both colors
200 Values whiteValues = evaluate_pawns<WHITE>(pos, whitePawns, blackPawns, pi);
201 Values blackValues = evaluate_pawns<BLACK>(pos, blackPawns, whitePawns, pi);
203 pi->mgValue = int16_t(whiteValues.first - blackValues.first);
204 pi->egValue = int16_t(whiteValues.second - blackValues.second);
209 /// PawnInfoTable::evaluate_pawns() evaluates each pawn of the given color
212 PawnInfoTable::Values PawnInfoTable::evaluate_pawns(const Position& pos, Bitboard ourPawns,
213 Bitboard theirPawns, PawnInfo* pi) {
217 bool passed, isolated, doubled, chain, backward, candidate;
219 Value mgValue = Value(0);
220 Value egValue = Value(0);
221 const Square* ptr = pos.piece_list_begin(Us, PAWN);
223 // Initialize pawn storm scores by giving bonuses for open files
224 for (File f = FILE_A; f <= FILE_H; f++)
225 if (!(ourPawns & file_bb(f)))
227 pi->ksStormValue[Us] += KStormOpenFileBonus[f];
228 pi->qsStormValue[Us] += QStormOpenFileBonus[f];
229 pi->halfOpenFiles[Us] |= (1 << f);
232 // Loop through all pawns of the current color and score each pawn
233 while ((s = *ptr++) != SQ_NONE)
238 assert(pos.piece_on(s) == piece_of_color_and_type(Us, PAWN));
240 // Passed, isolated or doubled pawn?
241 passed = Position::pawn_is_passed(theirPawns, Us, s);
242 isolated = Position::pawn_is_isolated(ourPawns, s);
243 doubled = Position::pawn_is_doubled(ourPawns, Us, s);
245 // We calculate kingside and queenside pawn storm
246 // scores for both colors. These are used when evaluating
247 // middle game positions with opposite side castling.
249 // Each pawn is given a base score given by a piece square table
250 // (KStormTable[] or QStormTable[]). Pawns which seem to have good
251 // chances of creating an open file by exchanging itself against an
252 // enemy pawn on an adjacent file gets an additional bonus.
254 // Kingside pawn storms
255 bonus = KStormTable[relative_square(Us, s)];
258 Bitboard b = outpost_mask(Us, s) & theirPawns & (FileFBB | FileGBB | FileHBB);
261 Square s2 = pop_1st_bit(&b);
262 if (!(theirPawns & neighboring_files_bb(s2) & rank_bb(s2)))
264 // The enemy pawn has no pawn beside itself, which makes it
265 // particularly vulnerable. Big bonus, especially against a
266 // weakness on the rook file.
267 if (square_file(s2) == FILE_H)
268 bonus += 4*StormLeverBonus[f] - 8*square_distance(s, s2);
270 bonus += 2*StormLeverBonus[f] - 4*square_distance(s, s2);
272 // There is at least one enemy pawn beside the enemy pawn we look
273 // at, which means that the pawn has somewhat better chances of
274 // defending itself by advancing. Smaller bonus.
275 bonus += StormLeverBonus[f] - 2*square_distance(s, s2);
278 pi->ksStormValue[Us] += bonus;
280 // Queenside pawn storms
281 bonus = QStormTable[relative_square(Us, s)];
284 Bitboard b = outpost_mask(Us, s) & theirPawns & (FileABB | FileBBB | FileCBB);
287 Square s2 = pop_1st_bit(&b);
288 if (!(theirPawns & neighboring_files_bb(s2) & rank_bb(s2)))
290 // The enemy pawn has no pawn beside itself, which makes it
291 // particularly vulnerable. Big bonus, especially against a
292 // weakness on the rook file.
293 if (square_file(s2) == FILE_A)
294 bonus += 4*StormLeverBonus[f] - 16*square_distance(s, s2);
296 bonus += 2*StormLeverBonus[f] - 8*square_distance(s, s2);
298 // There is at least one enemy pawn beside the enemy pawn we look
299 // at, which means that the pawn has somewhat better chances of
300 // defending itself by advancing. Smaller bonus.
301 bonus += StormLeverBonus[f] - 4*square_distance(s, s2);
304 pi->qsStormValue[Us] += bonus;
306 // Member of a pawn chain (but not the backward one)? We could speed up
307 // the test a little by introducing an array of masks indexed by color
308 // and square for doing the test, but because everything is hashed,
309 // it probably won't make any noticable difference.
311 & neighboring_files_bb(f)
312 & (rank_bb(r) | rank_bb(r - (Us == WHITE ? 1 : -1)));
314 // Test for backward pawn
316 // If the pawn is passed, isolated, or member of a pawn chain
317 // it cannot be backward. If can capture an enemy pawn or if
318 // there are friendly pawns behind on neighboring files it cannot
319 // be backward either.
320 if ( (passed | isolated | chain)
321 || (ourPawns & behind_bb(Us, r) & neighboring_files_bb(f))
322 || (pos.attacks_from<PAWN>(s, Us) & theirPawns))
326 // We now know that there are no friendly pawns beside or behind this
327 // pawn on neighboring files. We now check whether the pawn is
328 // backward by looking in the forward direction on the neighboring
329 // files, and seeing whether we meet a friendly or an enemy pawn first.
330 Bitboard b = pos.attacks_from<PAWN>(s, Us);
332 // Note that we are sure to find something because pawn is not passed
333 // nor isolated, so loop is potentially infinite, but it isn't.
334 while (!(b & (ourPawns | theirPawns)))
335 Us == WHITE ? b <<= 8 : b >>= 8;
337 // The friendly pawn needs to be at least two ranks closer than the enemy
338 // pawn in order to help the potentially backward pawn advance.
339 backward = (b | (Us == WHITE ? b << 8 : b >> 8)) & theirPawns;
342 // Test for candidate passed pawn
344 && !(theirPawns & file_bb(f))
345 && ( count_1s_max_15(neighboring_files_bb(f) & (behind_bb(Us, r) | rank_bb(r)) & ourPawns)
346 - count_1s_max_15(neighboring_files_bb(f) & in_front_bb(Us, r) & theirPawns)
349 // In order to prevent doubled passed pawns from receiving a too big
350 // bonus, only the frontmost passed pawn on each file is considered as
351 // a true passed pawn.
352 if (passed && (ourPawns & squares_in_front_of(Us, s)))
357 set_bit(&(pi->passedPawns), s);
361 mgValue -= IsolatedPawnMidgamePenalty[f];
362 egValue -= IsolatedPawnEndgamePenalty[f];
363 if (!(theirPawns & file_bb(f)))
365 mgValue -= IsolatedPawnMidgamePenalty[f] / 2;
366 egValue -= IsolatedPawnEndgamePenalty[f] / 2;
371 mgValue -= DoubledPawnMidgamePenalty[f];
372 egValue -= DoubledPawnEndgamePenalty[f];
376 mgValue -= BackwardPawnMidgamePenalty[f];
377 egValue -= BackwardPawnEndgamePenalty[f];
378 if (!(theirPawns & file_bb(f)))
380 mgValue -= BackwardPawnMidgamePenalty[f] / 2;
381 egValue -= BackwardPawnEndgamePenalty[f] / 2;
386 mgValue += ChainMidgameBonus[f];
387 egValue += ChainEndgameBonus[f];
391 mgValue += CandidateMidgameBonus[relative_rank(Us, s)];
392 egValue += CandidateEndgameBonus[relative_rank(Us, s)];
396 return Values(mgValue, egValue);
400 /// PawnInfo::updateShelter calculates and caches king shelter. It is called
401 /// only when king square changes, about 20% of total get_king_shelter() calls.
402 int PawnInfo::updateShelter(const Position& pos, Color c, Square ksq) {
404 unsigned shelter = 0;
405 Bitboard pawns = pos.pieces(PAWN, c) & this_and_neighboring_files_bb(ksq);
406 unsigned r = ksq & (7 << 3);
407 for (int i = 1, k = (c ? -8 : 8); i < 4; i++)
410 shelter += BitCount8Bit[(pawns >> r) & 0xFF] * (128 >> i);
412 kingSquares[c] = ksq;
413 kingShelters[c] = shelter;