Cinnamon  1.0
chess engine
Perft.cpp
Go to the documentation of this file.
00001 #include "Perft.h"
00002 
00003 Perft::PerftThread::PerftThread()  {}
00004 
00005 Perft::PerftThread::PerftThread(int cpuID1,string fen1, int from1, int to1, Perft* perft1) :
00006     GenMoves() {
00007     perftMode=true;
00008     if(!fen1.empty())
00009         START_FEN=fen1;
00010     loadFen(START_FEN);
00011     this->cpuID = cpuID1;
00012     this->perft = perft1;
00013     this->from = from1;
00014     this->to = to1;
00015 }
00016 
00017 Perft::~Perft() {
00018     for (int i = 0; i < PERFT_HASH_SIZE; i++)
00019         free(hash[i].nMovesXply);
00020     free(hash);
00021 }
00022 
00023 Perft::Perft(string fen, int depth, int nCpu1, int hash_size) {
00024     PerftThread* p=new PerftThread();
00025     if(!fen.empty())p->loadFen(fen);
00026     p->setPerft(true);
00027     p->display();
00028     struct timeb start1, end1;
00029     totMoves = nCollisions = 0;
00030     int side=p->getSide()?1:0;
00031     this->PERFT_HASH_SIZE = hash_size*1024*1024/(sizeof(u64)*depth+sizeof(_ThashPerft));
00032     this->hash = NULL;
00033     if (PERFT_HASH_SIZE) {
00034         hash = (_ThashPerft *) calloc(PERFT_HASH_SIZE, sizeof(_ThashPerft));
00035         assert (hash);
00036         for (int i = 0; i < PERFT_HASH_SIZE; i++) {
00037             this->hash[i].key = NULL_KEY;
00038             hash[i].nMovesXply = (u64*) malloc((depth - 1) * sizeof(u64));
00039             assert (hash[i].nMovesXply);
00040             for (int j = 0; j < depth - 1; j++) {
00041                 hash[i].nMovesXply[j] = NULL_KEY;
00042             }
00043         }
00044     }
00045     ftime(&start1);
00046     this->mainDepth = depth - 1;
00047     this->nCpu = nCpu1;
00048     p->incListId();
00049 
00050     u64 friends=side?p->getBitBoard<WHITE>():p->getBitBoard<BLACK>();
00051     u64 enemies=side?p->getBitBoard<BLACK>():p->getBitBoard<WHITE>();
00052 
00053     u64 dummy=0;
00054     p->generateCaptures(side,enemies,friends,&dummy);
00055     p->generateMoves(side,friends|enemies);
00056     int listcount = p->getListCount();
00057     delete(p);
00058     p=NULL;
00059     ASSERT(nCpu1>0);
00060     int block = listcount / nCpu1;
00061     int i,s = 0;
00062     for (i = 0; i < nCpu1 - 1; i++) {
00063         threadList.push_back(new PerftThread(i,fen, s, s + block, this));
00064         s += block ;
00065     }
00066     threadList.push_back(new PerftThread(i,fen, s, listcount, this));
00067 
00068     for (vector<PerftThread*>::iterator it = threadList.begin(); it != threadList.end(); ++it) {
00069         (*it)->start();
00070     }
00071 
00072     for (vector<PerftThread*>::iterator it = threadList.begin(); it != threadList.end(); ++it) {
00073         (*it)->join();
00074         (*it)->stop();
00075         delete *it;
00076     }
00077 
00078     ftime(&end1);
00079 #ifdef DEBUG_MODE
00080     cout << endl << endl <<"collisions: " << nCollisions ;
00081 #endif
00082     int t= _time::diffTime(end1, start1) / 1000;
00083 
00084     int days = t / 60 / 60 / 24;
00085     int hours = (t / 60 / 60) % 24;
00086     int minutes = (t / 60) % 60;
00087     int seconds = t % 60;
00088     cout << endl<<endl<<"Perft moves: " << totMoves << " in ";
00089     if(days)cout <<days << " days, ";
00090     if(days || hours )cout <<hours << " hours, ";
00091     if(days || hours || minutes)cout <<minutes << " minutes, ";
00092     if(!days) cout <<seconds << " seconds";
00093     if(t)cout <<" ("<< (totMoves / t)/1000- ((totMoves / t)/1000)%1000 <<"k nodes per seconds"<<")";
00094     cout <<endl<<flush;
00095 
00096 }
00097 template <int side>
00098 u64 Perft::PerftThread::search( int depth,u64 key) {
00099     if (depth == 0) {
00100         return 1;
00101     }
00102     _ThashPerft * phashe = NULL;
00103     if (depth >= 2 && perft->hash) {
00104         phashe = &(perft->hash[key % perft->PERFT_HASH_SIZE]);
00105         if (key == phashe->key && phashe->nMovesXply[depth - 2] != NULL_KEY) {
00106             return phashe->nMovesXply[depth - 2];
00107         }
00108     }
00109     u64 n_perft = 0;
00110     int listcount;
00111     _Tmove * move;
00112     incListId();
00113     u64 friends=getBitBoard<side>();
00114     u64 enemies=getBitBoard<side^1>();
00115     if (generateCaptures<side>(enemies,friends,&key)) {
00116         decListId();
00117         return 0;
00118     }
00119     generateMoves<side>(friends|enemies);
00120     listcount = getListCount();
00121     if (!listcount) {
00122         decListId();
00123         return 0;
00124     }
00125     for (int ii = 0; ii < listcount; ii++) {
00126 
00127         move = getMove(ii);
00128         u64 keyold=key;
00129 
00130         makemove(move,&key,false);
00131         ASSERT(key==makeZobristKey());
00132         n_perft += search<side ^ 1>( depth - 1,key);
00133         takeback(move,&key,keyold,false);
00134     }
00135     resetList();
00136     decListId();
00137     if (phashe) {
00138         if (phashe->key == key) {
00139             phashe->nMovesXply[depth - 2] = n_perft;
00140         } else if (phashe->key == NULL_KEY) {
00141             phashe->nMovesXply[depth - 2] = n_perft;
00142             phashe->key = key;
00143         } else {
00144             perft->nCollisions++;
00145         }
00146     }
00147     return n_perft;
00148 }
00149 
00150 void Perft::PerftThread::run() {
00151     init();
00152     _Tmove * move;
00153     incListId();
00154     resetList();
00155 
00156     u64 friends=sideToMove?getBitBoard<WHITE>():getBitBoard<BLACK>();
00157     u64 enemies=sideToMove?getBitBoard<BLACK>():getBitBoard<WHITE>();
00158 
00159     u64 dummy=0;
00160     generateCaptures(sideToMove,enemies,friends,&dummy);
00161     generateMoves( sideToMove,friends|enemies);
00162     u64 tot = 0;
00163     u64 key = makeZobristKey();
00164     u64 keyold=key;
00165 
00166     for (int ii = to-1; ii >= from; ii--) {
00167         u64 n_perft = 0;
00168         move = getMove(ii);
00169 
00170         makemove(move,&key,false);
00171         n_perft = (sideToMove ^ 1)==WHITE?search<WHITE>( perft->mainDepth,key):search<BLACK>( perft->mainDepth,key);
00172         takeback(move,&key,keyold,false);
00173 
00174         char y;
00175         char x = FEN_PIECE[sideToMove?getPieceAt<WHITE>( POW2[move->from]):getPieceAt<BLACK>( POW2[move->from])];
00176         if (x == 'p' || x == 'P')
00177             x = ' ';
00178         if (move->capturedPiece != SQUARE_FREE)
00179             y = '*';
00180         else
00181             y = '-';
00182         cout << endl<<"#" << ii+1<< " cpuID# " << cpuID;
00183         if((decodeBoardinv(move->type, move->to,sideToMove)).length()>2)
00184             cout << "\t" << decodeBoardinv(move->type, move->to,sideToMove) << "\t" << n_perft << " ";
00185         else
00186             cout << "\t" << x << decodeBoardinv(move->type, move->from, sideToMove) << y << decodeBoardinv(move->type, move->to,sideToMove) << "\t" << n_perft << " ";
00187         cout << flush;
00188         tot += n_perft;
00189     }
00190 
00191     decListId();
00192     perft->setResult(tot);
00193 }
00194 
00195 Perft::PerftThread::~PerftThread() {
00196 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines