Rev 154 | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 33 | pmbaty | 1 | #include "chess.h" |
| 108 | pmbaty | 2 | #include "evaluate.h" |
| 33 | pmbaty | 3 | #include "data.h" |
| 154 | pmbaty | 4 | /* last modified 08/03/16 */ |
| 33 | pmbaty | 5 | /* |
| 6 | ******************************************************************************* |
||
| 7 | * * |
||
| 8 | * Evaluate() is used to evaluate the chess board. Broadly, it addresses * |
||
| 9 | * four (4) distinct areas: (1) material score which is simply a summing of * |
||
| 10 | * piece types multiplied by piece values; (2) pawn scoring which considers * |
||
| 11 | * placement of pawns and also evaluates passed pawns, particularly in end- * |
||
| 12 | * game situations; (3) piece scoring which evaluates the placement of each * |
||
| 13 | * piece as well as things like piece mobility; (4) king safety which * |
||
| 108 | pmbaty | 14 | * considers the pawn shelter around the king and enemy pieces and how close * |
| 15 | * they are to assist in a king-side attack. * |
||
| 33 | pmbaty | 16 | * * |
| 17 | ******************************************************************************* |
||
| 18 | */ |
||
| 19 | int Evaluate(TREE * RESTRICT tree, int ply, int wtm, int alpha, int beta) { |
||
| 20 | PAWN_HASH_ENTRY *ptable; |
||
| 21 | PXOR *pxtable; |
||
| 108 | pmbaty | 22 | int score, side, can_win = 3, phase, lscore, cutoff; |
| 33 | pmbaty | 23 | |
| 24 | /* |
||
| 108 | pmbaty | 25 | ************************************************************* |
| 26 | * * |
||
| 27 | * First thing we do is if -DSKILL was passed in to the * |
||
| 28 | * compiler, we burn some time to slow the search down, * |
||
| 29 | * then we fall into the normal evaluation code. * |
||
| 30 | * * |
||
| 31 | ************************************************************* |
||
| 33 | pmbaty | 32 | */ |
| 33 | #if defined(SKILL) |
||
| 34 | if (skill < 100) { |
||
| 35 | int i, j; |
||
| 108 | pmbaty | 36 | for (i = 0; i < burnc[skill / 10] && !abort_search; i++) |
| 37 | for (j = 1; j < 10 && !abort_search; j++) |
||
| 33 | pmbaty | 38 | burner[j - 1] = burner[j - 1] * burner[j]; |
| 108 | pmbaty | 39 | if (TimeCheck(tree, 1)) |
| 40 | abort_search = 1; |
||
| 33 | pmbaty | 41 | } |
| 42 | #endif |
||
| 43 | /* |
||
| 108 | pmbaty | 44 | ************************************************************* |
| 45 | * * |
||
| 46 | * First lazy cutoff attempt. If the material score is way * |
||
| 47 | * below alpha or way above beta (way above means so far * |
||
| 48 | * above it is very unlikely the positional score can bring * |
||
| 49 | * the total score back into the alpha / beta window) then * |
||
| 50 | * we take what is known as a "lazy evaluation exit" and * |
||
| 51 | * avoid the computational cost of a full evaluation in a * |
||
| 52 | * position where one side is way ahead or behind. * |
||
| 53 | * * |
||
| 54 | ************************************************************* |
||
| 33 | pmbaty | 55 | */ |
| 108 | pmbaty | 56 | cutoff = (TotalPieces(white, occupied) && TotalPieces(black, occupied)) |
| 57 | ? KNIGHT_VALUE : ROOK_VALUE; |
||
| 58 | lscore = MaterialSTM(wtm); |
||
| 59 | if (lscore + cutoff < alpha) |
||
| 60 | return alpha; |
||
| 61 | if (lscore - cutoff > beta) |
||
| 62 | return beta; |
||
| 33 | pmbaty | 63 | /* |
| 108 | pmbaty | 64 | ************************************************************* |
| 65 | * * |
||
| 66 | * Check for draws where one side seems to be ahead, but * |
||
| 67 | * has no actual winning chances. One simple example is a * |
||
| 68 | * king, bishop and rook pawn, with the wrong colored * |
||
| 69 | * bishop and the enemy king too close to the promotion * |
||
| 70 | * square. * |
||
| 71 | * * |
||
| 72 | * The variable "can_win" uses 2 bits. If White can * |
||
| 73 | * actually win in this position, bit 1 is set. If Black * |
||
| 74 | * can actually win in this position, bit 0 is set. If * |
||
| 75 | * both sides can win, both bits are set. This is used * |
||
| 76 | * later to drag the score closer to a draw score if the * |
||
| 77 | * side with the better score can't actually win. * |
||
| 78 | * * |
||
| 79 | * Note that we only set these bits in minimal material * |
||
| 80 | * positions (both sides have < 13 points of material * |
||
| 81 | * total). Otherwise we assume normal scoring should * |
||
| 82 | * apply. * |
||
| 83 | * * |
||
| 84 | ************************************************************* |
||
| 33 | pmbaty | 85 | */ |
| 108 | pmbaty | 86 | tree->evaluations++; |
| 87 | tree->score_mg = 0; |
||
| 88 | tree->score_eg = 0; |
||
| 89 | EvaluateMaterial(tree, wtm); |
||
| 90 | if (TotalPieces(white, occupied) < 13 && TotalPieces(black, occupied) < 13) |
||
| 91 | for (side = black; side <= white; side++) |
||
| 92 | if (!EvaluateWinningChances(tree, side, wtm)) |
||
| 93 | can_win ^= (1 << side); |
||
| 33 | pmbaty | 94 | /* |
| 108 | pmbaty | 95 | ************************************************************* |
| 96 | * * |
||
| 97 | * Determine if this position should be evaluated to force * |
||
| 98 | * mate (neither side has pawns) or if it should be * |
||
| 99 | * evaluated normally. * |
||
| 100 | * * |
||
| 101 | * Note the special case of no pawns, one side is ahead in * |
||
| 102 | * total material, but the game is a hopeless draw. KRN vs * |
||
| 103 | * KR is one example. If EvaluateWinningChances() * |
||
| 104 | * determines that the side with extra material can not * |
||
| 105 | * win, the score is pulled closer to a draw although it * |
||
| 106 | * can not collapse completely to the drawscore as it is * |
||
| 107 | * possible to lose KRB vs KR if the KR side lets the king * |
||
| 108 | * get trapped on the edge of the board. * |
||
| 109 | * * |
||
| 110 | ************************************************************* |
||
| 33 | pmbaty | 111 | */ |
| 112 | tree->all_pawns = Pawns(black) | Pawns(white); |
||
| 113 | if (!tree->all_pawns) { |
||
| 114 | if (TotalPieces(white, occupied) > 3 || TotalPieces(black, occupied) > 3) { |
||
| 115 | if (Material > 0) |
||
| 116 | EvaluateMate(tree, white); |
||
| 117 | else if (Material < 0) |
||
| 118 | EvaluateMate(tree, black); |
||
| 108 | pmbaty | 119 | if (tree->score_eg > DrawScore(1) && !(can_win & 2)) |
| 120 | tree->score_eg = tree->score_eg / 16; |
||
| 121 | if (tree->score_eg < DrawScore(1) && !(can_win & 1)) |
||
| 122 | tree->score_eg = tree->score_eg / 16; |
||
| 33 | pmbaty | 123 | #if defined(SKILL) |
| 124 | if (skill < 100) |
||
| 156 | pmbaty | 125 | tree->score_eg = (int) // Pierre-Marie Baty -- added type cast |
| 126 | (skill * tree->score_eg / 100 + ((100 - |
||
| 33 | pmbaty | 127 | skill) * PAWN_VALUE * (uint64_t) Random32() / |
| 156 | pmbaty | 128 | 0x100000000ull) / 100); |
| 33 | pmbaty | 129 | #endif |
| 130 | return (wtm) ? tree->score_eg : -tree->score_eg; |
||
| 131 | } |
||
| 132 | } |
||
| 133 | /* |
||
| 108 | pmbaty | 134 | ************************************************************* |
| 135 | * * |
||
| 136 | * Now evaluate pawns. If the pawn hash signature has not * |
||
| 137 | * changed from the last entry to Evaluate() then we * |
||
| 138 | * already have everything we need in the pawn hash entry. * |
||
| 139 | * In this case, we do not need to call EvaluatePawns() at * |
||
| 140 | * all. EvaluatePawns() does all of the analysis for * |
||
| 141 | * information specifically regarding only pawns. In many * |
||
| 142 | * cases, it merely records the presence/absence of * |
||
| 143 | * positional pawn features because those features also * |
||
| 144 | * depends on pieces. * |
||
| 145 | * * |
||
| 146 | * Note that anything put into EvaluatePawns() can only * |
||
| 147 | * consider the placement of pawns. Kings or other pieces * |
||
| 148 | * can not influence the score because those pieces are not * |
||
| 149 | * hashed into the pawn hash signature. Violating this * |
||
| 150 | * principle leads to lots of very difficult and * |
||
| 151 | * challenging debugging problems. * |
||
| 152 | * * |
||
| 153 | ************************************************************* |
||
| 33 | pmbaty | 154 | */ |
| 155 | else { |
||
| 156 | if (PawnHashKey == tree->pawn_score.key) { |
||
| 157 | tree->score_mg += tree->pawn_score.score_mg; |
||
| 158 | tree->score_eg += tree->pawn_score.score_eg; |
||
| 159 | } |
||
| 160 | /* |
||
| 108 | pmbaty | 161 | ************************************************************* |
| 162 | * * |
||
| 163 | * First check to see if this position has been handled * |
||
| 164 | * before. If so, we can skip the work saved in the pawn * |
||
| 165 | * hash table. * |
||
| 166 | * * |
||
| 167 | ************************************************************* |
||
| 33 | pmbaty | 168 | */ |
| 169 | else { |
||
| 170 | ptable = pawn_hash_table + (PawnHashKey & pawn_hash_mask); |
||
| 171 | pxtable = (PXOR *) & (tree->pawn_score); |
||
| 172 | tree->pawn_score = *ptable; |
||
| 108 | pmbaty | 173 | tree->pawn_score.key ^= pxtable->entry[1] ^ pxtable->entry[2]; |
| 33 | pmbaty | 174 | if (tree->pawn_score.key != PawnHashKey) { |
| 175 | tree->pawn_score.key = PawnHashKey; |
||
| 176 | tree->pawn_score.score_mg = 0; |
||
| 177 | tree->pawn_score.score_eg = 0; |
||
| 178 | for (side = black; side <= white; side++) |
||
| 179 | EvaluatePawns(tree, side); |
||
| 180 | ptable->key = |
||
| 108 | pmbaty | 181 | pxtable->entry[0] ^ pxtable->entry[1] ^ pxtable->entry[2]; |
| 182 | memcpy((char *) ptable + 8, (char *) &(tree->pawn_score) + 8, |
||
| 183 | sizeof(PAWN_HASH_ENTRY) - 8); |
||
| 33 | pmbaty | 184 | } |
| 185 | tree->score_mg += tree->pawn_score.score_mg; |
||
| 186 | tree->score_eg += tree->pawn_score.score_eg; |
||
| 187 | } |
||
| 188 | /* |
||
| 108 | pmbaty | 189 | ************************************************************* |
| 190 | * * |
||
| 191 | * If there are any passed pawns, first call * |
||
| 192 | * EvaluatePassedPawns() to evaluate them. Then, if one * |
||
| 193 | * side has a passed pawn and the other side has no pieces, * |
||
| 194 | * call EvaluatePassedPawnRaces() to see if the passed pawn * |
||
| 195 | * can be stopped from promoting. * |
||
| 196 | * * |
||
| 197 | ************************************************************* |
||
| 33 | pmbaty | 198 | */ |
| 199 | if (tree->pawn_score.passed[black] || tree->pawn_score.passed[white]) { |
||
| 200 | for (side = black; side <= white; side++) |
||
| 201 | if (tree->pawn_score.passed[side]) |
||
| 202 | EvaluatePassedPawns(tree, side, wtm); |
||
| 203 | if ((TotalPieces(white, occupied) == 0 && |
||
| 204 | tree->pawn_score.passed[black]) |
||
| 205 | || (TotalPieces(black, occupied) == 0 && |
||
| 206 | tree->pawn_score.passed[white])) |
||
| 207 | EvaluatePassedPawnRaces(tree, wtm); |
||
| 208 | } |
||
| 209 | } |
||
| 210 | /* |
||
| 108 | pmbaty | 211 | ************************************************************* |
| 212 | * * |
||
| 213 | * Call EvaluateCastling() to evaluate castling potential. * |
||
| 214 | * Note we only do this when that side has not castled at * |
||
| 215 | * the root. * |
||
| 216 | * * |
||
| 217 | ************************************************************* |
||
| 33 | pmbaty | 218 | */ |
| 219 | for (side = black; side <= white; side++) |
||
| 108 | pmbaty | 220 | if (Castle(1, side) > 0) |
| 221 | EvaluateCastling(tree, ply, side); |
||
| 33 | pmbaty | 222 | /* |
| 108 | pmbaty | 223 | ************************************************************* |
| 224 | * * |
||
| 225 | * The "dangerous" flag simply indicates whether that side * |
||
| 226 | * has enough material to whip up a mating attack if the * |
||
| 227 | * other side is careless (Q + minor or better, or RR + two * |
||
| 228 | * minors or better). * |
||
| 229 | * * |
||
| 230 | ************************************************************* |
||
| 33 | pmbaty | 231 | */ |
| 108 | pmbaty | 232 | tree->dangerous[white] = (Queens(white) && TotalPieces(white, occupied) > 9) |
| 233 | || (TotalPieces(white, rook) > 1 && TotalPieces(white, occupied) > 15); |
||
| 234 | tree->dangerous[black] = (Queens(black) && TotalPieces(black, occupied) > 9) |
||
| 235 | || (TotalPieces(black, rook) > 1 && TotalPieces(black, occupied) > 15); |
||
| 236 | /* |
||
| 237 | ************************************************************* |
||
| 238 | * * |
||
| 239 | * Second lazy evaluation test. We have computed the large * |
||
| 240 | * positional scores (except for king safety). If the * |
||
| 241 | * score is too far outside the alpha/beta window, we skip * |
||
| 242 | * the piece scoring which is the most expensive of all the * |
||
| 243 | * evaluation terms, and simply use what we have at this * |
||
| 244 | * point. * |
||
| 245 | * * |
||
| 246 | ************************************************************* |
||
| 247 | */ |
||
| 33 | pmbaty | 248 | phase = |
| 249 | Min(62, TotalPieces(white, occupied) + TotalPieces(black, occupied)); |
||
| 250 | score = ((tree->score_mg * phase) + (tree->score_eg * (62 - phase))) / 62; |
||
| 251 | lscore = (wtm) ? score : -score; |
||
| 108 | pmbaty | 252 | int w_mat = (2 * TotalPieces(white, rook)) + TotalPieces(white, |
| 253 | knight) + TotalPieces(white, bishop); |
||
| 254 | int b_mat = (2 * TotalPieces(black, rook)) + TotalPieces(black, |
||
| 255 | knight) + TotalPieces(black, bishop); |
||
| 256 | cutoff = 72 + (w_mat + b_mat) * 8 + abs(w_mat - b_mat) * 16; |
||
| 257 | if (tree->dangerous[white] || tree->dangerous[black]) |
||
| 258 | cutoff += 35; |
||
| 259 | /* |
||
| 260 | ************************************************************* |
||
| 261 | * * |
||
| 262 | * Then evaluate pieces if the lazy eval test fails. * |
||
| 263 | * * |
||
| 264 | * Note: We MUST evaluate kings last, since their scoring * |
||
| 265 | * depends on the tropism scores computed by the other * |
||
| 266 | * piece evaluators. Do NOT try to collapse the following * |
||
| 267 | * loops into one loop. That will break things since it * |
||
| 268 | * would violate the kings last rule. More importantly * |
||
| 269 | * there is no benefit as the loops below are unrolled by * |
||
| 270 | * the compiler anyway. * |
||
| 271 | * * |
||
| 272 | ************************************************************* |
||
| 273 | */ |
||
| 33 | pmbaty | 274 | if (lscore + cutoff > alpha && lscore - cutoff < beta) { |
| 275 | tree->tropism[white] = 0; |
||
| 276 | tree->tropism[black] = 0; |
||
| 277 | for (side = black; side <= white; side++) |
||
| 154 | pmbaty | 278 | if (Knights(side)) |
| 279 | EvaluateKnights(tree, side); |
||
| 33 | pmbaty | 280 | for (side = black; side <= white; side++) |
| 154 | pmbaty | 281 | if (Bishops(side)) |
| 282 | EvaluateBishops(tree, side); |
||
| 33 | pmbaty | 283 | for (side = black; side <= white; side++) |
| 154 | pmbaty | 284 | if (Rooks(side)) |
| 285 | EvaluateRooks(tree, side); |
||
| 33 | pmbaty | 286 | for (side = black; side <= white; side++) |
| 154 | pmbaty | 287 | if (Queens(side)) |
| 288 | EvaluateQueens(tree, side); |
||
| 33 | pmbaty | 289 | for (side = black; side <= white; side++) |
| 108 | pmbaty | 290 | EvaluateKing(tree, ply, side); |
| 33 | pmbaty | 291 | } |
| 292 | /* |
||
| 108 | pmbaty | 293 | ************************************************************* |
| 294 | * * |
||
| 295 | * Caclulate the final score, which is interpolated between * |
||
| 296 | * the middlegame score and endgame score based on the * |
||
| 297 | * material left on the board. * |
||
| 298 | * * |
||
| 299 | * Adjust the score if one side can't win, but the score * |
||
| 300 | * actually favors that side significantly. * |
||
| 301 | * * |
||
| 302 | ************************************************************* |
||
| 33 | pmbaty | 303 | */ |
| 304 | score = ((tree->score_mg * phase) + (tree->score_eg * (62 - phase))) / 62; |
||
| 305 | score = EvaluateDraws(tree, ply, can_win, score); |
||
| 306 | #if defined(SKILL) |
||
| 307 | if (skill < 100) |
||
| 156 | pmbaty | 308 | score = (int) // Pierre-Marie Baty -- added type cast |
| 309 | (skill * score / 100 + ((100 - |
||
| 33 | pmbaty | 310 | skill) * PAWN_VALUE * (uint64_t) Random32() / 0x100000000ull) / |
| 156 | pmbaty | 311 | 100); |
| 33 | pmbaty | 312 | #endif |
| 313 | return (wtm) ? score : -score; |
||
| 314 | } |
||
| 315 | |||
| 108 | pmbaty | 316 | /* last modified 10/19/15 */ |
| 33 | pmbaty | 317 | /* |
| 318 | ******************************************************************************* |
||
| 319 | * * |
||
| 320 | * EvaluateBishops() is used to evaluate bishops. * |
||
| 321 | * * |
||
| 322 | ******************************************************************************* |
||
| 323 | */ |
||
| 324 | void EvaluateBishops(TREE * RESTRICT tree, int side) { |
||
| 325 | uint64_t temp, moves; |
||
| 108 | pmbaty | 326 | int square, special, i, mobility; |
| 327 | int score_eg = 0, score_mg = 0, enemy = Flip(side), tpawns; |
||
| 33 | pmbaty | 328 | /* |
| 329 | ************************************************************ |
||
| 330 | * * |
||
| 331 | * First, locate each bishop and add in its piece/square * |
||
| 108 | pmbaty | 332 | * table score. * |
| 33 | pmbaty | 333 | * * |
| 334 | ************************************************************ |
||
| 335 | */ |
||
| 336 | for (temp = Bishops(side); temp; temp &= temp - 1) { |
||
| 337 | square = LSB(temp); |
||
| 338 | score_mg += bval[mg][side][square]; |
||
| 339 | score_eg += bval[eg][side][square]; |
||
| 340 | /* |
||
| 341 | ************************************************************ |
||
| 342 | * * |
||
| 343 | * Evaluate for "outposts" which is a bishop that can't be * |
||
| 344 | * driven off by an enemy pawn, and which is supported by * |
||
| 345 | * a friendly pawn. * |
||
| 346 | * * |
||
| 347 | * If the enemy has NO minor to take this bishop, then * |
||
| 348 | * increase the bonus. * |
||
| 349 | * * |
||
| 350 | ************************************************************ |
||
| 351 | */ |
||
| 108 | pmbaty | 352 | special = bishop_outpost[side][square]; |
| 353 | if (special) { |
||
| 354 | if (!(mask_pattacks[enemy][square] & Pawns(enemy))) { |
||
| 355 | if (pawn_attacks[enemy][square] & Pawns(side)) { |
||
| 356 | special += special / 2; |
||
| 357 | if (!Knights(enemy) && !(Color(square) & Bishops(enemy))) |
||
| 358 | special += bishop_outpost[side][square]; |
||
| 33 | pmbaty | 359 | } |
| 108 | pmbaty | 360 | score_eg += special; |
| 361 | score_mg += special; |
||
| 33 | pmbaty | 362 | } |
| 108 | pmbaty | 363 | } |
| 33 | pmbaty | 364 | /* |
| 365 | ************************************************************ |
||
| 366 | * * |
||
| 108 | pmbaty | 367 | * Next we count the number of friendly pawns on the same * |
| 368 | * color squares as the bishop. This is a bad thing since * |
||
| 369 | * it restricts the bishop's ability to move. We only do * |
||
| 370 | * this if there is only one bishop for this side. * |
||
| 33 | pmbaty | 371 | * * |
| 372 | ************************************************************ |
||
| 373 | */ |
||
| 108 | pmbaty | 374 | if (TotalPieces(side, bishop) == 1) { |
| 375 | if (dark_squares & SetMask(square)) |
||
| 376 | tpawns = PopCnt(dark_squares & Pawns(side)); |
||
| 377 | else |
||
| 378 | tpawns = PopCnt(~dark_squares & Pawns(side)); |
||
| 379 | score_mg -= tpawns * bishop_pawns_on_color[mg]; |
||
| 380 | score_eg -= tpawns * bishop_pawns_on_color[eg]; |
||
| 33 | pmbaty | 381 | } |
| 382 | /* |
||
| 383 | ************************************************************ |
||
| 384 | * * |
||
| 108 | pmbaty | 385 | * Mobility counts the number of squares the bishop * |
| 386 | * attacks, excluding squares with friendly pieces, and * |
||
| 387 | * weighs each square according to centralization. * |
||
| 33 | pmbaty | 388 | * * |
| 389 | ************************************************************ |
||
| 390 | */ |
||
| 391 | mobility = BishopMobility(square, OccupiedSquares); |
||
| 392 | if (mobility < 0 && (pawn_attacks[enemy][square] & Pawns(side)) |
||
| 393 | && (File(square) == FILEA || File(square) == FILEH)) |
||
| 394 | mobility -= 8; |
||
| 395 | score_mg += mobility; |
||
| 396 | score_eg += mobility; |
||
| 397 | /* |
||
| 398 | ************************************************************ |
||
| 399 | * * |
||
| 400 | * Adjust the tropism count for this piece. * |
||
| 401 | * * |
||
| 402 | ************************************************************ |
||
| 403 | */ |
||
| 404 | if (tree->dangerous[side]) { |
||
| 405 | moves = king_attacks[KingSQ(enemy)]; |
||
| 108 | pmbaty | 406 | i = ((bishop_attacks[square] & moves) && |
| 407 | ((BishopAttacks(square, OccupiedSquares & ~Queens(side))) & moves)) |
||
| 408 | ? 1 : Distance(square, KingSQ(enemy)); |
||
| 409 | tree->tropism[side] += king_tropism_b[i]; |
||
| 33 | pmbaty | 410 | } |
| 411 | } |
||
| 108 | pmbaty | 412 | /* |
| 413 | ************************************************************ |
||
| 414 | * * |
||
| 415 | * Add a bonus if this side has a pair of bishops, which * |
||
| 416 | * can become very strong in open positions. * |
||
| 417 | * * |
||
| 418 | ************************************************************ |
||
| 419 | */ |
||
| 420 | if (TotalPieces(side, bishop) > 1) { |
||
| 421 | score_mg += bishop_pair[mg]; |
||
| 422 | score_eg += bishop_pair[eg]; |
||
| 423 | } |
||
| 154 | pmbaty | 424 | /* |
| 425 | ************************************************************ |
||
| 426 | * * |
||
| 427 | * Check for pawns on both wings, which makes a bishop * |
||
| 428 | * even more valuable against an enemy knight * |
||
| 429 | * * |
||
| 430 | ************************************************************ |
||
| 431 | */ |
||
| 432 | else { |
||
| 433 | if (tree->all_pawns & mask_fgh && tree->all_pawns & mask_abc) { |
||
| 434 | score_mg += bishop_wing_pawns[mg]; |
||
| 435 | score_eg += bishop_wing_pawns[eg]; |
||
| 436 | } |
||
| 437 | } |
||
| 33 | pmbaty | 438 | tree->score_mg += sign[side] * score_mg; |
| 439 | tree->score_eg += sign[side] * score_eg; |
||
| 440 | } |
||
| 441 | |||
| 108 | pmbaty | 442 | /* last modified 01/03/15 */ |
| 33 | pmbaty | 443 | /* |
| 444 | ******************************************************************************* |
||
| 445 | * * |
||
| 108 | pmbaty | 446 | * EvaluateCastling() is called when "side" has not castled at the root. * |
| 447 | * Its main purpose is to determine if it has either castled somewhere in * |
||
| 448 | * the tree, or else has lost all (or some) castling rights, which reduces * |
||
| 449 | * options significantly. * |
||
| 33 | pmbaty | 450 | * * |
| 451 | ******************************************************************************* |
||
| 452 | */ |
||
| 108 | pmbaty | 453 | void EvaluateCastling(TREE * RESTRICT tree, int ply, int side) { |
| 454 | int enemy = Flip(side), oq, score_mg = 0;; |
||
| 33 | pmbaty | 455 | |
| 456 | /* |
||
| 457 | ************************************************************ |
||
| 458 | * * |
||
| 108 | pmbaty | 459 | * If the king castled during the search, we are done and * |
| 460 | * we leave it to EvaluateKing() to figure out how safe it * |
||
| 461 | * is. If it has not castled, we give a significant * |
||
| 462 | * penalty if the king moves since that loses all castling * |
||
| 463 | * rights, otherwise we give a smaller penalty for moving * |
||
| 464 | * a rook and giving up castling rights to that side of * |
||
| 465 | * the board. The penalty is always increased if the * |
||
| 466 | * opponent has a queen since the position is much more * |
||
| 467 | * dangerous. * |
||
| 33 | pmbaty | 468 | * * |
| 469 | ************************************************************ |
||
| 470 | */ |
||
| 108 | pmbaty | 471 | oq = (Queens(enemy)) ? 3 : 1; |
| 472 | if (Castle(ply, side) != Castle(1, side)) { |
||
| 473 | if (Castle(ply, side) == 0) |
||
| 474 | score_mg -= oq * development_losing_castle; |
||
| 475 | else if (Castle(ply, side) > 0) |
||
| 476 | score_mg -= (oq * development_losing_castle) / 2; |
||
| 477 | } else |
||
| 478 | score_mg -= oq * development_not_castled; |
||
| 33 | pmbaty | 479 | tree->score_mg += sign[side] * score_mg; |
| 480 | } |
||
| 481 | |||
| 108 | pmbaty | 482 | /* last modified 01/03/15 */ |
| 33 | pmbaty | 483 | /* |
| 484 | ******************************************************************************* |
||
| 485 | * * |
||
| 486 | * EvaluateDraws() is used to adjust the score based on whether the side * |
||
| 487 | * that appears to be better according the computed score can actually win * |
||
| 488 | * the game or not. If the answer is "no" then the score is reduced * |
||
| 489 | * significantly to reflect the lack of winning chances. * |
||
| 490 | * * |
||
| 491 | ******************************************************************************* |
||
| 492 | */ |
||
| 493 | int EvaluateDraws(TREE * RESTRICT tree, int ply, int can_win, int score) { |
||
| 494 | /* |
||
| 495 | ************************************************************ |
||
| 496 | * * |
||
| 497 | * If the ending has only bishops of opposite colors, the * |
||
| 108 | pmbaty | 498 | * score is pulled closer to a draw. * |
| 33 | pmbaty | 499 | * * |
| 500 | * If this is a pure BOC ending, it is very drawish unless * |
||
| 501 | * one side has at least 4 pawns. More pawns makes it * |
||
| 502 | * harder for a bishop and king to stop them all from * |
||
| 503 | * advancing. * |
||
| 504 | * * |
||
| 108 | pmbaty | 505 | * If the following are both true: * |
| 506 | * * |
||
| 507 | * black and white have less than a queen left (pieces * |
||
| 508 | * only). * |
||
| 509 | * * |
||
| 510 | * both have one bishop and they are opposite colored. * |
||
| 511 | * * |
||
| 512 | * then either * |
||
| 513 | * * |
||
| 514 | * (a) both have just one bishop, both have less than 4 * |
||
| 515 | * pawns or one side has only one more pawn than the * |
||
| 516 | * other side then score is divided by 2 with draw score * |
||
| 517 | * added in; or * |
||
| 518 | * * |
||
| 519 | * (b) pieces are equal, then score is reduced by 25% * |
||
| 520 | * with draw score added in. * |
||
| 521 | * * |
||
| 33 | pmbaty | 522 | ************************************************************ |
| 523 | */ |
||
| 524 | if (TotalPieces(white, occupied) <= 8 && TotalPieces(black, occupied) <= 8) { |
||
| 525 | if (TotalPieces(white, bishop) == 1 && TotalPieces(black, bishop) == 1) |
||
| 526 | if (square_color[LSB(Bishops(black))] != |
||
| 527 | square_color[LSB(Bishops(white))]) { |
||
| 528 | if (TotalPieces(white, occupied) == 3 && |
||
| 529 | TotalPieces(black, occupied) == 3 && |
||
| 530 | ((TotalPieces(white, pawn) < 4 && TotalPieces(black, pawn) < 4) |
||
| 531 | || Abs(TotalPieces(white, pawn) - TotalPieces(black, |
||
| 532 | pawn)) < 2)) |
||
| 533 | score = score / 2 + DrawScore(1); |
||
| 534 | else if (TotalPieces(white, occupied) == TotalPieces(black, occupied)) |
||
| 535 | score = 3 * score / 4 + DrawScore(1); |
||
| 536 | } |
||
| 537 | } |
||
| 108 | pmbaty | 538 | /* |
| 539 | ************************************************************ |
||
| 540 | * * |
||
| 541 | * Final score adjustment. If the score says white is * |
||
| 542 | * better, but can_win says white can not win, or if the * |
||
| 543 | * score says black is better, but can_win says black can * |
||
| 544 | * not win, then we divide the score by 16, and then add * |
||
| 545 | * in the draw score. If the can_win says neither side * |
||
| 546 | * can win, we just set the score to draw score and exit. * |
||
| 547 | * * |
||
| 548 | ************************************************************ |
||
| 549 | */ |
||
| 33 | pmbaty | 550 | if (can_win != 3) { |
| 108 | pmbaty | 551 | if (can_win & 1) { |
| 552 | if (score > DrawScore(1)) |
||
| 553 | score = score / 16 + DrawScore(1); |
||
| 554 | } else if (can_win & 2) { |
||
| 555 | if (score < DrawScore(1)) |
||
| 556 | score = score / 16 + DrawScore(1); |
||
| 557 | } else |
||
| 558 | score = DrawScore(1); |
||
| 33 | pmbaty | 559 | } |
| 560 | /* |
||
| 561 | ************************************************************ |
||
| 562 | * * |
||
| 563 | * If we are running into the 50-move rule, then start * |
||
| 564 | * dragging the score toward draw. This is the idea of a * |
||
| 565 | * "weariness factor" as mentioned by Dave Slate many * |
||
| 566 | * times. This avoids slamming into a draw at move 50 and * |
||
| 567 | * having to move something quickly, rather than slowly * |
||
| 568 | * discovering that the score is dropping and that pushing * |
||
| 569 | * a pawn or capturing something will cause it to go back * |
||
| 570 | * to its correct value a bit more smoothly. * |
||
| 571 | * * |
||
| 572 | ************************************************************ |
||
| 573 | */ |
||
| 574 | if (Reversible(ply) > 80) { |
||
| 108 | pmbaty | 575 | int closeness = 101 - Reversible(ply); |
| 33 | pmbaty | 576 | |
| 108 | pmbaty | 577 | score = DrawScore(1) + score * closeness / 20; |
| 33 | pmbaty | 578 | } |
| 579 | return score; |
||
| 580 | } |
||
| 581 | |||
| 108 | pmbaty | 582 | /* last modified 01/03/15 */ |
| 33 | pmbaty | 583 | /* |
| 584 | ******************************************************************************* |
||
| 585 | * * |
||
| 586 | * EvaluateHasOpposition() is used to determine if one king stands in * |
||
| 587 | * "opposition" to the other. If the kings are opposed on the same file or * |
||
| 588 | * else are opposed on the same diagonal, then the side not-to-move has the * |
||
| 589 | * opposition and the side-to-move must give way. * |
||
| 590 | * * |
||
| 591 | ******************************************************************************* |
||
| 592 | */ |
||
| 593 | int EvaluateHasOpposition(int on_move, int king, int enemy_king) { |
||
| 594 | int file_distance, rank_distance; |
||
| 595 | |||
| 596 | file_distance = FileDistance(king, enemy_king); |
||
| 597 | rank_distance = RankDistance(king, enemy_king); |
||
| 598 | if (rank_distance < 2) |
||
| 599 | return 1; |
||
| 600 | if (on_move) { |
||
| 601 | if (rank_distance & 1) |
||
| 602 | rank_distance--; |
||
| 603 | if (file_distance & 1) |
||
| 604 | file_distance--; |
||
| 605 | } |
||
| 606 | if (!(file_distance & 1) && !(rank_distance & 1)) |
||
| 607 | return 1; |
||
| 608 | return 0; |
||
| 609 | } |
||
| 610 | |||
| 108 | pmbaty | 611 | /* last modified 01/03/15 */ |
| 33 | pmbaty | 612 | /* |
| 613 | ******************************************************************************* |
||
| 614 | * * |
||
| 108 | pmbaty | 615 | * EvaluateKing() is used to evaluate a king. * |
| 33 | pmbaty | 616 | * * |
| 617 | ******************************************************************************* |
||
| 618 | */ |
||
| 108 | pmbaty | 619 | void EvaluateKing(TREE * RESTRICT tree, int ply, int side) { |
| 33 | pmbaty | 620 | int score_eg = 0, score_mg = 0, defects; |
| 621 | int ksq = KingSQ(side), enemy = Flip(side); |
||
| 622 | |||
| 623 | /* |
||
| 624 | ************************************************************ |
||
| 625 | * * |
||
| 626 | * First, check for where the king should be if this is an * |
||
| 108 | pmbaty | 627 | * endgame. The basic idea is to centralize unless the * |
| 628 | * king is needed to deal with a passed enemy pawn. * |
||
| 33 | pmbaty | 629 | * * |
| 630 | ************************************************************ |
||
| 631 | */ |
||
| 108 | pmbaty | 632 | score_eg += kval[side][ksq]; |
| 33 | pmbaty | 633 | /* |
| 634 | ************************************************************ |
||
| 635 | * * |
||
| 636 | * Do castle scoring, if the king has castled, the pawns * |
||
| 637 | * in front are important. If not castled yet, the pawns * |
||
| 638 | * on the kingside should be preserved for this. * |
||
| 639 | * * |
||
| 640 | ************************************************************ |
||
| 641 | */ |
||
| 642 | if (tree->dangerous[enemy]) { |
||
| 643 | defects = 0; |
||
| 644 | if (Castle(ply, side) <= 0) { |
||
| 108 | pmbaty | 645 | if (File(ksq) > FILEE) |
| 646 | defects = tree->pawn_score.defects_k[side]; |
||
| 647 | else if (File(ksq) < FILED) |
||
| 648 | defects = tree->pawn_score.defects_q[side]; |
||
| 649 | else |
||
| 650 | defects = tree->pawn_score.defects_m[side]; |
||
| 33 | pmbaty | 651 | } else { |
| 652 | if (Castle(ply, side) == 3) |
||
| 653 | defects = |
||
| 654 | Min(Min(tree->pawn_score.defects_k[side], |
||
| 108 | pmbaty | 655 | tree->pawn_score.defects_m[side]), |
| 33 | pmbaty | 656 | tree->pawn_score.defects_q[side]); |
| 657 | else if (Castle(ply, side) == 1) |
||
| 658 | defects = |
||
| 659 | Min(tree->pawn_score.defects_k[side], |
||
| 108 | pmbaty | 660 | tree->pawn_score.defects_m[side]); |
| 33 | pmbaty | 661 | else |
| 662 | defects = |
||
| 663 | Min(tree->pawn_score.defects_q[side], |
||
| 108 | pmbaty | 664 | tree->pawn_score.defects_m[side]); |
| 33 | pmbaty | 665 | if (defects < 3) |
| 666 | defects = 3; |
||
| 667 | } |
||
| 668 | /* |
||
| 669 | ************************************************************ |
||
| 670 | * * |
||
| 671 | * Fold in the king tropism and king pawn shelter scores * |
||
| 672 | * together. * |
||
| 673 | * * |
||
| 674 | ************************************************************ |
||
| 675 | */ |
||
| 676 | if (tree->tropism[enemy] < 0) |
||
| 677 | tree->tropism[enemy] = 0; |
||
| 678 | else if (tree->tropism[enemy] > 15) |
||
| 679 | tree->tropism[enemy] = 15; |
||
| 680 | if (defects > 15) |
||
| 681 | defects = 15; |
||
| 682 | score_mg -= king_safety[defects][tree->tropism[enemy]]; |
||
| 683 | } |
||
| 684 | tree->score_mg += sign[side] * score_mg; |
||
| 685 | tree->score_eg += sign[side] * score_eg; |
||
| 686 | } |
||
| 687 | |||
| 108 | pmbaty | 688 | /* last modified 01/03/15 */ |
| 33 | pmbaty | 689 | /* |
| 690 | ******************************************************************************* |
||
| 691 | * * |
||
| 692 | * EvaluateKingsFile computes defects for a file, based on whether the file * |
||
| 693 | * is open or half-open. If there are friendly pawns still on the file, * |
||
| 694 | * they are penalized for advancing in front of the king. * |
||
| 695 | * * |
||
| 696 | ******************************************************************************* |
||
| 697 | */ |
||
| 108 | pmbaty | 698 | int EvaluateKingsFile(TREE * RESTRICT tree, int side, int first, int last) { |
| 699 | int defects = 0, file, enemy = Flip(side); |
||
| 33 | pmbaty | 700 | |
| 108 | pmbaty | 701 | for (file = first; file <= last; file++) |
| 33 | pmbaty | 702 | if (!(file_mask[file] & tree->all_pawns)) |
| 703 | defects += open_file[file]; |
||
| 704 | else { |
||
| 705 | if (!(file_mask[file] & Pawns(enemy))) |
||
| 706 | defects += half_open_file[file] / 2; |
||
| 707 | else |
||
| 708 | defects += |
||
| 108 | pmbaty | 709 | pawn_defects[side][Rank(MostAdvanced(enemy, |
| 33 | pmbaty | 710 | file_mask[file] & Pawns(enemy)))]; |
| 711 | if (!(file_mask[file] & Pawns(side))) |
||
| 712 | defects += half_open_file[file]; |
||
| 713 | else if (!(Pawns(side) & SetMask(sqflip[side][A2] + file))) { |
||
| 714 | defects++; |
||
| 715 | if (!(Pawns(side) & SetMask(sqflip[side][A3] + file))) |
||
| 716 | defects++; |
||
| 717 | } |
||
| 718 | } |
||
| 719 | return defects; |
||
| 720 | } |
||
| 721 | |||
| 108 | pmbaty | 722 | /* last modified 10/19/15 */ |
| 33 | pmbaty | 723 | /* |
| 724 | ******************************************************************************* |
||
| 725 | * * |
||
| 726 | * EvaluateKnights() is used to evaluate knights. * |
||
| 727 | * * |
||
| 728 | ******************************************************************************* |
||
| 729 | */ |
||
| 730 | void EvaluateKnights(TREE * RESTRICT tree, int side) { |
||
| 731 | uint64_t temp; |
||
| 108 | pmbaty | 732 | int square, special, i, score_eg = 0, score_mg = 0, enemy = Flip(side); |
| 33 | pmbaty | 733 | |
| 734 | /* |
||
| 735 | ************************************************************ |
||
| 736 | * * |
||
| 737 | * First fold in centralization score from the piece/ * |
||
| 738 | * square table "nval". * |
||
| 739 | * * |
||
| 740 | ************************************************************ |
||
| 741 | */ |
||
| 742 | for (temp = Knights(side); temp; temp &= temp - 1) { |
||
| 743 | square = LSB(temp); |
||
| 744 | score_mg += nval[mg][side][square]; |
||
| 745 | score_eg += nval[eg][side][square]; |
||
| 746 | /* |
||
| 747 | ************************************************************ |
||
| 748 | * * |
||
| 749 | * Evaluate for "outposts" which is a knight that can't * |
||
| 750 | * be driven off by an enemy pawn, and which is supported * |
||
| 751 | * by a friendly pawn. * |
||
| 752 | * * |
||
| 753 | * If the enemy has NO minor to take this knight, then * |
||
| 754 | * increase the bonus. * |
||
| 755 | * * |
||
| 756 | ************************************************************ |
||
| 757 | */ |
||
| 108 | pmbaty | 758 | special = knight_outpost[side][square]; |
| 759 | if (special && !(mask_pattacks[enemy][square] & Pawns(enemy))) { |
||
| 33 | pmbaty | 760 | if (pawn_attacks[enemy][square] & Pawns(side)) { |
| 108 | pmbaty | 761 | special += special / 2; |
| 33 | pmbaty | 762 | if (!Knights(enemy) && !(Color(square) & Bishops(enemy))) |
| 108 | pmbaty | 763 | special += knight_outpost[side][square]; |
| 33 | pmbaty | 764 | } |
| 108 | pmbaty | 765 | score_eg += special; |
| 766 | score_mg += special; |
||
| 33 | pmbaty | 767 | } |
| 768 | /* |
||
| 769 | ************************************************************ |
||
| 770 | * * |
||
| 771 | * Adjust the tropism count for this piece. * |
||
| 772 | * * |
||
| 773 | ************************************************************ |
||
| 774 | */ |
||
| 775 | if (tree->dangerous[side]) { |
||
| 108 | pmbaty | 776 | i = Distance(square, KingSQ(enemy)); |
| 777 | tree->tropism[side] += king_tropism_n[i]; |
||
| 33 | pmbaty | 778 | } |
| 779 | } |
||
| 780 | tree->score_mg += sign[side] * score_mg; |
||
| 781 | tree->score_eg += sign[side] * score_eg; |
||
| 782 | } |
||
| 783 | |||
| 108 | pmbaty | 784 | /* last modified 03/30/15 */ |
| 33 | pmbaty | 785 | /* |
| 786 | ******************************************************************************* |
||
| 787 | * * |
||
| 788 | * EvaluateMate() is used to evaluate positions where neither side has pawns * |
||
| 789 | * and one side has enough material to force checkmate. It simply trys to * |
||
| 790 | * force the losing king to the edge of the board, and then to the corner * |
||
| 791 | * where mates are easier to find. * |
||
| 792 | * * |
||
| 793 | ******************************************************************************* |
||
| 794 | */ |
||
| 795 | void EvaluateMate(TREE * RESTRICT tree, int side) { |
||
| 108 | pmbaty | 796 | int mate_score = 0, enemy = Flip(side); |
| 33 | pmbaty | 797 | |
| 798 | /* |
||
| 799 | ************************************************************ |
||
| 800 | * * |
||
| 108 | pmbaty | 801 | * If the winning side has a bishop + knight and the other * |
| 802 | * side has no pieces or pawns, then use the special * |
||
| 803 | * bishop_knight scoring board for the losing king to * |
||
| 804 | * force it to the right corner for mate. * |
||
| 33 | pmbaty | 805 | * * |
| 806 | ************************************************************ |
||
| 807 | */ |
||
| 108 | pmbaty | 808 | if (!TotalPieces(enemy, occupied) && TotalPieces(side, bishop) == 1 && |
| 809 | TotalPieces(side, knight) == 1) { |
||
| 33 | pmbaty | 810 | if (dark_squares & Bishops(side)) |
| 811 | mate_score = b_n_mate_dark_squares[KingSQ(enemy)]; |
||
| 812 | else |
||
| 813 | mate_score = b_n_mate_light_squares[KingSQ(enemy)]; |
||
| 814 | } |
||
| 815 | /* |
||
| 816 | ************************************************************ |
||
| 817 | * * |
||
| 108 | pmbaty | 818 | * The winning side has to force the losing king to the * |
| 33 | pmbaty | 819 | * edge of the board. * |
| 820 | * * |
||
| 821 | ************************************************************ |
||
| 822 | */ |
||
| 108 | pmbaty | 823 | else |
| 33 | pmbaty | 824 | mate_score = mate[KingSQ(enemy)]; |
| 108 | pmbaty | 825 | /* |
| 826 | ************************************************************ |
||
| 827 | * * |
||
| 828 | * And for either, it is important to bring the winning * |
||
| 829 | * king to help force mate. * |
||
| 830 | * * |
||
| 831 | ************************************************************ |
||
| 832 | */ |
||
| 833 | mate_score -= Distance(KingSQ(side), KingSQ(enemy)) * king_king_tropism; |
||
| 33 | pmbaty | 834 | tree->score_eg += sign[side] * mate_score; |
| 835 | } |
||
| 836 | |||
| 108 | pmbaty | 837 | /* last modified 10/19/15 */ |
| 33 | pmbaty | 838 | /* |
| 839 | ******************************************************************************* |
||
| 840 | * * |
||
| 841 | * EvaluateMaterial() is used to evaluate material on the board. It really * |
||
| 842 | * accomplishes detecting cases where one side has made a 'bad trade' as the * |
||
| 843 | * comments below show. * |
||
| 844 | * * |
||
| 845 | ******************************************************************************* |
||
| 846 | */ |
||
| 847 | void EvaluateMaterial(TREE * RESTRICT tree, int wtm) { |
||
| 108 | pmbaty | 848 | int score_mg, score_eg, majors, minors; |
| 33 | pmbaty | 849 | |
| 850 | /* |
||
| 108 | pmbaty | 851 | ************************************************************* |
| 852 | * * |
||
| 853 | * We start with the raw Material balance for the current * |
||
| 854 | * position, then adjust this with a small bonus for the * |
||
| 855 | * side on move. * |
||
| 856 | * * |
||
| 857 | ************************************************************* |
||
| 33 | pmbaty | 858 | */ |
| 859 | score_mg = Material + ((wtm) ? wtm_bonus[mg] : -wtm_bonus[mg]); |
||
| 860 | score_eg = Material + ((wtm) ? wtm_bonus[eg] : -wtm_bonus[eg]); |
||
| 861 | /* |
||
| 108 | pmbaty | 862 | ************************************************************* |
| 863 | * * |
||
| 864 | * test 1. if Majors or Minors are not balanced, then if * |
||
| 865 | * one side is only an exchange up or down, we give a * |
||
| 866 | * penalty to the side that is an exchange down, but not as * |
||
| 867 | * big a penalty as the bad trade case below. * |
||
| 868 | * * |
||
| 869 | * test 2. if Majors or Minors are not balanced, then if * |
||
| 870 | * one side has more piece material points than the other * |
||
| 871 | * (using normal piece values of 3, 3, 5, 9 for N, B, R * |
||
| 872 | * and Q) then the side that is behind in piece material * |
||
| 873 | * gets a penalty. * |
||
| 874 | * * |
||
| 875 | ************************************************************* |
||
| 33 | pmbaty | 876 | */ |
| 108 | pmbaty | 877 | majors = |
| 878 | TotalPieces(white, rook) + 2 * TotalPieces(white, |
||
| 879 | queen) - TotalPieces(black, rook) - 2 * TotalPieces(black, queen); |
||
| 880 | minors = |
||
| 881 | TotalPieces(white, knight) + TotalPieces(white, |
||
| 882 | bishop) - TotalPieces(black, knight) - TotalPieces(black, bishop); |
||
| 883 | if (majors || minors) { |
||
| 884 | if (Abs(TotalPieces(white, occupied) - TotalPieces(black, occupied)) != 2 |
||
| 885 | && TotalPieces(white, occupied) - TotalPieces(black, occupied) != 0) { |
||
| 886 | score_mg += |
||
| 887 | Sign(TotalPieces(white, occupied) - TotalPieces(black, |
||
| 888 | occupied)) * bad_trade; |
||
| 889 | score_eg += |
||
| 890 | Sign(TotalPieces(white, occupied) - TotalPieces(black, |
||
| 891 | occupied)) * bad_trade; |
||
| 33 | pmbaty | 892 | } |
| 893 | } |
||
| 894 | tree->score_mg += score_mg; |
||
| 895 | tree->score_eg += score_eg; |
||
| 896 | } |
||
| 897 | |||
| 108 | pmbaty | 898 | /* last modified 11/27/15 */ |
| 33 | pmbaty | 899 | /* |
| 900 | ******************************************************************************* |
||
| 901 | * * |
||
| 902 | * EvaluatePassedPawns() is used to evaluate passed pawns and the danger * |
||
| 108 | pmbaty | 903 | * they produce. This code considers pieces as well, so it MUST NOT be done * |
| 904 | * in the normal EvaluatePawns() code since that hashes information based * |
||
| 905 | * only on the position of pawns. * |
||
| 33 | pmbaty | 906 | * * |
| 108 | pmbaty | 907 | * This is a significant rewrite of passed pawn evaluation, with the primary * |
| 908 | * change being to collect the passed pawn scoring into one place, rather * |
||
| 909 | * than have it scattered around all over the place. One example is the old * |
||
| 910 | * rook_behind_passed_pawn scoring term that was done in rook scoring. It * |
||
| 911 | * is now done here along with other passed pawn terms such as blockaded and * |
||
| 912 | * the ability to advance or not. * |
||
| 913 | * * |
||
| 33 | pmbaty | 914 | ******************************************************************************* |
| 915 | */ |
||
| 916 | void EvaluatePassedPawns(TREE * RESTRICT tree, int side, int wtm) { |
||
| 108 | pmbaty | 917 | uint64_t behind, forward, backward, attacked, defended, thispawn; |
| 918 | int file, square, score, score_mg = 0, score_eg = 0, next_sq; |
||
| 919 | int pawns, rank, mg_base, eg_base, bonus, enemy = Flip(side); |
||
| 920 | uint64_t fsliders = Queens(side) | Rooks(side); |
||
| 921 | uint64_t esliders = Queens(enemy) | Rooks(enemy); |
||
| 33 | pmbaty | 922 | |
| 923 | /* |
||
| 924 | ************************************************************ |
||
| 925 | * * |
||
| 108 | pmbaty | 926 | * Initialize. The base value "passed_pawn[rank]" is * |
| 927 | * almost the "square" of the rank. That got a bit too * |
||
| 928 | * big, so a hand-tuned set of values, one per rank, * |
||
| 929 | * proved to be a better value. * |
||
| 33 | pmbaty | 930 | * * |
| 931 | ************************************************************ |
||
| 932 | */ |
||
| 933 | for (pawns = tree->pawn_score.passed[side]; pawns; pawns &= pawns - 1) { |
||
| 934 | file = LSB8Bit(pawns); |
||
| 108 | pmbaty | 935 | thispawn = Pawns(side) & file_mask[file]; |
| 936 | if (thispawn) { |
||
| 937 | square = MostAdvanced(side, thispawn); |
||
| 938 | rank = rankflip[side][Rank(square)]; |
||
| 939 | score = passed_pawn[rank]; |
||
| 33 | pmbaty | 940 | /* |
| 941 | ************************************************************ |
||
| 942 | * * |
||
| 108 | pmbaty | 943 | * For endgame only, we add in a bonus based on how close * |
| 944 | * our king is to this pawn and a penalty based on how * |
||
| 945 | * close the enemy king is. We also try to keep our king * |
||
| 946 | * ahead of the pawn so it can escort it to promotion. We * |
||
| 947 | * only do this for passed pawns whose base score value is * |
||
| 948 | * greater than zero (ie pawns on ranks 4-7 since those * |
||
| 949 | * are the ones threatening to become a major problem.) * |
||
| 950 | * Also, if you happen to think that a small bonus for a * |
||
| 951 | * passed pawn on the 3rd rank might be useful, consider * |
||
| 952 | * speed. If the 3rd rank score is non-zero, that will * |
||
| 953 | * trigger a significant amount of work below. In testing * |
||
| 954 | * the additional cost more than offset the gain and so it * |
||
| 955 | * is basically ignored unless rank > 3. * |
||
| 956 | * * |
||
| 33 | pmbaty | 957 | ************************************************************ |
| 958 | */ |
||
| 108 | pmbaty | 959 | if (score) { |
| 960 | mg_base = score * passed_pawn_base[mg]; |
||
| 961 | eg_base = score * passed_pawn_base[eg]; |
||
| 962 | next_sq = square + direction[side]; |
||
| 963 | eg_base += |
||
| 964 | Distance(KingSQ(enemy), |
||
| 965 | next_sq) * 2 * score - Distance(KingSQ(side), next_sq) * score; |
||
| 966 | if (rank < RANK7) |
||
| 967 | eg_base -= |
||
| 968 | Distance(KingSQ(side), next_sq + direction[side]) * score / 2; |
||
| 33 | pmbaty | 969 | /* |
| 970 | ************************************************************ |
||
| 971 | * * |
||
| 108 | pmbaty | 972 | * If the pawn is not blockaded, we need to see whether it * |
| 973 | * can actually advance or not. Note that this directly * |
||
| 974 | * gives a bonus for blockading a passed pawn since the * |
||
| 975 | * mobility evaluation below will not be applied when the * |
||
| 976 | * pawn is blockaded by any piece. * |
||
| 33 | pmbaty | 977 | * * |
| 108 | pmbaty | 978 | * Step one is to determine if the squares in front of the * |
| 979 | * pawn are attacked by the enemy. If not, we add in a * |
||
| 980 | * significant score bonus. If some are attacked, we look * |
||
| 981 | * to see if at least the square directly in front of the * |
||
| 982 | * pawn is not attacked so that we can advance one square, * |
||
| 983 | * anyway. This gets a smaller score bonus. * |
||
| 33 | pmbaty | 984 | * * |
| 985 | ************************************************************ |
||
| 986 | */ |
||
| 108 | pmbaty | 987 | if (!(OccupiedSquares & SetMask(next_sq))) { |
| 988 | bonus = 0; |
||
| 989 | if (Pawns(side) & pawn_attacks[enemy][next_sq]) |
||
| 990 | bonus = passed_pawn_free_advance; |
||
| 991 | else { |
||
| 992 | attacked = 0; |
||
| 993 | forward = (side) ? plus8dir[square] : minus8dir[square]; |
||
| 994 | backward = (side) ? minus8dir[square] : plus8dir[square]; |
||
| 995 | if ((behind = backward & esliders) && |
||
| 996 | (FileAttacks(square) & behind)) |
||
| 997 | attacked = forward; |
||
| 998 | else |
||
| 999 | attacked = Attacked(tree, enemy, forward); |
||
| 1000 | if (!attacked) |
||
| 1001 | bonus = passed_pawn_free_advance; |
||
| 1002 | else if (!(attacked & SetMask(next_sq))) |
||
| 1003 | bonus = passed_pawn_free_advance_1; |
||
| 33 | pmbaty | 1004 | /* |
| 1005 | ************************************************************ |
||
| 1006 | * * |
||
| 108 | pmbaty | 1007 | * Step two is to determine if the squares in front of the * |
| 1008 | * pawn are are defended by the friendly side. If all are * |
||
| 1009 | * defended (such as with a rook or queen behind the pawn * |
||
| 1010 | * or the king in front and to one side of the pawn, then * |
||
| 1011 | * we give a bonus (but smaller than the previous cases). * |
||
| 1012 | * As a last resort, if we at least defend the square in * |
||
| 1013 | * front of the pawn, we give a small bonus. * |
||
| 33 | pmbaty | 1014 | * * |
| 1015 | ************************************************************ |
||
| 1016 | */ |
||
| 108 | pmbaty | 1017 | if ((behind = backward & fsliders) && |
| 1018 | (FileAttacks(square) & behind)) |
||
| 1019 | defended = forward; |
||
| 1020 | else |
||
| 1021 | defended = Attacked(tree, side, forward); |
||
| 1022 | if (defended == forward) |
||
| 1023 | bonus += passed_pawn_defended; |
||
| 1024 | else if (defended & SetMask(next_sq)) |
||
| 1025 | bonus += passed_pawn_defended_1; |
||
| 1026 | } |
||
| 33 | pmbaty | 1027 | /* |
| 1028 | ************************************************************ |
||
| 1029 | * * |
||
| 108 | pmbaty | 1030 | * Fold in the bonus for this pawn and move on to the next * |
| 1031 | * (if there is one). Note that the bonus computed above * |
||
| 1032 | * is multiplied by the base passed pawn score for this * |
||
| 1033 | * particular rank. * |
||
| 33 | pmbaty | 1034 | * * |
| 1035 | ************************************************************ |
||
| 1036 | */ |
||
| 108 | pmbaty | 1037 | mg_base += bonus * score; |
| 1038 | eg_base += bonus * score; |
||
| 1039 | } |
||
| 1040 | score_mg += mg_base; |
||
| 1041 | score_eg += eg_base; |
||
| 1042 | } else |
||
| 1043 | score_eg += 4; |
||
| 33 | pmbaty | 1044 | } |
| 1045 | } |
||
| 1046 | /* |
||
| 1047 | ************************************************************ |
||
| 1048 | * * |
||
| 108 | pmbaty | 1049 | * All pawns done, add score to the two evaluation values * |
| 1050 | * and return. * |
||
| 33 | pmbaty | 1051 | * * |
| 1052 | ************************************************************ |
||
| 1053 | */ |
||
| 1054 | tree->score_mg += sign[side] * score_mg; |
||
| 1055 | tree->score_eg += sign[side] * score_eg; |
||
| 1056 | } |
||
| 1057 | |||
| 108 | pmbaty | 1058 | /* last modified 11/27/15 */ |
| 33 | pmbaty | 1059 | /* |
| 1060 | ******************************************************************************* |
||
| 1061 | * * |
||
| 1062 | * EvaluatePassedPawnRaces() is used to evaluate passed pawns when one * |
||
| 1063 | * side has passed pawns and the other side (or neither) has pieces. In * |
||
| 108 | pmbaty | 1064 | * such a case, the critical question is can the defending king stop the * |
| 1065 | * pawn from queening or is it too far away? If only one side has pawns * |
||
| 1066 | * that can "run" then the situation is simple. When both sides have pawns * |
||
| 1067 | * that can "run" it becomes more complex as it then becomes necessary to * |
||
| 1068 | * see if one side can use a forced king move to stop the other side, while * |
||
| 1069 | * the other side doesn't have the same ability to stop ours. * |
||
| 33 | pmbaty | 1070 | * * |
| 1071 | * In the case of king and pawn endings with exactly one pawn, the simple * |
||
| 1072 | * evaluation rules are used: if the king is two squares in front of the * |
||
| 1073 | * pawn then it is a win, if the king is one one square in front with the * |
||
| 1074 | * opposition, then it is a win, if the king is on the 6th rank with the * |
||
| 1075 | * pawn close by, it is a win. Rook pawns are handled separately and are * |
||
| 1076 | * more difficult to queen because the king can get trapped in front of the * |
||
| 1077 | * pawn blocking promotion. * |
||
| 1078 | * * |
||
| 1079 | ******************************************************************************* |
||
| 1080 | */ |
||
| 1081 | void EvaluatePassedPawnRaces(TREE * RESTRICT tree, int wtm) { |
||
| 108 | pmbaty | 1082 | uint64_t pawns, thispawn; |
| 1083 | int file, square, queen_distance, pawnsq, passed, side, enemy; |
||
| 33 | pmbaty | 1084 | int queener[2] = { 8, 8 }; |
| 1085 | /* |
||
| 1086 | ************************************************************ |
||
| 1087 | * * |
||
| 1088 | * Check to see if side has one pawn and neither side has * |
||
| 1089 | * any pieces. If so, use the simple pawn evaluation * |
||
| 1090 | * logic. * |
||
| 1091 | * * |
||
| 1092 | ************************************************************ |
||
| 1093 | */ |
||
| 1094 | for (side = black; side <= white; side++) { |
||
| 1095 | enemy = Flip(side); |
||
| 1096 | if (Pawns(side) && !Pawns(enemy) && TotalPieces(white, occupied) == 0 && |
||
| 1097 | TotalPieces(black, occupied) == 0) { |
||
| 1098 | for (pawns = Pawns(side); pawns; pawns &= pawns - 1) { |
||
| 1099 | pawnsq = LSB(pawns); |
||
| 1100 | /* |
||
| 1101 | ************************************************************ |
||
| 1102 | * * |
||
| 1103 | * King must be in front of the pawn or we go no further. * |
||
| 1104 | * * |
||
| 1105 | ************************************************************ |
||
| 1106 | */ |
||
| 1107 | if (sign[side] * Rank(KingSQ(side)) <= sign[side] * Rank(pawnsq)) |
||
| 1108 | continue; |
||
| 1109 | /* |
||
| 1110 | ************************************************************ |
||
| 1111 | * * |
||
| 1112 | * First a special case. If this is a rook pawn, then the * |
||
| 1113 | * king must be on the adjacent file, and be closer to the * |
||
| 1114 | * queening square than the opposing king. * |
||
| 1115 | * * |
||
| 1116 | ************************************************************ |
||
| 1117 | */ |
||
| 1118 | if (File(pawnsq) == FILEA) { |
||
| 1119 | if (File(KingSQ(side)) == FILEB && |
||
| 1120 | Distance(KingSQ(side), |
||
| 1121 | sqflip[side][A8]) < Distance(KingSQ(enemy), |
||
| 1122 | sqflip[side][A8])) { |
||
| 1123 | tree->score_eg += sign[side] * pawn_can_promote; |
||
| 1124 | return; |
||
| 1125 | } |
||
| 1126 | continue; |
||
| 1127 | } else if (File(pawnsq) == FILEH) { |
||
| 1128 | if (File(KingSQ(side)) == FILEG && |
||
| 1129 | Distance(KingSQ(side), |
||
| 1130 | sqflip[side][H8]) < Distance(KingSQ(enemy), |
||
| 1131 | sqflip[side][H8])) { |
||
| 1132 | tree->score_eg += sign[side] * pawn_can_promote; |
||
| 1133 | return; |
||
| 1134 | } |
||
| 1135 | continue; |
||
| 1136 | } |
||
| 1137 | /* |
||
| 1138 | ************************************************************ |
||
| 1139 | * * |
||
| 1140 | * If king is two squares in front of the pawn then it's a * |
||
| 1141 | * win immediately. If the king is on the 6th rank and * |
||
| 1142 | * closer to the pawn than the opposing king, it's also a * |
||
| 1143 | * win. * |
||
| 1144 | * * |
||
| 1145 | ************************************************************ |
||
| 1146 | */ |
||
| 1147 | if (Distance(KingSQ(side), pawnsq) < Distance(KingSQ(enemy), pawnsq)) { |
||
| 1148 | if (sign[side] * Rank(KingSQ(side)) > |
||
| 1149 | sign[side] * (Rank(pawnsq) - 1 + 2 * side)) { |
||
| 1150 | tree->score_eg += sign[side] * pawn_can_promote; |
||
| 1151 | return; |
||
| 1152 | } |
||
| 108 | pmbaty | 1153 | if (Rank(KingSQ(side)) == rank6[side]) { |
| 33 | pmbaty | 1154 | tree->score_eg += sign[side] * pawn_can_promote; |
| 1155 | return; |
||
| 1156 | } |
||
| 1157 | /* |
||
| 1158 | ************************************************************ |
||
| 1159 | * * |
||
| 1160 | * Last chance: if the king is one square in front of the * |
||
| 1161 | * pawn and has the opposition, then it's still a win. * |
||
| 1162 | * * |
||
| 1163 | ************************************************************ |
||
| 1164 | */ |
||
| 1165 | if (Rank(KingSQ(side)) == Rank(pawnsq) - 1 + 2 * side && |
||
| 1166 | EvaluateHasOpposition(wtm == side, KingSQ(side), |
||
| 1167 | KingSQ(enemy))) { |
||
| 1168 | tree->score_eg += sign[side] * pawn_can_promote; |
||
| 1169 | return; |
||
| 1170 | } |
||
| 1171 | } |
||
| 1172 | } |
||
| 1173 | } |
||
| 1174 | /* |
||
| 1175 | ************************************************************ |
||
| 1176 | * * |
||
| 1177 | * Check to see if enemy is out of pieces and stm has * |
||
| 1178 | * passed pawns. If so, see if any of these passed pawns * |
||
| 1179 | * can outrun the defending king and promote. * |
||
| 1180 | * * |
||
| 1181 | ************************************************************ |
||
| 1182 | */ |
||
| 1183 | if (TotalPieces(enemy, occupied) == 0 && tree->pawn_score.passed[side]) { |
||
| 1184 | passed = tree->pawn_score.passed[side]; |
||
| 1185 | for (; passed; passed &= passed - 1) { |
||
| 1186 | file = LSB8Bit(passed); |
||
| 108 | pmbaty | 1187 | thispawn = Pawns(side) & file_mask[file]; |
| 1188 | if (thispawn) { |
||
| 1189 | square = MostAdvanced(side, thispawn); |
||
| 1190 | if (!(pawn_race[side][wtm][square] & Kings(enemy))) { |
||
| 1191 | queen_distance = Abs(rank8[side] - Rank(square)); |
||
| 1192 | if (Kings(side) & ((side) ? plus8dir[square] : minus8dir[square])) { |
||
| 1193 | if (file == FILEA || file == FILEH) |
||
| 1194 | queen_distance = 99; |
||
| 1195 | queen_distance++; |
||
| 1196 | } |
||
| 1197 | if (Rank(square) == rank2[side]) |
||
| 1198 | queen_distance--; |
||
| 1199 | if (queen_distance < queener[side]) |
||
| 1200 | queener[side] = queen_distance; |
||
| 33 | pmbaty | 1201 | } |
| 1202 | } |
||
| 1203 | } |
||
| 1204 | } |
||
| 1205 | } |
||
| 1206 | /* |
||
| 1207 | ************************************************************ |
||
| 1208 | * * |
||
| 1209 | * Now that we know which pawns can outrun the kings for * |
||
| 108 | pmbaty | 1210 | * each side, we need to do determine if one side queens * |
| 1211 | * before the other. If so, that side wins. If they * |
||
| 1212 | * queen at the same time, then we will have to rely on * |
||
| 1213 | * the search to handle queening with check or queening * |
||
| 1214 | * and attacking the opponent's queening square. * |
||
| 33 | pmbaty | 1215 | * * |
| 1216 | ************************************************************ |
||
| 1217 | */ |
||
| 108 | pmbaty | 1218 | if (queener[white] < queener[black]) |
| 33 | pmbaty | 1219 | tree->score_eg += pawn_can_promote + (5 - queener[white]) * 10; |
| 108 | pmbaty | 1220 | else if (queener[black] < queener[white]) |
| 1221 | tree->score_eg -= pawn_can_promote + (5 - queener[black]) * 10; |
||
| 33 | pmbaty | 1222 | } |
| 1223 | |||
| 108 | pmbaty | 1224 | /* last modified 11/27/15 */ |
| 33 | pmbaty | 1225 | /* |
| 1226 | ******************************************************************************* |
||
| 1227 | * * |
||
| 1228 | * EvaluatePawns() is used to evaluate pawns. It evaluates pawns for only * |
||
| 1229 | * one side, and fills in the pawn hash entry information. It requires two * |
||
| 1230 | * calls to evaluate all pawns on the board. Comments below indicate the * |
||
| 1231 | * particular pawn structure features that are evaluated. * |
||
| 1232 | * * |
||
| 108 | pmbaty | 1233 | * This procedure also flags which pawns are passed, since this is scored in * |
| 1234 | * another part of the evaluation because that includes piece information * |
||
| 1235 | * which can not be used here since the pawn hash signature does not include * |
||
| 1236 | * piece information of any kind. * |
||
| 33 | pmbaty | 1237 | * * |
| 108 | pmbaty | 1238 | * Note that a pawn is not penalized for two different reasons. If it is * |
| 1239 | * isolated, it is not backward. Etc. This simplifies evaluation tuning * |
||
| 1240 | * not to mention eliminating the overlap and interaction that was happening * |
||
| 1241 | * previously when multiple penalties could be applied. * |
||
| 1242 | * * |
||
| 33 | pmbaty | 1243 | ******************************************************************************* |
| 1244 | */ |
||
| 1245 | void EvaluatePawns(TREE * RESTRICT tree, int side) { |
||
| 108 | pmbaty | 1246 | uint64_t pawns, attackers, defenders; |
| 1247 | uint64_t doubled, supported, connected, passed, backward; |
||
| 1248 | int square, file, rank, score_eg = 0, score_mg = 0, enemy = Flip(side); |
||
| 1249 | unsigned int isolated, pawn_files = 0; |
||
| 33 | pmbaty | 1250 | |
| 1251 | /* |
||
| 1252 | ************************************************************ |
||
| 1253 | * * |
||
| 108 | pmbaty | 1254 | * Loop through all pawns for this side. * |
| 33 | pmbaty | 1255 | * * |
| 1256 | ************************************************************ |
||
| 1257 | */ |
||
| 1258 | tree->pawn_score.passed[side] = 0; |
||
| 1259 | for (pawns = Pawns(side); pawns; pawns &= pawns - 1) { |
||
| 1260 | square = LSB(pawns); |
||
| 1261 | file = File(square); |
||
| 1262 | rank = rankflip[side][Rank(square)]; |
||
| 108 | pmbaty | 1263 | pawn_files |= 1 << file; |
| 33 | pmbaty | 1264 | /* |
| 1265 | ************************************************************ |
||
| 1266 | * * |
||
| 1267 | * Evaluate pawn advances. Center pawns are encouraged to * |
||
| 108 | pmbaty | 1268 | * occupy central squares, edge pawns are penalized on all * |
| 1269 | * edge squares to encourage capture toward the center, * |
||
| 1270 | * the rest are neutral. * |
||
| 33 | pmbaty | 1271 | * * |
| 1272 | ************************************************************ |
||
| 1273 | */ |
||
| 154 | pmbaty | 1274 | score_mg += pval[side][square]; |
| 33 | pmbaty | 1275 | /* |
| 1276 | ************************************************************ |
||
| 1277 | * * |
||
| 108 | pmbaty | 1278 | * Evaluate isolated pawns, which are penalized based on * |
| 1279 | * which file they occupy. * |
||
| 33 | pmbaty | 1280 | * * |
| 1281 | ************************************************************ |
||
| 1282 | */ |
||
| 108 | pmbaty | 1283 | isolated = !(Pawns(side) & mask_pawn_isolated[square]); |
| 1284 | if (isolated) { |
||
| 1285 | score_mg -= pawn_isolated[mg][file]; |
||
| 1286 | score_eg -= pawn_isolated[eg][file]; |
||
| 33 | pmbaty | 1287 | } |
| 1288 | /* |
||
| 1289 | ************************************************************ |
||
| 1290 | * * |
||
| 108 | pmbaty | 1291 | * Evaluate unsupported pawns, which provide a target * |
| 1292 | * since they are undefended by a pawn. We exclude pawns * |
||
| 1293 | * that are isolated since they have already been given a * |
||
| 1294 | * penalty. * |
||
| 33 | pmbaty | 1295 | * * |
| 1296 | ************************************************************ |
||
| 1297 | */ |
||
| 108 | pmbaty | 1298 | supported = Pawns(side) & pawn_attacks[enemy][square]; |
| 1299 | if (!isolated && !supported) { |
||
| 1300 | score_mg += pawn_unsupported[mg]; |
||
| 1301 | score_eg += pawn_unsupported[eg]; |
||
| 1302 | } |
||
| 33 | pmbaty | 1303 | /* |
| 1304 | ************************************************************ |
||
| 1305 | * * |
||
| 108 | pmbaty | 1306 | * Evaluate doubled pawns. If there are other pawns on * |
| 1307 | * this file in front of this pawn, penalize this pawn. * |
||
| 1308 | * Note that this will NOT penalize both pawns, just the * |
||
| 1309 | * most rearward one that is really almost worthless. * |
||
| 33 | pmbaty | 1310 | * * |
| 108 | pmbaty | 1311 | * The farther apart two doubled pawns (same file) are, * |
| 1312 | * the less weak they are, so the penalty is reduced as * |
||
| 1313 | * this distance increases. * |
||
| 1314 | * * |
||
| 33 | pmbaty | 1315 | ************************************************************ |
| 1316 | */ |
||
| 108 | pmbaty | 1317 | doubled = Pawns(side) & ((side) ? plus8dir[square] : minus8dir[square]); |
| 1318 | if (doubled) { |
||
| 1319 | score_mg -= |
||
| 1320 | pawn_doubled[mg][file] / RankDistance(square, MostAdvanced(side, |
||
| 1321 | doubled)); |
||
| 1322 | score_eg -= |
||
| 1323 | pawn_doubled[eg][file] / RankDistance(square, MostAdvanced(side, |
||
| 1324 | doubled)); |
||
| 1325 | } |
||
| 33 | pmbaty | 1326 | /* |
| 1327 | ************************************************************ |
||
| 1328 | * * |
||
| 108 | pmbaty | 1329 | * Test the pawn to see if it is connected to a neighbor * |
| 1330 | * which makes it easier to defend. * |
||
| 33 | pmbaty | 1331 | * * |
| 1332 | ************************************************************ |
||
| 1333 | */ |
||
| 108 | pmbaty | 1334 | connected = Pawns(side) & mask_pawn_connected[side][square]; |
| 1335 | if (connected) { |
||
| 154 | pmbaty | 1336 | score_mg += pawn_connected[mg][rank][file]; |
| 1337 | score_eg += pawn_connected[eg][rank][file]; |
||
| 108 | pmbaty | 1338 | } |
| 33 | pmbaty | 1339 | /* |
| 1340 | ************************************************************ |
||
| 1341 | * * |
||
| 108 | pmbaty | 1342 | * Flag passed pawns for use later when we finally call * |
| 1343 | * EvaluatePassedPawns. * |
||
| 33 | pmbaty | 1344 | * * |
| 1345 | ************************************************************ |
||
| 1346 | */ |
||
| 108 | pmbaty | 1347 | passed = !(Pawns(enemy) & mask_passed[side][square]); |
| 1348 | if (passed) |
||
| 1349 | tree->pawn_score.passed[side] |= 1 << file; |
||
| 33 | pmbaty | 1350 | /* |
| 1351 | ************************************************************ |
||
| 1352 | * * |
||
| 108 | pmbaty | 1353 | * Test the pawn to see if it is backward which makes it a * |
| 1354 | * target that ties down pieces to defend it. * |
||
| 33 | pmbaty | 1355 | * * |
| 1356 | ************************************************************ |
||
| 1357 | */ |
||
| 108 | pmbaty | 1358 | backward = 0; |
| 1359 | if (!(passed | isolated | connected | (Pawns(side) & |
||
| 1360 | mask_pattacks[side][square]) | (Pawns(enemy) & |
||
| 1361 | PawnAttacks(side, square)))) |
||
| 1362 | backward = Pawns(enemy) & PawnAttacks(side, square + direction[side]); |
||
| 1363 | if (backward) { |
||
| 1364 | score_mg -= pawn_backward[mg][file]; |
||
| 1365 | score_eg -= pawn_backward[eg][file]; |
||
| 1366 | } |
||
| 33 | pmbaty | 1367 | /* |
| 1368 | ************************************************************ |
||
| 1369 | * * |
||
| 108 | pmbaty | 1370 | * Determine if this pawn is a candidate passed pawn, * |
| 1371 | * which is a pawn on a file with no enemy pawns in front * |
||
| 1372 | * of it, and if it advances until it contacts an enemy * |
||
| 1373 | * pawn, and it is defended at least as many times as it * |
||
| 1374 | * is attacked when it reaches that pawn, then it will end * |
||
| 1375 | * up passed. * |
||
| 33 | pmbaty | 1376 | * * |
| 1377 | ************************************************************ |
||
| 1378 | */ |
||
| 108 | pmbaty | 1379 | if (!(passed | backward | isolated) && |
| 1380 | !(Pawns(enemy) & ((side) ? plus8dir[square] : minus8dir[square]))) { |
||
| 1381 | defenders = mask_pattacks[side][square + direction[side]] & Pawns(side); |
||
| 1382 | attackers = mask_pattacks[enemy][square] & Pawns(enemy); |
||
| 1383 | if (PopCnt(defenders) >= PopCnt(attackers)) { |
||
| 1384 | score_mg += passed_pawn_candidate[mg][rank]; |
||
| 1385 | score_eg += passed_pawn_candidate[eg][rank]; |
||
| 33 | pmbaty | 1386 | } |
| 1387 | } |
||
| 108 | pmbaty | 1388 | } |
| 33 | pmbaty | 1389 | /* |
| 1390 | ************************************************************ |
||
| 1391 | * * |
||
| 108 | pmbaty | 1392 | * Give a bonus for distance between left-most pawn and * |
| 1393 | * right-most pawn. The idea is that the wider the gap * |
||
| 1394 | * between the pawns, the harder they are for a lone king * |
||
| 1395 | * to control in the endgame. Botvinnik referred to this * |
||
| 1396 | * concept as "trousers" (pants with two legs, the farther * |
||
| 1397 | * the legs are apart, the better for the side with those * |
||
| 1398 | * pawns). * |
||
| 33 | pmbaty | 1399 | * * |
| 1400 | ************************************************************ |
||
| 1401 | */ |
||
| 108 | pmbaty | 1402 | score_eg += pawn_file_width * (MSB8Bit(pawn_files) - LSB8Bit(pawn_files)); |
| 33 | pmbaty | 1403 | /* |
| 1404 | ************************************************************ |
||
| 1405 | * * |
||
| 1406 | * Evaluate king safety. * |
||
| 1407 | * * |
||
| 108 | pmbaty | 1408 | * This uses the function EvaluateKingsFile() and looks at * |
| 1409 | * three possible positions for the king, either castled * |
||
| 33 | pmbaty | 1410 | * kingside, queenside or else standing on the d or e file * |
| 1411 | * stuck in the middle. This essentially is about the * |
||
| 1412 | * pawns in front of the king and what kind of "shelter" * |
||
| 1413 | * they provide for the king during the middlegame. * |
||
| 1414 | * * |
||
| 1415 | ************************************************************ |
||
| 1416 | */ |
||
| 108 | pmbaty | 1417 | tree->pawn_score.defects_q[side] = |
| 1418 | EvaluateKingsFile(tree, side, FILEA, FILEC); |
||
| 1419 | tree->pawn_score.defects_m[side] = |
||
| 1420 | EvaluateKingsFile(tree, side, FILEC, FILEF); |
||
| 1421 | tree->pawn_score.defects_k[side] = |
||
| 1422 | EvaluateKingsFile(tree, side, FILEF, FILEH); |
||
| 1423 | /* |
||
| 1424 | ************************************************************ |
||
| 1425 | * * |
||
| 1426 | * Done. Add mg/eg scores to final result (sign-corrected * |
||
| 1427 | * so that black = -, white = +) and return. * |
||
| 1428 | * * |
||
| 1429 | ************************************************************ |
||
| 1430 | */ |
||
| 33 | pmbaty | 1431 | tree->pawn_score.score_mg += sign[side] * score_mg; |
| 1432 | tree->pawn_score.score_eg += sign[side] * score_eg; |
||
| 1433 | } |
||
| 1434 | |||
| 108 | pmbaty | 1435 | /* last modified 10/19/15 */ |
| 33 | pmbaty | 1436 | /* |
| 1437 | ******************************************************************************* |
||
| 1438 | * * |
||
| 1439 | * EvaluateQueens() is used to evaluate queens. * |
||
| 1440 | * * |
||
| 1441 | ******************************************************************************* |
||
| 1442 | */ |
||
| 1443 | void EvaluateQueens(TREE * RESTRICT tree, int side) { |
||
| 1444 | uint64_t temp; |
||
| 108 | pmbaty | 1445 | int square, i, score_mg = 0, score_eg = 0, enemy = Flip(side); |
| 33 | pmbaty | 1446 | |
| 1447 | /* |
||
| 1448 | ************************************************************ |
||
| 1449 | * * |
||
| 1450 | * First locate each queen and obtain it's centralization * |
||
| 1451 | * score from the static piece/square table for queens. * |
||
| 1452 | * * |
||
| 1453 | ************************************************************ |
||
| 1454 | */ |
||
| 1455 | for (temp = Queens(side); temp; temp &= temp - 1) { |
||
| 1456 | square = LSB(temp); |
||
| 1457 | /* |
||
| 1458 | ************************************************************ |
||
| 1459 | * * |
||
| 1460 | * Then, add in the piece/square table value for the * |
||
| 1461 | * queen. * |
||
| 1462 | * * |
||
| 1463 | ************************************************************ |
||
| 1464 | */ |
||
| 1465 | score_mg += qval[mg][side][square]; |
||
| 1466 | score_eg += qval[eg][side][square]; |
||
| 1467 | /* |
||
| 1468 | ************************************************************ |
||
| 1469 | * * |
||
| 1470 | * Adjust the tropism count for this piece. * |
||
| 1471 | * * |
||
| 1472 | ************************************************************ |
||
| 1473 | */ |
||
| 1474 | if (tree->dangerous[side]) { |
||
| 108 | pmbaty | 1475 | i = KingSQ(enemy); |
| 1476 | tree->tropism[side] += king_tropism_q[Distance(square, i)]; |
||
| 1477 | i = 8 - (RankDistance(square, i) + FileDistance(square, i)); |
||
| 1478 | score_mg += i; |
||
| 1479 | score_eg += i; |
||
| 33 | pmbaty | 1480 | } |
| 1481 | } |
||
| 1482 | tree->score_mg += sign[side] * score_mg; |
||
| 1483 | tree->score_eg += sign[side] * score_eg; |
||
| 1484 | } |
||
| 1485 | |||
| 108 | pmbaty | 1486 | /* last modified 10/19/15 */ |
| 33 | pmbaty | 1487 | /* |
| 1488 | ******************************************************************************* |
||
| 1489 | * * |
||
| 1490 | * EvaluateRooks() is used to evaluate rooks. * |
||
| 1491 | * * |
||
| 1492 | ******************************************************************************* |
||
| 1493 | */ |
||
| 1494 | void EvaluateRooks(TREE * RESTRICT tree, int side) { |
||
| 1495 | uint64_t temp, moves; |
||
| 108 | pmbaty | 1496 | int square, rank, file, i, mobility, score_mg = 0, score_eg = 0; |
| 33 | pmbaty | 1497 | int enemy = Flip(side); |
| 1498 | |||
| 1499 | /* |
||
| 1500 | ************************************************************ |
||
| 1501 | * * |
||
| 1502 | * Initialize. * |
||
| 1503 | * * |
||
| 1504 | ************************************************************ |
||
| 1505 | */ |
||
| 1506 | for (temp = Rooks(side); temp; temp &= temp - 1) { |
||
| 1507 | square = LSB(temp); |
||
| 1508 | file = File(square); |
||
| 1509 | rank = Rank(square); |
||
| 1510 | /* |
||
| 1511 | ************************************************************ |
||
| 1512 | * * |
||
| 1513 | * Determine if the rook is on an open file or on a half- * |
||
| 1514 | * open file, either of which increases its ability to * |
||
| 1515 | * attack important squares. * |
||
| 1516 | * * |
||
| 1517 | ************************************************************ |
||
| 1518 | */ |
||
| 1519 | if (!(file_mask[file] & Pawns(side))) { |
||
| 1520 | if (!(file_mask[file] & Pawns(enemy))) { |
||
| 1521 | score_mg += rook_open_file[mg]; |
||
| 1522 | score_eg += rook_open_file[eg]; |
||
| 1523 | } else { |
||
| 1524 | score_mg += rook_half_open_file[mg]; |
||
| 1525 | score_eg += rook_half_open_file[eg]; |
||
| 1526 | } |
||
| 1527 | } |
||
| 1528 | /* |
||
| 1529 | ************************************************************ |
||
| 1530 | * * |
||
| 108 | pmbaty | 1531 | * Mobility counts the number of squares the rook attacks, * |
| 1532 | * excluding squares with friendly pieces, and weighs each * |
||
| 1533 | * square according to a complex formula that includes * |
||
| 1534 | * files as well as total number of squares attacked. * |
||
| 1535 | * * |
||
| 1536 | ************************************************************ |
||
| 1537 | */ |
||
| 1538 | mobility = RookMobility(square, OccupiedSquares); |
||
| 1539 | score_mg += mobility; |
||
| 1540 | score_eg += mobility; |
||
| 1541 | /* |
||
| 1542 | ************************************************************ |
||
| 1543 | * * |
||
| 33 | pmbaty | 1544 | * Check to see if the king has been forced to move and * |
| 1545 | * has trapped a rook at a1/b1/g1/h1, if so, then penalize * |
||
| 108 | pmbaty | 1546 | * the trapped rook to help extricate it. We only need to * |
| 1547 | * check this if the rooks mobility is very low. * |
||
| 33 | pmbaty | 1548 | * * |
| 1549 | ************************************************************ |
||
| 1550 | */ |
||
| 108 | pmbaty | 1551 | if (mobility < 0 && rank == rank1[side] && rank == Rank(KingSQ(side))) { |
| 1552 | i = File(KingSQ(side)); |
||
| 1553 | if (i > FILEE) { |
||
| 1554 | if (file > i) { |
||
| 1555 | score_mg += mobility * 3; |
||
| 1556 | score_eg += mobility * 3; |
||
| 33 | pmbaty | 1557 | } |
| 108 | pmbaty | 1558 | } else if (i < FILED && file < i) { |
| 1559 | score_mg += mobility * 3; |
||
| 1560 | score_eg += mobility * 3; |
||
| 33 | pmbaty | 1561 | } |
| 1562 | } |
||
| 1563 | /* |
||
| 1564 | ************************************************************ |
||
| 1565 | * * |
||
| 108 | pmbaty | 1566 | * finally check to see if any rooks are on the 7th rank, * |
| 1567 | * with the opponent having pawns on that rank or the * |
||
| 1568 | * opponent's king being hemmed in on the 7th/8th rank. * |
||
| 1569 | * If so, we give a bonus for the strong rook. If there * |
||
| 1570 | * is another rook or queen on the 7th that is connected * |
||
| 1571 | * with this one, then the positional advantage is even * |
||
| 1572 | * stronger. * |
||
| 33 | pmbaty | 1573 | * * |
| 1574 | ************************************************************ |
||
| 1575 | */ |
||
| 108 | pmbaty | 1576 | else if (rank == rank7[side] && (Rank(KingSQ(enemy)) == rank8[side] |
| 1577 | || Pawns(enemy) & rank_mask[rank])) { |
||
| 33 | pmbaty | 1578 | score_mg += rook_on_7th[mg]; |
| 1579 | score_eg += rook_on_7th[eg]; |
||
| 108 | pmbaty | 1580 | if (RankAttacks(square) & (Queens(side) | Rooks(side))) { |
| 1581 | score_mg += rook_connected_7th[mg]; |
||
| 1582 | score_eg += rook_connected_7th[eg]; |
||
| 1583 | } |
||
| 33 | pmbaty | 1584 | } |
| 1585 | /* |
||
| 1586 | ************************************************************ |
||
| 1587 | * * |
||
| 1588 | * Adjust the tropism count for this piece. * |
||
| 1589 | * * |
||
| 1590 | ************************************************************ |
||
| 1591 | */ |
||
| 1592 | if (tree->dangerous[side]) { |
||
| 1593 | moves = king_attacks[KingSQ(enemy)]; |
||
| 108 | pmbaty | 1594 | i = (rook_attacks[square] & moves && |
| 33 | pmbaty | 1595 | RookAttacks(square, |
| 108 | pmbaty | 1596 | OccupiedSquares & ~(Queens(side) | Rooks(side))) & moves) ? 1 : |
| 1597 | Distance(square, KingSQ(enemy)); |
||
| 1598 | tree->tropism[side] += king_tropism_r[i]; |
||
| 33 | pmbaty | 1599 | } |
| 1600 | } |
||
| 1601 | tree->score_mg += sign[side] * score_mg; |
||
| 1602 | tree->score_eg += sign[side] * score_eg; |
||
| 1603 | } |
||
| 1604 | |||
| 108 | pmbaty | 1605 | /* last modified 01/03/15 */ |
| 33 | pmbaty | 1606 | /* |
| 1607 | ******************************************************************************* |
||
| 1608 | * * |
||
| 1609 | * EvaluateWinningChances() is used to determine if one side has reached a * |
||
| 1610 | * position which can not be won, period, even though side may be ahead in * |
||
| 1611 | * material in some way. * |
||
| 1612 | * * |
||
| 1613 | * Return values: * |
||
| 108 | pmbaty | 1614 | * 0 -> side on move can not win. * |
| 1615 | * 1 -> side on move can win. * |
||
| 33 | pmbaty | 1616 | * * |
| 1617 | ******************************************************************************* |
||
| 1618 | */ |
||
| 1619 | int EvaluateWinningChances(TREE * RESTRICT tree, int side, int wtm) { |
||
| 108 | pmbaty | 1620 | int square, ekd, promote, majors, minors, enemy = Flip(side); |
| 33 | pmbaty | 1621 | |
| 108 | pmbaty | 1622 | if (!Pawns(side)) { |
| 33 | pmbaty | 1623 | /* |
| 1624 | ************************************************************ |
||
| 1625 | * * |
||
| 1626 | * If side has a piece and no pawn, it can not possibly * |
||
| 1627 | * win. If side is a piece ahead, the only way it can win * |
||
| 1628 | * is if the enemy is already trapped on the edge of the * |
||
| 1629 | * board (special case to handle KRB vs KR which can be * |
||
| 1630 | * won if the king gets trapped). * |
||
| 1631 | * * |
||
| 1632 | ************************************************************ |
||
| 1633 | */ |
||
| 1634 | if (TotalPieces(side, occupied) <= 3) |
||
| 1635 | return 0; |
||
| 1636 | if (TotalPieces(side, occupied) - TotalPieces(enemy, occupied) <= 3 && |
||
| 1637 | mask_not_edge & Kings(enemy)) |
||
| 1638 | return 0; |
||
| 108 | pmbaty | 1639 | /* |
| 1640 | ************************************************************ |
||
| 1641 | * * |
||
| 1642 | * If one side is an exchange up, but has no pawns, then * |
||
| 1643 | * that side can not possibly win. * |
||
| 1644 | * * |
||
| 1645 | ************************************************************ |
||
| 1646 | */ |
||
| 1647 | majors = |
||
| 1648 | TotalPieces(white, rook) + 2 * TotalPieces(white, |
||
| 1649 | queen) - TotalPieces(black, rook) - 2 * TotalPieces(black, queen); |
||
| 1650 | if (Abs(majors) == 1) { |
||
| 1651 | minors = |
||
| 1652 | TotalPieces(black, knight) + TotalPieces(black, |
||
| 1653 | bishop) - TotalPieces(white, knight) - TotalPieces(white, bishop); |
||
| 1654 | if (majors == minors) |
||
| 1655 | return 0; |
||
| 1656 | } |
||
| 1657 | } else { |
||
| 1658 | /* |
||
| 1659 | ************************************************************ |
||
| 1660 | * * |
||
| 1661 | * If neither side has any pieces, and both sides have * |
||
| 1662 | * non-rookpawns, then either side can win. * |
||
| 1663 | * * |
||
| 1664 | ************************************************************ |
||
| 1665 | */ |
||
| 1666 | if (TotalPieces(white, occupied) == 0 && TotalPieces(black, occupied) == 0 |
||
| 1667 | && Pawns(white) & not_rook_pawns && Pawns(black) & not_rook_pawns) |
||
| 1668 | return 1; |
||
| 33 | pmbaty | 1669 | } |
| 1670 | /* |
||
| 1671 | ************************************************************ |
||
| 1672 | * * |
||
| 1673 | * If "side" has a pawn, then either the pawn had better * |
||
| 108 | pmbaty | 1674 | * not be a rook pawn, or else side had better have the * |
| 33 | pmbaty | 1675 | * right color bishop or any other piece, otherwise it is * |
| 1676 | * not winnable if the enemy king can get to the queening * |
||
| 1677 | * square first. * |
||
| 1678 | * * |
||
| 1679 | ************************************************************ |
||
| 1680 | */ |
||
| 108 | pmbaty | 1681 | if (!(Pawns(side) & not_rook_pawns)) |
| 33 | pmbaty | 1682 | do { |
| 1683 | if (TotalPieces(side, occupied) > 3 || (TotalPieces(side, occupied) == 3 |
||
| 1684 | && Knights(side))) |
||
| 1685 | continue; |
||
| 1686 | if (file_mask[FILEA] & Pawns(side) && file_mask[FILEH] & Pawns(side)) |
||
| 1687 | continue; |
||
| 1688 | if (Bishops(side)) { |
||
| 1689 | if (Bishops(side) & dark_squares) { |
||
| 1690 | if (file_mask[dark_corner[side]] & Pawns(side)) |
||
| 1691 | continue; |
||
| 1692 | } else if (file_mask[light_corner[side]] & Pawns(side)) |
||
| 1693 | continue; |
||
| 1694 | } |
||
| 1695 | if (Pawns(side) & file_mask[FILEA]) |
||
| 1696 | promote = A8; |
||
| 1697 | else |
||
| 1698 | promote = H8; |
||
| 1699 | ekd = Distance(KingSQ(enemy), sqflip[side][promote]) - (wtm != side); |
||
| 1700 | if (ekd <= 1) |
||
| 1701 | return 0; |
||
| 1702 | } while (0); |
||
| 1703 | /* |
||
| 1704 | ************************************************************ |
||
| 1705 | * * |
||
| 108 | pmbaty | 1706 | * Check to see if this is a KRP vs KR ending. If so, and * |
| 1707 | * the losing king is in front of the passer, then this is * |
||
| 1708 | * a drawish ending. * |
||
| 33 | pmbaty | 1709 | * * |
| 1710 | ************************************************************ |
||
| 1711 | */ |
||
| 1712 | if (TotalPieces(side, pawn) == 1 && TotalPieces(enemy, pawn) == 0 && |
||
| 108 | pmbaty | 1713 | TotalPieces(side, occupied) == 5 && TotalPieces(enemy, occupied) == 5) { |
| 33 | pmbaty | 1714 | square = LSB(Pawns(side)); |
| 1715 | if (FileDistance(KingSQ(enemy), square) <= 1 && |
||
| 1716 | InFront(side, Rank(KingSQ(enemy)), Rank(square))) |
||
| 1717 | return 0; |
||
| 1718 | } |
||
| 1719 | /* |
||
| 1720 | ************************************************************ |
||
| 1721 | * * |
||
| 1722 | * If this side has pawns, and we have made it through the * |
||
| 1723 | * previous tests, then this side has winning chances. * |
||
| 1724 | * * |
||
| 1725 | ************************************************************ |
||
| 1726 | */ |
||
| 1727 | if (TotalPieces(side, pawn)) |
||
| 1728 | return 1; |
||
| 1729 | /* |
||
| 1730 | ************************************************************ |
||
| 1731 | * * |
||
| 1732 | * If this side has two bishops, and the enemy has only a * |
||
| 1733 | * single kinght, the two bishops win. * |
||
| 1734 | * * |
||
| 1735 | ************************************************************ |
||
| 1736 | */ |
||
| 1737 | if (TotalPieces(side, occupied) == 6) |
||
| 1738 | if (TotalPieces(enemy, occupied) == 3 && (Knights(side) |
||
| 1739 | || !Knights(enemy))) |
||
| 1740 | return 0; |
||
| 1741 | /* |
||
| 1742 | ************************************************************ |
||
| 1743 | * * |
||
| 1744 | * If one side is two knights ahead and the opponent has * |
||
| 1745 | * no remaining material, it is a draw. * |
||
| 1746 | * * |
||
| 1747 | ************************************************************ |
||
| 1748 | */ |
||
| 1749 | if (TotalPieces(side, occupied) == 6 && !Bishops(side) |
||
| 1750 | && TotalPieces(enemy, occupied) + TotalPieces(enemy, pawn) == 0) |
||
| 1751 | return 0; |
||
| 108 | pmbaty | 1752 | /* |
| 1753 | ************************************************************ |
||
| 1754 | * * |
||
| 1755 | * If we make it through all the above tests, then "side" * |
||
| 1756 | * can win so we return 1. * |
||
| 1757 | * * |
||
| 1758 | ************************************************************ |
||
| 1759 | */ |
||
| 33 | pmbaty | 1760 | return 1; |
| 1761 | } |
||
| 108 | pmbaty | 1762 | |
| 1763 | /* |
||
| 1764 | ******************************************************************************* |
||
| 1765 | * * |
||
| 1766 | * InitializeKingSafety() is used to initialize the king safety matrix. * |
||
| 1767 | * This is set so that the matrix, indexed by king safety pawn structure * |
||
| 1768 | * index and by king safety piece tropism, combines the two indices to * |
||
| 1769 | * produce a single score. As either index rises, the king safety score * |
||
| 1770 | * tracks along, but as both rise, the king safety score rises much more * |
||
| 1771 | * quickly. * |
||
| 1772 | * * |
||
| 1773 | ******************************************************************************* |
||
| 1774 | */ |
||
| 1775 | void InitializeKingSafety() { |
||
| 1776 | int safety, tropism; |
||
| 1777 | |||
| 1778 | for (safety = 0; safety < 16; safety++) { |
||
| 1779 | for (tropism = 0; tropism < 16; tropism++) { |
||
| 1780 | king_safety[safety][tropism] = |
||
| 1781 | 180 * ((safety_vector[safety] + 100) * (tropism_vector[tropism] + |
||
| 1782 | 100) / 100 - 100) / 100; |
||
| 1783 | } |
||
| 1784 | } |
||
| 1785 | } |