Cinnamon  1.0
chess engine
GenMoves.cpp
Go to the documentation of this file.
00001 #include "GenMoves.h"
00002 
00003 GenMoves::GenMoves() {
00004     perftMode=false;
00005     currentPly=0;
00006     gen_list = (_TmoveP*) calloc(MAX_PLY, sizeof(_TmoveP));
00007     assert(gen_list);
00008     for (int i = 0; i < MAX_PLY; i++) {
00009         gen_list[i].moveList = (_Tmove*) calloc(MAX_MOVE, sizeof(_Tmove));
00010         assert(gen_list[i].moveList);
00011     }
00012     repetitionMap=(u64*)malloc(sizeof(u64)*MAX_REP_COUNT);
00013     assert(repetitionMap);
00014     listId = -1;
00015     repetitionMapCount=0;
00016 }
00017 
00018 void GenMoves::generateMoves( const int side, u64 allpieces) {
00019     side?generateMoves<WHITE>(allpieces):generateMoves<BLACK>(allpieces);
00020 }
00021 
00022 template <int side>
00023 void GenMoves::generateMoves(u64 allpieces) {
00024     ASSERT( chessboard[KING_BLACK]);
00025     ASSERT(chessboard[KING_WHITE]);
00026     tryAllCastle(side, allpieces);
00027     performBishopShift( BISHOP_BLACK+side, side, allpieces);
00028     performRookQueenShift( ROOK_BLACK+side, side, allpieces);
00029     performRookQueenShift( QUEEN_BLACK+side, side, allpieces);
00030     performBishopShift( QUEEN_BLACK+side, side, allpieces);
00031     performPawnShift<side>(~allpieces);
00032     performKnightShiftCapture( KNIGHT_BLACK+side, ~allpieces, side);
00033     performKingShiftCapture(side,~allpieces);
00034 }
00035 
00036 bool GenMoves::generateCaptures( const int side, u64 enemies,u64 friends,u64* key) {
00037     return side?generateCaptures<WHITE>( enemies,friends,key):generateCaptures<BLACK>( enemies,friends,key);
00038 }
00039 
00040 template <int side>
00041 bool GenMoves::generateCaptures( u64 enemies,u64 friends,u64* key) {
00042     ASSERT(chessboard[KING_BLACK]);
00043     ASSERT(chessboard[KING_WHITE]);
00044     u64 allpieces = enemies|friends;
00045 
00046     if (performPawnCapture<side>( enemies,key))
00047         return true;
00048     if (performKingShiftCapture(side, enemies))
00049         return true;
00050 
00051     if (performKnightShiftCapture( KNIGHT_BLACK+side, enemies, side))
00052         return true;
00053 
00054     if (performBishopCapture( BISHOP_BLACK+side, enemies, side, allpieces))
00055         return true;
00056 
00057     if (performRookQueenCapture( ROOK_BLACK+side, enemies, side, allpieces))
00058         return true;
00059 
00060     if (performRookQueenCapture( QUEEN_BLACK+side, enemies, side, allpieces))
00061         return true;
00062     if (performBishopCapture( QUEEN_BLACK+side, enemies, side, allpieces))
00063         return true;
00064 
00065     return false;
00066 }
00067 
00068 void GenMoves::setKillerHeuristic(int from, int to, int value) {
00069     ASSERT(from >= 0 && from <64 && to >=0 && to <64);
00070     killerHeuristic[from][to] = value;
00071 }
00072 
00073 void GenMoves::incKillerHeuristic(int from, int to, int value) {
00074     ASSERT(from >= 0 && from <64 && to >=0 && to <64);
00075     ASSERT (killerHeuristic[from][to] <= killerHeuristic[from][to] + value);
00076     killerHeuristic[from][to] += value;
00077 }
00078 
00079 void GenMoves::setPerft(bool b) {
00080     perftMode=b;
00081 }
00082 
00083 void GenMoves::clearKillerHeuristic() {
00084     memset(killerHeuristic, 0, sizeof(killerHeuristic));
00085 }
00086 
00087 _Tmove* GenMoves::getNextMove(_TmoveP* list) {
00088     _Tmove* gen_list1=list->moveList;
00089     int listcount = list->size;
00090     int bestId = -1;
00091     int j,bestScore;
00092     for (j = 0; j < listcount; j++) {
00093         if (!gen_list1[j].used) {
00094             bestId = j;
00095             bestScore=gen_list1[bestId].score;
00096             break;
00097         }
00098     }
00099     if (bestId == -1)
00100         return NULL;
00101     for (int i = j+1; i < listcount; i++) {
00102         if (!gen_list1[i].used && gen_list1[i].score > bestScore)
00103             bestId = i;
00104         bestScore=gen_list1[bestId].score;
00105     }
00106     gen_list1[bestId].used = true;
00107     return &gen_list1[bestId];
00108 }
00109 
00110 GenMoves::~GenMoves() {
00111     for (int i = 0; i < MAX_PLY; i++)
00112         free(gen_list[i].moveList);
00113     free(gen_list);
00114     free(repetitionMap);
00115 }
00116 
00117 bool GenMoves::isPinned(const int side, const uchar position, const uchar piece) {
00118     u64 king = chessboard[KING_BLACK + side];
00119     int posKing =BITScanForward(king);
00120     u64 pow2position=POW2[position];
00121     if(!(LEFT_RIGHT_RANK_FILE[posKing] & pow2position))
00122         return false;
00123     int xside = side ^ 1;
00124     chessboard[piece] &= NOTPOW2[position];
00125     u64 allpieces = getBitBoard<WHITE>()|getBitBoard<BLACK>();
00126     u64 qr=chessboard[QUEEN_BLACK + xside]|chessboard[ROOK_BLACK + xside];
00127     u64 qb=chessboard[QUEEN_BLACK + xside]|chessboard[BISHOP_BLACK + xside];
00128 
00129     if (king & RANK[position] && RANK[position]&qr) {
00130         //rank
00131         for(int n=position+1; n<=ORIZ_LEFT[position]; n++) {
00132             if(qr & POW2[n]) {
00133                 chessboard[piece] |= pow2position;
00134                 return true;
00135             }
00136             if(allpieces & POW2[n])break;
00137         }
00138         for(int n=position-1; n>=ORIZ_RIGHT[position]; n--) {
00139             if(qr & POW2[n]) {
00140                 chessboard[piece] |= pow2position;
00141                 return true;
00142             }
00143             if(allpieces & POW2[n])break;
00144 
00145         }
00146     } else if (king & FILE_[position] && FILE_[position] & qr) {
00147         for(int n=posKing+8; n<=VERT_UPPER[posKing]; n+=8) {
00148             if(qr & POW2[n]) {
00149                 chessboard[piece] |= pow2position;
00150                 return true;
00151             }
00152             if(POW2[n]&allpieces)break;
00153         }
00154         for(int n=posKing-8; n>=VERT_LOWER[posKing]; n-=8) {
00155             if(qr & POW2[n]) {
00156                 chessboard[piece] |= pow2position;
00157                 return true;
00158             }
00159             if(POW2[n]&allpieces)break;
00160         }
00161     } else if (king & LEFT_DIAG[position] && LEFT_DIAG[position] &qb) {
00162         for(int n=position+7; n<=LEFT_UPPER[position]; n+=7) {
00163             if(qb & POW2[n]) {
00164                 chessboard[piece] |= pow2position;
00165                 return true;
00166             }
00167             if(allpieces & POW2[n])break;
00168         }
00169         for(int n=position-7; n>=LEFT_LOWER[position]; n-=7) {
00170             if(qb & POW2[n]) {
00171                 chessboard[piece] |= pow2position;
00172                 return true;
00173             }
00174             if(allpieces & POW2[n])break;
00175         }
00176     } else if (king & RIGHT_DIAG[position] && RIGHT_DIAG[position] & qb) {
00177         for(int n=position+9; n<=RIGHT_UPPER[position]; n+=9) {
00178             if(qb & POW2[n]) {
00179                 chessboard[piece] |= pow2position;
00180                 return true;
00181             }
00182             if(allpieces & POW2[n])break;
00183         }
00184         for(int n=position-9; n>=RIGHT_LOWER[position]; n-=9) {
00185             if(qb & POW2[n]) {
00186                 chessboard[piece] |= pow2position;
00187                 return true;
00188             }
00189             if(allpieces & POW2[n])break;
00190         }
00191     }
00192     chessboard[piece] |= pow2position;
00193     return false;
00194 }
00195 
00196 
00197 void GenMoves::performCastle(const int side, const uchar type, u64*key) {
00198     if (side == WHITE) {
00199         if (type & KING_SIDE_CASTLE_MOVE_MASK) {
00200             ASSERT(getPieceAt(side, POW2_3) == KING_WHITE);
00201             ASSERT(getPieceAt(side, POW2_1) == SQUARE_FREE);
00202             ASSERT(getPieceAt(side, POW2_2) == SQUARE_FREE);
00203             ASSERT(getPieceAt(side, POW2_0) == ROOK_WHITE);
00204 
00205             updateZobristKey(key, KING_WHITE, 3);
00206             updateZobristKey(key, KING_WHITE, 1);
00207             chessboard[KING_WHITE] = (chessboard[KING_WHITE] | POW2_1) & NOTPOW2_3;
00208 
00209             updateZobristKey(key, ROOK_WHITE, 2);
00210             updateZobristKey(key, ROOK_WHITE, 0);
00211             chessboard[ROOK_WHITE] = (chessboard[ROOK_WHITE] | POW2_2) & NOTPOW2_0;
00212 
00213         } else {
00214             ASSERT(type & QUEEN_SIDE_CASTLE_MOVE_MASK);
00215             ASSERT(getPieceAt(side, POW2_3) == KING_WHITE);
00216             ASSERT(getPieceAt(side, POW2_4) == SQUARE_FREE);
00217             ASSERT(getPieceAt(side, POW2_5) == SQUARE_FREE);
00218             ASSERT(getPieceAt(side, POW2_6) == SQUARE_FREE);
00219             ASSERT(getPieceAt(side, POW2_7) == ROOK_WHITE);
00220             chessboard[KING_WHITE] = (chessboard[KING_WHITE] | POW2_5) & NOTPOW2_3;
00221 
00222             updateZobristKey(key, KING_WHITE, 5);
00223             updateZobristKey(key, KING_WHITE, 3);
00224             chessboard[ROOK_WHITE] = (chessboard[ROOK_WHITE] | POW2_4) & NOTPOW2_7;
00225 
00226             updateZobristKey(key, ROOK_WHITE, 4);
00227             updateZobristKey(key, ROOK_WHITE, 7);
00228         }
00229     } else {
00230         if (type & KING_SIDE_CASTLE_MOVE_MASK) {
00231 
00232             ASSERT(getPieceAt(side, POW2_59) == KING_BLACK);
00233             ASSERT(getPieceAt(side, POW2_58) == SQUARE_FREE);
00234             ASSERT(getPieceAt(side, POW2_57) == SQUARE_FREE);
00235             ASSERT(getPieceAt(side, POW2_56) == ROOK_BLACK);
00236 
00237             chessboard[KING_BLACK] = (chessboard[KING_BLACK] | POW2_57) & NOTPOW2_59;
00238 
00239             updateZobristKey(key, KING_BLACK, 57);
00240             updateZobristKey(key, KING_BLACK, 59);
00241             chessboard[ROOK_BLACK] = (chessboard[ROOK_BLACK] | POW2_58) & NOTPOW2_56;
00242 
00243             updateZobristKey(key, ROOK_BLACK, 58);
00244             updateZobristKey(key, ROOK_BLACK, 56);
00245         } else {
00246             ASSERT(type & QUEEN_SIDE_CASTLE_MOVE_MASK);
00247             ASSERT(getPieceAt(side, POW2_59) == KING_BLACK);
00248             ASSERT(getPieceAt(side, POW2_60) == SQUARE_FREE);
00249             ASSERT(getPieceAt(side, POW2_61) == SQUARE_FREE);
00250             ASSERT(getPieceAt(side, POW2_62) == SQUARE_FREE);
00251             ASSERT(getPieceAt(side, POW2_63) == ROOK_BLACK);
00252 
00253             chessboard[KING_BLACK] = (chessboard[KING_BLACK] | POW2_61) & NOTPOW2_59;
00254 
00255             updateZobristKey(key, KING_BLACK, 61);
00256             updateZobristKey(key, KING_BLACK, 59);
00257             chessboard[ROOK_BLACK] = (chessboard[ROOK_BLACK] | POW2_60) & NOTPOW2_63;
00258 
00259             updateZobristKey(key, ROOK_BLACK, 60);
00260             updateZobristKey(key, ROOK_BLACK, 63);
00261         }
00262     }
00263 }
00264 
00265 void GenMoves::performRookQueenShift(const int piece, const int side, const u64 allpieces) {
00266     ASSERT(piece >= 0 && piece < 12);
00267     int n, position;
00268     u64 x2 = chessboard[piece];
00269     while (x2) {
00270         position = BITScanForward(x2);
00271         for(n=position+1; n<=ORIZ_LEFT[position]; n++) {
00272             if((allpieces & POW2[n])==0)
00273                 pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece);
00274             else break;
00275         }
00276         for(n=position-1; n>=ORIZ_RIGHT[position]; n--) {
00277             if((allpieces & POW2[n])==0)
00278                 pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece);
00279             else break;
00280         }
00281         for(n=position+8; n<=VERT_UPPER[position]; n+=8) {
00282             if((allpieces & POW2[n])==0)
00283                 pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece);
00284             else break;
00285         }
00286         for(n=position-8; n>=VERT_LOWER[position]; n-=8) {
00287             if((allpieces & POW2[n])==0)
00288                 pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece);
00289             else break;
00290         }
00291         x2 &= NOTPOW2[position];
00292     };
00293 }
00294 
00295 void GenMoves::performBishopShift( const int piece, const int side, const u64 allpieces) {
00296     ASSERT(piece >= 0 && piece < 12);
00297     int position;
00298     int n;
00299     u64 x2 = chessboard[piece];
00300     while (x2) {
00301         position = BITScanForward(x2);
00302         for(n=position+7; n<=LEFT_UPPER[position]; n+=7) {
00303             if((allpieces & POW2[n])==0)
00304                 pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece);
00305             else break;
00306         }
00307 
00308         for(n=position-7; n>=LEFT_LOWER[position]; n-=7) {
00309             if((allpieces & POW2[n])==0)
00310                 pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece);
00311             else break;
00312         }
00313 
00314         for(n=position+9; n<=RIGHT_UPPER[position]; n+=9) {
00315             if((allpieces & POW2[n])==0)
00316                 pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece);
00317             else
00318                 break;
00319         }
00320 
00321         for(n=position-9; n>=RIGHT_LOWER[position]; n-=9) {
00322             if((allpieces & POW2[n])==0)
00323                 pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece);
00324             else break;
00325         }
00326         x2 &= NOTPOW2[position];
00327     };
00328 }
00329 
00330 void GenMoves::tryAllCastle(const int side, const u64 allpieces) {
00331     if (side == WHITE) {
00332         if (POW2_3 & chessboard[KING_WHITE] && !(allpieces & 0x6ULL) && RIGHT_CASTLE & RIGHT_KING_CASTLE_WHITE_MASK
00333                 && chessboard[ROOK_WHITE] & POW2_0 && !attackSquare<WHITE>( 1) && !attackSquare<WHITE>( 2) && !attackSquare<WHITE>( 3)) {
00334             pushmove<KING_SIDE_CASTLE_MOVE_MASK>( -1, -1, WHITE, NO_PROMOTION,-1);
00335         }
00336         if (POW2_3 & chessboard[KING_WHITE] && !(allpieces & 0x70ULL) && RIGHT_CASTLE & RIGHT_QUEEN_CASTLE_WHITE_MASK
00337                 && chessboard[ROOK_WHITE] & POW2_7 && !attackSquare<WHITE>( 3) && !attackSquare<WHITE>( 4) && !attackSquare<WHITE>(5)) {
00338             pushmove<QUEEN_SIDE_CASTLE_MOVE_MASK>( -1, -1, WHITE, NO_PROMOTION,-1);
00339         }
00340     } else {
00341         if (POW2_59 & chessboard[KING_BLACK] && RIGHT_CASTLE & RIGHT_KING_CASTLE_BLACK_MASK && !(allpieces & 0x600000000000000ULL)
00342                 && chessboard[ROOK_BLACK] & POW2_56 && !attackSquare<BLACK>( 57) && !attackSquare<BLACK>(58) && !attackSquare<BLACK>(59)) {
00343             pushmove<KING_SIDE_CASTLE_MOVE_MASK>( -1, -1, BLACK, NO_PROMOTION,-1);
00344         }
00345         if (POW2_59 & chessboard[KING_BLACK] && RIGHT_CASTLE & RIGHT_QUEEN_CASTLE_BLACK_MASK && !(allpieces & 0x7000000000000000ULL)
00346                 && chessboard[ROOK_BLACK] & POW2_63 && !attackSquare<BLACK>(59) && !attackSquare<BLACK>(60) && !attackSquare<BLACK>(61)) {
00347             pushmove<QUEEN_SIDE_CASTLE_MOVE_MASK>( -1, -1, BLACK, NO_PROMOTION,-1);
00348         }
00349     }
00350 }
00351 
00352 bool GenMoves::performRookQueenCapture( const int piece, const u64 enemies, const int side, const u64 allpieces) {
00353     ASSERT(piece >= 0 && piece < 12);
00354     int n, position;
00355     u64 x2 = chessboard[piece];
00356     while (x2) {
00357         position = BITScanForward(x2);
00358         for(n=position+1; n<=ORIZ_LEFT[position]; n++) {
00359             if(allpieces & POW2[n]) {
00360                 if(enemies & POW2[n])if(pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece))return true;
00361                 break;
00362             }
00363         }
00364         for(n=position-1; n>=ORIZ_RIGHT[position]; n--) {
00365             if(allpieces & POW2[n]) {
00366                 if(enemies & POW2[n])if(pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece))return true;
00367                 break;
00368             }
00369         }
00370 
00371         for(n=position+8; n<=VERT_UPPER[position]; n+=8) {
00372             if(allpieces & POW2[n]) {
00373                 if(enemies & POW2[n])if(pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece))return true;
00374                 break;
00375             }
00376         }
00377         for(n=position-8; n>=VERT_LOWER[position]; n-=8) {
00378             if(allpieces & POW2[n]) {
00379                 if(enemies & POW2[n])if(pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece))return true;
00380                 break;
00381             }
00382         }
00383         x2 &= NOTPOW2[position];
00384     };
00385     return false;
00386 }
00387 
00388 bool GenMoves::performBishopCapture( const int piece, const u64 enemies, const int side, const u64 allpieces) {
00389     ASSERT(piece >= 0 && piece < 12);
00390     int position,n;
00391     u64 x2 = chessboard[piece];
00392     while (x2) {
00393         position = BITScanForward(x2);
00394 
00395         for(n=position+7; n<=LEFT_UPPER[position]; n+=7) {
00396             if(allpieces & POW2[n]) {
00397                 if (enemies & POW2[n]) if(pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece))return true;
00398                 break;
00399             }
00400         }
00401 
00402         for(n=position-7; n>=LEFT_LOWER[position]; n-=7) {
00403             if((allpieces & POW2[n])) {
00404                 if (enemies & POW2[n])if(pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece))return true;
00405                 break;
00406             }
00407         }
00408 
00409         for(n=position+9; n<=RIGHT_UPPER[position]; n+=9) {
00410             if((allpieces & POW2[n])) {
00411                 if (enemies & POW2[n]) if(pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece))return true;
00412                 break;
00413             }
00414         }
00415 
00416         for(n=position-9; n>=RIGHT_LOWER[position]; n-=9) {
00417             if((allpieces & POW2[n])) {
00418                 if (enemies & POW2[n]) if(pushmove<STANDARD_MOVE_MASK>( position, n, side, NO_PROMOTION,piece))return true;
00419                 break;
00420             }
00421         }
00422         x2 &= NOTPOW2[position];
00423     };
00424     return false;
00425 }
00426 
00427 bool GenMoves::performKnightShiftCapture(const int piece, const u64 enemies, const int side) {
00428     u64 x1;
00429     int o, pos;
00430     u64 x = chessboard[piece];
00431     while (x) {
00432         pos = BITScanForward(x);
00433         x1 = enemies & KNIGHT_MASK[pos];
00434         while (x1) {
00435             o = BITScanForward(x1);
00436             if (pushmove<STANDARD_MOVE_MASK>( pos, o, side, NO_PROMOTION,piece))
00437                 return true;
00438             x1 &= NOTPOW2[o];
00439         };
00440         x &= NOTPOW2[pos];
00441     }
00442     return false;
00443 }
00444 
00445 bool GenMoves::performKingShiftCapture(int side , const u64 enemies) {
00446     int o;
00447     int pos = BITScanForward(chessboard[KING_BLACK+side]);
00448     ASSERT(pos != -1);
00449     u64 x1 = enemies & NEAR_MASK1[pos];
00450     while (x1) {
00451         o = BITScanForward(x1);
00452         if (pushmove<STANDARD_MOVE_MASK>( pos, o, side, NO_PROMOTION,KING_BLACK+side))
00453             return true;
00454         x1 &= NOTPOW2[o];
00455     };
00456     return false;
00457 }
00458 
00459 template <int side>
00460 void GenMoves::checkJumpPawn(u64 x, const u64 xallpieces) {
00461     x &= TABJUMPPAWN;
00462     if (side) {
00463         x=(((x<<8)&xallpieces)<<8)&xallpieces;
00464     } else {
00465         x=(((x>>8)&xallpieces)>>8)&xallpieces;
00466     };
00467     int o;
00468     while (x) {
00469         o = BITScanForward(x);
00470         pushmove<STANDARD_MOVE_MASK>( o + (side?-16:16), o, side, NO_PROMOTION,side);
00471         x &= NOTPOW2[o];
00472     };
00473 }
00474 
00475 template <int side>
00476 void GenMoves::performPawnShift( const u64 xallpieces) {
00477     int o, tt;
00478     u64 x = chessboard[side];
00479     if (x & PAWNS_7_2[side])
00480         checkJumpPawn<side>( x, xallpieces);
00481     if (side) {
00482         x <<= 8;
00483         tt = -8;
00484     } else {
00485         tt = 8;
00486         x >>= 8;
00487     };
00488     x &= xallpieces;
00489     while (x) {
00490         o = BITScanForward(x);
00491         ASSERT(getPieceAt(side, POW2[o + tt]) != SQUARE_FREE);
00492         ASSERT(getBitBoard(side) & POW2[o + tt]);
00493         if (o > 55 || o < 8) {
00494             pushmove<PROMOTION_MOVE_MASK>( o + tt, o, side, QUEEN_BLACK + side,side); //queen
00495             if( perftMode) {
00496                 pushmove<PROMOTION_MOVE_MASK>( o + tt, o, side, KNIGHT_BLACK + side,side); //knight
00497                 pushmove<PROMOTION_MOVE_MASK>( o + tt, o, side, BISHOP_BLACK + side,side);//bishop
00498                 pushmove<PROMOTION_MOVE_MASK>( o + tt, o, side, ROOK_BLACK + side,side);//rock
00499             }
00500         } else
00501             pushmove<STANDARD_MOVE_MASK>( o + tt, o, side, NO_PROMOTION,side);
00502         x &= NOTPOW2[o];
00503     };
00504 }
00505 
00506 template <int side>
00507 bool GenMoves::performPawnCapture( const u64 enemies,u64*key) {
00508     if (!chessboard[side]) {
00509         if(enpassantPosition!=-1)
00510             updateZobristKey(key, 13, enpassantPosition);
00511         enpassantPosition = -1;
00512         return false;
00513     }
00514     int GG;
00515     u64 x;
00516     if (side) {
00517         x = (chessboard[side] << 7) & TABCAPTUREPAWN_LEFT & enemies;
00518         GG = -7;
00519     } else {
00520         x = (chessboard[side] >> 7) & TABCAPTUREPAWN_RIGHT & enemies;
00521         GG = 7;
00522     };
00523     int o;
00524     while (x) {
00525         o = BITScanForward(x);
00526         if ( (side && o > 55) || (!side && o < 8)) {//PROMOTION
00527             if (pushmove<PROMOTION_MOVE_MASK>( o + GG, o, side, QUEEN_BLACK + side,side))
00528                 return true; //queen
00529             if( perftMode) {
00530                 if (pushmove<PROMOTION_MOVE_MASK>( o + GG, o, side, KNIGHT_BLACK + side,side))
00531                     return true;//knight
00532                 if (pushmove<PROMOTION_MOVE_MASK>( o + GG, o, side, ROOK_BLACK + side,side))
00533                     return true;//rock
00534                 if (pushmove<PROMOTION_MOVE_MASK>( o + GG, o, side, BISHOP_BLACK + side,side))
00535                     return true;//bishop
00536             }
00537         } else if (pushmove<STANDARD_MOVE_MASK>( o + GG, o, side, NO_PROMOTION,side))
00538             return true;
00539         x &= NOTPOW2[o];
00540     };
00541     if (side) {
00542         GG = -9;
00543         x= (chessboard[side] << 9)&TABCAPTUREPAWN_RIGHT & enemies;
00544     } else {
00545         GG = 9;
00546         x= (chessboard[side] >> 9)&TABCAPTUREPAWN_LEFT & enemies;
00547     };
00548     while (x) {
00549         o = BITScanForward(x);
00550         if ( (side && o > 55) || (!side && o < 8)) {//PROMOTION
00551             if (pushmove<PROMOTION_MOVE_MASK>( o + GG, o, side, QUEEN_BLACK + side,side))
00552                 return true; //queen
00553             if( perftMode) {
00554                 if (pushmove<PROMOTION_MOVE_MASK>( o + GG, o, side, KNIGHT_BLACK + side,side))
00555 
00556                     return true; //knight
00557                 if (pushmove<PROMOTION_MOVE_MASK>( o + GG, o, side, BISHOP_BLACK + side,side))
00558 
00559                     return true;//bishop
00560                 if (pushmove<PROMOTION_MOVE_MASK>( o + GG, o, side, ROOK_BLACK + side,side))
00561 
00562                     return true;//rock
00563             }
00564         } else if (pushmove<STANDARD_MOVE_MASK>( o + GG, o, side, NO_PROMOTION,side))
00565             return true;
00566         x &= NOTPOW2[o];
00567     };
00568 
00569     //ENPASSANT
00570     if(enpassantPosition!=-1) {
00571         x = ENPASSANT_MASK[side ^ 1][enpassantPosition] & chessboard[side];
00572         while (x) {
00573             o = BITScanForward(x);
00574             pushmove<ENPASSANT_MOVE_MASK>( o, (side?enpassantPosition + 8:enpassantPosition - 8), side, NO_PROMOTION,side);
00575             x &= NOTPOW2[o];
00576         }
00577         updateZobristKey(key, 13, enpassantPosition);
00578         enpassantPosition = -1;
00579     }
00580 
00581     return false;
00582 }
00583 
00584 
00585 u64 GenMoves::getKingAttackers(const int side) {
00586     int kingPosition=BITScanForward(chessboard[KING_BLACK + side]);
00587     int xside=side^1;
00588     u64 attackers=0;
00589     attackers|=KNIGHT_MASK[kingPosition] & chessboard[KNIGHT_BLACK + xside];
00590     attackers|=NEAR_MASK1[kingPosition] & chessboard[KING_BLACK + xside];
00591     attackers|=PAWN_CAPTURE_MASK[side][kingPosition] & chessboard[PAWN_BLACK + xside];
00592     if (!
00593             ((RANK_FILE[kingPosition] & (chessboard[ROOK_BLACK + xside] | chessboard[QUEEN_BLACK + xside]))
00594              | (LEFT_RIGHT_DIAG[kingPosition] & (chessboard[QUEEN_BLACK + xside] | chessboard[BISHOP_BLACK + xside])))
00595        ) {
00596         return attackers;
00597     }
00598     u64 allpieces =getBitBoard<WHITE>() | getBitBoard<BLACK>()|POW2[kingPosition];
00599 
00600     //right
00601     u64 qb=chessboard[QUEEN_BLACK + xside]|chessboard[BISHOP_BLACK + xside];
00602     for(int n=kingPosition+9; n<=RIGHT_UPPER[kingPosition]; n+=9) {
00603         if(qb & POW2[n])
00604             attackers|=POW2[n];
00605         if(allpieces & POW2[n])break;
00606     }
00607     for(int n=kingPosition-9; n>=RIGHT_LOWER[kingPosition]; n-=9) {
00608         if(qb & POW2[n])
00609             attackers|=POW2[n];
00610         if(allpieces & POW2[n])break;
00611     }
00612     // left
00613     for(int n=kingPosition+7; n<=LEFT_UPPER[kingPosition]; n+=7) {
00614         if(qb & POW2[n])
00615             attackers|=POW2[n];
00616         if(allpieces & POW2[n])break;
00617     }
00618     for(int n=kingPosition-7; n>=LEFT_LOWER[kingPosition]; n-=7) {
00619         if(qb & POW2[n])
00620             attackers|=POW2[n];
00621         if(allpieces & POW2[n])break;
00622     }
00623 
00624     //file
00625     u64 qr=chessboard[QUEEN_BLACK + xside]|chessboard[ROOK_BLACK + xside];
00626     for(int n=kingPosition+8; n<=VERT_UPPER[kingPosition]; n+=8) {
00627         if(qr & POW2[n]) {
00628             attackers|=POW2[n];
00629         }
00630         if(allpieces & POW2[n])break;
00631     }
00632     for(int n=kingPosition-8; n>=VERT_LOWER[kingPosition]; n-=8) {
00633         if(qr & POW2[n]) {
00634             attackers|=POW2[n];
00635         }
00636         if(allpieces & POW2[n])break;
00637 
00638     }
00639     //rank
00640     for(int n=kingPosition+1; n<=ORIZ_LEFT[kingPosition]; n++) {
00641         if(qr & POW2[n]) {
00642             attackers|=POW2[n];
00643         }
00644         if(allpieces & POW2[n])break;
00645     }
00646     for(int n=kingPosition-1; n>=ORIZ_RIGHT[kingPosition]; n--) {
00647         if(qr & POW2[n]) {
00648             attackers|=POW2[n];
00649         }
00650         if(allpieces & POW2[n])break;
00651 
00652     }
00653     return attackers;
00654 }
00655 
00656 template <int side>
00657 bool GenMoves::attackSquare(const uchar Position) {
00658     if (KNIGHT_MASK[Position] & chessboard[KNIGHT_BLACK + (side^1)]) {
00659         return true;
00660     }
00661     if (NEAR_MASK1[Position] & chessboard[KING_BLACK + (side^1)]) {
00662         return true;
00663     }
00664     //enpassant
00665     if (PAWN_CAPTURE_MASK[side][Position] & chessboard[PAWN_BLACK + (side^1)]) {
00666         return true;
00667     }
00668     ASSERT(Position < 64);
00669     if (!
00670             ((RANK_FILE[Position] & (chessboard[ROOK_BLACK + (side^1)] | chessboard[QUEEN_BLACK + (side^1)]))
00671              | (LEFT_RIGHT_DIAG[Position] & (chessboard[QUEEN_BLACK + (side^1)] | chessboard[BISHOP_BLACK + (side^1)])))
00672        ) {
00673         return false;
00674     }
00675     u64 allpieces =getBitBoard<WHITE>() | getBitBoard<BLACK>()|POW2[Position];
00676 
00677     //right
00678     u64 qb=chessboard[QUEEN_BLACK + (side^1)]|chessboard[BISHOP_BLACK + (side^1)];
00679     for(int n=Position+9; n<=RIGHT_UPPER[Position]; n+=9) {
00680         if(qb & POW2[n])
00681             return true;
00682         if(allpieces & POW2[n])break;
00683     }
00684     for(int n=Position-9; n>=RIGHT_LOWER[Position]; n-=9) {
00685         if(qb & POW2[n])
00686             return true;
00687         if(allpieces & POW2[n])break;
00688     }
00689     // left
00690     for(int n=Position+7; n<=LEFT_UPPER[Position]; n+=7) {
00691         if(qb & POW2[n])
00692             return true;
00693         if(allpieces & POW2[n])break;
00694     }
00695     for(int n=Position-7; n>=LEFT_LOWER[Position]; n-=7) {
00696         if(qb & POW2[n])
00697             return true;
00698         if(allpieces & POW2[n])break;
00699     }
00700 
00701     //file
00702     u64 qr=chessboard[QUEEN_BLACK + (side^1)]|chessboard[ROOK_BLACK + (side^1)];
00703     for(int n=Position+8; n<=VERT_UPPER[Position]; n+=8) {
00704         if(qr & POW2[n]) {
00705             return true;
00706         }
00707         if(allpieces & POW2[n])break;
00708     }
00709     for(int n=Position-8; n>=VERT_LOWER[Position]; n-=8) {
00710         if(qr & POW2[n]) {
00711             return true;
00712         }
00713         if(allpieces & POW2[n])break;
00714 
00715     }
00716     //rank
00717     for(int n=Position+1; n<=ORIZ_LEFT[Position]; n++) {
00718         if(qr & POW2[n]) {
00719             return true;
00720         }
00721         if(allpieces & POW2[n])break;
00722     }
00723     for(int n=Position-1; n>=ORIZ_RIGHT[Position]; n--) {
00724         if(qr & POW2[n]) {
00725             return true;
00726         }
00727         if(allpieces & POW2[n])break;
00728 
00729     }
00730     return false;
00731 }
00732 
00733 void GenMoves::unPerformCastle(const int side, const uchar type) {
00734     if (side == WHITE) {
00735         if (type & KING_SIDE_CASTLE_MOVE_MASK) {
00736             ASSERT(getPieceAt (side, POW2_1) == KING_WHITE);
00737             ASSERT(getPieceAt (side, POW2_0) == 12);
00738             ASSERT(getPieceAt (side, POW2_3) == 12);
00739             ASSERT(getPieceAt (side, POW2_2) == ROOK_WHITE);
00740             chessboard[KING_WHITE] = (chessboard[KING_WHITE] | POW2_3) & NOTPOW2_1;
00741             chessboard[ROOK_WHITE] = (chessboard[ROOK_WHITE] | POW2_0) & NOTPOW2_2;
00742         } else {
00743             chessboard[KING_WHITE] = (chessboard[KING_WHITE] | POW2_3) & NOTPOW2_5;
00744             chessboard[ROOK_WHITE] = (chessboard[ROOK_WHITE] | POW2_7) & NOTPOW2_4;
00745         }
00746     } else {
00747         if (type & KING_SIDE_CASTLE_MOVE_MASK) {
00748             chessboard[KING_BLACK] = (chessboard[KING_BLACK] | POW2_59) & NOTPOW2_57;
00749             chessboard[ROOK_BLACK] = (chessboard[ROOK_BLACK] | POW2_56) & NOTPOW2_58;
00750         } else {
00751             chessboard[KING_BLACK] = (chessboard[KING_BLACK] | POW2_59) & NOTPOW2_61;
00752             chessboard[ROOK_BLACK] = (chessboard[ROOK_BLACK] | POW2_63) & NOTPOW2_60;
00753         }
00754     }
00755 }
00756 template <int side>
00757 bool GenMoves::inCheck(const int from, const int to, const uchar type, const int pieceFrom, const int pieceTo, int promotionPiece) {
00758     ASSERT(!(type & 0xC));
00759     bool result = 0;
00760     if ((type & 0x3) == STANDARD_MOVE_MASK) {
00761         u64 from1, to1 = -1;
00762         ASSERT (pieceFrom != SQUARE_FREE);
00763         ASSERT (pieceTo != KING_BLACK);
00764         ASSERT (pieceTo != KING_WHITE);
00765 
00766         from1 = chessboard[pieceFrom];
00767         if (pieceTo != SQUARE_FREE) {
00768             to1 = chessboard[pieceTo];
00769             chessboard[pieceTo] &= NOTPOW2[to];
00770         };
00771         chessboard[pieceFrom] &= NOTPOW2[from];
00772         chessboard[pieceFrom] |= POW2[to];
00773 
00774         ASSERT (chessboard[KING_BLACK]);
00775         ASSERT (chessboard[KING_WHITE]);
00776 
00777         result = attackSquare<side>(BITScanForward(chessboard[KING_BLACK + side]));
00778         chessboard[pieceFrom] = from1;
00779         if (pieceTo != SQUARE_FREE)
00780             chessboard[pieceTo] = to1;
00781     } else if ((type & 0x3) == PROMOTION_MOVE_MASK) {
00782         u64 to1 = 0;
00783         if (pieceTo != SQUARE_FREE)
00784             to1 = chessboard[pieceTo];
00785         u64 from1 = chessboard[pieceFrom];
00786         u64 p1 = chessboard[promotionPiece];
00787         chessboard[pieceFrom] &= NOTPOW2[from];
00788         if (pieceTo != SQUARE_FREE)
00789             chessboard[pieceTo] &= NOTPOW2[to];
00790         chessboard[promotionPiece] = chessboard[promotionPiece] | POW2[to];
00791         result = attackSquare<side>(BITScanForward(chessboard[KING_BLACK + side]));
00792         if (pieceTo != SQUARE_FREE)
00793             chessboard[pieceTo] = to1;
00794         chessboard[pieceFrom] = from1;
00795         chessboard[promotionPiece] = p1;
00796     } else if ((type & 0x3) == ENPASSANT_MOVE_MASK) {
00797         u64 to1 = chessboard[side ^ 1];
00798         u64 from1 = chessboard[side];
00799         chessboard[side] &= NOTPOW2[from];
00800         chessboard[side] |= POW2[to];
00801         if (side)
00802             chessboard[side ^ 1] &= NOTPOW2[to - 8];
00803         else
00804             chessboard[side ^ 1] &= NOTPOW2[to + 8];
00805         result = attackSquare<side>( BITScanForward(chessboard[KING_BLACK + side]));
00806         chessboard[side ^ 1] = to1;
00807         chessboard[side] = from1;
00808     }
00809 #ifdef DEBUG_MODE
00810     else
00811         ASSERT (0);
00812 #endif
00813     return result;
00814 }
00815 
00816 void GenMoves::takeback(_Tmove * move, u64* key, const u64 oldkey,bool rep) {
00817     if(rep)popStackMove();
00818     *key = oldkey;
00819     enpassantPosition = -1;
00820     int pieceFrom, posTo, posFrom, movecapture;
00821     RIGHT_CASTLE = move->type & 0b11110000;
00822     if ((move->type & 0b00000011) == STANDARD_MOVE_MASK || (move->type & 0b00000011) == ENPASSANT_MOVE_MASK) {
00823         posTo = move->to;
00824         posFrom = move->from;
00825         movecapture = move->capturedPiece;
00826         ASSERT(posFrom >= 0 && posFrom < 64);
00827         ASSERT(posTo >= 0 && posTo < 64);
00828         pieceFrom = move->pieceFrom;
00829         chessboard[pieceFrom] = (chessboard[pieceFrom] & NOTPOW2[posTo]) | POW2[posFrom];
00830         if (movecapture != SQUARE_FREE) {
00831             if (((move->type & 0b00000011) != ENPASSANT_MOVE_MASK)) {
00832                 chessboard[movecapture] |= POW2[posTo];
00833             } else {
00834                 ASSERT(movecapture == (move->side^1));
00835                 if (move->side) {
00836                     chessboard[movecapture] |= POW2[posTo - 8];
00837                 } else {
00838                     chessboard[movecapture] |= POW2[posTo + 8];
00839                 }
00840             }
00841         }
00842 
00843     } else if ((move->type & 0b00000011) == PROMOTION_MOVE_MASK) {
00844         posTo = move->to;
00845         posFrom = move->from;
00846         movecapture = move->capturedPiece;
00847         ASSERT(posTo >= 0);
00848         chessboard[(uchar)move->side] |= POW2[posFrom];
00849         chessboard[move->promotionPiece] &= NOTPOW2[posTo];
00850         if (movecapture != SQUARE_FREE) {
00851             chessboard[movecapture] |= POW2[posTo];
00852         }
00853     } else if (move->type & 0b00001100) { //castle
00854         unPerformCastle(move->side, move->type);
00855     }
00856 }
00857 template <uchar type>
00858 bool GenMoves::pushmove( const int from, const int to, const int side, int promotionPiece, int pieceFrom) {
00859     ASSERT(chessboard[KING_BLACK]);
00860     ASSERT(chessboard[KING_WHITE]);
00861     int piece_captured = SQUARE_FREE;
00862     bool res = false;
00863     if (((type & 0b00000011) != ENPASSANT_MOVE_MASK) && !(type & 0b00001100)) {
00864         piece_captured = side ^ 1? getPieceAt<WHITE>( POW2[to]):getPieceAt<BLACK>( POW2[to]);
00865 
00866         if (piece_captured == KING_BLACK + (side ^ 1))
00867             res = true;
00868     } else if (!(type & 0b00001100)) //no castle
00869         piece_captured = side ^ 1;
00870 
00871     if (!(type & 0b00001100) && perftMode) { //no castle
00872         if (side==WHITE && inCheck<WHITE>(from, to, type, pieceFrom,piece_captured, promotionPiece))
00873             return false;
00874         if (side==BLACK && inCheck<BLACK>(from, to, type, pieceFrom,piece_captured, promotionPiece))
00875             return false;
00876     }
00877     _Tmove * mos;
00878     ASSERT (listId >= 0) ;
00879     ASSERT(listId < MAX_PLY);
00880     ASSERT(gen_list[listId].size < MAX_MOVE);
00881     mos = &gen_list[listId].moveList[gen_list[listId].size];
00882     ++gen_list[listId].size;
00883     mos->type = RIGHT_CASTLE | type;
00884     mos->side = (char) side;
00885 
00886     mos->capturedPiece = piece_captured;
00887     if (type &  0b00000011) {
00888         mos->from = (uchar) from;
00889         mos->to = (uchar) to;
00890         mos->pieceFrom=  pieceFrom;
00891         mos->promotionPiece = (char) promotionPiece;
00892         if( !perftMode) {
00893             if (res == true) {
00894                 mos->score = _INFINITE;
00895             } else {
00896                 mos->score = 0;
00897                 mos->score += killerHeuristic[from][to];
00898                 mos->score +=
00899                     (PIECES_VALUE[piece_captured] >= PIECES_VALUE[pieceFrom]) ? (PIECES_VALUE[piece_captured] - PIECES_VALUE[pieceFrom]) * 2 :
00900                     PIECES_VALUE[piece_captured];
00901                 ASSERT (pieceFrom >= 0 && pieceFrom < 12 && to >= 0 && to < 64 && from >= 0 && from < 64);
00902             }
00903         }
00904     }
00905 
00906     else if (type & 0b00001100) { //castle
00907         ASSERT(RIGHT_CASTLE);
00908         mos->score = 100;
00909     }
00910     mos->used=false;
00911     ASSERT(gen_list[listId].size < MAX_MOVE);
00912     return res;
00913 }
00914 
00915 void GenMoves::makemove(_Tmove * move, u64* key,bool rep) {
00916     ASSERT(move);
00917     ASSERT(_bits::bitCount(chessboard[KING_WHITE])==1 && _bits::bitCount(chessboard[KING_BLACK])==1);
00918     int pieceFrom=SQUARE_FREE, posTo, posFrom, movecapture=SQUARE_FREE;
00919     uchar RIGHT_CASTLE_old=RIGHT_CASTLE;
00920     if (!(move->type & 0b00001100)) { //no castle
00921         posTo = move->to;
00922         posFrom = move->from;
00923         ASSERT(posTo >= 0);
00924         movecapture = move->capturedPiece;
00925         ASSERT(posFrom >= 0 && posFrom < 64);
00926         ASSERT(posTo >= 0 && posTo < 64);
00927         pieceFrom = move->pieceFrom;
00928         if ((move->type & 0b00000011) == PROMOTION_MOVE_MASK) {
00929             chessboard[pieceFrom] &= NOTPOW2[posFrom];
00930             updateZobristKey(key, pieceFrom, posFrom);
00931             chessboard[move->promotionPiece] |= POW2[posTo];
00932             updateZobristKey(key, move->promotionPiece, posTo);
00933         } else {
00934             chessboard[pieceFrom] = (chessboard[pieceFrom] | POW2[posTo]) & NOTPOW2[posFrom];
00935             updateZobristKey(key, pieceFrom, posFrom);
00936             updateZobristKey(key, pieceFrom, posTo);
00937         }
00938 
00939         if (movecapture != SQUARE_FREE) {
00940             if ((move->type & 0b00000011) != ENPASSANT_MOVE_MASK) {
00941                 chessboard[movecapture] &= NOTPOW2[posTo];
00942                 updateZobristKey(key, movecapture, posTo);
00943             } else {
00944                 ASSERT(movecapture == (move->side^1));
00945                 if (move->side) {
00946                     chessboard[movecapture] &= NOTPOW2[posTo - 8];
00947                     updateZobristKey(key, movecapture, posTo - 8);
00948                 } else {
00949                     chessboard[movecapture] &= NOTPOW2[posTo + 8];
00950                     updateZobristKey(key, movecapture, posTo + 8);
00951                 }
00952             }
00953         }
00954 
00955         //lost castle right
00956 
00957         switch (pieceFrom) {
00958         case KING_WHITE: {
00959             RIGHT_CASTLE &= 0b11001111;
00960         }
00961         break;
00962         case KING_BLACK: {
00963             RIGHT_CASTLE &= 0b00111111;
00964         }
00965         break;
00966 
00967         case ROOK_WHITE:
00968             if (posFrom == 0) {
00969                 RIGHT_CASTLE &= 0b11101111;
00970             } else if (posFrom == 7) {
00971                 RIGHT_CASTLE &= 0b11011111;
00972             }
00973             break;
00974         case ROOK_BLACK:
00975             if (posFrom == 56) {
00976                 RIGHT_CASTLE &= 0b10111111;
00977             } else if (posFrom == 63) {
00978                 RIGHT_CASTLE &= 0b01111111;
00979             }
00980             break;
00981             //en passant
00982         case PAWN_WHITE:
00983             if ((RANK_1 & POW2[posFrom]) && (RANK_3 & POW2[posTo])) {
00984                 enpassantPosition = posTo;
00985                 updateZobristKey(key, 13, enpassantPosition);
00986             }
00987             break;
00988 
00989         case PAWN_BLACK:
00990             if ((RANK_6 & POW2[posFrom]) && (RANK_4 & POW2[posTo])) {
00991                 enpassantPosition = posTo;
00992                 updateZobristKey(key, 13, enpassantPosition);
00993             }
00994             break;
00995         default:
00996             ;
00997         }
00998     } else if (move->type & 0b00001100) { //castle
00999         performCastle(move->side, move->type, key);
01000         if (move->side == WHITE) {
01001             RIGHT_CASTLE &= 0b11001111;
01002         } else {
01003             RIGHT_CASTLE &= 0b00111111;
01004         }
01005     }
01006     u64 x2=RIGHT_CASTLE_old^RIGHT_CASTLE;
01007     while (x2) {
01008         int position = BITScanForward(x2);
01009         updateZobristKey(key, 14, position);
01010         x2 &= NOTPOW2[position];
01011     }
01012 
01013     if(rep) {
01014         if (movecapture != SQUARE_FREE || pieceFrom==WHITE || pieceFrom==BLACK || move->type & 0b00001100)
01015             pushStackMove(0);
01016         pushStackMove(*key);
01017     }
01018 }
01019 
01020 void GenMoves::init() {
01021     numMoves = numMovesq = 0;
01022 #ifdef DEBUG_MODE
01023 #ifndef NO_FP_MODE
01024     nCutFp = nCutRazor = 0;
01025 #endif
01026     betaEfficency = betaEfficencyCumulative = 0.0;
01027     nCutAB = 0;
01028     nNullMoveCut = 0;
01029 #endif
01030     listId = 0;
01031 }
01032 
01033 u64 GenMoves::getTotMoves() {
01034     return numMoves + numMovesq;
01035 }
01036 void GenMoves::setRepetitionMapCount(int i) {
01037     repetitionMapCount=i;
01038 }
01039 
01040 int GenMoves::loadFen() {
01041     return loadFen("");
01042 }
01043 
01044 int GenMoves::loadFen(string fen) {
01045     repetitionMapCount=0;
01046     int side= ChessBoard::loadFen(fen);
01047     return side;
01048 }
01049 
01050 void GenMoves::makemove(_Tmove * move) {
01051     makemove(move,&zobristKey,true);
01052 }
01053 
01054 int GenMoves::getMoveFromSan(const string fenStr,_Tmove* move) {
01055     enpassantPosition=-1;
01056     memset(move,0,sizeof(_Tmove));
01057     static const string MATCH_QUEENSIDE = "O-O-O e1c1 e8c8";
01058     static const string MATCH_QUEENSIDE_WHITE = "O-O-O e1c1";
01059     static const string MATCH_KINGSIDE_WHITE = "O-O e1g1";
01060     static const string MATCH_QUEENSIDE_BLACK = "O-O-O e8c8";
01061     static const string MATCH_KINGSIDE_BLACK = "O-O e8g8";
01062 
01063     if (
01064         ( (MATCH_QUEENSIDE_WHITE.find(fenStr)!=string::npos || MATCH_KINGSIDE_WHITE.find(fenStr)!=string::npos ) && getPieceAt<WHITE>( POW2[E1]) == KING_WHITE)
01065         ||
01066         ((MATCH_QUEENSIDE_BLACK.find(fenStr)!=string::npos || MATCH_KINGSIDE_BLACK.find(fenStr)!=string::npos)
01067          && getPieceAt<BLACK>( POW2[E8]) == KING_BLACK)
01068     ) {
01069         if (MATCH_QUEENSIDE.find(fenStr)!=string::npos) {
01070             move->type = QUEEN_SIDE_CASTLE_MOVE_MASK;
01071             move->from = QUEEN_SIDE_CASTLE_MOVE_MASK;
01072         } else {
01073             move->from = KING_SIDE_CASTLE_MOVE_MASK;
01074             move->type = KING_SIDE_CASTLE_MOVE_MASK;
01075         }
01076         if(fenStr.find("1")!=string::npos) {
01077             move->side = WHITE;
01078 
01079         } else if(fenStr.find("8")!=string::npos) {
01080             move->side = BLACK;
01081 
01082         } else assert(0);
01083         move->from=-1;
01084         move->capturedPiece=SQUARE_FREE;
01085         return move->side;
01086     }
01087 
01088     int from=-1;
01089     int to=-1;
01090     for (int i = 0; i < 64; i++) {
01091         if (!fenStr.compare(0,2,BOARD[i])) {
01092             from = i;
01093             break;
01094         }
01095     }
01096     if (from==-1) {
01097         cout << fenStr<<endl;
01098         assert(0);
01099     }
01100 
01101     for (int i = 0; i < 64; i++) {
01102         if (!fenStr.compare(2,2,BOARD[i])) {
01103             to = i;
01104             break;
01105         }
01106     }
01107     if (to==-1) {
01108         cout << fenStr<<endl;
01109         assert(0);
01110     }
01111 
01112     int pieceFrom;
01113     if ((pieceFrom = getPieceAt<WHITE>( POW2[from])) != 12) {
01114         move->side = WHITE;
01115     } else if ((pieceFrom = getPieceAt<BLACK>( POW2[from])) != 12) {
01116         move->side = BLACK;
01117     } else {
01118         display();
01119         cout <<"fenStr: "<<fenStr<<" from: "<<from<<endl;
01120         assert(0);
01121     }
01122     move->from = from;
01123     move->to = to;
01124     if (fenStr.length() == 4) {
01125         move->type = STANDARD_MOVE_MASK;
01126         if (pieceFrom == PAWN_WHITE || pieceFrom == PAWN_BLACK) {
01127             if (FILE_AT[from] != FILE_AT[to] && (move->side ^ 1?getPieceAt<WHITE>( POW2[to]):getPieceAt<BLACK>( POW2[to])) == SQUARE_FREE) {
01128                 move->type = ENPASSANT_MOVE_MASK;
01129             }
01130         }
01131     } else if (fenStr.length() == 5) {
01132         move->type = PROMOTION_MOVE_MASK;
01133         if (move->side == WHITE)
01134             move->promotionPiece = INV_FEN[toupper(fenStr.at(4))];
01135         else
01136             move->promotionPiece = INV_FEN[(uchar)fenStr.at(4)];
01137         ASSERT(move->promotionPiece != 0xFF);
01138     }
01139     if(move->side==WHITE) {
01140         move->capturedPiece=getPieceAt<BLACK>( POW2[move->to]);
01141         move->pieceFrom=getPieceAt<WHITE>( POW2[move->from]);
01142     } else {
01143         move->capturedPiece=getPieceAt<WHITE>( POW2[move->to]);
01144         move->pieceFrom=getPieceAt<BLACK>( POW2[move->from]);
01145     }
01146     return move->side;
01147 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines