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