#include using namespace std; #include "EpdProcessor.h" #include "Skiplist.hpp" static SkipList < EpdBinary > EpdList; static void findpm(char *pm, char *pv); void BinaryLoad( int min_distance_to_mate = 2, int min_piece_count = 5) { char *bfile = getenv("BINARY_BRAINFILE"); char edata[EPD_BINARY_LENGTH] = {0}; int distance_discards = 0; int piece_count_discards = 0; int status = EPD_STATUS_SUCCESS; epd_solid es = {0}; // Do allow duplicates in the list. EpdList.SetDuplicateFlag(1); if (bfile == NULL) bfile = "cap.bin"; FILE *fEpd = fopen(bfile, "rb"); if (fEpd == NULL) { puts("Cannot open binary brain file for reading"); exit(EXIT_FAILURE); } EpdBinary eb; EpdBinary *pebnew; while (status != EPD_STATUS_FAILURE) { status = eb.GetFromFile(es, edata, fEpd); if (status != EPD_STATUS_FAILURE) { if ((32767 - fabs(es.ce)) >= min_distance_to_mate) { // Mate distance within // range eb = edata; if (eb.GetPieceCount() > min_piece_count) { // mate distance ok & // piece count ok... pebnew = new EpdBinary(es, edata); EpdList.InsertData(pebnew); } // piece count too small: else piece_count_discards++; } else distance_discards++; } // if status != EPD_STATUS_FAILURE } // while status != EPD_STATUS_FAILURE cout << "There were " << EpdList.ListLength() << " elements in the binary list." << endl; cout << "There were " << piece_count_discards << " records discarded because piece count was too low." << endl; cout << "There were " << distance_discards << " records discarded because distance to mate was too small." << endl; fclose(fEpd); } void BinarySave(void) { char *bfile = getenv("BINARY_BRAINFILE"); if (bfile == NULL) bfile = "cap.bin"; FILE *fEpd = fopen(bfile, "wb"); if (fEpd == NULL) { puts(strerror(errno)); puts("Cannot create binary brain file"); exit(EXIT_FAILURE); } SkipNode < EpdBinary > *snEB; snEB = EpdList.GetFirst(); while (snEB != NULL) { snEB->data->SaveToFile(fEpd); snEB = EpdList.GetNext(); } fclose(fEpd); } int AsciiLoad( int min_distance_to_mate = 2, int min_piece_count = 5) { EpdBinary EpdBin; EPD EpdString = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -"; EpdProcessor EpdProc; bool bEpdValid; int nPvValid; std::string EpdErrorMsg; std::string PvErrorMsg; PV Pv = "e4 e6"; EPD Result; EPD_VECTOR ResultVector; int Status = EpdList.SetDuplicateFlag(0); long usedlinecount = 0; EpdProc.GenerateOutputOpcodes(false); EpdProc.SetOutputOpcodeTypes(false, false, false); EpdBinary *k; long linecount = 0; char string[1024]; char *where; char *acsloc; char *amloc; char *bmloc; char *idloc; char *token; char *acdloc; char *acnloc; char *celoc; char *pvloc; char *crlf; char *bfile = getenv("TEXT_BRAINFILE"); if (bfile == NULL) bfile = "cap.epd"; FILE *fEpd = fopen(bfile, "r"); if (fEpd == NULL) { puts("Missing brain file"); exit(EXIT_FAILURE); } while (fgets(string, sizeof string, fEpd)) { char output[1024] = {0}; char acd[512] = {0}; char pm[512] = {0}; char acn[512] = {0}; char ce[512] = {0}; char pv[512] = {0}; char epd[512] = {0}; char acs[512] = {0}; char am[512] = {0}; char bm[512] = {0}; char id[512] = {0}; linecount++; if (linecount % 1000 == 0) printf("Current lines read is %ld\n", linecount); crlf = strchr(string, '\n'); if (crlf) *crlf = 0; token = strtok(string, ";"); if (token) { acdloc = strstr(token, " acd "); if (acdloc) { *acdloc = 0; acdloc += 5; strcpy(acd, acdloc); } strcpy(epd, token); while (token != NULL) { acdloc = strstr(token, " acd "); if (acdloc) { *acdloc = 0; acdloc += 5; strcpy(acd, acdloc); } acnloc = strstr(token, " acn "); if (acnloc) { *acnloc = 0; acnloc += 5; strcpy(acn, acnloc); } celoc = strstr(token, " ce "); if (celoc) { *celoc = 0; celoc += 4; strcpy(ce, celoc); } pvloc = strstr(token, " pv "); if (pvloc) { *pvloc = 0; pvloc += 4; strcpy(pv, pvloc); } bmloc = strstr(token, " bm "); if (bmloc) { *bmloc = 0; bmloc += 4; strcpy(bm, bmloc); } acsloc = strstr(token, " acs "); if (acsloc) { *acsloc = 0; acsloc += 5; strcpy(acs, acsloc); } amloc = strstr(token, " am "); if (amloc) { *amloc = 0; amloc += 4; strcpy(am, amloc); } idloc = strstr(token, " id "); if (idloc) { *idloc = 0; idloc += 4; strcpy(id, idloc); } /* While there are tokens in "string" */ /* Get next token: */ token = strtok(NULL, ";"); } findpm(pm, pv); if ((where = strstr(epd, " am "))) *where = 0; if ((where = strstr(epd, " bm "))) *where = 0; EpdString = epd; Pv = pv; bEpdValid = EpdProc.SetEpd(EpdString); EpdBin = EpdProc.GetEpdBinary(0); if (!bEpdValid) { EpdErrorMsg = "*** EPD ERROR *** "; EpdErrorMsg += EpdProc.GetEpdError(); } nPvValid = EpdProc.SetPv(pv); if (nPvValid <= EPD_STATUS_WARNING) { if (nPvValid == EPD_STATUS_WARNING) { Pv = EpdProc.GetPv(); } // Now that we have parsed the crap out of it, and made sure // it is OK, // cram it into a binary EPD object and see if it is one that // we want to use. k = new EpdBinary(EpdString); if (k->GetPieceCount() > min_piece_count) { // Enough pieces to be // interesting ? int ice = atoi(ce); // Find the ce to check for distance to mate... if ((32767 - fabs(ice)) >= min_distance_to_mate) { // OK, we want this one.Populate the rest of the data // and add it k->SetACD(atoi(acd)); k->SetCE(atoi(ce)); k->SetPM(pm); if (strlen(bm) > 0) k->SetBM(bm); if (strlen(am) > 0) k->SetAM(am); EpdList.InsertData(k); usedlinecount++; } else { // Tell everyone why we threw it away... puts("Discarded easy checkmate"); printf("Board: %s has ce: %d\n", epd, ice); } } else { // Tell everyone why we threw it away... puts("Discarded bare board"); printf("Board: %s contains: %d pieces\n", epd, k->GetPieceCount()); } delete k; } else { // Tell everyone why we threw it away... PvErrorMsg = "*** PV ERROR *** "; PvErrorMsg += EpdProc.GetPvError(); cout << PvErrorMsg.c_str() << endl; cout << epd << endl; cout << pv << endl; } } } cout << "There were " << usedlinecount << " insertions attempted." << endl; cout << "There were " << EpdList.ListLength() << " elements in the text list." << endl; fclose(fEpd); return 0; } static void findpm(char *pm, char *pv) { char *token; char pvcopy[1024]; strcpy(pvcopy, pv); token = strtok(pvcopy, " ;,"); if (token) { if (*token == '"') token++; strcpy(pm, token); } else strcpy(pm, ""); } //Function: //BinaryInquire(position *inquiry_vector, inquiry_count, answer *answer_vector) //A position is a struct containing 192 bits of data as described above. //The inquiry count tells me how many items are in your vector. The minimum is 1 and the maximum is 256. //The answer_vector contains structures the following information: //ce //pm //bm (if any) //am (if any) //acd int BinaryInquire(position * inquiry_vector, int inquiry_count, epd_info ** answer_vector) { int i; EpdBinary t; EpdBinary *k = &t; SkipNode < EpdBinary > *snEB; for (i = 0; i < inquiry_count; i++) { answer_vector[i] = (epd_info *) NULL; t = inquiry_vector[i]; snEB = EpdList.FindData(k); if (snEB) answer_vector[i] = (epd_info *) snEB->data->epd_goo(); } return 0; } //Function: AsciiInquire(char **ascii_inquiry_vector, inquiry_count, answers *answer_vector) //Same as above, except that an array of character strings is passed with positions in standard EPD format. //The binary function is faster, but many people will only have character strings available. int AsciiInquire(char **inquiry_vector, int inquiry_count, epd_info ** answer_vector) { int i; EpdBinary t; EpdBinary *k = &t; EPD EpdString; EpdProcessor EpdProc; SkipNode < EpdBinary > *snEB; for (i = 0; i < inquiry_count; i++) { answer_vector[i] = (epd_info *) NULL; EpdString = inquiry_vector[i]; EpdProc.SetEpd(EpdString); t = EpdProc.GetEpdBinary(0); snEB = EpdList.FindData(k); if (snEB) answer_vector[i] = (epd_info *) snEB->data->epd_goo(); } return 0; } //Function: BinaryInform(position, answer) //Function BinaryInform is used to update the data in memory with a binary position structure like the above. If the data does not exist, it is added. //If it exists, it is added if acd is greater for the new position. If acd is the same and pm is different, then it writes an exception record to disk. //Function: AsciiInform(char *ascii_position, answer) //Function AsciiInform is used to update the data in memory with an ASCII EPD string. If the data does not exist, it is added. //If it exists, it is added if acd is greater for the new position. If acd is the same and pm is different, then it writes an exception report to disk.