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/>.
33 //// Local definitions
38 /// Constants and variables
40 // Doubled pawn penalty by file, middle game.
41 const Value DoubledPawnMidgamePenalty[8] = {
42 Value(13), Value(20), Value(23), Value(23),
43 Value(23), Value(23), Value(20), Value(13)
46 // Doubled pawn penalty by file, endgame.
47 const Value DoubledPawnEndgamePenalty[8] = {
48 Value(43), Value(48), Value(48), Value(48),
49 Value(48), Value(48), Value(48), Value(43)
52 // Isolated pawn penalty by file, middle game.
53 const Value IsolatedPawnMidgamePenalty[8] = {
54 Value(25), Value(36), Value(40), Value(40),
55 Value(40), Value(40), Value(36), Value(25)
58 // Isolated pawn penalty by file, endgame.
59 const Value IsolatedPawnEndgamePenalty[8] = {
60 Value(30), Value(35), Value(35), Value(35),
61 Value(35), Value(35), Value(35), Value(30)
64 // Backward pawn penalty by file, middle game.
65 const Value BackwardPawnMidgamePenalty[8] = {
66 Value(20), Value(29), Value(33), Value(33),
67 Value(33), Value(33), Value(29), Value(20)
70 // Backward pawn penalty by file, endgame.
71 const Value BackwardPawnEndgamePenalty[8] = {
72 Value(28), Value(31), Value(31), Value(31),
73 Value(31), Value(31), Value(31), Value(28)
76 // Pawn chain membership bonus by file, middle game.
77 const Value ChainMidgameBonus[8] = {
78 Value(11), Value(13), Value(13), Value(14),
79 Value(14), Value(13), Value(13), Value(11)
82 // Pawn chain membership bonus by file, endgame.
83 const Value ChainEndgameBonus[8] = {
84 Value(-1), Value(-1), Value(-1), Value(-1),
85 Value(-1), Value(-1), Value(-1), Value(-1)
88 // Candidate passed pawn bonus by rank, middle game.
89 const Value CandidateMidgameBonus[8] = {
90 Value( 0), Value( 6), Value(6), Value(14),
91 Value(34), Value(83), Value(0), Value( 0)
94 // Candidate passed pawn bonus by rank, endgame.
95 const Value CandidateEndgameBonus[8] = {
96 Value( 0), Value( 13), Value(13), Value(29),
97 Value(68), Value(166), 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,-14,-6, 0, 0, 0,
104 -6,-10,-10,-10,-6, 0, 0, 0,
105 4, 12, 16, 12, 4, 0, 0, 0,
106 16, 23, 23, 16, 0, 0, 0, 0,
107 23, 31, 31, 23, 0, 0, 0, 0,
108 23, 31, 31, 23, 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,-10,-19,-28,-33,-33,
115 0, 0, 0,-10,-15,-19,-24,-24,
116 0, 0, 0, 0, 1, 1, 1, 1,
117 0, 0, 0, 0, 1, 10, 19, 19,
118 0, 0, 0, 0, 1, 19, 31, 27,
119 0, 0, 0, 0, 0, 22, 31, 22,
120 0, 0, 0, 0, 0, 0, 0, 0
123 // Pawn storm open file bonuses by file
124 const int16_t KStormOpenFileBonus[8] = { 31, 31, 18, 0, 0, 0, 0, 0 };
125 const int16_t QStormOpenFileBonus[8] = { 0, 0, 0, 0, 0, 26, 42, 26 };
127 // Pawn storm lever bonuses by file
128 const int StormLeverBonus[8] = { -8, -8, -13, 0, 0, -13, -8, -8 };
139 PawnInfoTable::PawnInfoTable(unsigned numOfEntries) {
142 entries = new PawnInfo[size];
145 std::cerr << "Failed to allocate " << (numOfEntries * sizeof(PawnInfo))
146 << " bytes for pawn hash table." << std::endl;
147 Application::exit_with_failure();
154 PawnInfoTable::~PawnInfoTable() {
159 /// PawnInfoTable::get_pawn_info() takes a position object as input, computes
160 /// a PawnInfo object, and returns a pointer to it. The result is also
161 /// stored in a hash table, so we don't have to recompute everything when
162 /// the same pawn structure occurs again.
164 PawnInfo *PawnInfoTable::get_pawn_info(const Position &pos) {
168 Key key = pos.get_pawn_key();
169 int index = int(key & (size - 1));
170 PawnInfo *pi = entries + index;
172 // If pi->key matches the position's pawn hash key, it means that we
173 // have analysed this pawn structure before, and we can simply return the
174 // information we found the last time instead of recomputing it
178 // Clear the PawnInfo object, and set the key
182 Value mgValue[2] = {Value(0), Value(0)};
183 Value egValue[2] = {Value(0), Value(0)};
185 // Loop through the pawns for both colors
186 for (Color us = WHITE; us <= BLACK; us++)
188 Color them = opposite_color(us);
189 Bitboard ourPawns = pos.pawns(us);
190 Bitboard theirPawns = pos.pawns(them);
191 Bitboard pawns = ourPawns;
194 // Initialize pawn storm scores by giving bonuses for open files
195 for (File f = FILE_A; f <= FILE_H; f++)
196 if (Position::file_is_half_open(ourPawns, f))
198 pi->ksStormValue[us] += KStormOpenFileBonus[f];
199 pi->qsStormValue[us] += QStormOpenFileBonus[f];
202 // Loop through all pawns of the current color and score each pawn
205 bool passed, doubled, isolated, backward, chain, candidate;
206 Square s = pop_1st_bit(&pawns);
207 File f = square_file(s);
208 Rank r = square_rank(s);
210 assert(pos.piece_on(s) == piece_of_color_and_type(us, PAWN));
212 // The file containing the pawn is not half open
213 pi->halfOpenFiles[us] &= ~(1 << f);
215 // Passed, isolated or doubled pawn?
216 passed = Position::pawn_is_passed(theirPawns, us, s);
217 isolated = Position::pawn_is_isolated(ourPawns, s);
218 doubled = Position::pawn_is_doubled(ourPawns, us, s);
220 // We calculate kingside and queenside pawn storm
221 // scores for both colors. These are used when evaluating
222 // middle game positions with opposite side castling.
224 // Each pawn is given a base score given by a piece square table
225 // (KStormTable[] or QStormTable[]). Pawns which seem to have good
226 // chances of creating an open file by exchanging itself against an
227 // enemy pawn on an adjacent file gets an additional bonus.
229 // Kingside pawn storms
230 bonus = KStormTable[relative_square(us, s)];
233 Bitboard b = outpost_mask(us, s) & theirPawns & (FileFBB | FileGBB | FileHBB);
236 Square s2 = pop_1st_bit(&b);
237 if (!(theirPawns & neighboring_files_bb(s2) & rank_bb(s2)))
239 // The enemy pawn has no pawn beside itself, which makes it
240 // particularly vulnerable. Big bonus, especially against a
241 // weakness on the rook file.
242 if (square_file(s2) == FILE_H)
243 bonus += 4*StormLeverBonus[f] - 8*square_distance(s, s2);
245 bonus += 2*StormLeverBonus[f] - 4*square_distance(s, s2);
247 // There is at least one enemy pawn beside the enemy pawn we look
248 // at, which means that the pawn has somewhat better chances of
249 // defending itself by advancing. Smaller bonus.
250 bonus += StormLeverBonus[f] - 2*square_distance(s, s2);
253 pi->ksStormValue[us] += bonus;
255 // Queenside pawn storms
256 bonus = QStormTable[relative_square(us, s)];
259 Bitboard b = outpost_mask(us, s) & theirPawns & (FileABB | FileBBB | FileCBB);
262 Square s2 = pop_1st_bit(&b);
263 if (!(theirPawns & neighboring_files_bb(s2) & rank_bb(s2)))
265 // The enemy pawn has no pawn beside itself, which makes it
266 // particularly vulnerable. Big bonus, especially against a
267 // weakness on the rook file.
268 if (square_file(s2) == FILE_A)
269 bonus += 4*StormLeverBonus[f] - 16*square_distance(s, s2);
271 bonus += 2*StormLeverBonus[f] - 8*square_distance(s, s2);
273 // There is at least one enemy pawn beside the enemy pawn we look
274 // at, which means that the pawn has somewhat better chances of
275 // defending itself by advancing. Smaller bonus.
276 bonus += StormLeverBonus[f] - 4*square_distance(s, s2);
279 pi->qsStormValue[us] += bonus;
281 // Member of a pawn chain (but not the backward one)? We could speed up
282 // the test a little by introducing an array of masks indexed by color
283 // and square for doing the test, but because everything is hashed,
284 // it probably won't make any noticable difference.
286 & neighboring_files_bb(f)
287 & (rank_bb(r) | rank_bb(r - (us == WHITE ? 1 : -1)));
289 // Test for backward pawn
291 // If the pawn is passed, isolated, or member of a pawn chain
292 // it cannot be backward. If can capture an enemy pawn or if
293 // there are friendly pawns behind on neighboring files it cannot
294 // be backward either.
298 || (pos.pawn_attacks(us, s) & theirPawns)
299 || (ourPawns & behind_bb(us, r) & neighboring_files_bb(f)))
303 // We now know that there are no friendly pawns beside or behind this
304 // pawn on neighboring files. We now check whether the pawn is
305 // backward by looking in the forward direction on the neighboring
306 // files, and seeing whether we meet a friendly or an enemy pawn first.
310 for (b = pos.pawn_attacks(us, s); !(b & (ourPawns | theirPawns)); b <<= 8);
311 backward = (b | (b << 8)) & theirPawns;
315 for (b = pos.pawn_attacks(us, s); !(b & (ourPawns | theirPawns)); b >>= 8);
316 backward = (b | (b >> 8)) & theirPawns;
320 // Test for candidate passed pawn
322 && Position::file_is_half_open(theirPawns, f)
323 && ( count_1s_max_15(neighboring_files_bb(f) & (behind_bb(us, r) | rank_bb(r)) & ourPawns)
324 - count_1s_max_15(neighboring_files_bb(f) & in_front_bb(us, r) & theirPawns)
327 // In order to prevent doubled passed pawns from receiving a too big
328 // bonus, only the frontmost passed pawn on each file is considered as
329 // a true passed pawn.
330 if (passed && (ourPawns & squares_in_front_of(us, s)))
337 Value mv = Value(0), ev = Value(0);
340 mv -= IsolatedPawnMidgamePenalty[f];
341 ev -= IsolatedPawnEndgamePenalty[f];
342 if (Position::file_is_half_open(theirPawns, f))
344 mv -= IsolatedPawnMidgamePenalty[f] / 2;
345 ev -= IsolatedPawnEndgamePenalty[f] / 2;
350 mv -= DoubledPawnMidgamePenalty[f];
351 ev -= DoubledPawnEndgamePenalty[f];
355 mv -= BackwardPawnMidgamePenalty[f];
356 ev -= BackwardPawnEndgamePenalty[f];
357 if (Position::file_is_half_open(theirPawns, f))
359 mv -= BackwardPawnMidgamePenalty[f] / 2;
360 ev -= BackwardPawnEndgamePenalty[f] / 2;
365 mv += ChainMidgameBonus[f];
366 ev += ChainEndgameBonus[f];
370 mv += CandidateMidgameBonus[relative_rank(us, s)];
371 ev += CandidateEndgameBonus[relative_rank(us, s)];
377 // If the pawn is passed, set the square of the pawn in the passedPawns
380 set_bit(&(pi->passedPawns), s);
384 pi->mgValue = int16_t(mgValue[WHITE] - mgValue[BLACK]);
385 pi->egValue = int16_t(egValue[WHITE] - egValue[BLACK]);