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/>.
32 //// Local definitions
37 /// Constants and variables
39 // Doubled pawn penalty by file, middle game.
40 const Value DoubledPawnMidgamePenalty[8] = {
41 Value(20), Value(30), Value(34), Value(34),
42 Value(34), Value(34), Value(30), Value(20)
45 // Doubled pawn penalty by file, endgame.
46 const Value DoubledPawnEndgamePenalty[8] = {
47 Value(35), Value(40), Value(40), Value(40),
48 Value(40), Value(40), Value(40), Value(35)
51 // Isolated pawn penalty by file, middle game.
52 const Value IsolatedPawnMidgamePenalty[8] = {
53 Value(20), Value(30), Value(34), Value(34),
54 Value(34), Value(34), Value(30), Value(20)
57 // Isolated pawn penalty by file, endgame.
58 const Value IsolatedPawnEndgamePenalty[8] = {
59 Value(35), Value(40), Value(40), Value(40),
60 Value(40), Value(40), Value(40), Value(35)
63 // Backward pawn penalty by file, middle game.
64 const Value BackwardPawnMidgamePenalty[8] = {
65 Value(16), Value(24), Value(27), Value(27),
66 Value(27), Value(27), Value(24), Value(16)
69 // Backward pawn penalty by file, endgame.
70 const Value BackwardPawnEndgamePenalty[8] = {
71 Value(28), Value(32), Value(32), Value(32),
72 Value(32), Value(32), Value(32), Value(28)
75 // Pawn chain membership bonus by file, middle game.
76 const Value ChainMidgameBonus[8] = {
77 Value(14), Value(16), Value(17), Value(18),
78 Value(18), Value(17), Value(16), Value(14)
81 // Pawn chain membership bonus by file, endgame.
82 const Value ChainEndgameBonus[8] = {
83 Value(16), Value(16), Value(16), Value(16),
84 Value(16), Value(16), Value(16), Value(16)
87 // Candidate passed pawn bonus by rank, middle game.
88 const Value CandidateMidgameBonus[8] = {
89 Value( 0), Value(12), Value(12), Value(20),
90 Value(40), Value(90), Value( 0), Value( 0)
93 // Candidate passed pawn bonus by rank, endgame.
94 const Value CandidateEndgameBonus[8] = {
95 Value( 0), Value(24), Value(24), Value(40),
96 Value(80), Value(180), Value(0), Value( 0)
99 // Pawn storm tables for positions with opposite castling:
100 const int QStormTable[64] = {
101 0, 0, 0, 0, 0, 0, 0, 0,
102 -22,-22,-22,-13,-4, 0, 0, 0,
103 -4, -9, -9, -9,-4, 0, 0, 0,
104 9, 18, 22, 18, 9, 0, 0, 0,
105 22, 31, 31, 22, 0, 0, 0, 0,
106 31, 40, 40, 31, 0, 0, 0, 0,
107 31, 40, 40, 31, 0, 0, 0, 0,
108 0, 0, 0, 0, 0, 0, 0, 0
111 const int KStormTable[64] = {
112 0, 0, 0, 0, 0, 0, 0, 0,
113 0, 0, 0,-4,-13,-22,-27,-27,
114 0, 0, 0,-4, -9,-13,-18,-18,
115 0, 0, 0, 0, 9, 9, 9, 9,
116 0, 0, 0, 0, 9, 18, 27, 27,
117 0, 0, 0, 0, 9, 27, 40, 36,
118 0, 0, 0, 0, 0, 31, 40, 31,
119 0, 0, 0, 0, 0, 0, 0, 0
122 // Pawn storm open file bonuses by file:
123 const int KStormOpenFileBonus[8] = {
124 45, 45, 30, 0, 0, 0, 0, 0
127 const int QStormOpenFileBonus[8] = {
128 0, 0, 0, 0, 0, 30, 45, 30
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;
156 PawnInfoTable::~PawnInfoTable() {
161 /// PawnInfoTable::clear() clears the pawn hash table by setting all
164 void PawnInfoTable::clear() {
165 memset(entries, 0, size * sizeof(PawnInfo));
169 /// PawnInfoTable::get_pawn_info() takes a position object as input, computes
170 /// a PawnInfo object, and returns a pointer to it. The result is also
171 /// stored in a hash table, so we don't have to recompute everything when
172 /// the same pawn structure occurs again.
174 PawnInfo *PawnInfoTable::get_pawn_info(const Position &pos) {
178 Key key = pos.get_pawn_key();
179 int index = int(key & (size - 1));
180 PawnInfo *pi = entries + index;
182 // If pi->key matches the position's pawn hash key, it means that we
183 // have analysed this pawn structure before, and we can simply return the
184 // information we found the last time instead of recomputing it
188 // Clear the PawnInfo object, and set the key
192 Value mgValue[2] = {Value(0), Value(0)};
193 Value egValue[2] = {Value(0), Value(0)};
195 // Loop through the pawns for both colors
196 for (Color us = WHITE; us <= BLACK; us++)
198 Color them = opposite_color(us);
199 Bitboard ourPawns = pos.pawns(us);
200 Bitboard theirPawns = pos.pawns(them);
201 Bitboard pawns = ourPawns;
203 // Initialize pawn storm scores by giving bonuses for open files
204 for (File f = FILE_A; f <= FILE_H; f++)
205 if (pos.file_is_half_open(us, f))
207 pi->ksStormValue[us] += KStormOpenFileBonus[f];
208 pi->qsStormValue[us] += QStormOpenFileBonus[f];
211 // Loop through all pawns of the current color and score each pawn
214 bool passed, doubled, isolated, backward, chain, candidate;
215 Square s = pop_1st_bit(&pawns);
216 File f = square_file(s);
217 Rank r = square_rank(s);
219 assert(pos.piece_on(s) == piece_of_color_and_type(us, PAWN));
221 // The file containing the pawn is not half open
222 pi->halfOpenFiles[us] &= ~(1 << f);
224 // Passed, isolated or doubled pawn?
225 passed = pos.pawn_is_passed(us, s);
226 isolated = pos.pawn_is_isolated(us, s);
227 doubled = pos.pawn_is_doubled(us, s);
229 // We calculate kingside and queenside pawn storm scores
230 // for both colors. These are used when evaluating middle
231 // game positions with opposite side castling.
233 // Each pawn is given a base score given by a piece square table
234 // (KStormTable[] or QStormTable[]). This score is increased if
235 // there are enemy pawns on adjacent files in front of the pawn.
236 // This is because we want to be able to open files against the
237 // enemy king, and to avoid blocking the pawn structure (e.g. white
238 // pawns on h6, g5, black pawns on h7, g6, f7).
240 // Kingside and queenside pawn storms
241 int KBonus = KStormTable[relative_square(us, s)];
242 int QBonus = QStormTable[relative_square(us, s)];
243 bool outPostFlag = (KBonus > 0 && (outpost_mask(us, s) & theirPawns));
244 bool passedFlag = (QBonus > 0 && (passed_pawn_mask(us, s) & theirPawns));
249 QBonus += passedFlag * QBonus / 2;
253 QBonus += passedFlag * (QBonus / 2 + QBonus / 4);
257 QBonus += passedFlag * QBonus / 2;
261 KBonus += outPostFlag * KBonus / 4;
265 KBonus += outPostFlag * (KBonus / 2 + KBonus / 4);
269 KBonus += outPostFlag * KBonus / 2;
275 pi->ksStormValue[us] += KBonus;
276 pi->qsStormValue[us] += QBonus;
278 // Member of a pawn chain (but not the backward one)? We could speed up
279 // the test a little by introducing an array of masks indexed by color
280 // and square for doing the test, but because everything is hashed,
281 // it probably won't make any noticable difference.
283 & neighboring_files_bb(f)
284 & (rank_bb(r) | rank_bb(r - (us == WHITE ? 1 : -1)));
286 // Test for backward pawn
288 // If the pawn is passed, isolated, or member of a pawn chain
289 // it cannot be backward. If can capture an enemy pawn or if
290 // there are friendly pawns behind on neighboring files it cannot
291 // be backward either.
295 || (pos.pawn_attacks(us, s) & theirPawns)
296 || (ourPawns & behind_bb(us, r) & neighboring_files_bb(f)))
300 // We now know that there are no friendly pawns beside or behind this
301 // pawn on neighboring files. We now check whether the pawn is
302 // backward by looking in the forward direction on the neighboring
303 // files, and seeing whether we meet a friendly or an enemy pawn first.
307 for (b = pos.pawn_attacks(us, s); !(b & (ourPawns | theirPawns)); b <<= 8);
308 backward = (b | (b << 8)) & theirPawns;
312 for (b = pos.pawn_attacks(us, s); !(b & (ourPawns | theirPawns)); b >>= 8);
313 backward = (b | (b >> 8)) & theirPawns;
317 // Test for candidate passed pawn
319 && pos.file_is_half_open(them, f)
320 && ( count_1s_max_15(neighboring_files_bb(f) & (behind_bb(us, r) | rank_bb(r)) & ourPawns)
321 - count_1s_max_15(neighboring_files_bb(f) & in_front_bb(us, r) & theirPawns)
324 // In order to prevent doubled passed pawns from receiving a too big
325 // bonus, only the frontmost passed pawn on each file is considered as
326 // a true passed pawn.
327 if (passed && (ourPawns & squares_in_front_of(us, s)))
334 Value mv = Value(0), ev = Value(0);
337 mv -= IsolatedPawnMidgamePenalty[f];
338 ev -= IsolatedPawnEndgamePenalty[f];
339 if (pos.file_is_half_open(them, f))
341 mv -= IsolatedPawnMidgamePenalty[f] / 2;
342 ev -= IsolatedPawnEndgamePenalty[f] / 2;
347 mv -= DoubledPawnMidgamePenalty[f];
348 ev -= DoubledPawnEndgamePenalty[f];
352 mv -= BackwardPawnMidgamePenalty[f];
353 ev -= BackwardPawnEndgamePenalty[f];
354 if (pos.file_is_half_open(them, f))
356 mv -= BackwardPawnMidgamePenalty[f] / 2;
357 ev -= BackwardPawnEndgamePenalty[f] / 2;
362 mv += ChainMidgameBonus[f];
363 ev += ChainEndgameBonus[f];
367 mv += CandidateMidgameBonus[relative_rank(us, s)];
368 ev += CandidateEndgameBonus[relative_rank(us, s)];
374 // If the pawn is passed, set the square of the pawn in the passedPawns
377 set_bit(&(pi->passedPawns), s);
381 pi->mgValue = int16_t(mgValue[WHITE] - mgValue[BLACK]);
382 pi->egValue = int16_t(egValue[WHITE] - egValue[BLACK]);