Line data Source code
1 : #include "material.hpp"
2 :
3 : #include "attack.hpp"
4 : #include "dynamicConfig.hpp"
5 : #include "evalConfig.hpp"
6 : #include "kpk.hpp"
7 : #include "logging.hpp"
8 : #include "positionTools.hpp"
9 : #include "tools.hpp"
10 :
11 : namespace MaterialHash { // idea from Gull
12 :
13 : // helper function function pointer table
14 : ScoreType (*helperTable[TotalMat])(const Position &, Color, ScoreType, DepthType);
15 :
16 : // the material cache
17 : array1d<MaterialHashEntry,TotalMat> materialHashTable;
18 :
19 : #ifndef WITH_MATERIAL_TABLE
20 : [[nodiscard]] Hash getMaterialHash(const Position::Material &) {
21 : return nullHash;
22 : }
23 : [[nodiscard]] Hash getMaterialHash2(const Position::Material &mat) {
24 : #else
25 5013568 : [[nodiscard]] Hash getMaterialHash(const Position::Material &mat) {
26 : #endif
27 5013568 : if (mat[Co_White][M_q] > 2 || mat[Co_Black][M_q] > 2
28 5013568 : || mat[Co_White][M_r] > 2 || mat[Co_Black][M_r] > 2
29 5012604 : || mat[Co_White][M_bl] > 2 || mat[Co_Black][M_bl] > 2
30 5012604 : || mat[Co_White][M_bd] > 2 || mat[Co_Black][M_bd] > 2
31 5012604 : || mat[Co_White][M_n] > 2 || mat[Co_Black][M_n] > 2
32 10026172 : || mat[Co_White][M_p] > 8 || mat[Co_Black][M_p] > 8) return nullHash;
33 :
34 5012604 : return mat[Co_White][M_p] * MatWP + mat[Co_Black][M_p] * MatBP
35 5012604 : + mat[Co_White][M_n] * MatWN + mat[Co_Black][M_n] * MatBN
36 5012604 : + mat[Co_White][M_bl] * MatWL + mat[Co_Black][M_bl] * MatBL
37 5012604 : + mat[Co_White][M_bd] * MatWD + mat[Co_Black][M_bd] * MatBD
38 5012604 : + mat[Co_White][M_r] * MatWR + mat[Co_Black][M_r] * MatBR
39 5012604 : + mat[Co_White][M_q] * MatWQ + mat[Co_Black][M_q] * MatBQ;
40 : }
41 :
42 105225318 : [[nodiscard]] Position::Material indexToMat(int index) {
43 105225318 : Position::Material m = {{{{0}}}};
44 : using MatType = Position::Material::value_type::value_type;
45 105225318 : m[Co_White][M_q] = static_cast<MatType>(index % 3); index /= 3;
46 105225318 : m[Co_Black][M_q] = static_cast<MatType>(index % 3); index /= 3;
47 105225318 : m[Co_White][M_r] = static_cast<MatType>(index % 3); index /= 3;
48 105225318 : m[Co_Black][M_r] = static_cast<MatType>(index % 3); index /= 3;
49 105225318 : m[Co_White][M_bl]= static_cast<MatType>(index % 3); index /= 3;
50 105225318 : m[Co_Black][M_bl]= static_cast<MatType>(index % 3); index /= 3;
51 105225318 : m[Co_White][M_bd]= static_cast<MatType>(index % 3); index /= 3;
52 105225318 : m[Co_Black][M_bd]= static_cast<MatType>(index % 3); index /= 3;
53 105225318 : m[Co_White][M_n] = static_cast<MatType>(index % 3); index /= 3;
54 105225318 : m[Co_Black][M_n] = static_cast<MatType>(index % 3); index /= 3;
55 105225318 : m[Co_White][M_p] = static_cast<MatType>(index % 9); index /= 9;
56 105225318 : m[Co_Black][M_p] = static_cast<MatType>(index);
57 105225318 : m[Co_White][M_b] = m[Co_White][M_bl] + m[Co_White][M_bd];
58 105225318 : m[Co_Black][M_b] = m[Co_Black][M_bl] + m[Co_Black][M_bd];
59 105225318 : m[Co_White][M_M] = m[Co_White][M_q] + m[Co_White][M_r]; m[Co_Black][M_M] = m[Co_Black][M_q] + m[Co_Black][M_r];
60 105225318 : m[Co_White][M_m] = m[Co_White][M_b] + m[Co_White][M_n]; m[Co_Black][M_m] = m[Co_Black][M_b] + m[Co_Black][M_n];
61 105225318 : m[Co_White][M_t] = m[Co_White][M_M] + m[Co_White][M_m]; m[Co_Black][M_t] = m[Co_Black][M_M] + m[Co_Black][M_m];
62 105225318 : return m;
63 : }
64 :
65 2090 : [[nodiscard]] Position::Material getMatReverseColor(const Position::Material &mat) {
66 2090 : Position::Material rev = {{{{0}}}};
67 2090 : rev[Co_White][M_k] = mat[Co_Black][M_k]; rev[Co_Black][M_k] = mat[Co_White][M_k];
68 2090 : rev[Co_White][M_q] = mat[Co_Black][M_q]; rev[Co_Black][M_q] = mat[Co_White][M_q];
69 2090 : rev[Co_White][M_r] = mat[Co_Black][M_r]; rev[Co_Black][M_r] = mat[Co_White][M_r];
70 2090 : rev[Co_White][M_b] = mat[Co_Black][M_b]; rev[Co_Black][M_b] = mat[Co_White][M_b];
71 2090 : rev[Co_White][M_bl] = mat[Co_Black][M_bl]; rev[Co_Black][M_bl] = mat[Co_White][M_bl];
72 2090 : rev[Co_White][M_bd] = mat[Co_Black][M_bd]; rev[Co_Black][M_bd] = mat[Co_White][M_bd];
73 2090 : rev[Co_White][M_n] = mat[Co_Black][M_n]; rev[Co_Black][M_n] = mat[Co_White][M_n];
74 2090 : rev[Co_White][M_p] = mat[Co_Black][M_p]; rev[Co_Black][M_p] = mat[Co_White][M_p];
75 2090 : rev[Co_White][M_M] = mat[Co_Black][M_M]; rev[Co_Black][M_M] = mat[Co_White][M_M];
76 2090 : rev[Co_White][M_m] = mat[Co_Black][M_m]; rev[Co_Black][M_m] = mat[Co_White][M_m];
77 2090 : rev[Co_White][M_t] = mat[Co_Black][M_t]; rev[Co_Black][M_t] = mat[Co_White][M_t];
78 2090 : return rev;
79 : }
80 :
81 2090 : [[nodiscard]] Position::Material materialFromString(const std::string &strMat) {
82 2090 : Position::Material mat = {{{{0}}}};
83 : Color c = Co_Black;
84 11902 : for (const auto & it : strMat) {
85 9812 : switch (it) {
86 4180 : case 'K':
87 : c = ~c;
88 4180 : mat[c][M_k] += 1;
89 4180 : break;
90 946 : case 'Q':
91 946 : mat[c][M_q] += 1;
92 946 : mat[c][M_M] += 1;
93 946 : mat[c][M_t] += 1;
94 946 : break;
95 1144 : case 'R':
96 1144 : mat[c][M_r] += 1;
97 1144 : mat[c][M_M] += 1;
98 1144 : mat[c][M_t] += 1;
99 1144 : break;
100 1144 : case 'L':
101 1144 : mat[c][M_bl] += 1;
102 1144 : mat[c][M_b] += 1;
103 1144 : mat[c][M_m] += 1;
104 1144 : mat[c][M_t] += 1;
105 1144 : break;
106 1144 : case 'D':
107 1144 : mat[c][M_bd] += 1;
108 1144 : mat[c][M_b] += 1;
109 1144 : mat[c][M_m] += 1;
110 1144 : mat[c][M_t] += 1;
111 1144 : break;
112 1056 : case 'N':
113 1056 : mat[c][M_n] += 1;
114 1056 : mat[c][M_m] += 1;
115 1056 : mat[c][M_t] += 1;
116 1056 : break;
117 198 : case 'P': mat[c][M_p] += 1; break;
118 0 : default: Logging::LogIt(Logging::logFatal) << "Bad char in material definition";
119 : }
120 : }
121 2090 : return mat;
122 : }
123 :
124 0 : [[nodiscard]] Terminaison reverseTerminaison(Terminaison t) {
125 0 : switch (t) {
126 : case Ter_Unknown: case Ter_Draw: case Ter_MaterialDraw: case Ter_LikelyDraw: case Ter_HardToWin: return t;
127 66 : case Ter_WhiteWin: return Ter_BlackWin;
128 264 : case Ter_WhiteWinWithHelper: return Ter_BlackWinWithHelper;
129 0 : case Ter_BlackWin: return Ter_WhiteWin;
130 0 : case Ter_BlackWinWithHelper: return Ter_WhiteWinWithHelper;
131 0 : default: return Ter_Unknown;
132 : }
133 : }
134 :
135 : const array1d<ScoreType,NbSquare> pushToEdges = {
136 : 100, 90, 80, 70, 70, 80, 90, 100,
137 : 90, 70, 60, 50, 50, 60, 70, 90,
138 : 80, 60, 40, 30, 30, 40, 60, 80,
139 : 70, 50, 30, 0, 0, 30, 50, 70,
140 : 70, 50, 30, 0, 0, 30, 50, 70,
141 : 80, 60, 40, 30, 30, 40, 60, 80,
142 : 90, 70, 60, 50, 50, 60, 70, 90,
143 : 100, 90, 80, 70, 70, 80, 90, 100
144 : };
145 :
146 : const array1d<ScoreType,NbSquare> pushToCorners = {
147 : 200, 190, 180, 170, 160, 150, 140, 130,
148 : 190, 180, 170, 160, 150, 140, 130, 140,
149 : 180, 170, 155, 140, 140, 125, 140, 150,
150 : 170, 160, 140, 120, 110, 140, 150, 160,
151 : 160, 150, 140, 110, 120, 140, 160, 170,
152 : 150, 140, 125, 140, 140, 155, 170, 180,
153 : 140, 130, 140, 150, 160, 170, 180, 190,
154 : 130, 140, 150, 160, 170, 180, 190, 200
155 : };
156 :
157 : const array1d<ScoreType,8> pushClose = {0, 0, 100, 80, 60, 40, 20, 10};
158 : //const array1d<ScoreType,8> pushAway = { 0, 5, 20, 40, 60, 80, 90, 100 };
159 :
160 20 : ScoreType helperKXK(const Position &p, Color winningSide, ScoreType s, DepthType height) {
161 : if (p.c != winningSide) {
162 : ///@todo stale mate detection for losing side
163 : }
164 20 : const Square winningK = p.king[winningSide];
165 20 : const Square losingK = p.king[~winningSide];
166 20 : const ScoreType sc = 12 * pushToEdges[losingK] + pushClose[chebyshevDistance(winningK, losingK)];
167 20 : return clampScore(s + ((winningSide == Co_White) ? (sc + WIN - height + 1) : (-sc - WIN + height)));
168 : }
169 :
170 0 : ScoreType helperKmmK(const Position &p, Color winningSide, ScoreType s, DepthType height) {
171 0 : Square winningK = p.king[winningSide];
172 0 : Square losingK = p.king[~winningSide];
173 0 : if ((p.allBishop() & BB::whiteSquare) != 0) {
174 : winningK = VFlip(winningK);
175 : losingK = VFlip(losingK);
176 : }
177 0 : const ScoreType sc = 12 * pushToCorners[losingK] + pushClose[chebyshevDistance(winningK, losingK)];
178 0 : return clampScore(s + ((winningSide == Co_White) ? (sc + WIN - height + 1) : (-sc - WIN + height)));
179 : }
180 :
181 0 : ScoreType helperDummy(const Position &, Color, ScoreType, DepthType) { return 0; } ///@todo not 0 for debug purpose ??
182 :
183 : #if !defined(WITH_SMALL_MEMORY)
184 11 : ScoreType helperKPK(const Position &p, Color winningSide, [[maybe_unused]] ScoreType s, DepthType height) {
185 11 : const Square psq = KPK::normalizeSquare(p, winningSide, BBTools::SquareFromBitBoard(p.pieces_const<P_wp>(winningSide))); // we know there is at least one pawn
186 11 : const Square wksq = KPK::normalizeSquare(p, winningSide, p.king[winningSide]);
187 11 : const Square lksq = KPK::normalizeSquare(p, winningSide, p.king[~winningSide]);
188 11 : if (!KPK::probe(wksq, psq, lksq, winningSide == p.c ? Co_White : Co_Black)) {
189 8 : if (DynamicConfig::armageddon) {
190 0 : if (p.c == Co_White) return matedScore(height);
191 0 : else return matingScore(height-1);
192 : }
193 : return 0; // shall be drawScore but we don't care, this is not 3rep
194 : }
195 6 : return clampScore(((winningSide == Co_White) ? +1 : -1) * (WIN + valueEG(P_wp) + 10 * SQRANK(psq)));
196 : }
197 : #endif
198 :
199 0 : ScoreType helperKBPK(const Position & p, Color winningSide, ScoreType s, DepthType height) {
200 0 : const Square winningPawn = BBTools::SquareFromBitBoard(p.allPawn()); // assume only one pawn
201 0 : const Square promSquare = winningSide == Co_White ? PromotionSquare<Co_White>(winningPawn) : PromotionSquare<Co_Black>(winningPawn);
202 0 : const Color bc = (p.allBishop() & BB::whiteSquare) ? Co_White : Co_Black;
203 0 : const Color pc = (SquareToBitboard(promSquare) & BB::whiteSquare) ? Co_White : Co_Black;
204 0 : if ( bc != pc ){
205 : // let's approximate score by the KPK one ...
206 0 : return helperKPK(p,winningSide,0,height);
207 : }
208 : else {
209 : return s;
210 : }
211 : }
212 :
213 : // Second-degree polynomial material imbalance, by Tord Romstad (old version, not the current Stockfish stuff)
214 210450636 : EvalScore Imbalance(const Position::Material &mat, Color c) {
215 : EvalScore bonus = 0;
216 1262703816 : for (Mat m1 = M_p; m1 <= M_q; ++m1) {
217 1052253180 : if (!mat[c][m1]) continue;
218 3086609328 : for (Mat m2 = M_p; m2 <= m1; ++m2) {
219 2291573592 : bonus += EvalConfig::imbalance_mines[m1 - 1][m2 - 1] * mat[c][m1] * mat[c][m2] +
220 4583147184 : EvalConfig::imbalance_theirs[m1 - 1][m2 - 1] * mat[c][m1] * mat[~c][m2];
221 : }
222 : }
223 210450636 : return bonus / 16;
224 : }
225 :
226 : #pragma GCC diagnostic push
227 : #pragma GCC diagnostic ignored "-Wconversion"
228 :
229 22 : void InitMaterialScore(bool display) {
230 44 : if (display) Logging::LogIt(Logging::logInfo) << "Material hash init";
231 105225340 : for (int k = 0; k < TotalMat; ++k) {
232 105225318 : const Position::Material mat = indexToMat(k);
233 : // MG
234 105225318 : const ScoreType matPieceScoreW = mat[Co_White][M_q] * absValue(P_wq) + mat[Co_White][M_r] * absValue(P_wr) +
235 105225318 : mat[Co_White][M_b] * absValue(P_wb) + mat[Co_White][M_n] * absValue(P_wn);
236 105225318 : const ScoreType matPieceScoreB = mat[Co_Black][M_q] * absValue(P_wq) + mat[Co_Black][M_r] * absValue(P_wr) +
237 105225318 : mat[Co_Black][M_b] * absValue(P_wb) + mat[Co_Black][M_n] * absValue(P_wn);
238 105225318 : const ScoreType matPawnScoreW = mat[Co_White][M_p] * absValue(P_wp);
239 105225318 : const ScoreType matPawnScoreB = mat[Co_Black][M_p] * absValue(P_wp);
240 105225318 : const ScoreType matScoreW = matPieceScoreW + matPawnScoreW;
241 105225318 : const ScoreType matScoreB = matPieceScoreB + matPawnScoreB;
242 : // EG
243 105225318 : const ScoreType matPieceScoreWEG = mat[Co_White][M_q] * absValueEG(P_wq) + mat[Co_White][M_r] * absValueEG(P_wr) +
244 105225318 : mat[Co_White][M_b] * absValueEG(P_wb) + mat[Co_White][M_n] * absValueEG(P_wn);
245 105225318 : const ScoreType matPieceScoreBEG = mat[Co_Black][M_q] * absValueEG(P_wq) + mat[Co_Black][M_r] * absValueEG(P_wr) +
246 105225318 : mat[Co_Black][M_b] * absValueEG(P_wb) + mat[Co_Black][M_n] * absValueEG(P_wn);
247 105225318 : const ScoreType matPawnScoreWEG = mat[Co_White][M_p] * absValueEG(P_wp);
248 105225318 : const ScoreType matPawnScoreBEG = mat[Co_Black][M_p] * absValueEG(P_wp);
249 105225318 : const ScoreType matScoreWEG = matPieceScoreWEG + matPawnScoreWEG;
250 105225318 : const ScoreType matScoreBEG = matPieceScoreBEG + matPawnScoreBEG;
251 : #ifdef WITH_EVAL_TUNING
252 : const EvalScore imbalanceW = {0, 0};
253 : const EvalScore imbalanceB = {0, 0};
254 : #else
255 105225318 : const EvalScore imbalanceW = Imbalance(mat, Co_White);
256 105225318 : const EvalScore imbalanceB = Imbalance(mat, Co_Black);
257 : #endif
258 105225318 : ScoreType dummyW = 0;
259 105225318 : ScoreType dummyB = 0;
260 105225318 : materialHashTable[k].setGamePhase(gamePhase(mat, dummyW, dummyB));
261 : materialHashTable[k].score =
262 210450636 : EvalScore(imbalanceW[MG] + matScoreW - (imbalanceB[MG] + matScoreB), imbalanceW[EG] + matScoreWEG - (imbalanceB[EG] + matScoreBEG));
263 : }
264 44 : if (display) Logging::LogIt(Logging::logInfo) << "...Done";
265 22 : }
266 :
267 : #pragma GCC diagnostic pop
268 :
269 22 : void MaterialHashInitializer::init() {
270 22 : Logging::LogIt(Logging::logInfo) << "Material hash total : " << TotalMat;
271 22 : Logging::LogIt(Logging::logInfo) << "Material hash size : " << TotalMat * sizeof(MaterialHashEntry) / 1024 / 1024 << "Mb";
272 :
273 : #ifdef WITH_MATERIAL_TABLE
274 22 : InitMaterialScore();
275 105225340 : for (size_t k = 0; k < TotalMat; ++k) helperTable[k] = &helperDummy;
276 :
277 : #define DEF_MAT(x,t) const Position::Material MAT##x = materialFromString(TO_STR(x)); MaterialHashInitializer LINE_NAME(dummyMaterialInitializer,MAT##x)( MAT##x ,t );
278 : #define DEF_MAT_H(x,t,h) const Position::Material MAT##x = materialFromString(TO_STR(x)); MaterialHashInitializer LINE_NAME(dummyMaterialInitializer,MAT##x)( MAT##x ,t, h);
279 : #define DEF_MAT_REV(rev,x) const Position::Material MAT##rev = MaterialHash::getMatReverseColor(MAT##x); MaterialHashInitializer LINE_NAME(dummyMaterialInitializerRev,MAT##x)( MAT##rev,reverseTerminaison(materialHashTable[getMaterialHash(MAT##x)].t) );
280 : #define DEF_MAT_REV_H(rev,x,h) const Position::Material MAT##rev = MaterialHash::getMatReverseColor(MAT##x); MaterialHashInitializer LINE_NAME(dummyMaterialInitializerRev,MAT##x)( MAT##rev,reverseTerminaison(materialHashTable[getMaterialHash(MAT##x)].t), h);
281 :
282 : // WARNING : we assume STM has no capture
283 :
284 : ///@todo some Ter_MaterialDraw are Ter_Draw (FIDE)
285 :
286 : // other FIDE draw
287 : //DEF_MAT(KLKL, Ter_MaterialDraw) // useless
288 : //DEF_MAT(KDKD, Ter_MaterialDraw) // useless
289 :
290 : // sym (and pseudo sym) : all should be draw (or very nearly)
291 : //DEF_MAT(KK, Ter_MaterialDraw) // this is invalid hash
292 : //DEF_MAT(KQQKQQ, Ter_LikelyDraw) // useless
293 : //DEF_MAT(KQKQ, Ter_LikelyDraw) // useless
294 : //DEF_MAT(KRRKRR, Ter_LikelyDraw) // useless
295 : //DEF_MAT(KRKR, Ter_LikelyDraw) // useless
296 : //DEF_MAT(KLDKLD, Ter_MaterialDraw) // useless
297 : //DEF_MAT(KLLKLL, Ter_MaterialDraw) // useless
298 : //DEF_MAT(KDDKDD, Ter_MaterialDraw) // useless
299 : //DEF_MAT(KNNKNN, Ter_MaterialDraw) // useless
300 : //DEF_MAT(KNKN , Ter_MaterialDraw) // useless
301 :
302 : //DEF_MAT(KLDKLL, Ter_MaterialDraw) DEF_MAT_REV(KLLKLD, KLDKLL) // useless
303 : //DEF_MAT(KLDKDD, Ter_MaterialDraw) DEF_MAT_REV(KDDKLD, KLDKDD) // useless
304 : //DEF_MAT(KLKD, Ter_MaterialDraw) DEF_MAT_REV(KDKL, KLKD) // useless
305 :
306 : // 2M M
307 44 : DEF_MAT(KQQKQ, Ter_WhiteWin) DEF_MAT_REV(KQKQQ, KQQKQ)
308 44 : DEF_MAT(KQQKR, Ter_WhiteWin) DEF_MAT_REV(KRKQQ, KQQKR)
309 44 : DEF_MAT(KRRKQ, Ter_LikelyDraw) DEF_MAT_REV(KQKRR, KRRKQ)
310 44 : DEF_MAT(KRRKR, Ter_WhiteWin) DEF_MAT_REV(KRKRR, KRRKR)
311 44 : DEF_MAT(KQRKQ, Ter_WhiteWin) DEF_MAT_REV(KQKQR, KQRKQ)
312 44 : DEF_MAT(KQRKR, Ter_WhiteWin) DEF_MAT_REV(KRKQR, KQRKR)
313 :
314 : // 2M m (all easy wins)
315 44 : DEF_MAT(KQQKL, Ter_WhiteWin) DEF_MAT_REV(KLKQQ, KQQKL)
316 44 : DEF_MAT(KRRKL, Ter_WhiteWin) DEF_MAT_REV(KLKRR, KRRKL)
317 44 : DEF_MAT(KQRKL, Ter_WhiteWin) DEF_MAT_REV(KLKQR, KQRKL)
318 44 : DEF_MAT(KQQKD, Ter_WhiteWin) DEF_MAT_REV(KDKQQ, KQQKD)
319 44 : DEF_MAT(KRRKD, Ter_WhiteWin) DEF_MAT_REV(KDKRR, KRRKD)
320 44 : DEF_MAT(KQRKD, Ter_WhiteWin) DEF_MAT_REV(KDKQR, KQRKD)
321 44 : DEF_MAT(KQQKN, Ter_WhiteWin) DEF_MAT_REV(KNKQQ, KQQKN)
322 44 : DEF_MAT(KRRKN, Ter_WhiteWin) DEF_MAT_REV(KNKRR, KRRKN)
323 44 : DEF_MAT(KQRKN, Ter_WhiteWin) DEF_MAT_REV(KNKQR, KQRKN)
324 :
325 : // 2m M
326 44 : DEF_MAT(KLDKQ, Ter_HardToWin) DEF_MAT_REV(KQKLD,KLDKQ)
327 44 : DEF_MAT(KLDKR, Ter_LikelyDraw) DEF_MAT_REV(KRKLD,KLDKR)
328 44 : DEF_MAT(KLLKQ, Ter_HardToWin) DEF_MAT_REV(KQKLL,KLLKQ)
329 44 : DEF_MAT(KLLKR, Ter_LikelyDraw) DEF_MAT_REV(KRKLL,KLLKR)
330 44 : DEF_MAT(KDDKQ, Ter_HardToWin) DEF_MAT_REV(KQKDD,KDDKQ)
331 44 : DEF_MAT(KDDKR, Ter_LikelyDraw) DEF_MAT_REV(KRKDD,KDDKR)
332 44 : DEF_MAT(KNNKQ, Ter_HardToWin) DEF_MAT_REV(KQKNN,KNNKQ)
333 44 : DEF_MAT(KNNKR, Ter_LikelyDraw) DEF_MAT_REV(KRKNN,KNNKR)
334 44 : DEF_MAT(KLNKQ, Ter_HardToWin) DEF_MAT_REV(KQKLN,KLNKQ)
335 44 : DEF_MAT(KLNKR, Ter_LikelyDraw) DEF_MAT_REV(KRKLN,KLNKR)
336 44 : DEF_MAT(KDNKQ, Ter_HardToWin) DEF_MAT_REV(KQKDN,KDNKQ)
337 44 : DEF_MAT(KDNKR, Ter_LikelyDraw) DEF_MAT_REV(KRKDN,KDNKR)
338 :
339 : // 2m m : all draw
340 44 : DEF_MAT(KLDKL, Ter_LikelyDraw) DEF_MAT_REV(KLKLD,KLDKL)
341 44 : DEF_MAT(KLDKD, Ter_LikelyDraw) DEF_MAT_REV(KDKLD,KLDKD)
342 44 : DEF_MAT(KLDKN, Ter_LikelyDraw) DEF_MAT_REV(KNKLD,KLDKN)
343 44 : DEF_MAT(KLLKL, Ter_LikelyDraw) DEF_MAT_REV(KLKLL,KLLKL)
344 44 : DEF_MAT(KLLKD, Ter_LikelyDraw) DEF_MAT_REV(KDKLL,KLLKD)
345 44 : DEF_MAT(KLLKN, Ter_LikelyDraw) DEF_MAT_REV(KNKLL,KLLKN)
346 44 : DEF_MAT(KDDKL, Ter_LikelyDraw) DEF_MAT_REV(KLKDD,KDDKL)
347 44 : DEF_MAT(KDDKD, Ter_LikelyDraw) DEF_MAT_REV(KDKDD,KDDKD)
348 44 : DEF_MAT(KDDKN, Ter_LikelyDraw) DEF_MAT_REV(KNKDD,KDDKN)
349 44 : DEF_MAT(KNNKL, Ter_LikelyDraw) DEF_MAT_REV(KLKNN,KNNKL)
350 44 : DEF_MAT(KNNKD, Ter_LikelyDraw) DEF_MAT_REV(KDKNN,KNNKD)
351 44 : DEF_MAT(KNNKN, Ter_LikelyDraw) DEF_MAT_REV(KNKNN,KNNKN)
352 44 : DEF_MAT(KLNKL, Ter_LikelyDraw) DEF_MAT_REV(KLKLN,KLNKL)
353 44 : DEF_MAT(KLNKD, Ter_LikelyDraw) DEF_MAT_REV(KDKLN,KLNKD)
354 44 : DEF_MAT(KLNKN, Ter_LikelyDraw) DEF_MAT_REV(KNKLN,KLNKN)
355 44 : DEF_MAT(KDNKL, Ter_LikelyDraw) DEF_MAT_REV(KLKDN,KDNKL)
356 44 : DEF_MAT(KDNKD, Ter_LikelyDraw) DEF_MAT_REV(KDKDN,KDNKD)
357 44 : DEF_MAT(KDNKN, Ter_LikelyDraw) DEF_MAT_REV(KNKDN,KDNKN)
358 :
359 : // Q x : all should be win (against rook with helper)
360 66 : DEF_MAT_H(KQKR, Ter_WhiteWinWithHelper,&helperKXK) DEF_MAT_REV_H(KRKQ,KQKR,&helperKXK)
361 66 : DEF_MAT_H(KQKL, Ter_WhiteWinWithHelper,&helperKXK) DEF_MAT_REV_H(KLKQ,KQKL,&helperKXK)
362 66 : DEF_MAT_H(KQKD, Ter_WhiteWinWithHelper,&helperKXK) DEF_MAT_REV_H(KDKQ,KQKD,&helperKXK)
363 66 : DEF_MAT_H(KQKN, Ter_WhiteWinWithHelper,&helperKXK) DEF_MAT_REV_H(KNKQ,KQKN,&helperKXK)
364 :
365 : // R x : all should be draw
366 44 : DEF_MAT(KRKL, Ter_LikelyDraw) DEF_MAT_REV(KLKR,KRKL)
367 44 : DEF_MAT(KRKD, Ter_LikelyDraw) DEF_MAT_REV(KDKR,KRKD)
368 44 : DEF_MAT(KRKN, Ter_LikelyDraw) DEF_MAT_REV(KNKR,KRKN)
369 :
370 : // B x : all are draw
371 44 : DEF_MAT(KLKN, Ter_MaterialDraw) DEF_MAT_REV(KNKL,KLKN)
372 44 : DEF_MAT(KDKN, Ter_MaterialDraw) DEF_MAT_REV(KNKD,KDKN)
373 :
374 : // X 0 : QR win, BN draw
375 66 : DEF_MAT_H(KQK, Ter_WhiteWinWithHelper,&helperKXK) DEF_MAT_REV_H(KKQ,KQK,&helperKXK)
376 66 : DEF_MAT_H(KRK, Ter_WhiteWinWithHelper,&helperKXK) DEF_MAT_REV_H(KKR,KRK,&helperKXK)
377 44 : DEF_MAT(KLK, Ter_MaterialDraw) DEF_MAT_REV(KKL,KLK)
378 44 : DEF_MAT(KDK, Ter_MaterialDraw) DEF_MAT_REV(KKD,KDK)
379 44 : DEF_MAT(KNK, Ter_MaterialDraw) DEF_MAT_REV(KKN,KNK)
380 :
381 : // 2X 0 : all win except LL, DD, NN
382 44 : DEF_MAT(KQQK, Ter_WhiteWin) DEF_MAT_REV(KKQQ,KQQK)
383 44 : DEF_MAT(KRRK, Ter_WhiteWin) DEF_MAT_REV(KKRR,KRRK)
384 66 : DEF_MAT_H(KLDK, Ter_WhiteWinWithHelper,&helperKmmK) DEF_MAT_REV_H(KKLD,KLDK,&helperKmmK)
385 44 : DEF_MAT(KLLK, Ter_MaterialDraw) DEF_MAT_REV(KKLL,KLLK)
386 44 : DEF_MAT(KDDK, Ter_MaterialDraw) DEF_MAT_REV(KKDD,KDDK)
387 44 : DEF_MAT(KNNK, Ter_MaterialDraw) DEF_MAT_REV(KKNN,KNNK)
388 66 : DEF_MAT_H(KLNK, Ter_WhiteWinWithHelper,&helperKmmK) DEF_MAT_REV_H(KKLN,KLNK,&helperKmmK)
389 66 : DEF_MAT_H(KDNK, Ter_WhiteWinWithHelper,&helperKmmK) DEF_MAT_REV_H(KKDN,KDNK,&helperKmmK)
390 :
391 : // Rm R : draws
392 44 : DEF_MAT(KRNKR, Ter_LikelyDraw) DEF_MAT_REV(KRKRN,KRNKR)
393 44 : DEF_MAT(KRLKR, Ter_LikelyDraw) DEF_MAT_REV(KRKRL,KRLKR)
394 44 : DEF_MAT(KRDKR, Ter_LikelyDraw) DEF_MAT_REV(KRKRD,KRDKR)
395 :
396 : // Rm m : draws
397 44 : DEF_MAT(KRNKN, Ter_HardToWin) DEF_MAT_REV(KNKRN,KRNKN)
398 44 : DEF_MAT(KRNKL, Ter_HardToWin) DEF_MAT_REV(KLKRN,KRNKL)
399 44 : DEF_MAT(KRNKD, Ter_HardToWin) DEF_MAT_REV(KDKRN,KRNKD)
400 44 : DEF_MAT(KRLKN, Ter_HardToWin) DEF_MAT_REV(KNKRL,KRLKN)
401 44 : DEF_MAT(KRLKL, Ter_HardToWin) DEF_MAT_REV(KLKRL,KRLKL)
402 44 : DEF_MAT(KRLKD, Ter_HardToWin) DEF_MAT_REV(KDKRL,KRLKD)
403 44 : DEF_MAT(KRDKN, Ter_HardToWin) DEF_MAT_REV(KNKRD,KRDKN)
404 44 : DEF_MAT(KRDKL, Ter_HardToWin) DEF_MAT_REV(KLKRD,KRDKL)
405 44 : DEF_MAT(KRDKD, Ter_HardToWin) DEF_MAT_REV(KDKRD,KRDKD)
406 :
407 : // Qm Q : draws
408 44 : DEF_MAT(KQNKQ, Ter_LikelyDraw) DEF_MAT_REV(KQKQN,KQNKQ)
409 44 : DEF_MAT(KQLKQ, Ter_LikelyDraw) DEF_MAT_REV(KQKQL,KQLKQ)
410 44 : DEF_MAT(KQDKQ, Ter_LikelyDraw) DEF_MAT_REV(KQKQD,KQDKQ)
411 :
412 : // Qm R : wins
413 66 : DEF_MAT_H(KQNKR, Ter_WhiteWin,&helperKXK) DEF_MAT_REV_H(KRKQN,KQNKR,&helperKXK)
414 66 : DEF_MAT_H(KQLKR, Ter_WhiteWin,&helperKXK) DEF_MAT_REV_H(KRKQL,KQLKR,&helperKXK)
415 66 : DEF_MAT_H(KQDKR, Ter_WhiteWin,&helperKXK) DEF_MAT_REV_H(KRKQD,KQRKR,&helperKXK)
416 :
417 : // Q Rm : draws
418 44 : DEF_MAT(KQKRN, Ter_LikelyDraw) DEF_MAT_REV(KRNKQ,KQKRN)
419 44 : DEF_MAT(KQKRL, Ter_LikelyDraw) DEF_MAT_REV(KRLKQ,KQKRL)
420 44 : DEF_MAT(KQKRD, Ter_LikelyDraw) DEF_MAT_REV(KRDKQ,KQKRD)
421 :
422 : // Opposite bishop with Ps
423 44 : DEF_MAT(KLPKD, Ter_LikelyDraw) DEF_MAT_REV(KDKLP,KLPKD)
424 44 : DEF_MAT(KDPKL, Ter_LikelyDraw) DEF_MAT_REV(KLKDP,KDPKL)
425 44 : DEF_MAT(KLPPKD, Ter_LikelyDraw) DEF_MAT_REV(KDKLPP,KLPPKD)
426 44 : DEF_MAT(KDPPKL, Ter_LikelyDraw) DEF_MAT_REV(KLKDPP,KDPPKL)
427 :
428 : // KPK
429 66 : DEF_MAT_H(KPK, Ter_WhiteWinWithHelper,&helperKPK) DEF_MAT_REV_H(KKP,KPK,&helperKPK)
430 :
431 : // KBPK
432 66 : DEF_MAT_H(KLPK, Ter_WhiteWinWithHelper,&helperKBPK) DEF_MAT_REV_H(KKLP,KLPK,&helperKBPK)
433 66 : DEF_MAT_H(KDPK, Ter_WhiteWinWithHelper,&helperKBPK) DEF_MAT_REV_H(KKDP,KDPK,&helperKBPK)
434 :
435 : ///@todo other (with more pawn ...)
436 :
437 : #endif
438 22 : }
439 :
440 22218 : Terminaison probeMaterialHashTable(const Position::Material &mat) {
441 22218 : const Hash h = getMaterialHash(mat);
442 22218 : if (h == nullHash) return Ter_Unknown;
443 22218 : return materialHashTable[h].t;
444 : }
445 :
446 10853906 : void updateMaterialOther(Position &p) {
447 10853906 : p.mat[Co_White][M_M] = p.mat[Co_White][M_q] + p.mat[Co_White][M_r];
448 10853906 : p.mat[Co_White][M_m] = p.mat[Co_White][M_b] + p.mat[Co_White][M_n];
449 10853906 : p.mat[Co_White][M_t] = p.mat[Co_White][M_M] + p.mat[Co_White][M_m];
450 : const BitBoard wb = p.whiteBishop();
451 10853906 : p.mat[Co_White][M_bl] = (uint8_t)BB::countBit(wb & BB::whiteSquare);
452 10853906 : p.mat[Co_White][M_bd] = (uint8_t)BB::countBit(wb & BB::blackSquare);
453 :
454 10853906 : p.mat[Co_Black][M_M] = p.mat[Co_Black][M_q] + p.mat[Co_Black][M_r];
455 10853906 : p.mat[Co_Black][M_m] = p.mat[Co_Black][M_b] + p.mat[Co_Black][M_n];
456 10853906 : p.mat[Co_Black][M_t] = p.mat[Co_Black][M_M] + p.mat[Co_Black][M_m];
457 : const BitBoard bb = p.blackBishop();
458 10853906 : p.mat[Co_Black][M_bl] = (uint8_t)BB::countBit(bb & BB::whiteSquare);
459 10853906 : p.mat[Co_Black][M_bd] = (uint8_t)BB::countBit(bb & BB::blackSquare);
460 10853906 : }
461 :
462 308 : void initMaterial(Position &p) { // M_p .. M_k is the same as P_wp .. P_wk
463 924 : for (Color c = Co_White; c < Co_End; ++c)
464 4312 : for (Piece pp = P_wp; pp <= P_wk; ++pp)
465 3696 : p.mat[c][pp] = static_cast<uint8_t>(BB::countBit(p.pieces_const(c, pp)));
466 308 : updateMaterialOther(p);
467 308 : }
468 :
469 422894 : void updateMaterialProm(Position &p, const Square toBeCaptured, const MType mt) {
470 422894 : --p.mat[~p.c][PieceTools::getPieceType(p, toBeCaptured)]; // capture if to square is not empty
471 422894 : --p.mat[p.c][M_p]; // pawn
472 422894 : ++p.mat[p.c][promShift(mt)]; // prom piece
473 422894 : }
474 :
475 : } // namespace MaterialHash
|