/* Sjeng - a chess variants playing program Copyright (C) 2000 Gian-Carlo Pascutto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA File: eval.c Purpose: evaluate crazyhouse/bughouse positions */ #include "sjeng.h" #include "extvars.h" #include "protos.h" #include "squares.h" int Material; int std_material[] = { 0, 100, -100, 310, -310, 4000, -4000, 500, -500, 900, -900, 325, -325, 0 }; int zh_material[] = { 0, 100, -100, 210, -210, 4000, -4000, 250, -250, 450, -450, 230, -230, 0 }; int suicide_material[] = { 0, 15, -15, 150, -150, 500, -500, 150, -150, 50, -50, 0, 0, 0 }; int losers_material[] = { 0, 80, -80, 320, -320, 1000, -1000, 350, -350, 400, -400, 270, -270, 0 }; int material[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const int file[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,1,2,3,4,5,6,7,8,0,0, 0,0,1,2,3,4,5,6,7,8,0,0, 0,0,1,2,3,4,5,6,7,8,0,0, 0,0,1,2,3,4,5,6,7,8,0,0, 0,0,1,2,3,4,5,6,7,8,0,0, 0,0,1,2,3,4,5,6,7,8,0,0, 0,0,1,2,3,4,5,6,7,8,0,0, 0,0,1,2,3,4,5,6,7,8,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0 }; const int rank[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,1,1,1,1,1,1,1,1,0,0, 0,0,2,2,2,2,2,2,2,2,0,0, 0,0,3,3,3,3,3,3,3,3,0,0, 0,0,4,4,4,4,4,4,4,4,0,0, 0,0,5,5,5,5,5,5,5,5,0,0, 0,0,6,6,6,6,6,6,6,6,0,0, 0,0,7,7,7,7,7,7,7,7,0,0, 0,0,8,8,8,8,8,8,8,8,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0 }; const int diagl[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0, 1, 2, 3, 4, 5, 6, 7, 8,0,0, 0,0, 9, 1, 2, 3, 4, 5, 6, 7,0,0, 0,0,10, 9, 1, 2, 3, 4, 5, 6,0,0, 0,0,11,10, 9, 1, 2, 3, 4, 5,0,0, 0,0,12,11,10, 9, 1, 2, 3, 4,0,0, 0,0,13,12,11,10, 9, 1, 2, 3,0,0, 0,0,14,13,12,11,10, 9, 1, 2,0,0, 0,0,15,14,13,12,11,10, 9, 1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0 }; const int diagr[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,15,14,13,12,11,10,9,1,0,0, 0,0,14,13,12,11,10,9,1,2,0,0, 0,0,13,12,11,10,9,1,2,3,0,0, 0,0,12,11,10,9,1,2,3,4,0,0, 0,0,11,10,9,1,2,3,4,5,0,0, 0,0,10,9,1,2,3,4,5,6,0,0, 0,0,9,1,2,3,4,5,6,7,0,0, 0,0,1,2,3,4,5,6,7,8,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0 }; const int sqcolor[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,1,0,1,0,1,0,1,0,0,0, 0,0,0,1,0,1,0,1,0,1,0,0, 0,0,1,0,1,0,1,0,1,0,0,0, 0,0,0,1,0,1,0,1,0,1,0,0, 0,0,1,0,1,0,1,0,1,0,0,0, 0,0,0,1,0,1,0,1,0,1,0,0, 0,0,1,0,1,0,1,0,1,0,0,0, 0,0,0,1,0,1,0,1,0,1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0 }; /* these tables will be used for positional bonuses: */ const int bishop[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,-5,-5,-10,-5,-5,-10,-5,-5,0,0, 0,0,-5,10,5,10,10,5,10,-5,0,0, 0,0,-5,5,6,15,15,6,5,-5,0,0, 0,0,-5,3,15,10,10,15,3,-5,0,0, 0,0,-5,3,15,10,10,15,3,-5,0,0, 0,0,-5,5,6,15,15,6,5,-5,0,0, 0,0,-5,10,5,10,10,5,10,-5,0,0, 0,0,-5,-5,-10,-5,-5,-10,-5,-5,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0}; const int black_knight[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,-20,-10,-10,-10,-10, -10,-10,-20,0,0, 0,0,-10, 15, 25, 25, 25, 25, 15,-10,0,0, 0,0,-10, 15, 25, 35, 35 , 35, 15,-10,0,0, 0,0,-10, 10, 25, 20, 25, 25, 10,-10,0,0, 0,0,-10, 0, 20, 20, 20, 20, 0,-10,0,0, 0,0,-10, 0, 15, 15, 15, 15, 0,-10,0,0, 0,0,-10, 0, 0, 3, 3, 0, 0,-10,0,0, 0,0,-20,-35,-10,-10,-10, -10,-35,-20,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0}; const int white_knight[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,-20, -35,-10, -10, -10,-10, -35, -20,0,0, 0,0,-10, 0, 0, 3, 3, 0, 0, -10,0,0, 0,0,-10, 0, 15, 15, 15, 15, 0, -10,0,0, 0,0,-10, 0, 20, 20, 20, 20, 0, -10,0,0, 0,0,-10, 10, 25, 20, 25, 25, 10, -10,0,0, 0,0,-10, 15, 25, 35, 35, 35, 15, -10,0,0, 0,0,-10, 15, 25, 25, 25, 25, 15, -10,0,0, 0,0,-20, -10,-10, -10, -10,-10, -10, -20,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0}; const int white_pawn[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,25, 25, 35, 5, 5, 50, 45, 30,0,0, 0,0, 0, 0, 0, 7, 7, 5, 5, 0,0,0, 0,0, 0, 0, 0, 14, 14, 0, 0, 0,0,0, 0,0, 0, 0, 10, 20, 20, 10, 5, 5,0,0, 0,0,12, 18, 18, 27, 27, 18, 18, 18,0,0, 0,0,25, 30, 30, 35, 35, 35, 30, 25,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0 }; const int black_pawn[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,30, 30, 30, 35, 35, 35, 30, 25,0,0, 0,0,12, 18, 18, 27, 27, 18, 18, 18,0,0, 0,0, 0, 0, 10, 20, 20, 10, 5, 5,0,0, 0,0, 0, 0, 0, 14, 14, 0, 0, 0,0,0, 0,0, 0, 0, 0, 7, 7, 5, 5, 0,0,0, 0,0,25, 25, 35, 5, 5, 50, 45, 30,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0 }; /* to be used during opening and middlegame for white king positioning: */ const int white_king[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,-100, 7, 4, 0, 10 , 4, 7,-100,0,0, 0,0,-250,-200,-150,-100,-100,-150,-200,-250,0,0, 0,0,-350,-300,-300,-250,-250,-300,-300,-350,0,0, 0,0,-400,-400,-400,-350,-350,-400,-400,-400,0,0, 0,0,-450,-450,-450,-450,-450,-450,-450,-450,0,0, 0,0,-500,-500,-500,-500,-500,-500,-500,-500,0,0, 0,0,-500,-500,-500,-500,-500,-500,-500,-500,0,0, 0,0,-500,-500,-500,-500,-500,-500,-500,-500,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0}; /* to be used during opening and middlegame for black king positioning: */ const int black_king[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,-500,-500,-500,-500,-500,-500,-500,-500,0,0, 0,0,-500,-500,-500,-500,-500,-500,-500,-500,0,0, 0,0,-500,-500,-500,-500,-500,-500,-500,-500,0,0, 0,0,-450,-450,-450,-450,-450,-450,-450,-450,0,0, 0,0,-400,-400,-400,-350,-350,-400,-400,-400,0,0, 0,0,-350,-300,-300,-250,-250,-300,-300,-350,0,0, 0,0,-250,-200,-150,-100,-100,-150,-200,-250,0,0, 0,0,-100, 7, 4, 0, 10 , 4, 7,-100,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0}; const int black_queen[144] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5,10,10, 5, 5, 5, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0,-30,-30,-30,-30,-30,-30,-30,-30,0, 0, 0,0,-60,-40,-40,-60,-60,-40,-40,-60,0,0, 0,0,-40,-40,-40,-40,-40,-40,-40,-40,0,0, 0,0,-15,-15,-15,-10,-10,-15,-15,-15,0,0, 0,0,0,0,0,7,10,5,0,0,0,0, 0,0,0,0,0, 5,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0}; const int white_queen[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,5,0,0,0,0,0,0, 0,0,0,0,0,7,10,5,0,0,0,0, 0,0,-15,-15,-15,-10,-10,-15,-15,-15,0,0, 0,0,-40,-40,-40,-40,-40,-40,-40,-40,0,0, 0,0,-60,-40,-40,-60,-60,-40,-40,-60,0,0, 0, 0,-30,-30,-30,-30,-30,-30,-30,-30,0, 0, 0, 0, 0, 0, 3, 3, 3,3,3, 0, 0, 0, 0, 0, 5, 5, 5,10,10,5,5,5, 0, 0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0}; const int black_rook[144] = { 0,0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0,0, 10, 15, 20, 25, 25, 20, 15, 10,0,0, 0,0, 0, 10, 15, 20, 20, 15, 10, 0,0,0, 0,0,-20,-20,-20,-20,-20,-20,-20,-20,0,0, 0,0,-20,-20,-20,-30,-30,-20,-20,-20,0,0, 0,0,-20,-20,-20,-20,-20,-20,-20,-20,0,0, 0,0,-15,-15,-15,-10,-10,-15,-15,-15,0,0, 0,0, 0, 0, 0, 7, 10, 0, 0, 0,0,0, 0,0, 2, 2, 2, 2, 2, 2, 2, 2,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0 }; const int white_rook[144] = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0, 2, 2, 2, 2, 2, 2, 2, 2,0,0, 0,0, 0, 0, 0, 7, 10, 0, 0, 0,0,0, 0,0,-15,-15,-15,-10,-10,-15,-15,-15,0,0, 0,0,-20,-20,-20,-20,-20,-20,-20,-20,0,0, 0,0,-20,-20,-20,-30,-30,-20,-20,-20,0,0, 0,0,-20,-20,-20,-20,-20,-20,-20,-20,0,0, 0,0, 0, 10, 15, 20, 20, 15, 10, 0,0,0, 0,0, 10, 15, 20, 25, 25, 20, 15, 10,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0 }; /* tropism values of 0 and 8 are bogus, and should never happen in the actual eval */ int pre_p_tropism[9] = { 9999, 40, 20, 10, 3, 1, 1, 0, 9999}; int pre_r_tropism[9] = { 9999, 50, 40, 15, 5, 1, 1, 0, 9999}; int pre_n_tropism[9] = { 9999, 50, 70, 35, 10, 2, 1, 0, 9999}; int pre_q_tropism[9] = { 9999, 100, 60, 20, 5, 2, 0, 0, 9999}; int pre_b_tropism[9] = { 9999, 50, 25, 15, 5, 2, 2, 2, 9999}; unsigned char p_tropism[144][144]; unsigned char q_tropism[144][144]; unsigned char n_tropism[144][144]; unsigned char r_tropism[144][144]; unsigned char b_tropism[144][144]; int ksafety_scaled[15][9] = { { -5, 5, 10, 15, 50, 80, 150, 150, 150 }, /* nothing */ { -5, 15, 20, 25, 70, 150, 200, 200, 200 }, /* 1 pawns */ { -5, 15, 30, 30, 100, 200, 300, 300, 300 }, /* 2 pawns */ { -10, 20, 40, 40, 100, 200, 300, 300, 400 }, /* 1 minor piece */ { -10, 30, 50, 80, 150, 300, 400, 400, 500 }, /* 1 minor piece + pawn */ { -10, 35, 60, 100, 200, 250, 400, 400, 500 }, /* queen */ { -10, 40, 70, 110, 210, 300, 500, 500, 600 }, /* queen + pawn */ { -10, 45, 75, 125, 215, 300, 500, 600, 700 }, /* queen + 2 pawn */ { -10, 60, 90, 130, 240, 350, 500, 600, 700 }, /* queen + piece */ { -15, 60, 95, 145, 260, 350, 500, 600, 700 }, /* queen + piece + pawn */ { -15, 60, 100, 150, 270, 350, 500, 600, 700 }, /* 2 queen */ { -15, 60, 110, 160, 280, 400, 600, 700, 800 }, { -20, 70, 115, 165, 290, 400, 600, 700, 800 }, { -20, 80, 120, 170, 300, 450, 700, 800, 900 }, { -20, 80, 125, 175, 310, 450, 700, 800, 900 } }; void initialize_eval(void) { int i, j; if (havercfile) { for (i = 0; i < 15; i++) { for(j = 0; j < 9; j++) { ksafety_scaled[i][j] = (int)((float)cfg_ksafety[i][j] * (float)cfg_scalefac); } } for(i = 1; i < 8; i++) { pre_p_tropism[i] = (int)((float)cfg_tropism[0][i-1] * (float)cfg_scalefac); pre_b_tropism[i] = (int)((float)cfg_tropism[1][i-1] * (float)cfg_scalefac); pre_n_tropism[i] = (int)((float)cfg_tropism[2][i-1] * (float)cfg_scalefac); pre_r_tropism[i] = (int)((float)cfg_tropism[3][i-1] * (float)cfg_scalefac); pre_q_tropism[i] = (int)((float)cfg_tropism[4][i-1] * (float)cfg_scalefac); } } for(i = 0; i < 144; i++) { for(j = 0; j < 144; j++) { p_tropism[i][j] = pre_p_tropism[max(abs(rank(i) - rank(j)), abs(file(i) - file(j)))]; b_tropism[i][j] = pre_b_tropism[max(abs(rank(i) - rank(j)), abs(file(i) - file(j)))]; n_tropism[i][j] = pre_n_tropism[max(abs(rank(i) - rank(j)), abs(file(i) - file(j)))]; r_tropism[i][j] = pre_r_tropism[max(abs(rank(i) - rank(j)), abs(file(i) - file(j)))]; q_tropism[i][j] = pre_q_tropism[max(abs(rank(i) - rank(j)), abs(file(i) - file(j)))]; } } } int32_t eval (void) { /* return a score for the current middlegame position: */ int i, a, j; int32_t score = 0; int in_cache; int safety, badsquares; int norm_white_hand_eval, norm_black_hand_eval; int wdev_dscale, bdev_dscale; if (Variant == Normal) { return std_eval(); } else if (Variant == Suicide) { return suicide_eval(); } else if (Variant == Losers) { return losers_eval(); } in_cache = 0; checkECache(&score, &in_cache); if(in_cache) { if (white_to_move == 1) return score; return -score; } /* set up development scalefactor depending on material * in hand */ if (cfg_devscale) { /* computer plays black -> no white downscaling */ if (white_to_move != comp_color) { if (white_hand_eval <= 200 && (Variant != Bughouse)) { /* 2 pawns or less */ wdev_dscale = 2; } else if (white_hand_eval >= 700) { /* queen + minor, three minors or more */ wdev_dscale = 0; } else { wdev_dscale = 1; } } else wdev_dscale = 0; if (white_to_move == comp_color) { if ((-black_hand_eval) <= 200 && (Variant != Bughouse)) { /* 2 pawns or less */ bdev_dscale = 2; } else if ((-black_hand_eval) >= 700) { /* queen + pawn, two minors + pawn */ bdev_dscale = 0; } else { bdev_dscale = 1; } } else bdev_dscale = 0; } else { wdev_dscale = bdev_dscale = 0; } /* loop through the board, adding material value, as well as positional bonuses for all pieces encountered: */ for (a = 1, j = 1;(a <= piece_count); j++) { i = pieces[j]; if (!i) continue; else a++; switch (board[i]) { case (wpawn): score += 100; score += white_pawn[i] >> wdev_dscale; score += p_tropism[i][bking_loc]; break; case (bpawn): score -= 100; score -= black_pawn[i] >> bdev_dscale; score -= p_tropism[i][wking_loc]; break; case (wrook): score += 250; score += white_rook[i] >> wdev_dscale; score += r_tropism[i][bking_loc]; break; case (brook): score -= 250; score -= black_rook[i] >> bdev_dscale; score -= r_tropism[i][wking_loc]; break; case (wbishop): score += 230; score += bishop[i] >> wdev_dscale; score += b_tropism[i][bking_loc]; break; case (bbishop): score -= 230; score -= bishop[i] >> bdev_dscale; score -= b_tropism[i][wking_loc]; break; case (wknight): score += 210; score += white_knight[i] >> wdev_dscale; score += n_tropism[i][bking_loc]; break; case (bknight): score -= 210; score -= black_knight[i] >> bdev_dscale; score -= n_tropism[i][wking_loc]; break; case (wqueen): score += 450; score += white_queen[i] >> wdev_dscale; score += q_tropism[i][bking_loc]; break; case (bqueen): score -= 450; score -= black_queen[i] >> bdev_dscale; score -= q_tropism[i][wking_loc]; break; } } /* we scale our kings position depending on how much material the _other_ side has in hand */ score += white_king[wking_loc] >> bdev_dscale; score -= black_king[bking_loc] >> wdev_dscale; /* we do not give a bonus for castling, but it is important to keep our options open */ if (!white_castled && moved[30]) { score -= 30; } if (!black_castled && moved[114]) { score += 30; } /* give penalties for blocking the e/d pawns: */ if (!moved[41] && board[53] != npiece) score -= 15; if (!moved[42] && board[54] != npiece) score -= 15; if (!moved[101] && board[89] != npiece) score += 15; if (!moved[102] && board[90] != npiece) score += 15; if (cfg_smarteval) { /* Pawn cover for the King please... */ /* White */ if (wking_loc != E1 && wking_loc != D1) { if (board[wking_loc+11] != wpawn) score -= 24; if (board[wking_loc+12] != wpawn) score -= 35; if (board[wking_loc+13] != wpawn) score -= 24; /* When castled, building a fortress wont hurt */ if (white_castled) { if (board[bking_loc-25] == bpawn) score += 11; if (board[bking_loc-24] == bpawn) score += 15; if (board[bking_loc-23] == bpawn) score += 11; } } /* Black */ if (bking_loc != E8 && bking_loc != D8) { if (board[bking_loc-13] != bpawn) score += 24; if (board[bking_loc-12] != bpawn) score += 35; if (board[bking_loc-11] != bpawn) score += 24; /* When castled, building a fortress wont hurt */ if (black_castled) { if (board[bking_loc-25] == bpawn) score -= 11; if (board[bking_loc-24] == bpawn) score -= 15; if (board[bking_loc-23] == bpawn) score -= 11; } } /* Develop stuff */ if (moved[E2]) { score += 30; if (moved[D2]) score += 25; if (moved[G1]) score += 20; if (moved[B1]) score += 15; if (moved[C1]) score += 10; } if (moved[E7]) { score -= 30; if (moved[D7]) score -= 25; if (moved[G8]) score -= 20; if (moved[B8]) score -= 15; if (moved[C8]) score -= 10; } /* Bad holes in the kingside (g2/e2) or (g7/e7) allow attacks */ if ((board[G2] != wpawn) && (board[F3] == bpawn || board[E4] == bpawn)) score -= 30; if ((board[G7] != bpawn) && (board[F6] == wpawn || board[E5] == wpawn)) score += 30; #define Fis_attacked(x,y) (board[(x)] == frame ? 0 : is_attacked((x),(y))) #define Gis_attacked(x,y) (board[(x)] == frame ? 0 : nk_attacked((x),(y))) /* An enemy pawn in front of the king can be deadly.*/ /* especially if it is protected */ if (board[wking_loc + 12] == bpawn || board[wking_loc + 12] == bbishop) { score -= 35; if (Fis_attacked(wking_loc + 12, 0)) score -= 150 >> bdev_dscale; } if (board[bking_loc - 12] == wpawn || board[bking_loc - 12] == wbishop) { score += 35; if (Fis_attacked(bking_loc - 12,1)) score += 150 >> wdev_dscale; } /* If e6 is attacked but there is no pawn there (just P-f7) */ /* I rely on CSE to remove the extra square checks and avoid the * is_attacked call */ if (((board[F2] == wpawn) || (board[E3] == wpawn) || board[E3] == bpawn) && Fis_attacked(E3,0)) { if (board[F2] == wpawn) score += 10; if (board[E3] == wpawn) score += 20; else if (board[E3] == bpawn) score -= 15; } if (((board[F7] == bpawn) || (board[E6] == bpawn) || board[E6] == wpawn) && Fis_attacked(E6,1)) { if (board[F7] == bpawn) score -= 10; if (board[E6] == bpawn) score -= 20; else if (board[E6] == wpawn) score += 15; } /* Bonus if in check */ if (Fis_attacked(bking_loc,1)) score += 50 >> wdev_dscale; else if (Fis_attacked(wking_loc,0)) score -= 50 >> bdev_dscale; /* Give big pentalty for knight or pawn at g2/g7 especially if supported */ /* Also protect with Rook and Bishop */ if (board[G2] == bknight) { score -= 20; if (Fis_attacked(G2,0)) score -= 40; if (board[G1] == wrook) score += 10; if (board[F1] == wbishop) score += 10; } if (board[G7] == wknight) { score += 20; if (Fis_attacked(G7,1)) score += 40; if (board[G8] == brook) score -= 10; if (board[F8] == bbishop)score -= 10; } /* Bishop at h3/h6 often leads to crushing attacks */ /* Especially when the king is trapped behind a N */ if ((board[H3] == bbishop) && (board[G2] != wpawn)) { score -= 20; if (board[G2] == bknight) { score -= 40; if (board[F1] == wking || board[G1] == wking || board[H1] == wking) score -= 80; } } if ((board[H6] == wbishop) && (board[G7] != bpawn)) { score += 20; if (board[G7] == wknight) { score += 40; if (board[F8] == bking || board[G8] == bking || board[H8] == bking) score += 80; } } } if (cfg_attackeval) { badsquares = 0; safety = 0; badsquares += Gis_attacked(wking_loc - 13, 0); badsquares += Gis_attacked(wking_loc - 12, 0); badsquares += Gis_attacked(wking_loc - 11, 0); badsquares += Gis_attacked(wking_loc - 1, 0); badsquares += Gis_attacked(wking_loc + 1, 0); badsquares += Gis_attacked(wking_loc + 11, 0); badsquares += Gis_attacked(wking_loc + 12, 0); badsquares += Gis_attacked(wking_loc + 13, 0); norm_black_hand_eval = ((-black_hand_eval) / 100); if (norm_black_hand_eval > 14) norm_black_hand_eval = 14; else if (norm_black_hand_eval < 0) norm_black_hand_eval = 0; safety -= ksafety_scaled[norm_black_hand_eval][badsquares]; badsquares = 0; badsquares += Gis_attacked(bking_loc - 13, 1); badsquares += Gis_attacked(bking_loc - 12, 1); badsquares += Gis_attacked(bking_loc - 11, 1); badsquares += Gis_attacked(bking_loc - 1, 1); badsquares += Gis_attacked(bking_loc + 1, 1); badsquares += Gis_attacked(bking_loc + 11, 1); badsquares += Gis_attacked(bking_loc + 12, 1); badsquares += Gis_attacked(bking_loc + 13, 1); norm_white_hand_eval = (white_hand_eval / 100); if (norm_white_hand_eval > 14) norm_white_hand_eval = 14; else if (norm_white_hand_eval < 0) norm_white_hand_eval = 0; safety += ksafety_scaled[norm_white_hand_eval][badsquares]; score += safety; } score += (white_hand_eval + black_hand_eval); storeECache(score); /* adjust for color: */ if (white_to_move == 1) { return score; } else { return -score; } }