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) {
145 entries = new PawnInfo[size];
146 if(entries == NULL) {
147 std::cerr << "Failed to allocate " << (numOfEntries * sizeof(PawnInfo))
148 << " bytes for pawn hash table." << std::endl;
157 PawnInfoTable::~PawnInfoTable() {
162 /// PawnInfoTable::clear() clears the pawn hash table by setting all
165 void PawnInfoTable::clear() {
166 memset(entries, 0, size * sizeof(PawnInfo));
170 /// PawnInfoTable::get_pawn_info() takes a position object as input, computes
171 /// a PawnInfo object, and returns a pointer to it. The result is also
172 /// stored in a hash table, so we don't have to recompute everything when
173 /// the same pawn structure occurs again.
175 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++) {
197 Color them = opposite_color(us);
198 Bitboard ourPawns = pos.pawns(us);
199 Bitboard theirPawns = pos.pawns(them);
200 Bitboard pawns = ourPawns;
202 // Initialize pawn storm scores by giving bonuses for open files:
203 if(EvaluatePawnStorms)
204 for(File f = FILE_A; f <= FILE_H; f++)
205 if(pos.file_is_half_open(us, f)) {
206 pi->ksStormValue[us] += KStormOpenFileBonus[f];
207 pi->qsStormValue[us] += QStormOpenFileBonus[f];
210 // Loop through all pawns of the current color and score each pawn:
212 Square s = pop_1st_bit(&pawns);
213 File f = square_file(s);
214 Rank r = square_rank(s);
215 bool passed, doubled, isolated, backward, chain, candidate;
218 assert(pos.piece_on(s) == pawn_of_color(us));
220 // The file containing the pawn is not half open:
221 pi->halfOpenFiles[us] &= ~(1 << f);
223 // Passed, isolated or doubled pawn?
224 passed = pos.pawn_is_passed(us, s);
225 isolated = pos.pawn_is_isolated(us, s);
226 doubled = pos.pawn_is_doubled(us, s);
228 if(EvaluatePawnStorms) {
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[]). 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 pawn storms:
241 bonus = KStormTable[relative_square(us, s)];
242 if(bonus > 0 && outpost_mask(us, s) & theirPawns) {
250 bonus += bonus / 2 + bonus / 4;
261 pi->ksStormValue[us] += bonus;
263 // Queenside pawn storms:
264 bonus = QStormTable[relative_square(us, s)];
265 if(bonus > 0 && passed_pawn_mask(us, s) & theirPawns) {
273 bonus += bonus / 2 + bonus / 4;
284 pi->qsStormValue[us] += bonus;
287 // Member of a pawn chain? We could speed up the test a little by
288 // introducing an array of masks indexed by color and square for doing
289 // the test, but because everything is hashed, it probably won't make
290 // any noticable difference.
291 chain = (us == WHITE)?
292 (ourPawns & neighboring_files_bb(f) & (rank_bb(r) | rank_bb(r-1))) :
293 (ourPawns & neighboring_files_bb(f) & (rank_bb(r) | rank_bb(r+1)));
296 // Test for backward pawn.
298 // If the pawn is isolated, passed, or member of a pawn chain, it cannot
300 if(passed || isolated || chain)
302 // If the pawn can capture an enemy pawn, it's not backward:
303 else if(pos.pawn_attacks(us, s) & theirPawns)
305 // Check for friendly pawns behind on neighboring files:
306 else if(ourPawns & in_front_bb(them, r) & neighboring_files_bb(f))
309 // We now know that there is no friendly pawns beside or behind this
310 // pawn on neighboring files. We now check whether the pawn is
311 // backward by looking in the forward direction on the neighboring
312 // files, and seeing whether we meet a friendly or an enemy pawn first.
315 for(b=pos.pawn_attacks(us, s); !(b&(ourPawns|theirPawns)); b<<=8);
316 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 (!passed && pos.file_is_half_open(them, f) &&
327 count_1s_max_15(neighboring_files_bb(f)
328 & (in_front_bb(them, r) | rank_bb(r))
330 - count_1s_max_15(neighboring_files_bb(f) & in_front_bb(us, r)
334 // In order to prevent doubled passed pawns from receiving a too big
335 // bonus, only the frontmost passed pawn on each file is considered as
336 // a true passed pawn.
337 if(passed && (ourPawns & squares_in_front_of(us, s))) {
343 Value mv = Value(0), ev = Value(0);
345 mv -= IsolatedPawnMidgamePenalty[f];
346 ev -= IsolatedPawnEndgamePenalty[f];
347 if(pos.file_is_half_open(them, f)) {
348 mv -= IsolatedPawnMidgamePenalty[f] / 2;
349 ev -= IsolatedPawnEndgamePenalty[f] / 2;
353 mv -= DoubledPawnMidgamePenalty[f];
354 ev -= DoubledPawnEndgamePenalty[f];
357 mv -= BackwardPawnMidgamePenalty[f];
358 ev -= BackwardPawnEndgamePenalty[f];
359 if(pos.file_is_half_open(them, f)) {
360 mv -= BackwardPawnMidgamePenalty[f] / 2;
361 ev -= BackwardPawnEndgamePenalty[f] / 2;
365 mv += ChainMidgameBonus[f];
366 ev += ChainEndgameBonus[f];
369 mv += CandidateMidgameBonus[relative_rank(us, s)];
370 ev += CandidateEndgameBonus[relative_rank(us, s)];
376 // If the pawn is passed, set the square of the pawn in the passedPawns
379 set_bit(&(pi->passedPawns), s);
383 pi->mgValue = int16_t(mgValue[WHITE] - mgValue[BLACK]);
384 pi->egValue = int16_t(egValue[WHITE] - egValue[BLACK]);