![]() |
Cinnamon
1.0
chess engine
|
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 }