static void parse_position(char string[]) { const char * fen; char * moves; const char * ptr; char move_string[256]; int move; undo_t undo[1]; // init fen = strstr(string,"fen "); moves = strstr(string,"moves "); // start position if (fen != NULL) { // "fen" present if (moves != NULL) { // "moves" present ASSERT(moves>fen); moves[-1] = '\0'; // dirty, but so is UCI } board_from_fen(SearchInput->board,fen+4); // CHANGE ME } else { // HACK: assumes startpos board_from_fen(SearchInput->board,StartFen); } // moves if (moves != NULL) { // "moves" present ptr = moves + 6; while (*ptr != '\0') { move_string[0] = *ptr++; move_string[1] = *ptr++; move_string[2] = *ptr++; move_string[3] = *ptr++; if (*ptr == '\0' || *ptr == ' ') { move_string[4] = '\0'; } else { // promote move_string[4] = *ptr++; move_string[5] = '\0'; } move = move_from_string(move_string,SearchInput->board); move_do(SearchInput->board,move,undo); while (*ptr == ' ') ptr++; } } }
bool test_epd(char *filename) { FILE *f; char c,*p; char line[255]; char buff[255]; uint64 nodes,result; int x,depth,position,errors,sum; f = fopen(filename, "r"); if(f == NULL) return false; pht_init(); timer_start(); sum = 0;position = 0;result = 0; while(fgets(&line[0], sizeof(line), f)) { x = 0; p = &line[0]; while(*p != ';'){ buff[x] = *p; p++; x++; } buff[x] = '\0'; position++; if(!board_from_fen(&buff[0])){ printf ("position %d - FEN error!\n\n", position); continue; } printf("\nposition %d\n",position); printf("----------------------\n"); printf("%s\n",&buff[0]); printf("----------------------\n"); depth = 0; errors = 0; while((*p != '\n') && (*p != 0)) { if(*p == 'D'){ depth++; sscanf(p,"%s %I64u",&c,&result); printf("depth %d: ",depth); nodes = perft(depth); if(nodes != result){ printf("error\n"); errors++; } else printf("done\n"); } p++; } printf("----------------------\n"); printf("unmatched: %d \n\n", errors); sum+=errors; } printf("----------------------\nend_of_file.\n"); printf("total mismatched depths: %d\n",sum); timer_stop(); fclose(f); pht_free(); return true; }
void TEngine::StartNewGame() { StateNewGame = true; LastMove = 0; move_history_len = 0; move_history[0] = 0; board_from_fen(&Board,StartFen); Process->Send("stop"); Process->Send("ucinewgame"); Process->Send("position startpos"); Process->Send("go infinite"); }
bool game_init(game_t * game, const char fen[]) { ASSERT(game!=NULL); ASSERT(fen!=NULL); if (!board_from_fen(game->start_board,fen)) return false; game->size = 0; board_copy(game->board,game->start_board); game->pos = 0; game_update(game); return true; }
void loop() { // init (to help debugging) Init = false; Searching = false; Infinite = false; Delay = false; search_clear(); board_from_fen(SearchInput->board,StartFen); // loop while (true) loop_step(); }
void board_start(board_t * board) { ASSERT(board!=NULL); if (!board_from_fen(board,StartFen)) ASSERT(false); }
TEngine::TEngine(AnsiString FileName) { util_init(); my_random_init(); square_init(); piece_init(); pawn_init_bit(); value_init(); vector_init(); attack_init(); move_do_init(); random_init(); hash_init(); Reversed = true; board_from_fen(&StartBoard,StartFen); board_from_fen(&Board,StartFen); GameStarted = false; StateNewGame = false; LastCommitMove[0] = 0; Process = new TProcess(FileName); Process->Send("uci"); char buf[10000]; do { Sleep(10); if (Process->Get(buf)) { char *next_line = buf; while (true) { char *cur_line = next_line; if (cur_line[0] == 0) break; char *end = strstr(cur_line,"\r\n"); end[0] = 0; end[1] = 0; next_line = end + 2; char *cur_word; while (cur_line) { cur_word = get_cur_word_str(&cur_line); int pos; if (string_equal(cur_word,"id")) { cur_word = get_cur_word_str(&cur_line); if (string_equal(cur_word,"name")) { AnsiString EngineName = cur_line; MainForm->lbEngineName->Caption = EngineName; } } if (string_equal(cur_word,"uciok")) { if (MainForm->MultiPV > 1) { Process->Send("setoption name MultiPV value " + IntToStr(MainForm->MultiPV)); Sleep(100); Process->Get(buf); } Process->Send("setoption name Hash value " + IntToStr(MainForm->HashSize)); return; } } } } } while (true); }
static void epd_test_file(const char file_name[]) { FILE * file; int hit, tot; char epd[StringSize]; char am[StringSize], bm[StringSize], id[StringSize]; board_t board[1]; char string[StringSize]; int move; char pv_string[StringSize]; bool correct; double depth_tot, time_tot, node_tot; ASSERT(file_name!=NULL); // init file = fopen(file_name,"r"); if (file == NULL) my_fatal("epd_test_file(): can't open file \"%s\": %s\n",file_name,strerror(errno)); hit = 0; tot = 0; depth_tot = 0.0; time_tot = 0.0; node_tot = 0.0; // loop while (my_file_read_line(file,epd,StringSize)) { if (UseTrace) printf("%s\n",epd); if (!epd_get_op(epd,"am",am,StringSize)) strcpy(am,""); if (!epd_get_op(epd,"bm",bm,StringSize)) strcpy(bm,""); if (!epd_get_op(epd,"id",id,StringSize)) strcpy(id,""); if (my_string_empty(am) && my_string_empty(bm)) { my_fatal("epd_test(): no am or bm field in EPD\n"); } // init uci_send_ucinewgame(Uci); uci_send_isready_sync(Uci); ASSERT(!Uci->searching); // position if (!board_from_fen(board,epd)) ASSERT(false); if (!board_to_fen(board,string,StringSize)) ASSERT(false); engine_send(Engine,"position fen %s",string); // search engine_send(Engine,"go movetime %.0f depth %d",MaxTime*1000.0,MaxDepth); // engine_send(Engine,"go infinite"); // engine data board_copy(Uci->board,board); uci_clear(Uci); Uci->searching = true; Uci->pending_nb++; FirstMove = MoveNone; FirstDepth = 0; FirstSelDepth = 0; FirstScore = 0; FirstTime = 0.0; FirstNodeNb = 0; line_clear(FirstPV); LastMove = MoveNone; LastDepth = 0; LastSelDepth = 0; LastScore = 0; LastTime = 0.0; LastNodeNb = 0; line_clear(LastPV); // parse engine output while (engine_step()) { // stop search? if (Uci->depth > MaxDepth || Uci->time >= MaxTime || (Uci->depth - FirstDepth >= DepthDelta && Uci->depth > MinDepth && Uci->time >= MinTime && is_solution(FirstMove,board,bm,am))) { engine_send(Engine,"stop"); } } move = FirstMove; correct = is_solution(move,board,bm,am); if (correct) hit++; tot++; if (correct) { depth_tot += double(FirstDepth); time_tot += FirstTime; node_tot += double(FirstNodeNb); } printf("%s %d %4d %4d",id,correct,hit,tot); if (!line_to_san(LastPV,Uci->board,pv_string,StringSize)) ASSERT(false); printf(" - %2d %6.2f %9lld %+6.2f %s\n",FirstDepth,FirstTime,FirstNodeNb,double(LastScore)/100.0,pv_string); } printf("%d/%d",hit,tot); if (hit != 0) { depth_tot /= double(hit); time_tot /= double(hit); node_tot /= double(hit); printf(" - %.1f %.2f %.0f",depth_tot,time_tot,node_tot); } printf("\n"); fclose(file); }
int main(int argc, char * argv[]) { const char *BoolValue[2] = { "false", "true" }; printf("Mars V0.3 UCCI based on Fruit 2.1 by Fabien Letouzey\n"); printf("作者:顾剑辉\n"); printf("网站:www.jsmaster.com\n"); printf("请键入ucci指令......\n"); //position fen rnbakab2/9/2c1c1n2/p1p1p3p/6p2/2PN3r1/P3P1P1P/1C2C1N2/9/1RBAKAB1R w - - 0 7 //position fen 1rbakab2/9/1cn5n/pR4p1p/2p1p4/4c1P2/P1P4rP/2N1C1NC1/4A4/2B1KABR1 w - - 0 10 //9/3ka4/3R5/5r2p/p5p2/4N4/P5P1P/9/4A2c1/2BK2B2 b - - 0 36 CommEnum IdleComm; CommDetail Command; int move,n; undo_t undo[1]; if(BootLine() == e_CommUcci) { zobrist_gen(); pre_move_gen(); trans_init(Trans); trans_alloc(Trans); material_init(); material_alloc(); OutFile = stdout; board_from_fen("rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR r - - 0 1"); //board_from_fen("3k5/9/9/9/9/4c4/9/9/4n4/4K4 r - - 0 1"); //board_from_fen("3k5/9/9/9/9/4c4/3C5/2n1n4/4K4/9 r - - 0 1"); printf("position fen rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR r - - 0 1\n\n"); print_board(); printf("\n"); printf("id name Mars v0.3\n"); fflush(stdout); printf("id copyright 版权所有(C) 2005-2008\n"); fflush(stdout); printf("id author 顾剑辉\n"); fflush(stdout); printf("id user 未知\n\n"); fflush(stdout); /* printf("option batch type check default %s\n", BoolValue[ThisSearch.bBatch]); fflush(stdout); // option debug 让引擎输出详细的搜索信息,并非真正的调试模式。 printf("option debug type check default %s\n", BoolValue[ThisSearch.Debug]); fflush(stdout); // 指定开局库文件的名称,可指定多个开局库文件,用分号“;”隔开,如不让引擎使用开局库,可以把值设成空 ThisSearch.bUseOpeningBook = ThisSearch.m_Hash.LoadBook(BookFile); if(ThisSearch.bUseOpeningBook) printf("option bookfiles type string default %s\n", BookFile); else printf("option bookfiles type string default %s\n", 0); fflush(stdout); // 残局库名称 printf("option egtbpaths type string default null\n"); fflush(stdout); // 显示Hash表的大小 printf("option hashsize type spin default %d MB\n", ThisSearch.m_Hash.nHashSize*2*sizeof(CHashRecord)/1024/1024); fflush(stdout); // 引擎的线程数 printf("option threads type spin default %d\n", 0); fflush(stdout); // 引擎达到自然限着的半回合数 printf("option drawmoves type spin default %d\n", ThisSearch.NaturalBouts); fflush(stdout); // 棋规 printf("option repetition type spin default %d 1999年版《中国象棋竞赛规则》\n", e_RepetitionChineseRule); fflush(stdout); // 空着裁减是否打开 printf("option pruning type check %d\n", ThisSearch); fflush(stdout); // 估值函数的使用情况 printf("option knowledge type check %d\n", ThisSearch); fflush(stdout); // 指定选择性系数,通常有0,1,2,3四个级别。给估值函数加减一定范围内的随机数,让引擎每次走出不相同的棋。 printf("option selectivity type spin min 0 max 3 default %d\n", ThisSearch.nSelectivity); fflush(stdout); // 指定下棋的风格,通常有solid(保守)、normal(均衡)和risky(冒进)三种 printf("option style type combo var solid var normal var risky default %s\n", ChessStyle[ThisSearch.nStyle]); fflush(stdout); */ // copyprotection 显示版权检查信息(正在检查,版权信息正确或版权信息错误)。 printf("copyprotection ok\n\n"); fflush(stdout); // ucciok 这是ucci指令的最后一条反馈信息,表示引擎已经进入用UCCI协议通讯的状态。 printf("ucciok\n\n"); fflush(stdout); //FILE * out=fopen("info.txt","w+"); do { IdleComm = IdleLine(Command, 0); switch (IdleComm) { // isready 检测引擎是否处于就绪状态,其反馈信息总是readyok,该指令仅仅用来检测引擎的“指令接收缓冲区”是否能正常容纳指令。 // readyok 表明引擎处于就绪状态(即可接收指令的状态),不管引擎处于空闲状态还是思考状态。 case e_CommIsReady: //fprintf(out,"readyok\n"); printf("readyok\n"); fflush(stdout); break; // stop 中断引擎的思考,强制出着。后台思考没有命中时,就用该指令来中止思考,然后重新输入局面。 case e_CommStop: //ThisSearch.bStopThinking = 1; printf("nobestmove\n"); printf("score 0\n"); fflush(stdout); break; // position fen 设置“内置棋盘”的局面,用fen来指定FEN格式串,moves后面跟的是随后走过的着法 case e_CommPosition: // 将界面传来的Fen串转化为棋局信息 // board_clear(); //fprintf(out,"%s\n",Command.Position.FenStr); //fprintf(out,"%d",Command.Position.MoveNum); //fprintf(out,"%s\n",Command.Position.CoordList); //trans_clear(Trans); board_from_fen(Command.Position.FenStr); print_board(); for(n=0; n<Command.Position.MoveNum; n++) { move = move_from_string(Command.Position.CoordList[n]); //fprintf(out,"%x ",move); if( !move ) break; move_do(move,undo); //ThisSearch.StepRecords[ThisSearch.nCurrentStep-1] |= ThisSearch.Checking(ThisSearch.Player) << 24; } // 将局面走到当前,主要是为了更新着法记录,用于循环检测。 break; // banmoves 为当前局面设置禁手,以解决引擎无法处理的长打问题。当出现长打局面时,棋手可以操控界面向引擎发出禁手指令。 case e_CommBanMoves: break; // setoption 设置引擎各种参数 case e_CommSetOption: switch(Command.Option.Type) { // setoption batch %d case e_OptionBatch: batch=(Command.Option.Value.Check == e_CheckTrue); printf("option batch type check default %s\n", BoolValue[batch]); fflush(stdout); break; // setoption debug %d 让引擎输出详细的搜索信息,并非真正的调试模式。 case e_OptionDebug: break; // setoption bookfiles %s 指定开局库文件的名称,可指定多个开局库文件,用分号“;”隔开,如不让引擎使用开局库,可以把值设成空 case e_OptionBookFiles: break; // setoption egtbpaths %s 指定残局库文件的名称,可指定多个残局库路径,用分号“;”隔开,如不让引擎使用残局库,可以把值设成空 case e_OptionEgtbPaths: // 引擎目前不支持开局库 break; // setoption hashsize %d 以MB为单位规定Hash表的大小,-1表示让引擎自动分配Hash表。1~1024MB // 象堡界面有个Bug,每次设置引擎时,这个命令应在开局库的前面 case e_OptionHashSize: // -1MB(自动), 0MB(自动), 1MB(16), 2MB(17), 4MB(18), 8MB(19), 16MB(20), 32MB(21), 64MB(22), 128MB(23), 256MB(24), 512MB(25), 1024MB(26) if( Command.Option.Value.Spin <= 0) n = 22; // 缺省情况下,引擎自动分配(1<<22)*16=64MB,红与黑两各表,双方各一半。 else { n = 15; // 0.5 MB = 512 KB 以此为基数 while( Command.Option.Value.Spin > 0 ) { Command.Option.Value.Spin >>= 1; // 每次除以2,直到为0 n ++; } } break; // setoption threads %d 引擎的线程数,为多处理器并行运算服务 case e_OptionThreads: // ThisSearch.nThreads = Command.Option.Value.Spin; // 0(auto),1,2,4,8,16,32 printf("option drawmoves type spin default %d\n", 0); fflush(stdout); break; // setoption drawmoves %d 达到自然限着的回合数:50,60,70,80,90,100,象堡已经自动转化为半回合数 case e_OptionDrawMoves: break; // setoption repetition %d 处理循环的棋规,目前只支持“中国象棋棋规1999” case e_OptionRepetition: // ThisSearch.nRepetitionStyle = Command.Option.Value.Repetition; // e_RepetitionAlwaysDraw 不变作和 // e_RepetitionCheckBan 禁止长将 // e_RepetitionAsianRule 亚洲规则 // e_RepetitionChineseRule 中国规则(缺省) break; // setoption pruning %d,“空着向前裁剪”是否打开 case e_OptionPruning: //ThisSearch.bPruning = Command.Option.Value.Scale; //printf("option pruning type check %d\n", ThisSearch); //fflush(stdout); break; // setoption knowledge %d,估值函数的使用 case e_OptionKnowledge: //ThisSearch.bKnowledge = Command.Option.Value.Scale; //printf("option knowledge type check %d\n", ThisSearch); //fflush(stdout); break; // setoption selectivity %d 指定选择性系数,通常有0,1,2,3四个级别 case e_OptionSelectivity: /*switch (Command.Option.Value.Scale) { case e_ScaleNone: ThisSearch.SelectMask = 0; break; case e_ScaleSmall: ThisSearch.SelectMask = 1; break; case e_ScaleMedium: ThisSearch.SelectMask = 3; break; case e_ScaleLarge: ThisSearch.SelectMask = 7; break; default: ThisSearch.SelectMask = 0; break; } printf("option selectivity type spin min 0 max 3 default %d\n", ThisSearch.SelectMask); fflush(stdout);*/ break; // setoption style %d 指定下棋的风格,通常有solid(保守)、normal(均衡)和risky(冒进)三种 case e_OptionStyle: //ThisSearch.nStyle = Command.Option.Value.Style; //printf("option style type combo var solid var normal var risky default %s\n", ChessStyle[Command.Option.Value.Style]); //fflush(stdout); break; // setoption loadbook UCCI界面ElephantBoard在每次新建棋局时都会发送这条指令 case e_OptionLoadBook: /*ThisSearch.m_Hash.ClearHashTable(); ThisSearch.bUseOpeningBook = ThisSearch.m_Hash.LoadBook(BookFile); if(ThisSearch.bUseOpeningBook) printf("option loadbook succeed. %s\n", BookFile); // 成功 else printf("option loadbook failed! %s\n", "Not found file BOOK.DAT"); // 没有开局库 fflush(stdout); printf("\n\n"); fflush(stdout); */ break; default: break; } break; // Prepare timer strategy according to "go depth %d" or "go ponder depth %d" command case e_CommGo: case e_CommGoPonder: switch (Command.Search.Mode) { // 固定深度Command.Search.DepthTime.Depth case e_TimeDepth: ponder = 2; search(Command.Search.DepthTime.Depth,0,0); break; // 时段制: 分配时间 = 剩余时间 / 要走的步数 case e_TimeMove: ponder = (IdleComm == e_CommGoPonder ? 1 : 0); search(32,Command.Search.DepthTime.Time * 1000 / Command.Search.TimeMode.MovesToGo, Command.Search.DepthTime.Time * 1000); // ThisSearch.Ponder = (IdleComm == e_CommGoPonder ? 1 : 0); // printf("%d\n", Command.Search.TimeMode.MovesToGo); // ThisSearch.MainSearch(127, Command.Search.DepthTime.Time * 1000 / Command.Search.TimeMode.MovesToGo, Command.Search.DepthTime.Time * 1000); break; // 加时制: 分配时间 = 每步增加的时间 + 剩余时间 / 20 (即假设棋局会在20步内结束) case e_TimeInc: ponder = (IdleComm == e_CommGoPonder ? 1 : 0); search(32,(Command.Search.DepthTime.Time + Command.Search.TimeMode.Increment * 20) * 1000 / 20, Command.Search.DepthTime.Time * 1000); // ThisSearch.Ponder = (IdleComm == e_CommGoPonder ? 1 : 0); // ThisSearch.MainSearch(127, (Command.Search.DepthTime.Time + Command.Search.TimeMode.Increment * 20) * 1000 / 20, Command.Search.DepthTime.Time * 1000); break; default: break; } break; } } while (IdleComm != e_CommQuit); //fprintf(out,"bye"); //fclose(out); printf("bye\n"); fflush(stdout); //getchar(); }