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 // Evaluate pawn storms?
100 const bool EvaluatePawnStorms = true;
102 // Pawn storm tables for positions with opposite castling:
103 const int QStormTable[64] = {
104 0, 0, 0, 0, 0, 0, 0, 0,
105 -22,-22,-22,-13,-4, 0, 0, 0,
106 -4, -9, -9, -9,-4, 0, 0, 0,
107 9, 18, 22, 18, 9, 0, 0, 0,
108 22, 31, 31, 22, 0, 0, 0, 0,
109 31, 40, 40, 31, 0, 0, 0, 0,
110 31, 40, 40, 31, 0, 0, 0, 0,
111 0, 0, 0, 0, 0, 0, 0, 0
114 const int KStormTable[64] = {
115 0, 0, 0, 0, 0, 0, 0, 0,
116 0, 0, 0,-4,-13,-22,-27,-27,
117 0, 0, 0,-4, -9,-13,-18,-18,
118 0, 0, 0, 0, 9, 9, 9, 9,
119 0, 0, 0, 0, 9, 18, 27, 27,
120 0, 0, 0, 0, 9, 27, 40, 36,
121 0, 0, 0, 0, 0, 31, 40, 31,
122 0, 0, 0, 0, 0, 0, 0, 0
125 // Pawn storm open file bonuses by file:
126 const int KStormOpenFileBonus[8] = {
127 45, 45, 30, 0, 0, 0, 0, 0
130 const int QStormOpenFileBonus[8] = {
131 0, 0, 0, 0, 0, 30, 45, 30
143 PawnInfoTable::PawnInfoTable(unsigned numOfEntries) {
146 entries = new PawnInfo[size];
149 std::cerr << "Failed to allocate " << (numOfEntries * sizeof(PawnInfo))
150 << " bytes for pawn hash table." << std::endl;
159 PawnInfoTable::~PawnInfoTable() {
164 /// PawnInfoTable::clear() clears the pawn hash table by setting all
167 void PawnInfoTable::clear() {
168 memset(entries, 0, size * sizeof(PawnInfo));
172 /// PawnInfoTable::get_pawn_info() takes a position object as input, computes
173 /// a PawnInfo object, and returns a pointer to it. The result is also
174 /// stored in a hash table, so we don't have to recompute everything when
175 /// the same pawn structure occurs again.
177 PawnInfo *PawnInfoTable::get_pawn_info(const Position &pos) {
181 Key key = pos.get_pawn_key();
182 int index = int(key & (size - 1));
183 PawnInfo *pi = entries + index;
185 // If pi->key matches the position's pawn hash key, it means that we
186 // have analysed this pawn structure before, and we can simply return the
187 // information we found the last time instead of recomputing it
191 // Clear the PawnInfo object, and set the key
195 Value mgValue[2] = {Value(0), Value(0)};
196 Value egValue[2] = {Value(0), Value(0)};
198 // Loop through the pawns for both colors
199 for (Color us = WHITE; us <= BLACK; us++)
201 Color them = opposite_color(us);
202 Bitboard ourPawns = pos.pawns(us);
203 Bitboard theirPawns = pos.pawns(them);
204 Bitboard pawns = ourPawns;
206 // Initialize pawn storm scores by giving bonuses for open files
207 if (EvaluatePawnStorms)
208 for(File f = FILE_A; f <= FILE_H; f++)
209 if(pos.file_is_half_open(us, f))
211 pi->ksStormValue[us] += KStormOpenFileBonus[f];
212 pi->qsStormValue[us] += QStormOpenFileBonus[f];
215 // Loop through all pawns of the current color and score each pawn
218 bool passed, doubled, isolated, backward, chain, candidate;
219 Square s = pop_1st_bit(&pawns);
220 File f = square_file(s);
221 Rank r = square_rank(s);
223 assert(pos.piece_on(s) == pawn_of_color(us));
225 // The file containing the pawn is not half open
226 pi->halfOpenFiles[us] &= ~(1 << f);
228 // Passed, isolated or doubled pawn?
229 passed = pos.pawn_is_passed(us, s);
230 isolated = pos.pawn_is_isolated(us, s);
231 doubled = pos.pawn_is_doubled(us, s);
233 if (EvaluatePawnStorms)
235 // We calculate kingside and queenside pawn storm scores
236 // for both colors. These are used when evaluating middle
237 // game positions with opposite side castling.
239 // Each pawn is given a base score given by a piece square table
240 // (KStormTable[] or QStormTable[]). This score is increased if
241 // there are enemy pawns on adjacent files in front of the pawn.
242 // This is because we want to be able to open files against the
243 // enemy king, and to avoid blocking the pawn structure (e.g. white
244 // pawns on h6, g5, black pawns on h7, g6, f7).
246 // Kingside and queenside pawn storms
247 bool outPost = (outpost_mask(us, s) & theirPawns);
248 bool passed = (passed_pawn_mask(us, s) & theirPawns);
249 int KBonus = KStormTable[relative_square(us, s)];
250 int QBonus = QStormTable[relative_square(us, s)];
255 QBonus += passed * QBonus / 4;
259 QBonus += passed * (QBonus / 2 + QBonus / 4);
263 QBonus += passed * QBonus / 2;
267 KBonus += outPost * KBonus / 4;
271 KBonus += outPost * (KBonus / 2 + KBonus / 4);
275 KBonus += outPost * KBonus / 2;
281 pi->ksStormValue[us] += KBonus;
282 pi->qsStormValue[us] += QBonus;
285 // Member of a pawn chain (but not the backward one)? We could speed up
286 // the test a little by introducing an array of masks indexed by color
287 // and square for doing the test, but because everything is hashed,
288 // it probably won't make any noticable difference.
290 & neighboring_files_bb(f)
291 & (rank_bb(r) | rank_bb(r - (us == WHITE ? 1 : -1)));
293 // Test for backward pawn
295 // If the pawn is passed, isolated, or member of a pawn chain
296 // it cannot be backward. If can capture an enemy pawn or if
297 // there are friendly pawns behind on neighboring files it cannot
298 // be backward either.
302 || (pos.pawn_attacks(us, s) & theirPawns)
303 || (ourPawns & behind_bb(us, r) & neighboring_files_bb(f)))
307 // We now know that there are no friendly pawns beside or behind this
308 // pawn on neighboring files. We now check whether the pawn is
309 // backward by looking in the forward direction on the neighboring
310 // files, and seeing whether we meet a friendly or an enemy pawn first.
314 for (b = pos.pawn_attacks(us, s); !(b & (ourPawns | theirPawns)); b <<= 8);
315 backward = (b | (b << 8)) & theirPawns;
319 for (b = pos.pawn_attacks(us, s); !(b & (ourPawns | theirPawns)); b >>= 8);
320 backward = (b | (b >> 8)) & theirPawns;
324 // Test for candidate passed pawn
326 && pos.file_is_half_open(them, f)
327 && ( count_1s_max_15(neighboring_files_bb(f) & (behind_bb(us, r) | rank_bb(r)) & ourPawns)
328 - count_1s_max_15(neighboring_files_bb(f) & in_front_bb(us, r) & theirPawns)
331 // In order to prevent doubled passed pawns from receiving a too big
332 // bonus, only the frontmost passed pawn on each file is considered as
333 // a true passed pawn.
334 if (passed && (ourPawns & squares_in_front_of(us, s)))
341 Value mv = Value(0), ev = Value(0);
344 mv -= IsolatedPawnMidgamePenalty[f];
345 ev -= IsolatedPawnEndgamePenalty[f];
346 if (pos.file_is_half_open(them, f))
348 mv -= IsolatedPawnMidgamePenalty[f] / 2;
349 ev -= IsolatedPawnEndgamePenalty[f] / 2;
354 mv -= DoubledPawnMidgamePenalty[f];
355 ev -= DoubledPawnEndgamePenalty[f];
359 mv -= BackwardPawnMidgamePenalty[f];
360 ev -= BackwardPawnEndgamePenalty[f];
361 if (pos.file_is_half_open(them, f))
363 mv -= BackwardPawnMidgamePenalty[f] / 2;
364 ev -= BackwardPawnEndgamePenalty[f] / 2;
369 mv += ChainMidgameBonus[f];
370 ev += ChainEndgameBonus[f];
374 mv += CandidateMidgameBonus[relative_rank(us, s)];
375 ev += CandidateEndgameBonus[relative_rank(us, s)];
381 // If the pawn is passed, set the square of the pawn in the passedPawns
384 set_bit(&(pi->passedPawns), s);
388 pi->mgValue = int16_t(mgValue[WHITE] - mgValue[BLACK]);
389 pi->egValue = int16_t(egValue[WHITE] - egValue[BLACK]);