1/* 2 Sjeng - a chess variants playing program 3 Copyright (C) 2000 Gian-Carlo Pascutto 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 19 File: seval.c 20 Purpose: functions for evaluating positions (suicide chess) 21 22*/ 23 24#include "sjeng.h" 25#include "extvars.h" 26#include "protos.h" 27 28static int scentral[144] = { 290,0,0,0,0,0,0,0,0,0,0,0, 300,0,0,0,0,0,0,0,0,0,0,0, 310,0,-20,-10,-10,-10,-10,-10,-10,-20,0,0, 320,0,-10,0,3,5,5,3,0,-10,0,0, 330,0,-10,2,15,15,15,15,2,-10,0,0, 340,0,-10,7,15,25,25,15,7,-10,0,0, 350,0,-10,7,15,25,25,15,7,-10,0,0, 360,0,-10,2,15,15,15,15,2,-10,0,0, 370,0,-10,0,3,5,5,3,0,-10,0,0, 380,0,-20,-10,-10,-10,-10,-10,-10,-20,0,0, 390,0,0,0,0,0,0,0,0,0,0,0, 400,0,0,0,0,0,0,0,0,0,0,0}; 41 42static const int rook_o[4] = {12, -12, 1, -1}; 43static const int bishop_o[4] = {11, -11, 13, -13}; 44static const int knight_o[8] = {10, -10, 14, -14, 23, -23, 25, -25}; 45 46static int s_bishop_mobility(int square) 47{ 48 register int l; 49 register int m = 0; 50 51 for (l = square-13; board[l] == npiece; l-=13) 52 m++; 53 for (l = square-11; board[l] == npiece; l-=11) 54 m++; 55 for (l = square+11; board[l] == npiece; l+=11) 56 m++; 57 for (l = square+13; board[l] == npiece; l+=13) 58 m++; 59 60 return m << 2; 61} 62 63static int s_rook_mobility(int square) 64{ 65 register int l; 66 register int m = 0; 67 68 for (l = square-12; board[l] == npiece; l-=12) 69 m++; 70 for (l = square-1; board[l] == npiece; l-=1) 71 m++; 72 for (l = square+1; board[l] == npiece; l+=1) 73 m++; 74 for (l = square+12; board[l] == npiece; l+=12) 75 m++; 76 77 return m << 2; 78} 79 80static int s_knight_mobility(int square) 81{ 82 static const int knight_o[8] = {10, -10, 14, -14, 23, -23, 25, -25}; 83 register int d, m = 0; 84 85 for (d = 0; d < 8; d++) 86 { 87 if (board[square + knight_o[d]] == npiece) m++; 88 } 89 90 return m << 2; 91} 92 93static int s_pawn_mobility(int square) 94{ 95 register int m = 0; 96 97 if (board[square] == wpawn) 98 { 99 if (board[square + 12] == npiece) m++; 100 } 101 else 102 { 103 if (board[square - 12] == npiece) m++; 104 } 105 106 return m << 3; 107} 108 109static int s_king_mobility(int square) 110{ 111 static const int king_o[8] = {13, 12, 11, 1, -1, -11, -12, -13}; 112 register int d, m = 0; 113 114 for (d = 0; d < 8; d++) 115 { 116 if (board[square + king_o[d]] == npiece) m++; 117 } 118 119 return m << 2; 120} 121 122static int black_saccers(int square) 123{ 124 register int ndir, a_sq; 125 register int basq, i; 126 register int f = FALSE; 127 128 /* for white pawn on square, any black 129 * pieces that can sac themselves to it? */ 130 131 /* check for case where is_attacked fails 132 because pawns dont move to their attacks */ 133 134 if (board[square + 24] == bpawn || 135 board[square + 22] == bpawn || 136 board[square + 26] == bpawn) 137 { 138 return 0; 139 } 140 141 /* ok, now check pawn moves */ 142 143 if ((rank(square) < 6) 144 && (board[square + 25] == bpawn 145 || 146 board[square + 23] == bpawn)) 147 { 148 f = TRUE; 149 } 150 else if (rank(square) == 4 && 151 (board[square + 35] == bpawn || 152 board[square + 37] == bpawn)) 153 { 154 f = TRUE; 155 } 156 157 if (!f) 158 { 159 f = (is_attacked(square + 11, 0) ? 1 : 0); 160 } 161 if (!f) 162 { 163 f = (is_attacked(square + 13, 0) ? 2 : 0); 164 } 165 166 if (!f) 167 { 168 return 0; 169 } 170 else 171 { 172 /* black can sac, but is the saccer defended ? */ 173 174 if (f == 1) 175 { 176 if (calc_attackers(square + 11, 0) > 1) 177 { 178 /* yep */ 179 return 0; 180 } 181 else 182 { 183 /* nope */ 184 return 30; 185 } 186 } 187 else 188 { 189 if (calc_attackers(square + 13, 0) > 1) 190 { 191 return 0; 192 } 193 else 194 { 195 return 30; 196 } 197 198 } 199 } 200 201} 202 203static int white_saccers(int square) 204{ 205 /* for black pawn on square, any black 206 * pieces that can sac themselves to it? */ 207 208 register int ndir, a_sq; 209 register int basq, i; 210 register int f = FALSE; 211 212 /* for white pawn on square, any black 213 * pieces that can sac themselves to it? */ 214 215 /* check for case where is_attacked fails 216 because pawns dont move to their attacks */ 217 218 if (board[square - 24] == wpawn || 219 board[square - 22] == wpawn || 220 board[square - 26] == wpawn) 221 { 222 return 0; 223 } 224 225 /* ok, now check pawn moves */ 226 227 if ((rank(square) > 3) 228 && (board[square - 25] == wpawn 229 || 230 board[square - 23] == wpawn)) 231 { 232 f = TRUE; 233 } 234 else if (rank(square) == 5 && 235 (board[square - 35] == wpawn || 236 board[square - 37] == wpawn)) 237 { 238 f = TRUE; 239 } 240 241 if (!f) 242 { 243 f = (is_attacked(square - 11, 1) ? 1 : 0); 244 } 245 if (!f) 246 { 247 f = (is_attacked(square - 13, 1) ? 2 : 0); 248 } 249 250 if (!f) 251 { 252 return 0; 253 } 254 else 255 { 256 /* black can sac, but is the saccer defended ? */ 257 258 if (f == 1) 259 { 260 if (calc_attackers(square - 11, 1) > 1) 261 { 262 /* yep */ 263 return 0; 264 } 265 else 266 { 267 /* nope */ 268 return 30; 269 } 270 } 271 else 272 { 273 if (calc_attackers(square - 13, 1) > 1) 274 { 275 return 0; 276 } 277 else 278 { 279 return 30; 280 } 281 282 } 283 } 284 285} 286 287int32_t suicide_eval (void) { 288 289 /* select the appropriate eval() routine: */ 290 return (suicide_mid_eval ()); 291} 292 293int32_t suicide_mid_eval (void) { 294 295 /* return a score for the current middlegame position: */ 296 297 int srank, pawn_file, pawns[2][11], white_back_pawn[11], black_back_pawn[11]; 298 int isolated, backwards, i, a, j; 299 int32_t score = 0; 300 int in_cache; 301 int wb = 0, bb = 0, wbc = 0, bbc = 0; 302 int wk = 0, bk = 0, wr = 0, br = 0; 303 int wn = 0, bn = 0, wp = 0, bp = 0; 304 305 in_cache = 0; 306 307 checkECache(&score, &in_cache); 308 309 if(in_cache) 310 { 311 if (white_to_move == 1) return score; 312 return -score; 313 } 314 315 score = Material; 316 317 /* initialize the pawns array, (files offset by one to use dummy files in 318 order to easier determine isolated status) and also initialize the 319 arrays keeping track of the rank of the most backward pawn: */ 320 memset (pawns, 0, sizeof (pawns)); 321 for (i = 0; i < 11; i++) { 322 white_back_pawn[i] = 7; 323 black_back_pawn[i] = 2; 324 } 325 for (j = 1, a = 1; (a <= piece_count); j++) { 326 i = pieces[j]; 327 328 if (!i) 329 continue; 330 else 331 a++; 332 333 assert((i > 0) && (i < 145)); 334 335 pawn_file = file (i)+1; 336 srank = rank (i); 337 if (board[i] == wpawn) { 338 pawns[1][pawn_file]++; 339 if (srank < white_back_pawn[pawn_file]) { 340 white_back_pawn[pawn_file] = srank; 341 } 342 } 343 else if (board[i] == bpawn) { 344 pawns[0][pawn_file]++; 345 if (srank > black_back_pawn[pawn_file]) { 346 black_back_pawn[pawn_file] = srank; 347 } 348 } 349 } 350 351 /* loop through the board, adding material value, as well as positional 352 bonuses for all pieces encountered: */ 353 for (j = 1, a = 1; (a <= piece_count); j++) { 354 i = pieces[j]; 355 356 if (!i) 357 continue; 358 else 359 a++; 360 361 pawn_file = file (i)+1; 362 srank = rank (i); 363 switch (board[i]) { 364 case (wpawn): 365 score += scentral[i]; 366 score += s_pawn_mobility(i); 367 score -= black_saccers(i); 368 wp++; 369 isolated = FALSE; 370 backwards = FALSE; 371 372 /* check for backwards pawns: */ 373 if (white_back_pawn[pawn_file+1] > srank 374 && white_back_pawn[pawn_file-1] > srank) { 375 score -= 8; 376 backwards = TRUE; 377 /* check to see if it is furthermore isolated: */ 378 if (!pawns[1][pawn_file+1] && !pawns[1][pawn_file-1]) { 379 score -= 12; 380 isolated = TRUE; 381 } 382 } 383 384 /* give weak, exposed pawns a penalty (not as much as in the midgame, 385 since there may be no pieces to take advantage of it): */ 386 if (!pawns[0][pawn_file]) { 387 if (backwards) score -= 5; 388 if (isolated) score -= 8; 389 } 390 391 /* give doubled, trippled, etc.. pawns a penalty (bigger in the 392 endgame, since they will become big targets): */ 393 if (pawns[1][pawn_file] > 1) 394 score -= 15*(pawns[1][pawn_file]-1); 395 396 /* give bonuses for passed pawns (bigger in the endgame since passed 397 pawns are what wins the endgame): */ 398 if (!pawns[0][pawn_file] && srank >= black_back_pawn[pawn_file-1] && 399 srank >= black_back_pawn[pawn_file+1]) { 400 score += 30 + 3*(rank(i)-2); 401 402 /* outside passer ? */ 403 if (file(i) == 1 || file(i) == 8) 404 score += 4 + 2*(rank(i)-2); 405 406 /* give an extra bonus if a connected, passed pawn: */ 407 if (!isolated) 408 { 409 score += 6; 410 } 411 } 412 413 /* check for pawn islands */ 414 if (!pawns[1][pawn_file-1]) 415 score -= 20; 416 417 break; 418 419 case (bpawn): 420 score -= scentral[i]; 421 score -= s_pawn_mobility(i); 422 score += white_saccers(i); 423 isolated = FALSE; 424 backwards = FALSE; 425 bp++; 426 427 /* in general, bonuses/penalties in the endgame evaluation will be 428 higher, since pawn structure becomes more important for the 429 creation of passed pawns */ 430 431 /* check for backwards pawns: */ 432 if (black_back_pawn[pawn_file+1] < srank 433 && black_back_pawn[pawn_file-1] < srank) { 434 score += 8; 435 backwards = TRUE; 436 /* check to see if it is furthermore isolated: */ 437 if (!pawns[0][pawn_file+1] && !pawns[0][pawn_file-1]) { 438 score += 12; 439 isolated = TRUE; 440 } 441 } 442 443 /* give weak, exposed pawns a penalty (not as much as in the midgame, 444 since there may be no pieces to take advantage of it): */ 445 if (!pawns[1][pawn_file]) { 446 if (backwards) score += 5; 447 if (isolated) score += 8; 448 } 449 450 /* give doubled, trippled, etc.. pawns a penalty (bigger in the 451 endgame, since they will become big targets): */ 452 if (pawns[0][pawn_file] > 1) 453 score += 15*(pawns[0][pawn_file]-1); 454 455 /* give bonuses for passed pawns (bigger in the endgame since passed 456 pawns are what wins the endgame): */ 457 if (!pawns[1][pawn_file] && srank <= white_back_pawn[pawn_file-1] && 458 srank <= white_back_pawn[pawn_file+1]) { 459 score -= 30 + 3*(7-rank(i)); 460 461 /* outside passer ? */ 462 if (file(i) == 1 || file(i) == 8) 463 score -= 4 + 2*(7-rank(i)); 464 465 /* give an extra bonus if a connected, passed pawn: */ 466 if (!isolated) 467 { 468 score -= 6; 469 } 470 } 471 472 if (!pawns[0][pawn_file-1]) 473 score += 20; 474 475 break; 476 477 case (wrook): 478 score += scentral[i]; 479 score += s_rook_mobility(i); 480 wr++; 481 break; 482 483 case (brook): 484 score -= scentral[i]; 485 score -= s_rook_mobility(i); 486 br++; 487 break; 488 489 case (wbishop): 490 score += scentral[i]; 491 score += s_bishop_mobility(i); 492 if (wb) 493 { 494 if (sqcolor[i] != wbc) 495 wb = 99; 496 } 497 wb++; 498 wbc = sqcolor[i]; 499 break; 500 501 case (bbishop): 502 score -= scentral[i]; 503 score -= s_bishop_mobility(i); 504 if (bb) 505 { 506 /* two bishops, check for same color */ 507 if (sqcolor[i] != bbc) 508 bb = 99; 509 } 510 bb++; 511 bbc = sqcolor[i]; 512 break; 513 514 case (wknight): 515 score += scentral[i]; 516 score += s_knight_mobility(i); 517 wn++; 518 break; 519 520 case (bknight): 521 score -= scentral[i]; 522 score -= s_knight_mobility(i); 523 bn++; 524 break; 525 526 case (wqueen): 527 score += scentral[i]; 528 score += s_rook_mobility(i); 529 score += s_bishop_mobility(i); 530 break; 531 532 case (bqueen): 533 score -= scentral[i]; 534 score -= s_rook_mobility(i); 535 score -= s_bishop_mobility(i); 536 break; 537 538 case (wking): 539 score += scentral[i] >> 1; 540 score += s_king_mobility(i); 541 wk++; 542 break; 543 544 case (bking): 545 score -= scentral[i] >> 1; 546 score -= s_king_mobility(i); 547 bk++; 548 break; 549 } 550 } 551 552 /* opposite color bishops */ 553 if ((wb < 99) && (bb < 99) && (wbc != bbc) && (piece_count < 32)) 554 { 555 score = (int)((float)score * (float)((float)piece_count / 32.0)); 556 } 557 558 storeECache(score); 559 560 /* adjust for color: */ 561 if (white_to_move == 1) { 562 return score; 563 } 564 else { 565 return -score; 566 } 567 568} 569