Cinnamon  1.0
chess engine
OpenBook.cpp
Go to the documentation of this file.
00001 #include "OpenBook.h"
00002 
00003 OpenBook::OpenBook() {
00004     book=NULL;
00005     sizeBook[WHITE]=sizeBook[BLACK]=0;
00006     bookFile="cinnamon_book.bin";
00007 }
00008 
00009 bool OpenBook::load() {
00010     book=NULL;
00011     fileSize=_file::fileSize(bookFile);
00012     if(fileSize==-1) {
00013         useMmap=false;
00014         miniBook ="WHITE\1.>YQ/?VN%7`Y$5XH08\1.>YQ/?VN%7`Y$5TL(D\1/?WG0@G@$5XH.6VN%@\1/?WG0@G@$5XH.6\\M\10@YQ/?`Y)8\\M\10@YQ/?\\M\1$5WG,4XP%,`<&$\\M/7\1BLACK\1)8XH.>aP%IP?I@TL$5]T\1)8XH.>aP$5VF%@]V/7WO\1$5\\M0@VN)8]A'0^\\2:A8\1$5\\M0@VN)8]A'0^\\/?XH\1/?\\M(DWGDMVM.6]O0@G@\1/?WG0@G@$5ZR.6\\M%@VN\1.>VF%@\\M/7XP$5WG@9]O\1.>VF%@\\M/7]H$5WO08HQ\1.>VF$5\\M5FWOF5M>/7>M\1";
00015         fileSize=miniBook.size();
00016         _string::replace(miniBook,1,0);
00017         book=(char*)miniBook.c_str();
00018     } else {
00019         useMmap=true;
00020         book =(char*)_memory::_mmap(bookFile);
00021     }
00022     sizeBook[WHITE]=sizeBook[BLACK]=0;
00023     if(!book) {
00024         cout <<"error on load open book"<<endl;
00025         return false;
00026     }
00027     char* b =book;
00028     int side=-1;
00029     while(b-book<fileSize) {
00030         if(!strcmp(b,"WHITE")) {
00031             side=WHITE;
00032             b+=6;
00033         } else if(!strcmp(b,"BLACK")) {
00034             side=BLACK;
00035             b+=6;
00036         }
00037         if(side!=-1)
00038             sizeBook[side]++;
00039         b+=strlen(b)+1;
00040     }
00041     if(!sizeBook[WHITE] || !sizeBook[BLACK]) {
00042         cout <<"invalid open book"<<endl;
00043         _memory::_munmap(book,fileSize);
00044         sizeBook[WHITE]=sizeBook[BLACK]=0;
00045         book=NULL;
00046         return false;
00047     }
00048     random[WHITE] = (int *)malloc (sizeBook[WHITE]*sizeof(int));
00049     random[BLACK] = (int *)malloc (sizeBook[BLACK]*sizeof(int));
00050     int k=-1;
00051     b =book;
00052     while(b-book<fileSize) {
00053         if(!strcmp(b,"WHITE")) {
00054             side=WHITE;
00055             b+=6;
00056             k=0;
00057         } else if(!strcmp(b,"BLACK")) {
00058             side=BLACK;
00059             b+=6;
00060             k=0;
00061         }
00062         assert(k!=-1);
00063         random[side][k++]=b-book;
00064         b+=strlen(b)+1;
00065     }
00066     //shuffle
00067     time_t seed;
00068     srand ((unsigned) time(&seed));
00069     for(side=0; side<2; side++) {
00070         for (int j=0; j<sizeBook[side]-1; j++) {
00071             unsigned  r =j  + (rand() % (sizeBook[side]-j));
00072             int temp = random[side][j];
00073             random[side][j] = random[side][r];
00074             random[side][r] = temp;
00075         }
00076     }
00077     return true;
00078 }
00079 
00080 OpenBook::~OpenBook() {
00081     if(book) {
00082         free(random[BLACK]);
00083         free(random[WHITE]);
00084         if(useMmap)
00085             _memory::_munmap(book,fileSize);
00086     }
00087 }
00088 
00089 string OpenBook::search(int side,string movesPath) {
00090     if (!book)return "";
00091     for(unsigned i=0; i<movesPath.size(); i++) {
00092         movesPath[i]+=SHIFT;
00093     }
00094     for (int ii1=0; ii1<sizeBook[side]; ii1++) {
00095         int i=random[side][ii1];
00096         if(!strncmp(book+i,movesPath.c_str(),movesPath.size())) {
00097             if(strlen(book+i)<movesPath.size()+2) {
00098                 return "";
00099             }
00100             string m;
00101             m+= BOARD[book[i+movesPath.size()]-SHIFT];
00102             m+= BOARD[book[i+movesPath.size()+1]-SHIFT];
00103             return m;
00104         }
00105     }
00106     return "";
00107 }
00108 
00109 int OpenBook::getAttackers(int piece,int side,int rank,int file,int to) {
00110 
00111     gen->incListId();
00112     gen->resetList();
00113     u64 friends=side?gen->getBitBoard<WHITE>():gen->getBitBoard<BLACK>();
00114     u64 enemies=side?gen->getBitBoard<BLACK>():gen->getBitBoard<WHITE>();
00115     u64 key;
00116     u64 allpieces = enemies|friends;
00117     if(piece==-1) {
00118         gen->generateCaptures(side,enemies,friends,&key);
00119         gen->generateMoves(side,allpieces);
00120 
00121     } else
00122         switch (piece) {
00123         case  ChessBoard::PAWN_WHITE:
00124             if(side) {
00125                 gen->performPawnShift<WHITE>(~allpieces);
00126                 gen->performPawnCapture<WHITE>( enemies, &key);
00127             } else {
00128                 gen->performPawnShift<BLACK>(~allpieces);
00129                 gen->performPawnCapture<BLACK>(enemies, &key);
00130             }
00131             break;
00132         case  ChessBoard::KNIGHT_WHITE:
00133             gen->performKnightShiftCapture(ChessBoard::KNIGHT_BLACK+side, enemies, side);
00134             gen->performKnightShiftCapture(ChessBoard::KNIGHT_BLACK+side, ~allpieces, side);
00135             break;
00136         case  ChessBoard::BISHOP_WHITE:
00137             gen->performBishopCapture(ChessBoard::BISHOP_BLACK+side, enemies, side, allpieces);
00138             gen->performBishopShift(ChessBoard::BISHOP_BLACK+side, side, allpieces);
00139             break;
00140         case  ChessBoard::QUEEN_WHITE:
00141             gen->performRookQueenCapture(ChessBoard::QUEEN_BLACK+side, enemies, side, allpieces);
00142             gen->performBishopCapture(ChessBoard::QUEEN_BLACK+side, enemies, side, allpieces);
00143             gen->performBishopShift(ChessBoard::QUEEN_BLACK+side, side, allpieces);
00144             gen->performRookQueenShift(ChessBoard::QUEEN_BLACK+side, side, allpieces);
00145             break;
00146         case  ChessBoard::ROOK_WHITE:
00147             gen->performRookQueenCapture(ChessBoard::ROOK_BLACK+side, enemies, side, allpieces);
00148             gen->performRookQueenShift(ChessBoard::ROOK_BLACK+side, side, allpieces);
00149             break;
00150         case  ChessBoard::KING_WHITE:
00151             if(side) {
00152                 gen->performKingShiftCapture(WHITE, enemies);
00153                 gen->performKingShiftCapture(WHITE,~allpieces);
00154             } else {
00155                 gen->performKingShiftCapture(BLACK,enemies);
00156                 gen->performKingShiftCapture(BLACK, ~allpieces);
00157             }
00158             break;
00159         default:
00160             return -1;
00161             break;
00162         }
00163 
00164     int listcount = gen->getListCount();
00165     if(!listcount) {
00166         return -1;
00167     };
00168     for (int j = 0; j < listcount; j++) {
00169         _Tmove* mov=gen->getMove(j);
00170         if(to==mov->to) {
00171 
00172             if( file==-1 &&rank==-1 && !gen->isPinned( side, mov->from,mov->side?gen->getPieceAt<WHITE>( POW2[mov->from]):gen->getPieceAt<BLACK>( POW2[mov->from]))) {
00173                 gen->decListId();
00174                 return mov->from;
00175             }
00176             if( file!=-1 && file==FILE_AT[ mov->from] && !gen->isPinned( side, mov->from,mov->side?gen->getPieceAt<WHITE>( POW2[mov->from]):gen->getPieceAt<BLACK>( POW2[mov->from]))) {
00177                 gen->decListId();
00178                 return mov->from;
00179             }
00180             if( rank!=-1 && rank==RANK_AT[ mov->from] && !gen->isPinned( side, mov->from,mov->side?gen->getPieceAt<WHITE>( POW2[mov->from]):gen->getPieceAt<BLACK>( POW2[mov->from]))) {
00181                 gen->decListId();
00182                 return mov->from;
00183             }
00184         }
00185     }
00186     gen->decListId();
00187     return -1;
00188 }
00189 
00190 bool OpenBook::san2coord(string san1, int *from, int *to, int side) {
00191     string san;
00192     for(unsigned i=0; i<san1.size(); i++)
00193         if(san1.at(i)!='x' && san1.at(i)!='+')san+=san1.at(i);
00194     int rank=-1;
00195     int file=-1;
00196     //castle
00197     if (san.at(0) == 'O') {
00198         //O-O
00199         //O-O-O
00200         if (!side) {
00201             *from = 59;
00202             if (!san.compare("O-O"))
00203                 *to=57;
00204             else
00205                 *to=61;
00206         } else {
00207             *from = 3;
00208             if (!san.compare("O-O"))
00209                 *to=1;
00210             else
00211                 *to=5;
00212         }
00213         return true;
00214     }
00215 
00216     if(san.find("=")!=string::npos) {
00217         assert(0);
00218     }
00219 
00220     int piece=-1;
00221     if(san.at(0)==toupper(san.at(0))) {
00222         piece=gen->getPieceByChar(san.at(0));
00223         if(san.size()==4) {
00224             if(isdigit(san.at(1))) {
00225                 rank=san.at(1)-49;
00226             } else
00227                 file=7-(san.at(1)-97);
00228         }
00229 
00230     } else {
00231         if(san.size()!=2) {
00232             if(isdigit(san.at(0)))
00233                 rank=san.at(0)+95-1;
00234             else
00235                 file=7-(san.at(0)-97);
00236         } else piece= ChessBoard::PAWN_WHITE;
00237     }
00238     *to=gen->decodeBoard((san.substr(san.size()-2,2)));
00239     *from=getAttackers(piece,side,rank,file,*to);
00240     if(*from==-1) {
00241         return false;
00242     }
00243     return true;
00244 }
00245 
00246 void OpenBook::create(string fileWhite,string fileBlack) {
00247     gen =new GenMoves();
00248     ofstream f;
00249     f.open (bookFile,fstream::out);
00250     if (!f.is_open()) {
00251         cout << "file error" << endl;
00252         return;
00253     }
00254     f <<"WHITE";
00255     //cout<<"WHITE"<<"\\1";;
00256     f.put (0);
00257     create(fileWhite,f);
00258     f <<"BLACK";
00259     //cout<< "BLACK"<<"\\1";;
00260     f.put (0);
00261     create(fileBlack,f);
00262     f.close();
00263     delete gen;
00264 }
00265 
00266 void OpenBook::create(string fileIn,ofstream& f) {
00267     ifstream inData;
00268     inData.open(fileIn.c_str());
00269     if (!inData) {
00270         cout << "error file not found: " << fileIn << endl;
00271         return;
00272     }
00273     string fen;
00274     string s1;
00275     stringstream s2;
00276     stringstream s3;
00277     bool error=false;
00278     while (!inData.eof()) {
00279         getline(inData, fen);
00280 
00281         if(fen.find("{")==string::npos)continue;
00282         if(fen.find(" {cycle")!=string::npos)fen.erase(fen.find(" {cycle"),fen.size()-fen.find(" {cycle"));
00283         if(fen.find(" {tran")!=string::npos)fen.erase(fen.find(" {tran"),fen.size()-fen.find(" {tran"));
00284         _string::replace(fen,"{"," ");
00285 
00286         if(fen.find("=Q")!=string::npos)continue;
00287         if(fen.find("=R")!=string::npos)continue;
00288         if(fen.find("=N")!=string::npos)continue;
00289         if(fen.find("=B")!=string::npos)continue;
00290         if(fen.find("#")!=string::npos)continue;
00291         _string::trimRight(fen);
00292         gen->loadFen();
00293 
00294         string token;
00295         istringstream uip(fen);
00296         uip >> token;
00297         int from,to;
00298         _Tmove move;
00299         u64 dummy;
00300         string san;
00301         int side=WHITE;
00302         string castle;
00303         s1.clear();
00304         s2.str("");
00305         s2.clear();
00306         s3.str("");
00307         s3.clear();
00308         while(!uip.eof() && !error) {
00309             token="";
00310             uip >> token;
00311             if(token.find(".")!=string::npos)continue;
00312             if(token.find("%")!=string::npos)continue;
00313             castle.clear();
00314             if(!san2coord(token,&from,&to,side)) {
00315                 error=true;
00316                 continue;
00317             }
00318 
00319             s1+=token+" ";
00320             s3 << BOARD[from]<<BOARD[to]<<" ";
00321             s2 << (char)(from+SHIFT) <<(char)(to+SHIFT);
00322             san.clear();
00323             san+=BOARD[from];
00324             san+=BOARD[to];
00325 
00326             gen->getMoveFromSan(san,&move);
00327             gen->makemove(&move,&dummy,true);
00328             side^=1;
00329         }
00330         if(!error) {
00331             f <<s2.str();
00332             f.put (0);
00333         }
00334         error=false;
00335     }
00336     inData.close();
00337 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines