![]() |
Cinnamon
1.0
chess engine
|
00001 #include "Eval.h" 00002 00003 Eval::Eval() { 00004 } 00005 00006 Eval::~Eval() { 00007 } 00008 00009 void Eval::openColumn(int side) { 00010 int o; 00011 u64 side_rooks = structure.rooks[side]; 00012 structure.openColumn = 0; 00013 structure.semiOpenColumn[side] = 0; 00014 while (side_rooks) { 00015 o = BITScanForward(side_rooks); 00016 if (!(FILE_[o] & (structure.pawns[WHITE] | structure.pawns[BLACK]))) 00017 structure.openColumn |= FILE_[o]; 00018 else if (FILE_[o] & structure.pawns[side ^ 1]) 00019 structure.semiOpenColumn[side] |= FILE_[o]; 00020 side_rooks &= NOTPOW2[o]; 00021 } 00022 } 00023 00024 template <int side,_Tstatus status> 00025 int Eval::evaluatePawn() { 00026 INC(N_EVALUATION[side]); 00027 u64 ped_friends = structure.pawns[side]; 00028 if (!ped_friends) 00029 return 0; 00030 int result = 0; 00031 structure.isolated[side] = 0; 00032 if (bitCount(structure.pawns[side ^ 1]) == 8) 00033 result -= ENEMIES_PAWNS_ALL; 00034 result += ATTACK_KING *bitCount(ped_friends & structure.kingAttackers[side^1]); 00035 //space - 2/7th 00036 if (side == WHITE) { 00037 if (status == OPEN) 00038 result += PAWN_CENTER * bitCount(ped_friends & CENTER_MASK); 00039 else { 00040 result += PAWN_7H * (bitCount(ped_friends & 0xFF000000000000ULL)); 00041 result += PAWN_IN_RACE * bitCount(0xFF00000000000000ULL & (((ped_friends << 8)) & (~structure.allPiecesSide[BLACK]))); 00042 } 00043 } else { 00044 if (status == OPEN) 00045 result += PAWN_CENTER * bitCount(ped_friends & CENTER_MASK); 00046 else { 00047 result += PAWN_7H * (bitCount(ped_friends & 0xFF00ULL)); 00048 result += PAWN_IN_RACE * bitCount(0xFFULL & ((ped_friends >> 8) & (~structure.allPiecesSide[BLACK]))); 00049 } 00050 } 00051 int o; 00052 u64 p = ped_friends; 00053 while (p) { 00054 o = BITScanForward(p); 00055 if (status != OPEN) { 00056 structure.kingSecurityDistance[side] += FRIEND_NEAR_KING * (NEAR_MASK2[structure.posKing[side]] & POW2[o]?1:0); 00057 structure.kingSecurityDistance[side ^ 1] -= ENEMY_NEAR_KING * (NEAR_MASK2[structure.posKing[side^1]] & POW2[o]?1:0); 00058 } 00059 //result +=VALUEPAWN;done in lazyeval 00060 //unprotected 00061 if (!(ped_friends & PAWN_PROTECTED_MASK[side][o])) { 00062 result -= UNPROTECTED_PAWNS; 00063 }; 00064 //isolated 00065 if (!(ped_friends & PAWN_ISOLATED_MASK[o])) { 00066 result -= PAWN_ISOLATED; 00067 structure.isolated[side] |= POW2[o]; 00068 } 00069 //doubled 00070 if (NOTPOW2[o] & FILE_[o] & ped_friends) { 00071 result -= DOUBLED_PAWNS; 00072 if (!(structure.isolated[side] & POW2[o])) 00073 result -= DOUBLED_ISOLATED_PAWNS; 00074 }; 00075 //backward 00076 if (!(ped_friends & PAWN_BACKWARD_MASK[side][o])) { 00077 result -= BACKWARD_PAWN; 00078 } 00079 //passed 00080 if (!(structure.pawns[side ^ 1] & PAWN_PASSED_MASK[side][o])) { 00081 result += PAWN_PASSED[side][o]; 00082 } 00083 00084 p &= NOTPOW2[o]; 00085 } 00086 return result; 00087 } 00088 template <int side,_Tstatus status> 00089 int Eval::evaluateBishop() { 00090 INC(N_EVALUATION[side]); 00091 u64 x = chessboard[BISHOP_BLACK + side]; 00092 if (!x) 00093 return 0; 00094 int o, result = 0; 00095 if (status == END && bitCount(x) > 1) 00096 result += BONUS2BISHOP; 00097 // Check to see if the bishop is trapped at a7 or h7 with a pawn at b6 or g6 that has trapped the bishop. 00098 if (side) { 00099 if (chessboard[PAWN_WHITE] & 0x400000ULL && chessboard[BISHOP_WHITE] & 0x8000ULL) 00100 result -= BISHOP_TRAPPED_DIAG; 00101 if (chessboard[PAWN_WHITE] & 0x20000ULL && chessboard[BISHOP_WHITE] & 0x100ULL) 00102 result -= BISHOP_TRAPPED_DIAG; 00103 } else { 00104 if (chessboard[PAWN_BLACK] & 0x400000000000ULL && chessboard[BISHOP_BLACK] & 0x80000000000000ULL) 00105 result -= BISHOP_TRAPPED_DIAG; 00106 if (chessboard[PAWN_BLACK] & 0x20000000000ULL && chessboard[BISHOP_BLACK] & 0x1000000000000ULL) 00107 result -= BISHOP_TRAPPED_DIAG; 00108 } 00109 while (x) { 00110 o = BITScanForward(x); 00111 //result+=VALUEBISHOP;done in lazyeval 00112 if (status != OPEN) { 00113 structure.kingSecurityDistance[side] += FRIEND_NEAR_KING *(NEAR_MASK2[structure.posKing[side]] & POW2[o]?1:0); 00114 structure.kingSecurityDistance[side] -= ENEMY_NEAR_KING * (NEAR_MASK2[structure.posKing[side^1]] & POW2[o]?1:0); 00115 } else 00116 //attack center 00117 if (status == OPEN) { 00118 // result += ATTACK_CENTER * bitCount(structure.mobility[o] & CENTER_MASK); 00119 if (side) { 00120 if (o == C1 || o == F1) 00121 result -= UNDEVELOPED; 00122 } else { 00123 if (o == C8 || o == F8) 00124 result -= UNDEVELOPED; 00125 } 00126 } 00127 else { 00128 if (BIG_DIAG_LEFT & POW2[o] && !(LEFT_DIAG[o] & structure.allPieces)) 00129 result += OPEN_FILE; 00130 if (BIG_DIAG_RIGHT & POW2[o] && !(RIGHT_DIAG[o] & structure.allPieces)) 00131 result += OPEN_FILE; 00132 } 00133 x &= NOTPOW2[o]; 00134 }; 00135 return result; 00136 } 00137 template <_Tstatus status> 00138 int Eval::evaluateQueen(int side) { 00139 INC(N_EVALUATION[side]); 00140 int o, result = 0; 00141 u64 queen = chessboard[QUEEN_BLACK + side]; 00142 while (queen) { 00143 o = BITScanForward(queen); 00144 //result+=VALUEQUEEN;done in lazyeval 00145 if (status != OPEN) { 00146 structure.kingSecurityDistance[side] += FRIEND_NEAR_KING * (NEAR_MASK2[structure.posKing[side]] & POW2[o]?1:0); 00147 structure.kingSecurityDistance[side] -= ENEMY_NEAR_KING * (NEAR_MASK2[structure.posKing[side^1]] & POW2[o]?1:0); 00148 } 00149 if ((structure.pawns[side ^ 1] & FILE_[o])) 00150 result += HALF_OPEN_FILE_Q; 00151 if ((FILE_[o] & structure.allPieces) == POW2[o]) 00152 result += OPEN_FILE_Q; 00153 if (LEFT_RIGHT_DIAG[o] & chessboard[BISHOP_BLACK + side]) 00154 result += BISHOP_ON_QUEEN; 00155 queen &= NOTPOW2[o]; 00156 }; 00157 return result; 00158 } 00159 00160 template <int side,_Tstatus status> 00161 int Eval::evaluateKnight() { 00162 INC(N_EVALUATION[side]); 00163 int o, result = 0; 00164 u64 x = chessboard[KNIGHT_BLACK + side]; 00165 if (status == OPEN) { 00166 side?result -= bitCount(x & 0x42ULL)*UNDEVELOPED:result -= bitCount(x & 0x4200000000000000ULL)*UNDEVELOPED; 00167 } 00168 while (x) { 00169 o = BITScanForward(x); 00170 //result+=VALUEKNIGHT;//done in lazyeval 00171 if (status != OPEN) { 00172 structure.kingSecurityDistance[side] += FRIEND_NEAR_KING * (NEAR_MASK2[structure.posKing[side]] & POW2[o]?1:0); 00173 structure.kingSecurityDistance[side] -= ENEMY_NEAR_KING * (NEAR_MASK2[structure.posKing[side^1]] & POW2[o]?1:0); 00174 } 00175 x &= NOTPOW2[o]; 00176 }; 00177 return result; 00178 } 00179 00180 template <int side,_Tstatus status> 00181 int Eval::evaluateRook() { 00182 INC(N_EVALUATION[side]); 00183 int firstRook = -1, secondRook = -1, o, result = 0; 00184 u64 x; 00185 if (!(x = chessboard[ROOK_BLACK + side])) 00186 return 0; 00187 if (status == MIDDLE) { 00188 if (!side && (o = bitCount(x & RANK_1))) 00189 result += ROOK_7TH_RANK * o; 00190 if (side && (o = bitCount(x & RANK_6))) 00191 result += o * ROOK_7TH_RANK; 00192 } 00193 while (x) { 00194 o = BITScanForward(x); 00195 00196 if (firstRook == -1) 00197 firstRook = o; 00198 else 00199 secondRook = o; 00200 //result +=VALUEROOK;done in lazyeval 00201 if (status != OPEN) { 00202 structure.kingSecurityDistance[side] += FRIEND_NEAR_KING * (NEAR_MASK2[structure.posKing[side]] & POW2[o]?1:0); 00203 structure.kingSecurityDistance[side] -= ENEMY_NEAR_KING * (NEAR_MASK2[structure.posKing[side^1]] & POW2[o]?1:0); 00204 /* Penalise if Rook is Blocked Horizontally */ 00205 if ((RANK_BOUND[o] & structure.allPieces) == RANK_BOUND[o]) { 00206 result -= ROOK_BLOCKED; 00207 }; 00208 } 00209 if (!(structure.pawns[side] & FILE_[o])) 00210 result += OPEN_FILE; 00211 if (!(structure.pawns[side ^ 1] & FILE_[o])) 00212 result += OPEN_FILE; 00213 00214 x &= NOTPOW2[o]; 00215 }; 00216 if (firstRook != -1 && secondRook != -1) 00217 if ((!(_bits::LINK_ROOKS[firstRook][secondRook] & structure.allPieces))) { 00218 result += CONNECTED_ROOKS; 00219 } 00220 return result; 00221 } 00222 00223 template <_Tstatus status> 00224 int Eval::evaluateKing(int side) { 00225 ASSERT(N_EVALUATION[side] == 5); 00226 int result = 0; 00227 u64 pos_king = structure.posKing[side]; 00228 if (status == END) 00229 result = SPACE * (DISTANCE_KING_ENDING[pos_king]); 00230 else 00231 result = SPACE * (DISTANCE_KING_OPENING[pos_king]); 00232 00233 u64 POW2_king = POW2[pos_king]; 00234 if (status != OPEN) { 00235 if ((structure.openColumn & POW2_king) || (structure.semiOpenColumn[side ^ 1] & POW2_king)) { 00236 result -= END_OPENING; 00237 if (bitCount(RANK[pos_king]) < 4) 00238 result -= END_OPENING; 00239 } 00240 } 00241 ASSERT(pos_king < 64); 00242 if (!(NEAR_MASK1[pos_king] & structure.pawns[side])) 00243 result -= PAWN_NEAR_KING; 00244 result += structure.kingSecurityDistance[side]; 00245 return result; 00246 } 00247 00248 int Eval::getScore(const int side , const int alpha, const int beta) { 00249 int lazyscore_white = lazyEvalSide<WHITE>(); 00250 int lazyscore_black = lazyEvalSide<BLACK>(); 00251 #ifndef NO_FP_MODE 00252 int lazyscore = lazyscore_black - lazyscore_white; 00253 if (side) 00254 lazyscore = -lazyscore; 00255 if (lazyscore > (beta + FUTIL_MARGIN) || lazyscore < (alpha - FUTIL_MARGIN)) { 00256 INC(LazyEvalCuts); 00257 if (side) { 00258 return lazyscore -= 5;//5 bonus for the side on move. 00259 } else { 00260 return lazyscore += 5; 00261 } 00262 } 00263 #endif 00264 #ifdef DEBUG_MODE 00265 N_EVALUATION[WHITE] = N_EVALUATION[BLACK] = 0; 00266 #endif 00267 memset(structure.kingSecurityDistance,0, sizeof(structure.kingSecurityDistance)); 00268 int npieces = getNpiecesNoPawnNoKing<WHITE>() + getNpiecesNoPawnNoKing<BLACK>(); 00269 _Tstatus status; 00270 if (npieces < 4) 00271 status = END; 00272 else if (npieces < 11) 00273 status = MIDDLE; 00274 else 00275 status = OPEN; 00276 structure.allPiecesSide[BLACK] = getBitBoard<BLACK>(); 00277 structure.allPiecesSide[WHITE] = getBitBoard<WHITE>(); 00278 00279 structure.allPieces = structure.allPiecesSide[BLACK]|structure.allPiecesSide[WHITE]; 00280 structure.posKing[BLACK] = (unsigned short) BITScanForward(chessboard[KING_BLACK]); 00281 structure.posKing[WHITE] = (unsigned short) BITScanForward(chessboard[KING_WHITE]); 00282 structure.kingAttackers[WHITE]=getKingAttackers(WHITE); 00283 structure.kingAttackers[BLACK]=getKingAttackers(BLACK); 00284 structure.pawns[BLACK] = chessboard[BLACK]; 00285 structure.pawns[WHITE] = chessboard[WHITE]; 00286 structure.queens[WHITE] = chessboard[QUEEN_WHITE]; 00287 structure.queens[BLACK] = chessboard[QUEEN_BLACK]; 00288 structure.rooks[BLACK] = chessboard[ROOK_BLACK]; 00289 structure.rooks[WHITE] = chessboard[ROOK_WHITE]; 00290 openColumn(WHITE); 00291 openColumn(BLACK); 00292 00293 int pawns_score_black ; 00294 int pawns_score_white ; 00295 int bishop_score_black; 00296 int bishop_score_white; 00297 int queens_score_black ; 00298 int queens_score_white ; 00299 int rooks_score_black ; 00300 int rooks_score_white ; 00301 int knights_score_black; 00302 int knights_score_white ; 00303 int kings_score_black; 00304 int kings_score_white; 00305 int bonus_attack_black_king = 0; 00306 int bonus_attack_white_king = 0; 00307 if (status == OPEN) { 00308 pawns_score_black = evaluatePawn<BLACK,OPEN>(); 00309 pawns_score_white = evaluatePawn<WHITE,OPEN>(); 00310 00311 bishop_score_black = evaluateBishop<BLACK,OPEN>(); 00312 bishop_score_white = evaluateBishop<WHITE,OPEN>(); 00313 00314 queens_score_black = evaluateQueen<OPEN>(BLACK); 00315 queens_score_white = evaluateQueen<OPEN>(WHITE); 00316 00317 rooks_score_black = evaluateRook<BLACK,OPEN>(); 00318 rooks_score_white = evaluateRook<WHITE,OPEN>(); 00319 00320 knights_score_black = evaluateKnight<BLACK,OPEN>(); 00321 knights_score_white = evaluateKnight<WHITE,OPEN>(); 00322 00323 kings_score_black =evaluateKing<OPEN>(BLACK); 00324 kings_score_white =evaluateKing<OPEN>(WHITE); 00325 } else { 00326 bonus_attack_black_king = BONUS_ATTACK_KING[bitCount(structure.kingAttackers[WHITE])]; 00327 bonus_attack_white_king = BONUS_ATTACK_KING[bitCount(structure.kingAttackers[BLACK])]; 00328 if (status == END) { 00329 pawns_score_black = evaluatePawn<BLACK,END>(); 00330 pawns_score_white = evaluatePawn<WHITE,END>(); 00331 00332 bishop_score_black = evaluateBishop<BLACK,END>(); 00333 bishop_score_white = evaluateBishop<WHITE,END>(); 00334 00335 queens_score_black = evaluateQueen<END>(BLACK); 00336 queens_score_white = evaluateQueen<END>(WHITE); 00337 00338 rooks_score_black = evaluateRook<BLACK,END>(); 00339 rooks_score_white = evaluateRook<WHITE,END>(); 00340 00341 knights_score_black = evaluateKnight<BLACK,END>(); 00342 knights_score_white = evaluateKnight<WHITE,END>(); 00343 00344 kings_score_black =evaluateKing<END>(BLACK); 00345 kings_score_white =evaluateKing<END>(WHITE); 00346 } else { 00347 pawns_score_black = evaluatePawn<BLACK,MIDDLE>(); 00348 pawns_score_white = evaluatePawn<WHITE,MIDDLE>(); 00349 00350 bishop_score_black = evaluateBishop<BLACK,MIDDLE>(); 00351 bishop_score_white = evaluateBishop<WHITE,MIDDLE>(); 00352 00353 queens_score_black = evaluateQueen<MIDDLE>(BLACK); 00354 queens_score_white = evaluateQueen<MIDDLE>(WHITE); 00355 00356 rooks_score_black = evaluateRook<BLACK,MIDDLE>(); 00357 rooks_score_white = evaluateRook<WHITE,MIDDLE>(); 00358 00359 knights_score_black = evaluateKnight<BLACK,MIDDLE>(); 00360 knights_score_white = evaluateKnight<WHITE,MIDDLE>(); 00361 00362 kings_score_black =evaluateKing<MIDDLE>(BLACK); 00363 kings_score_white =evaluateKing<MIDDLE>(WHITE); 00364 } 00365 } 00366 00367 int attack_king_white=ATTACK_KING *bitCount(structure.kingAttackers[BLACK]); 00368 int attack_king_black=ATTACK_KING *bitCount(structure.kingAttackers[WHITE]); 00369 00370 int result = (attack_king_black+bonus_attack_black_king + lazyscore_black + pawns_score_black + knights_score_black + bishop_score_black 00371 + rooks_score_black + queens_score_black + kings_score_black ) 00372 - (attack_king_white+bonus_attack_white_king + lazyscore_white + pawns_score_white + knights_score_white + bishop_score_white 00373 + rooks_score_white + queens_score_white + kings_score_white ); 00374 if (side) 00375 result -= 5; //5 bonus for the side on move. 00376 else 00377 result += 5; 00378 00379 if (side) 00380 result = -result; 00381 00382 return result; 00383 }