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 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/>.
33 //// Local definitions
38 /// Constants and variables
40 // Doubled pawn penalty by file, middle game.
41 const Value DoubledPawnMidgamePenalty[8] = {
42 Value(20), Value(30), Value(34), Value(34),
43 Value(34), Value(34), Value(30), Value(20)
46 // Doubled pawn penalty by file, endgame.
47 const Value DoubledPawnEndgamePenalty[8] = {
48 Value(35), Value(40), Value(40), Value(40),
49 Value(40), Value(40), Value(40), Value(35)
52 // Isolated pawn penalty by file, middle game.
53 const Value IsolatedPawnMidgamePenalty[8] = {
54 Value(20), Value(30), Value(34), Value(34),
55 Value(34), Value(34), Value(30), Value(20)
58 // Isolated pawn penalty by file, endgame.
59 const Value IsolatedPawnEndgamePenalty[8] = {
60 Value(35), Value(40), Value(40), Value(40),
61 Value(40), Value(40), Value(40), Value(35)
64 // Backward pawn penalty by file, middle game.
65 const Value BackwardPawnMidgamePenalty[8] = {
66 Value(16), Value(24), Value(27), Value(27),
67 Value(27), Value(27), Value(24), Value(16)
70 // Backward pawn penalty by file, endgame.
71 const Value BackwardPawnEndgamePenalty[8] = {
72 Value(28), Value(32), Value(32), Value(32),
73 Value(32), Value(32), Value(32), Value(28)
76 // Pawn chain membership bonus by file, middle game.
77 const Value ChainMidgameBonus[8] = {
78 Value(14), Value(16), Value(17), Value(18),
79 Value(18), Value(17), Value(16), Value(14)
82 // Pawn chain membership bonus by file, endgame.
83 const Value ChainEndgameBonus[8] = {
84 Value(16), Value(16), Value(16), Value(16),
85 Value(16), Value(16), Value(16), Value(16)
88 // Candidate passed pawn bonus by rank, middle game.
89 const Value CandidateMidgameBonus[8] = {
90 Value( 0), Value(12), Value(12), Value(20),
91 Value(40), Value(90), Value( 0), Value( 0)
94 // Candidate passed pawn bonus by rank, endgame.
95 const Value CandidateEndgameBonus[8] = {
96 Value( 0), Value(24), Value(24), Value(40),
97 Value(80), Value(180), Value(0), Value( 0)
100 // Pawn storm tables for positions with opposite castling:
101 const int QStormTable[64] = {
102 0, 0, 0, 0, 0, 0, 0, 0,
103 -22,-22,-22,-13,-4, 0, 0, 0,
104 -4, -9, -9, -9,-4, 0, 0, 0,
105 9, 18, 22, 18, 9, 0, 0, 0,
106 22, 31, 31, 22, 0, 0, 0, 0,
107 31, 40, 40, 31, 0, 0, 0, 0,
108 31, 40, 40, 31, 0, 0, 0, 0,
109 0, 0, 0, 0, 0, 0, 0, 0
112 const int KStormTable[64] = {
113 0, 0, 0, 0, 0, 0, 0, 0,
114 0, 0, 0,-4,-13,-22,-27,-27,
115 0, 0, 0,-4, -9,-13,-18,-18,
116 0, 0, 0, 0, 9, 9, 9, 9,
117 0, 0, 0, 0, 9, 18, 27, 27,
118 0, 0, 0, 0, 9, 27, 40, 36,
119 0, 0, 0, 0, 0, 31, 40, 31,
120 0, 0, 0, 0, 0, 0, 0, 0
123 // Pawn storm open file bonuses by file:
124 const int KStormOpenFileBonus[8] = {
125 45, 45, 30, 0, 0, 0, 0, 0
128 const int QStormOpenFileBonus[8] = {
129 0, 0, 0, 0, 0, 30, 45, 30
141 PawnInfoTable::PawnInfoTable(unsigned numOfEntries) {
144 entries = new PawnInfo[size];
147 std::cerr << "Failed to allocate " << (numOfEntries * sizeof(PawnInfo))
148 << " bytes for pawn hash table." << std::endl;
157 PawnInfoTable::~PawnInfoTable() {
162 /// PawnInfoTable::clear() clears the pawn hash table by setting all
165 void PawnInfoTable::clear() {
166 memset(entries, 0, size * sizeof(PawnInfo));
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 the
185 // information we found the last time instead of recomputing it
189 // Clear the PawnInfo object, and set the key
193 Value mgValue[2] = {Value(0), Value(0)};
194 Value egValue[2] = {Value(0), Value(0)};
196 // Loop through the pawns for both colors
197 for (Color us = WHITE; us <= BLACK; us++)
199 Color them = opposite_color(us);
200 Bitboard ourPawns = pos.pawns(us);
201 Bitboard theirPawns = pos.pawns(them);
202 Bitboard pawns = ourPawns;
204 // Initialize pawn storm scores by giving bonuses for open files
205 for (File f = FILE_A; f <= FILE_H; f++)
206 if (pos.file_is_half_open(us, f))
208 pi->ksStormValue[us] += KStormOpenFileBonus[f];
209 pi->qsStormValue[us] += QStormOpenFileBonus[f];
212 // Loop through all pawns of the current color and score each pawn
215 bool passed, doubled, isolated, backward, chain, candidate;
216 Square s = pop_1st_bit(&pawns);
217 File f = square_file(s);
218 Rank r = square_rank(s);
220 assert(pos.piece_on(s) == piece_of_color_and_type(us, PAWN));
222 // The file containing the pawn is not half open
223 pi->halfOpenFiles[us] &= ~(1 << f);
225 // Passed, isolated or doubled pawn?
226 passed = pos.pawn_is_passed(us, s);
227 isolated = pos.pawn_is_isolated(us, s);
228 doubled = pos.pawn_is_doubled(us, s);
230 // We calculate kingside and queenside pawn storm scores
231 // for both colors. These are used when evaluating middle
232 // game positions with opposite side castling.
234 // Each pawn is given a base score given by a piece square table
235 // (KStormTable[] or QStormTable[]). This score is increased if
236 // there are enemy pawns on adjacent files in front of the pawn.
237 // This is because we want to be able to open files against the
238 // enemy king, and to avoid blocking the pawn structure (e.g. white
239 // pawns on h6, g5, black pawns on h7, g6, f7).
241 // Kingside and queenside pawn storms
242 int KBonus = KStormTable[relative_square(us, s)];
243 int QBonus = QStormTable[relative_square(us, s)];
244 bool outPostFlag = (KBonus > 0 && (outpost_mask(us, s) & theirPawns));
245 bool passedFlag = (QBonus > 0 && (passed_pawn_mask(us, s) & theirPawns));
250 QBonus += passedFlag * QBonus / 2;
254 QBonus += passedFlag * (QBonus / 2 + QBonus / 4);
258 QBonus += passedFlag * QBonus / 2;
262 KBonus += outPostFlag * KBonus / 4;
266 KBonus += outPostFlag * (KBonus / 2 + KBonus / 4);
270 KBonus += outPostFlag * KBonus / 2;
276 pi->ksStormValue[us] += KBonus;
277 pi->qsStormValue[us] += QBonus;
279 // Member of a pawn chain (but not the backward one)? We could speed up
280 // the test a little by introducing an array of masks indexed by color
281 // and square for doing the test, but because everything is hashed,
282 // it probably won't make any noticable difference.
284 & neighboring_files_bb(f)
285 & (rank_bb(r) | rank_bb(r - (us == WHITE ? 1 : -1)));
287 // Test for backward pawn
289 // If the pawn is passed, isolated, or member of a pawn chain
290 // it cannot be backward. If can capture an enemy pawn or if
291 // there are friendly pawns behind on neighboring files it cannot
292 // be backward either.
296 || (pos.pawn_attacks(us, s) & theirPawns)
297 || (ourPawns & behind_bb(us, r) & neighboring_files_bb(f)))
301 // We now know that there are no friendly pawns beside or behind this
302 // pawn on neighboring files. We now check whether the pawn is
303 // backward by looking in the forward direction on the neighboring
304 // files, and seeing whether we meet a friendly or an enemy pawn first.
308 for (b = pos.pawn_attacks(us, s); !(b & (ourPawns | theirPawns)); b <<= 8);
309 backward = (b | (b << 8)) & theirPawns;
313 for (b = pos.pawn_attacks(us, s); !(b & (ourPawns | theirPawns)); b >>= 8);
314 backward = (b | (b >> 8)) & theirPawns;
318 // Test for candidate passed pawn
320 && pos.file_is_half_open(them, f)
321 && ( count_1s_max_15(neighboring_files_bb(f) & (behind_bb(us, r) | rank_bb(r)) & ourPawns)
322 - count_1s_max_15(neighboring_files_bb(f) & in_front_bb(us, r) & theirPawns)
325 // In order to prevent doubled passed pawns from receiving a too big
326 // bonus, only the frontmost passed pawn on each file is considered as
327 // a true passed pawn.
328 if (passed && (ourPawns & squares_in_front_of(us, s)))
335 Value mv = Value(0), ev = Value(0);
338 mv -= IsolatedPawnMidgamePenalty[f];
339 ev -= IsolatedPawnEndgamePenalty[f];
340 if (pos.file_is_half_open(them, f))
342 mv -= IsolatedPawnMidgamePenalty[f] / 2;
343 ev -= IsolatedPawnEndgamePenalty[f] / 2;
348 mv -= DoubledPawnMidgamePenalty[f];
349 ev -= DoubledPawnEndgamePenalty[f];
353 mv -= BackwardPawnMidgamePenalty[f];
354 ev -= BackwardPawnEndgamePenalty[f];
355 if (pos.file_is_half_open(them, f))
357 mv -= BackwardPawnMidgamePenalty[f] / 2;
358 ev -= BackwardPawnEndgamePenalty[f] / 2;
363 mv += ChainMidgameBonus[f];
364 ev += ChainEndgameBonus[f];
368 mv += CandidateMidgameBonus[relative_rank(us, s)];
369 ev += CandidateEndgameBonus[relative_rank(us, s)];
375 // If the pawn is passed, set the square of the pawn in the passedPawns
378 set_bit(&(pi->passedPawns), s);
382 pi->mgValue = int16_t(mgValue[WHITE] - mgValue[BLACK]);
383 pi->egValue = int16_t(egValue[WHITE] - egValue[BLACK]);