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(20), Value(30), Value(34), Value(34),
44 Value(34), Value(34), Value(30), Value(20)
47 // Doubled pawn penalty by file, endgame.
48 const Value DoubledPawnEndgamePenalty[8] = {
49 Value(35), Value(40), Value(40), Value(40),
50 Value(40), Value(40), Value(40), Value(35)
53 // Isolated pawn penalty by file, middle game.
54 const Value IsolatedPawnMidgamePenalty[8] = {
55 Value(20), Value(30), Value(34), Value(34),
56 Value(34), Value(34), Value(30), Value(20)
59 // Isolated pawn penalty by file, endgame.
60 const Value IsolatedPawnEndgamePenalty[8] = {
61 Value(35), Value(40), Value(40), Value(40),
62 Value(40), Value(40), Value(40), Value(35)
65 // Backward pawn penalty by file, middle game.
66 const Value BackwardPawnMidgamePenalty[8] = {
67 Value(16), Value(24), Value(27), Value(27),
68 Value(27), Value(27), Value(24), Value(16)
71 // Backward pawn penalty by file, endgame.
72 const Value BackwardPawnEndgamePenalty[8] = {
73 Value(28), Value(32), Value(32), Value(32),
74 Value(32), Value(32), Value(32), Value(28)
77 // Pawn chain membership bonus by file, middle game.
78 const Value ChainMidgameBonus[8] = {
79 Value(14), Value(16), Value(17), Value(18),
80 Value(18), Value(17), Value(16), Value(14)
83 // Pawn chain membership bonus by file, endgame.
84 const Value ChainEndgameBonus[8] = {
85 Value(16), Value(16), Value(16), Value(16),
86 Value(16), Value(16), Value(16), Value(16)
89 // Candidate passed pawn bonus by rank, middle game.
90 const Value CandidateMidgameBonus[8] = {
91 Value( 0), Value(12), Value(12), Value(20),
92 Value(40), Value(90), Value( 0), Value( 0)
95 // Candidate passed pawn bonus by rank, endgame.
96 const Value CandidateEndgameBonus[8] = {
97 Value( 0), Value(24), Value(24), Value(40),
98 Value(80), Value(180), 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,-13,-4, 0, 0, 0,
105 -4, -9, -9, -9,-4, 0, 0, 0,
106 9, 18, 22, 18, 9, 0, 0, 0,
107 22, 31, 31, 22, 0, 0, 0, 0,
108 31, 40, 40, 31, 0, 0, 0, 0,
109 31, 40, 40, 31, 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,-4,-13,-22,-27,-27,
116 0, 0, 0,-4, -9,-13,-18,-18,
117 0, 0, 0, 0, 9, 9, 9, 9,
118 0, 0, 0, 0, 9, 18, 27, 27,
119 0, 0, 0, 0, 9, 27, 40, 36,
120 0, 0, 0, 0, 0, 31, 40, 31,
121 0, 0, 0, 0, 0, 0, 0, 0
124 // Pawn storm open file bonuses by file
125 const int16_t KStormOpenFileBonus[8] = { 45, 45, 30, 0, 0, 0, 0, 0 };
126 const int16_t QStormOpenFileBonus[8] = { 0, 0, 0, 0, 0, 30, 45, 30 };
128 // Pawn storm lever bonuses by file
129 const int StormLeverBonus[8] = { 20, 20, 10, 0, 0, 10, 20, 20 };
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();
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;
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
231 // scores for both colors. These are used when evaluating
232 // middle game positions with opposite side castling.
234 // Each pawn is given a base score given by a piece square table
235 // (KStormTable[] or QStormTable[]). Pawns which seem to have good
236 // chances of creating an open file by exchanging itself against an
237 // enemy pawn on an adjacent file gets an additional bonus.
239 // Kingside pawn storms
240 bonus = KStormTable[relative_square(us, s)];
243 Bitboard b = outpost_mask(us, s) & theirPawns & (FileFBB | FileGBB | FileHBB);
246 Square s2 = pop_1st_bit(&b);
247 if (!(theirPawns & neighboring_files_bb(s2) & rank_bb(s2)))
249 // The enemy pawn has no pawn beside itself, which makes it
250 // particularly vulnerable. Big bonus, especially against a
251 // weakness on the rook file.
252 if (square_file(s2) == FILE_H)
253 bonus += 4*StormLeverBonus[f] - 8*square_distance(s, s2);
255 bonus += 2*StormLeverBonus[f] - 4*square_distance(s, s2);
257 // There is at least one enemy pawn beside the enemy pawn we look
258 // at, which means that the pawn has somewhat better chances of
259 // defending itself by advancing. Smaller bonus.
260 bonus += StormLeverBonus[f] - 2*square_distance(s, s2);
263 pi->ksStormValue[us] += bonus;
265 // Queenside pawn storms
266 bonus = QStormTable[relative_square(us, s)];
269 Bitboard b = outpost_mask(us, s) & theirPawns & (FileABB | FileBBB | FileCBB);
272 Square s2 = pop_1st_bit(&b);
273 if (!(theirPawns & neighboring_files_bb(s2) & rank_bb(s2)))
275 // The enemy pawn has no pawn beside itself, which makes it
276 // particularly vulnerable. Big bonus, especially against a
277 // weakness on the rook file.
278 if (square_file(s2) == FILE_A)
279 bonus += 4*StormLeverBonus[f] - 16*square_distance(s, s2);
281 bonus += 2*StormLeverBonus[f] - 8*square_distance(s, s2);
283 // There is at least one enemy pawn beside the enemy pawn we look
284 // at, which means that the pawn has somewhat better chances of
285 // defending itself by advancing. Smaller bonus.
286 bonus += StormLeverBonus[f] - 4*square_distance(s, s2);
289 pi->qsStormValue[us] += bonus;
291 // Member of a pawn chain (but not the backward one)? We could speed up
292 // the test a little by introducing an array of masks indexed by color
293 // and square for doing the test, but because everything is hashed,
294 // it probably won't make any noticable difference.
296 & neighboring_files_bb(f)
297 & (rank_bb(r) | rank_bb(r - (us == WHITE ? 1 : -1)));
299 // Test for backward pawn
301 // If the pawn is passed, isolated, or member of a pawn chain
302 // it cannot be backward. If can capture an enemy pawn or if
303 // there are friendly pawns behind on neighboring files it cannot
304 // be backward either.
308 || (pos.pawn_attacks(us, s) & theirPawns)
309 || (ourPawns & behind_bb(us, r) & neighboring_files_bb(f)))
313 // We now know that there are no friendly pawns beside or behind this
314 // pawn on neighboring files. We now check whether the pawn is
315 // backward by looking in the forward direction on the neighboring
316 // files, and seeing whether we meet a friendly or an enemy pawn first.
320 for (b = pos.pawn_attacks(us, s); !(b & (ourPawns | theirPawns)); b <<= 8);
321 backward = (b | (b << 8)) & theirPawns;
325 for (b = pos.pawn_attacks(us, s); !(b & (ourPawns | theirPawns)); b >>= 8);
326 backward = (b | (b >> 8)) & theirPawns;
330 // Test for candidate passed pawn
332 && pos.file_is_half_open(them, f)
333 && ( count_1s_max_15(neighboring_files_bb(f) & (behind_bb(us, r) | rank_bb(r)) & ourPawns)
334 - count_1s_max_15(neighboring_files_bb(f) & in_front_bb(us, r) & theirPawns)
337 // In order to prevent doubled passed pawns from receiving a too big
338 // bonus, only the frontmost passed pawn on each file is considered as
339 // a true passed pawn.
340 if (passed && (ourPawns & squares_in_front_of(us, s)))
347 Value mv = Value(0), ev = Value(0);
350 mv -= IsolatedPawnMidgamePenalty[f];
351 ev -= IsolatedPawnEndgamePenalty[f];
352 if (pos.file_is_half_open(them, f))
354 mv -= IsolatedPawnMidgamePenalty[f] / 2;
355 ev -= IsolatedPawnEndgamePenalty[f] / 2;
360 mv -= DoubledPawnMidgamePenalty[f];
361 ev -= DoubledPawnEndgamePenalty[f];
365 mv -= BackwardPawnMidgamePenalty[f];
366 ev -= BackwardPawnEndgamePenalty[f];
367 if (pos.file_is_half_open(them, f))
369 mv -= BackwardPawnMidgamePenalty[f] / 2;
370 ev -= BackwardPawnEndgamePenalty[f] / 2;
375 mv += ChainMidgameBonus[f];
376 ev += ChainEndgameBonus[f];
380 mv += CandidateMidgameBonus[relative_rank(us, s)];
381 ev += CandidateEndgameBonus[relative_rank(us, s)];
387 // If the pawn is passed, set the square of the pawn in the passedPawns
390 set_bit(&(pi->passedPawns), s);
394 pi->mgValue = int16_t(mgValue[WHITE] - mgValue[BLACK]);
395 pi->egValue = int16_t(egValue[WHITE] - egValue[BLACK]);