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