Cinnamon  1.0
chess engine
Eval.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines