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 int16_t KStormOpenFileBonus[8] = { 45, 45, 30, 0, 0, 0, 0, 0 };
125 const int16_t QStormOpenFileBonus[8] = { 0, 0, 0, 0, 0, 30, 45, 30 };
127 // Pawn storm lever bonuses by file
128 const int StormLeverBonus[8] = { 20, 20, 10, 0, 0, 10, 20, 20 };
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;
155 PawnInfoTable::~PawnInfoTable() {
160 /// PawnInfoTable::clear() clears the pawn hash table by setting all
163 void PawnInfoTable::clear() {
164 memset(entries, 0, size * sizeof(PawnInfo));
168 /// PawnInfoTable::get_pawn_info() takes a position object as input, computes
169 /// a PawnInfo object, and returns a pointer to it. The result is also
170 /// stored in a hash table, so we don't have to recompute everything when
171 /// the same pawn structure occurs again.
173 PawnInfo *PawnInfoTable::get_pawn_info(const Position &pos) {
177 Key key = pos.get_pawn_key();
178 int index = int(key & (size - 1));
179 PawnInfo *pi = entries + index;
181 // If pi->key matches the position's pawn hash key, it means that we
182 // have analysed this pawn structure before, and we can simply return the
183 // information we found the last time instead of recomputing it
187 // Clear the PawnInfo object, and set the key
191 Value mgValue[2] = {Value(0), Value(0)};
192 Value egValue[2] = {Value(0), Value(0)};
194 // Loop through the pawns for both colors
195 for (Color us = WHITE; us <= BLACK; us++)
197 Color them = opposite_color(us);
198 Bitboard ourPawns = pos.pawns(us);
199 Bitboard theirPawns = pos.pawns(them);
200 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
230 // scores for both colors. These are used when evaluating
231 // middle game positions with opposite side castling.
233 // Each pawn is given a base score given by a piece square table
234 // (KStormTable[] or QStormTable[]). Pawns which seem to have good
235 // chances of creating an open file by exchanging itself against an
236 // enemy pawn on an adjacent file gets an additional bonus.
238 // Kingside pawn storms
239 bonus = KStormTable[relative_square(us, s)];
242 Bitboard b = outpost_mask(us, s) & theirPawns & (FileFBB | FileGBB | FileHBB);
245 Square s2 = pop_1st_bit(&b);
246 if (!(theirPawns & neighboring_files_bb(s2) & rank_bb(s2)))
248 // The enemy pawn has no pawn beside itself, which makes it
249 // particularly vulnerable. Big bonus, especially against a
250 // weakness on the rook file.
251 if (square_file(s2) == FILE_H)
252 bonus += 4*StormLeverBonus[f] - 8*square_distance(s, s2);
254 bonus += 2*StormLeverBonus[f] - 4*square_distance(s, s2);
256 // There is at least one enemy pawn beside the enemy pawn we look
257 // at, which means that the pawn has somewhat better chances of
258 // defending itself by advancing. Smaller bonus.
259 bonus += StormLeverBonus[f] - 2*square_distance(s, s2);
262 pi->ksStormValue[us] += bonus;
264 // Queenside pawn storms
265 bonus = QStormTable[relative_square(us, s)];
268 Bitboard b = outpost_mask(us, s) & theirPawns & (FileABB | FileBBB | FileCBB);
271 Square s2 = pop_1st_bit(&b);
272 if (!(theirPawns & neighboring_files_bb(s2) & rank_bb(s2)))
274 // The enemy pawn has no pawn beside itself, which makes it
275 // particularly vulnerable. Big bonus, especially against a
276 // weakness on the rook file.
277 if (square_file(s2) == FILE_A)
278 bonus += 4*StormLeverBonus[f] - 16*square_distance(s, s2);
280 bonus += 2*StormLeverBonus[f] - 8*square_distance(s, s2);
282 // There is at least one enemy pawn beside the enemy pawn we look
283 // at, which means that the pawn has somewhat better chances of
284 // defending itself by advancing. Smaller bonus.
285 bonus += StormLeverBonus[f] - 4*square_distance(s, s2);
288 pi->qsStormValue[us] += bonus;
290 // Member of a pawn chain (but not the backward one)? We could speed up
291 // the test a little by introducing an array of masks indexed by color
292 // and square for doing the test, but because everything is hashed,
293 // it probably won't make any noticable difference.
295 & neighboring_files_bb(f)
296 & (rank_bb(r) | rank_bb(r - (us == WHITE ? 1 : -1)));
298 // Test for backward pawn
300 // If the pawn is passed, isolated, or member of a pawn chain
301 // it cannot be backward. If can capture an enemy pawn or if
302 // there are friendly pawns behind on neighboring files it cannot
303 // be backward either.
307 || (pos.pawn_attacks(us, s) & theirPawns)
308 || (ourPawns & behind_bb(us, r) & neighboring_files_bb(f)))
312 // We now know that there are no friendly pawns beside or behind this
313 // pawn on neighboring files. We now check whether the pawn is
314 // backward by looking in the forward direction on the neighboring
315 // files, and seeing whether we meet a friendly or an enemy pawn first.
319 for (b = pos.pawn_attacks(us, s); !(b & (ourPawns | theirPawns)); b <<= 8);
320 backward = (b | (b << 8)) & theirPawns;
324 for (b = pos.pawn_attacks(us, s); !(b & (ourPawns | theirPawns)); b >>= 8);
325 backward = (b | (b >> 8)) & theirPawns;
329 // Test for candidate passed pawn
331 && pos.file_is_half_open(them, f)
332 && ( count_1s_max_15(neighboring_files_bb(f) & (behind_bb(us, r) | rank_bb(r)) & ourPawns)
333 - count_1s_max_15(neighboring_files_bb(f) & in_front_bb(us, r) & theirPawns)
336 // In order to prevent doubled passed pawns from receiving a too big
337 // bonus, only the frontmost passed pawn on each file is considered as
338 // a true passed pawn.
339 if (passed && (ourPawns & squares_in_front_of(us, s)))
346 Value mv = Value(0), ev = Value(0);
349 mv -= IsolatedPawnMidgamePenalty[f];
350 ev -= IsolatedPawnEndgamePenalty[f];
351 if (pos.file_is_half_open(them, f))
353 mv -= IsolatedPawnMidgamePenalty[f] / 2;
354 ev -= IsolatedPawnEndgamePenalty[f] / 2;
359 mv -= DoubledPawnMidgamePenalty[f];
360 ev -= DoubledPawnEndgamePenalty[f];
364 mv -= BackwardPawnMidgamePenalty[f];
365 ev -= BackwardPawnEndgamePenalty[f];
366 if (pos.file_is_half_open(them, f))
368 mv -= BackwardPawnMidgamePenalty[f] / 2;
369 ev -= BackwardPawnEndgamePenalty[f] / 2;
374 mv += ChainMidgameBonus[f];
375 ev += ChainEndgameBonus[f];
379 mv += CandidateMidgameBonus[relative_rank(us, s)];
380 ev += CandidateEndgameBonus[relative_rank(us, s)];
386 // If the pawn is passed, set the square of the pawn in the passedPawns
389 set_bit(&(pi->passedPawns), s);
393 pi->mgValue = int16_t(mgValue[WHITE] - mgValue[BLACK]);
394 pi->egValue = int16_t(egValue[WHITE] - egValue[BLACK]);