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/>.
31 //// Local definitions
36 /// Constants and variables
38 // Doubled pawn penalty by file, middle game.
39 const Value DoubledPawnMidgamePenalty[8] = {
40 Value(20), Value(30), Value(34), Value(34),
41 Value(34), Value(34), Value(30), Value(20)
44 // Doubled pawn penalty by file, endgame.
45 const Value DoubledPawnEndgamePenalty[8] = {
46 Value(35), Value(40), Value(40), Value(40),
47 Value(40), Value(40), Value(40), Value(35)
50 // Isolated pawn penalty by file, middle game.
51 const Value IsolatedPawnMidgamePenalty[8] = {
52 Value(20), Value(30), Value(34), Value(34),
53 Value(34), Value(34), Value(30), Value(20)
56 // Isolated pawn penalty by file, endgame.
57 const Value IsolatedPawnEndgamePenalty[8] = {
58 Value(35), Value(40), Value(40), Value(40),
59 Value(40), Value(40), Value(40), Value(35)
62 // Backward pawn penalty by file, middle game.
63 const Value BackwardPawnMidgamePenalty[8] = {
64 Value(16), Value(24), Value(27), Value(27),
65 Value(27), Value(27), Value(24), Value(16)
68 // Backward pawn penalty by file, endgame.
69 const Value BackwardPawnEndgamePenalty[8] = {
70 Value(28), Value(32), Value(32), Value(32),
71 Value(32), Value(32), Value(32), Value(28)
74 // Pawn chain membership bonus by file, middle game.
75 const Value ChainMidgameBonus[8] = {
76 Value(14), Value(16), Value(17), Value(18),
77 Value(18), Value(17), Value(16), Value(14)
80 // Pawn chain membership bonus by file, endgame.
81 const Value ChainEndgameBonus[8] = {
82 Value(16), Value(16), Value(16), Value(16),
83 Value(16), Value(16), Value(16), Value(16)
86 // Candidate passed pawn bonus by rank, middle game.
87 const Value CandidateMidgameBonus[8] = {
88 Value(0), Value(12), Value(12), Value(20),
89 Value(40), Value(90), Value(0), Value(0)
92 // Candidate passed pawn bonus by rank, endgame.
93 const Value CandidateEndgameBonus[8] = {
94 Value(0), Value(24), Value(24), Value(40),
95 Value(80), Value(180), Value(0), Value(0)
98 // Evaluate pawn storms?
99 const bool EvaluatePawnStorms = true;
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 int KStormOpenFileBonus[8] = {
126 45, 45, 30, 0, 0, 0, 0, 0
129 const int QStormOpenFileBonus[8] = {
130 0, 0, 0, 0, 0, 30, 45, 30
142 PawnInfoTable::PawnInfoTable(unsigned numOfEntries) {
144 entries = new PawnInfo[size];
145 if(entries == NULL) {
146 std::cerr << "Failed to allocate " << (numOfEntries * sizeof(PawnInfo))
147 << " bytes for pawn hash table." << std::endl;
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) {
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++) {
196 Color them = opposite_color(us);
197 Bitboard ourPawns = pos.pawns(us);
198 Bitboard theirPawns = pos.pawns(them);
199 Bitboard pawns = ourPawns;
201 // Initialize pawn storm scores by giving bonuses for open files:
202 if(EvaluatePawnStorms)
203 for(File f = FILE_A; f <= FILE_H; f++)
204 if(pos.file_is_half_open(us, f)) {
205 pi->ksStormValue[us] += KStormOpenFileBonus[f];
206 pi->qsStormValue[us] += QStormOpenFileBonus[f];
209 // Loop through all pawns of the current color and score each pawn:
211 Square s = pop_1st_bit(&pawns);
212 File f = square_file(s);
213 Rank r = square_rank(s);
214 bool passed, doubled, isolated, backward, chain, candidate;
217 assert(pos.piece_on(s) == pawn_of_color(us));
219 // The file containing the pawn is not half open:
220 pi->halfOpenFiles[us] &= ~(1 << f);
222 // Passed, isolated or doubled pawn?
223 passed = pos.pawn_is_passed(us, s);
224 isolated = pos.pawn_is_isolated(us, s);
225 doubled = pos.pawn_is_doubled(us, s);
227 if(EvaluatePawnStorms) {
228 // We calculate kingside and queenside pawn storm
229 // scores for both colors. These are used when evaluating
230 // middle game positions with opposite side castling.
232 // Each pawn is given a base score given by a piece square table
233 // (KStormTable[] or QStormTable[]). This score is increased if
234 // there are enemy pawns on adjacent files in front of the pawn.
235 // This is because we want to be able to open files against the
236 // enemy king, and to avoid blocking the pawn structure (e.g. white
237 // pawns on h6, g5, black pawns on h7, g6, f7).
239 // Kingside pawn storms:
240 bonus = KStormTable[relative_square(us, s)];
241 if(bonus > 0 && outpost_mask(us, s) & theirPawns) {
249 bonus += bonus / 2 + bonus / 4;
260 pi->ksStormValue[us] += bonus;
262 // Queenside pawn storms:
263 bonus = QStormTable[relative_square(us, s)];
264 if(bonus > 0 && passed_pawn_mask(us, s) & theirPawns) {
272 bonus += bonus / 2 + bonus / 4;
283 pi->qsStormValue[us] += bonus;
286 // Member of a pawn chain? We could speed up the test a little by
287 // introducing an array of masks indexed by color and square for doing
288 // the test, but because everything is hashed, it probably won't make
289 // any noticable difference.
290 chain = (us == WHITE)?
291 (ourPawns & neighboring_files_bb(f) & (rank_bb(r) | rank_bb(r-1))) :
292 (ourPawns & neighboring_files_bb(f) & (rank_bb(r) | rank_bb(r+1)));
295 // Test for backward pawn.
297 // If the pawn is isolated, passed, or member of a pawn chain, it cannot
299 if(passed || isolated || chain)
301 // If the pawn can capture an enemy pawn, it's not backward:
302 else if(pos.pawn_attacks(us, s) & theirPawns)
304 // Check for friendly pawns behind on neighboring files:
305 else if(ourPawns & in_front_bb(them, r) & neighboring_files_bb(f))
308 // We now know that there is no friendly pawns beside or behind this
309 // pawn on neighboring files. We now check whether the pawn is
310 // backward by looking in the forward direction on the neighboring
311 // 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;
318 for(b=pos.pawn_attacks(us, s); !(b&(ourPawns|theirPawns)); b>>=8);
319 backward = (b | (b >> 8)) & theirPawns;
323 // Test for candidate passed pawn.
325 (!passed && pos.file_is_half_open(them, f) &&
326 count_1s_max_15(neighboring_files_bb(f)
327 & (in_front_bb(them, r) | rank_bb(r))
329 - count_1s_max_15(neighboring_files_bb(f) & in_front_bb(us, r)
333 // In order to prevent doubled passed pawns from receiving a too big
334 // bonus, only the frontmost passed pawn on each file is considered as
335 // a true passed pawn.
336 if(passed && (ourPawns & squares_in_front_of(us, s))) {
342 Value mv = Value(0), ev = Value(0);
344 mv -= IsolatedPawnMidgamePenalty[f];
345 ev -= IsolatedPawnEndgamePenalty[f];
346 if(pos.file_is_half_open(them, f)) {
347 mv -= IsolatedPawnMidgamePenalty[f] / 2;
348 ev -= IsolatedPawnEndgamePenalty[f] / 2;
352 mv -= DoubledPawnMidgamePenalty[f];
353 ev -= DoubledPawnEndgamePenalty[f];
356 mv -= BackwardPawnMidgamePenalty[f];
357 ev -= BackwardPawnEndgamePenalty[f];
358 if(pos.file_is_half_open(them, f)) {
359 mv -= BackwardPawnMidgamePenalty[f] / 2;
360 ev -= BackwardPawnEndgamePenalty[f] / 2;
364 mv += ChainMidgameBonus[f];
365 ev += ChainEndgameBonus[f];
368 mv += CandidateMidgameBonus[relative_rank(us, s)];
369 ev += CandidateEndgameBonus[relative_rank(us, s)];
375 // If the pawn is passed, set the square of the pawn in the passedPawns
378 set_bit(&(pi->passedPawns), s);
382 pi->mgValue = int16_t(mgValue[WHITE] - mgValue[BLACK]);
383 pi->egValue = int16_t(egValue[WHITE] - egValue[BLACK]);