]> git.sesse.net Git - stockfish/blob - src/pawns.cpp
Move halfOpenFiles[] calculation out of a loop
[stockfish] / src / pawns.cpp
1 /*
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
5
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.
10
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.
15
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/>.
18 */
19
20
21 ////
22 //// Includes
23 ////
24
25 #include <cassert>
26 #include <cstring>
27
28 #include "bitcount.h"
29 #include "pawns.h"
30 #include "position.h"
31
32
33 ////
34 //// Local definitions
35 ////
36
37 namespace {
38
39   /// Constants and variables
40
41   // Doubled pawn penalty by file, middle game
42   const Value DoubledPawnMidgamePenalty[8] = {
43     Value(13), Value(20), Value(23), Value(23),
44     Value(23), Value(23), Value(20), Value(13)
45   };
46
47   // Doubled pawn penalty by file, endgame
48   const Value DoubledPawnEndgamePenalty[8] = {
49     Value(43), Value(48), Value(48), Value(48),
50     Value(48), Value(48), Value(48), Value(43)
51   };
52
53   // Isolated pawn penalty by file, middle game
54   const Value IsolatedPawnMidgamePenalty[8] = {
55     Value(25), Value(36), Value(40), Value(40),
56     Value(40), Value(40), Value(36), Value(25)
57   };
58
59   // Isolated pawn penalty by file, endgame
60   const Value IsolatedPawnEndgamePenalty[8] = {
61     Value(30), Value(35), Value(35), Value(35),
62     Value(35), Value(35), Value(35), Value(30)
63   };
64
65   // Backward pawn penalty by file, middle game
66   const Value BackwardPawnMidgamePenalty[8] = {
67     Value(20), Value(29), Value(33), Value(33),
68     Value(33), Value(33), Value(29), Value(20)
69   };
70
71   // Backward pawn penalty by file, endgame
72   const Value BackwardPawnEndgamePenalty[8] = {
73     Value(28), Value(31), Value(31), Value(31),
74     Value(31), Value(31), Value(31), Value(28)
75   };
76
77   // Pawn chain membership bonus by file, middle game
78   const Value ChainMidgameBonus[8] = {
79     Value(11), Value(13), Value(13), Value(14),
80     Value(14), Value(13), Value(13), Value(11)
81   };
82
83   // Pawn chain membership bonus by file, endgame
84   const Value ChainEndgameBonus[8] = {
85     Value(-1), Value(-1), Value(-1), Value(-1),
86     Value(-1), Value(-1), Value(-1), Value(-1)
87   };
88
89   // Candidate passed pawn bonus by rank, middle game
90   const Value CandidateMidgameBonus[8] = {
91     Value( 0), Value( 6), Value(6), Value(14),
92     Value(34), Value(83), Value(0), Value( 0)
93   };
94
95   // Candidate passed pawn bonus by rank, endgame
96   const Value CandidateEndgameBonus[8] = {
97     Value( 0), Value( 13), Value(13), Value(29),
98     Value(68), Value(166), Value( 0), Value( 0)
99   };
100
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,-14,-6, 0, 0, 0,
105    -6,-10,-10,-10,-6, 0, 0, 0,
106     4, 12, 16, 12, 4, 0, 0, 0,
107    16, 23, 23, 16, 0, 0, 0, 0,
108    23, 31, 31, 23, 0, 0, 0, 0,
109    23, 31, 31, 23, 0, 0, 0, 0,
110     0,  0,  0,  0, 0, 0, 0, 0
111   };
112
113   const int KStormTable[64] = {
114     0, 0, 0,  0,  0,  0,  0,  0,
115     0, 0, 0,-10,-19,-28,-33,-33,
116     0, 0, 0,-10,-15,-19,-24,-24,
117     0, 0, 0,  0,  1,  1,  1,  1,
118     0, 0, 0,  0,  1, 10, 19, 19,
119     0, 0, 0,  0,  1, 19, 31, 27,
120     0, 0, 0,  0,  0, 22, 31, 22,
121     0, 0, 0,  0,  0,  0,  0,  0
122   };
123
124   // Pawn storm open file bonuses by file
125   const int16_t KStormOpenFileBonus[8] = { 31, 31, 18, 0, 0, 0, 0, 0 };
126   const int16_t QStormOpenFileBonus[8] = { 0, 0, 0, 0, 0, 26, 42, 26 };
127
128   // Pawn storm lever bonuses by file
129   const int StormLeverBonus[8] = { -8, -8, -13, 0, 0, -13, -8, -8 };
130
131 }
132
133
134 ////
135 //// Functions
136 ////
137
138 /// Constructor
139
140 PawnInfoTable::PawnInfoTable(unsigned numOfEntries) {
141
142   size = numOfEntries;
143   entries = new PawnInfo[size];
144   if (!entries)
145   {
146       std::cerr << "Failed to allocate " << (numOfEntries * sizeof(PawnInfo))
147                 << " bytes for pawn hash table." << std::endl;
148       Application::exit_with_failure();
149   }
150 }
151
152
153 /// Destructor
154
155 PawnInfoTable::~PawnInfoTable() {
156   delete [] entries;
157 }
158
159
160 /// PawnInfo::clear() resets to zero the PawnInfo entry. Note that
161 /// kingSquares[] is initialized to SQ_NONE instead.
162
163 void PawnInfo::clear() {
164
165   memset(this, 0, sizeof(PawnInfo));
166   kingSquares[WHITE] = kingSquares[BLACK] = SQ_NONE;
167 }
168
169
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.
174
175 PawnInfo* PawnInfoTable::get_pawn_info(const Position& pos) {
176
177   assert(pos.is_ok());
178
179   Key key = pos.get_pawn_key();
180   int index = int(key & (size - 1));
181   PawnInfo* pi = entries + index;
182
183   // If pi->key matches the position's pawn hash key, it means that we
184   // have analysed this pawn structure before, and we can simply return
185   // the information we found the last time instead of recomputing it.
186   if (pi->key == key)
187       return pi;
188
189   // Clear the PawnInfo object, and set the key
190   pi->clear();
191   pi->key = key;
192
193   Value mgValue[2] = {Value(0), Value(0)};
194   Value egValue[2] = {Value(0), Value(0)};
195
196   // Loop through the pawns for both colors
197   for (Color us = WHITE; us <= BLACK; us++)
198   {
199     Color them = opposite_color(us);
200     Bitboard ourPawns = pos.pawns(us);
201     Bitboard theirPawns = pos.pawns(them);
202     Bitboard pawns = ourPawns;
203
204     // Initialize pawn storm scores by giving bonuses for open files
205     for (File f = FILE_A; f <= FILE_H; f++)
206         if (!(pawns & file_bb(f)))
207         {
208             pi->ksStormValue[us] += KStormOpenFileBonus[f];
209             pi->qsStormValue[us] += QStormOpenFileBonus[f];
210             pi->halfOpenFiles[us] |= (1 << f);
211         }
212
213     // Loop through all pawns of the current color and score each pawn
214     while (pawns)
215     {
216         Square s = pop_1st_bit(&pawns);
217         File f = square_file(s);
218         Rank r = square_rank(s);
219
220         assert(pos.piece_on(s) == piece_of_color_and_type(us, PAWN));
221
222         // Passed, isolated or doubled pawn?
223         bool passed   = Position::pawn_is_passed(theirPawns, us, s);
224         bool isolated = Position::pawn_is_isolated(ourPawns, s);
225         bool doubled  = Position::pawn_is_doubled(ourPawns, us, s);
226
227         // We calculate kingside and queenside pawn storm
228         // scores for both colors. These are used when evaluating
229         // middle game positions with opposite side castling.
230         //
231         // Each pawn is given a base score given by a piece square table
232         // (KStormTable[] or QStormTable[]). Pawns which seem to have good
233         // chances of creating an open file by exchanging itself against an
234         // enemy pawn on an adjacent file gets an additional bonus.
235
236         // Kingside pawn storms
237         int bonus = KStormTable[relative_square(us, s)];
238         if (f >= FILE_F)
239         {
240             Bitboard b = outpost_mask(us, s) & theirPawns & (FileFBB | FileGBB | FileHBB);
241             while (b)
242             {
243                 Square s2 = pop_1st_bit(&b);
244                 if (!(theirPawns & neighboring_files_bb(s2) & rank_bb(s2)))
245                 {
246                     // The enemy pawn has no pawn beside itself, which makes it
247                     // particularly vulnerable. Big bonus, especially against a
248                     // weakness on the rook file.
249                     if (square_file(s2) == FILE_H)
250                         bonus += 4*StormLeverBonus[f] - 8*square_distance(s, s2);
251                     else
252                         bonus += 2*StormLeverBonus[f] - 4*square_distance(s, s2);
253                 } else
254                     // There is at least one enemy pawn beside the enemy pawn we look
255                     // at, which means that the pawn has somewhat better chances of
256                     // defending itself by advancing. Smaller bonus.
257                     bonus += StormLeverBonus[f] - 2*square_distance(s, s2);
258             }
259         }
260         pi->ksStormValue[us] += bonus;
261
262         // Queenside pawn storms
263         bonus = QStormTable[relative_square(us, s)];
264         if (f <= FILE_C)
265         {
266             Bitboard b = outpost_mask(us, s) & theirPawns & (FileABB | FileBBB | FileCBB);
267             while (b)
268             {
269                 Square s2 = pop_1st_bit(&b);
270                 if (!(theirPawns & neighboring_files_bb(s2) & rank_bb(s2)))
271                 {
272                     // The enemy pawn has no pawn beside itself, which makes it
273                     // particularly vulnerable. Big bonus, especially against a
274                     // weakness on the rook file.
275                     if (square_file(s2) == FILE_A)
276                         bonus += 4*StormLeverBonus[f] - 16*square_distance(s, s2);
277                     else
278                         bonus += 2*StormLeverBonus[f] - 8*square_distance(s, s2);
279                 } else
280                     // There is at least one enemy pawn beside the enemy pawn we look
281                     // at, which means that the pawn has somewhat better chances of
282                     // defending itself by advancing. Smaller bonus.
283                     bonus += StormLeverBonus[f] - 4*square_distance(s, s2);
284             }
285         }
286         pi->qsStormValue[us] += bonus;
287
288         // Member of a pawn chain (but not the backward one)? We could speed up
289         // the test a little by introducing an array of masks indexed by color
290         // and square for doing the test, but because everything is hashed,
291         // it probably won't make any noticable difference.
292         bool chain =  ourPawns
293                     & neighboring_files_bb(f)
294                     & (rank_bb(r) | rank_bb(r - (us == WHITE ? 1 : -1)));
295
296         // Test for backward pawn
297         //
298         // If the pawn is passed, isolated, or member of a pawn chain
299         // it cannot be backward. If can capture an enemy pawn or if
300         // there are friendly pawns behind on neighboring files it cannot
301         // be backward either.
302         bool backward;
303         if (   passed
304             || isolated
305             || chain
306             || (pos.pawn_attacks(us, s) & theirPawns)
307             || (ourPawns & behind_bb(us, r) & neighboring_files_bb(f)))
308             backward = false;
309         else
310         {
311             // We now know that there are no friendly pawns beside or behind this
312             // pawn on neighboring files. We now check whether the pawn is
313             // backward by looking in the forward direction on the neighboring
314             // files, and seeing whether we meet a friendly or an enemy pawn first.
315             Bitboard b = pos.pawn_attacks(us, s);
316             if (us == WHITE)
317             {
318                 for ( ; !(b & (ourPawns | theirPawns)); b <<= 8);
319                 backward = (b | (b << 8)) & theirPawns;
320             }
321             else
322             {
323                 for ( ; !(b & (ourPawns | theirPawns)); b >>= 8);
324                 backward = (b | (b >> 8)) & theirPawns;
325             }
326         }
327
328         // Test for candidate passed pawn
329         bool candidate;
330         candidate =    !passed
331                     && !(theirPawns & file_bb(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)
334                         >= 0);
335
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)))
340             passed = false;
341
342         // Score this pawn
343         if (passed)
344             set_bit(&(pi->passedPawns), s);
345
346         if (isolated)
347         {
348             mgValue[us] -= IsolatedPawnMidgamePenalty[f];
349             egValue[us] -= IsolatedPawnEndgamePenalty[f];
350             if (!(theirPawns & file_bb(f)))
351             {
352                 mgValue[us] -= IsolatedPawnMidgamePenalty[f] / 2;
353                 egValue[us] -= IsolatedPawnEndgamePenalty[f] / 2;
354             }
355         }
356         if (doubled)
357         {
358             mgValue[us] -= DoubledPawnMidgamePenalty[f];
359             egValue[us] -= DoubledPawnEndgamePenalty[f];
360         }
361         if (backward)
362         {
363             mgValue[us] -= BackwardPawnMidgamePenalty[f];
364             egValue[us] -= BackwardPawnEndgamePenalty[f];
365             if (!(theirPawns & file_bb(f)))
366             {
367                 mgValue[us] -= BackwardPawnMidgamePenalty[f] / 2;
368                 egValue[us] -= BackwardPawnEndgamePenalty[f] / 2;
369             }
370         }
371         if (chain)
372         {
373             mgValue[us] += ChainMidgameBonus[f];
374             egValue[us] += ChainEndgameBonus[f];
375         }
376         if (candidate)
377         {
378             mgValue[us] += CandidateMidgameBonus[relative_rank(us, s)];
379             egValue[us] += CandidateEndgameBonus[relative_rank(us, s)];
380         }
381     } // while(pawns)
382   } // for(colors)
383
384   pi->mgValue = int16_t(mgValue[WHITE] - mgValue[BLACK]);
385   pi->egValue = int16_t(egValue[WHITE] - egValue[BLACK]);
386   return pi;
387 }
388
389
390 /// PawnInfo::updateShelter calculates and caches king shelter. It is called
391 /// only when king square changes, about 20% of total get_king_shelter() calls.
392 int PawnInfo::updateShelter(const Position& pos, Color c, Square ksq) {
393
394   unsigned shelter = 0;
395   Bitboard pawns = pos.pawns(c) & this_and_neighboring_files_bb(ksq);
396   unsigned r = ksq & (7 << 3);
397   for (int i = 1, k = (c ? -8 : 8); i < 4; i++)
398   {
399       r += k;
400       shelter += BitCount8Bit[(pawns >> r) & 0xFF] * (128 >> i);
401   }
402   kingSquares[c] = ksq;
403   kingShelters[c] = shelter;
404   return shelter;
405 }