void bitbaseInit(void) { // Allocate memory. bitbase=malloc((FileNB/2)*RankNB*SqNB*ColourNB*sizeof(uint64_t)); if (bitbase==NULL) mainFatalError("Error: Could not allocate memory for KPvK bitbase.\n"); // Generate bitbase. bitbaseGen(); }
void ttInit(void) { // Setup tt as a HTable. tt=htableNew(sizeof(TTCluster), ttDefaultSizeMb); if (tt==NULL) mainFatalError("Error: Could not allocate transposition table.\n"); // Add uci options to change size and clear. uciOptionNewSpin("Hash", &htableResizeInterface, tt, 1, ttMaxSizeMb, ttDefaultSizeMb); uciOptionNewButton("Clear Hash", &htableClearInterface, tt); }
void bitbaseGen(void) { // Allocate array to use while generating bitbase. BitBaseResultFull *array=malloc((FileNB/2)*RankNB*SqNB*ColourNB*SqNB*sizeof(BitBaseResultFull)); if (array==NULL) mainFatalError("Error: Could not allocate memory for generating KPvK bitbase.\n"); // Mark positions which are obviously won/drawn/invalid (otherwise mark as unknown). Sq wKingSq, bKingSq; Colour stm; File pawnFile; Rank pawnRank; for(pawnFile=FileA;pawnFile<=FileD;++pawnFile) for(pawnRank=Rank8;pawnRank>=Rank2;--pawnRank) { Sq pawnSq=sqMake(pawnFile, pawnRank); for(wKingSq=0;wKingSq<SqNB;++wKingSq) for(stm=0;stm<ColourNB;++stm) for(bKingSq=0;bKingSq<SqNB;++bKingSq) { unsigned int index=bitbaseIndexFull(pawnFile, pawnRank, wKingSq, stm, bKingSq); array[index]=bitbaseComputeStaticResult(pawnSq, wKingSq, stm, bKingSq); } } // Loop over each pawn file and ranks in backwards order (from 7 to 2). // We can do this as different files are independent and, for example, rank 5 // positions do not depend on any rank 4 positions. for(pawnFile=FileA;pawnFile<=FileD;++pawnFile) for(pawnRank=Rank7;pawnRank>=Rank2;--pawnRank) { Sq pawnSq=sqMake(pawnFile, pawnRank); // Compute position results based on child positions. bool change; do { change=false; for(wKingSq=0;wKingSq<SqNB;++wKingSq) for(stm=0;stm<ColourNB;++stm) for(bKingSq=0;bKingSq<SqNB;++bKingSq) { // Position already solved? unsigned int index=bitbaseIndexFull(pawnFile, pawnRank, wKingSq, stm, bKingSq); if (array[index]!=BitBaseResultFullUnknown) continue; // Try to compute result and update change flag if successful. BitBaseResultFull result=bitbaseComputeDynamicResult(array, pawnSq, wKingSq, stm, bKingSq); change|=((array[index]=result)!=BitBaseResultFullUnknown); } } while(change); // Update global array. // Any positions left 'unknown' are draws (although neither side can 'force' it per se). for(wKingSq=0;wKingSq<SqNB;++wKingSq) for(stm=0;stm<ColourNB;++stm) { unsigned int index=bitbaseIndex(pawnFile, pawnRank, wKingSq, stm); bitbase[index]=0; for(bKingSq=0;bKingSq<SqNB;++bKingSq) { unsigned int fullIndex=bitbaseIndexFull(pawnFile, pawnRank, wKingSq, stm, bKingSq); STATICASSERT(BitBaseResultWin==1); if (array[fullIndex]==BitBaseResultFullWin) bitbase[index]|=(1llu<<bKingSq); } } } // Verify counts. # ifndef NDEBUG unsigned countTotal=0, countWin=0, countDraw=0, countInvalid=0, countUnknown=0; for(pawnFile=FileA;pawnFile<=FileD;++pawnFile) for(pawnRank=Rank2;pawnRank<=Rank7;++pawnRank) for(wKingSq=0;wKingSq<SqNB;++wKingSq) for(stm=0;stm<ColourNB;++stm) for(bKingSq=0;bKingSq<SqNB;++bKingSq) { unsigned int fullIndex=bitbaseIndexFull(pawnFile, pawnRank, wKingSq, stm, bKingSq); switch(array[fullIndex]) { case BitBaseResultFullWin: ++countWin; break; case BitBaseResultFullDraw: ++countDraw; break; case BitBaseResultFullInvalid: ++countInvalid; break; case BitBaseResultFullUnknown: ++countUnknown; break; } ++countTotal; } assert(countTotal==196608); assert(countWin==111282); assert(countInvalid==30932); assert(countDraw+countUnknown==54394); # endif // Free working array. free(array); }