9 /* unacceptable when the program is thinking, or quit pondering */
10 #define AbortDifficultCommand \
11 if ( game_status & flag_thinking ) \
13 str_error = str_busy_think; \
16 else if ( game_status & ( flag_pondering | flag_puzzling ) ) \
18 game_status |= flag_quit_ponder; \
23 # define CmdBook(x,y) cmd_book(y);
24 static int CONV cmd_book( char **lasts );
26 # define CmdBook(x,y) cmd_book(x,y);
27 static int CONV cmd_learn( tree_t * restrict ptree, char **lasts );
28 static int CONV cmd_book( tree_t * restrict ptree, char **lasts );
31 #if ! defined(NO_STDOUT)
32 static int CONV cmd_stress( char **lasts );
36 static int CONV proce_csalan( tree_t * restrict ptree );
37 static int CONV cmd_connect( tree_t * restrict ptree, char **lasts );
38 static int CONV cmd_sendpv( char **lasts );
42 static int CONV proce_mnj( tree_t * restrict ptree );
43 static int CONV cmd_mnjignore( tree_t *restrict ptree, char **lasts );
44 static int CONV cmd_mnj( char **lasts );
45 static int CONV cmd_mnjmove( tree_t * restrict ptree, char **lasts,
50 static int CONV proce_usi( tree_t * restrict ptree );
51 static int CONV usi_posi( tree_t * restrict ptree, char **lasts );
52 static int CONV usi_go( tree_t * restrict ptree, char **lasts );
53 static int CONV usi_ignore( tree_t * restrict ptree, char **lasts );
57 static int CONV cmd_thread( char **lasts );
61 static int CONV cmd_mpv( tree_t * restrict ptree, char **lasts );
65 static int CONV cmd_dfpn( tree_t * restrict ptree, char **lasts );
68 #if defined(DFPN_CLIENT)
69 static int CONV cmd_dfpn_client( tree_t * restrict ptree, char **lasts );
72 static int CONV proce_cui( tree_t * restrict ptree );
73 static int CONV cmd_usrmove( tree_t * restrict ptree, const char *str_move,
75 static int CONV cmd_outmove( tree_t * restrict ptree );
76 static int CONV cmd_move_now( void );
77 static int CONV cmd_ponder( char **lasts );
78 static int CONV cmd_limit( char **lasts );
79 static int CONV cmd_quit( void );
80 static int CONV cmd_beep( char **lasts );
81 static int CONV cmd_peek( char **lasts );
82 static int CONV cmd_stdout( char **lasts );
83 static int CONV cmd_newlog( char **lasts );
84 static int CONV cmd_hash( char **lasts );
85 static int CONV cmd_ping( void );
86 static int CONV cmd_suspend( void );
87 static int CONV cmd_problem( tree_t * restrict ptree, char **lasts );
88 static int CONV cmd_display( tree_t * restrict ptree, char **lasts );
89 static int CONV cmd_move( tree_t * restrict ptree, char **lasts );
90 static int CONV cmd_new( tree_t * restrict ptree, char **lasts );
91 static int CONV cmd_read( tree_t * restrict ptree, char **lasts );
92 static int CONV cmd_resign( tree_t * restrict ptree, char **lasts );
93 static int CONV cmd_undo( tree_t * restrict ptree ); // [HGM] undo
94 static int CONV cmd_time( char **lasts );
95 static int CONV cmd_undo( tree_t * restrict ptree ); // [HGM] undo
96 static int CONV cmd_analyze( tree_t * restrict ptree ); // [HGM] analyze
97 static int CONV cmd_exit( void );
100 int CONV is_move( const char *str )
102 if ( isdigit( (int)str[0] ) && isdigit( (int)str[1] )
103 && isdigit( (int)str[2] ) && isdigit( (int)str[3] )
104 && isupper( (int)str[4] ) && isupper( (int)str[5] )
105 && str[6] == '\0' ) { return 1; }
112 procedure( tree_t * restrict ptree )
115 if ( sckt_csa != SCKT_NULL ) { return proce_csalan( ptree ); }
119 if ( sckt_mnj != SCKT_NULL ) { return proce_mnj( ptree ); }
123 if ( usi_mode != usi_off ) { return proce_usi( ptree ); }
126 return proce_cui( ptree );
129 char *start_pos, start_data[512]; // [HGM] undo: for remembering start position
130 int move_list[1024], move_ptr;
133 #define IF(X) else if(!strcmp(command, X))
135 int myTime, hisTime, movesPerSession, inc, plyNr;
140 xboard_to_CSA( tree_t * restrict ptree, char *in, char *out )
142 char fromX=in[0], fromY=in[1], toX=in[2], toY=in[3], promo=in[4];
144 if(fromY == '@') { // drop (contains all info needed to convert it)
145 if(fromX >= 'a') fromX += 'A' - 'a';
146 switch(fromX) { // encode piece
147 case 'P': piece = pawn; break;
148 case 'L': piece = lance; break;
149 case 'N': piece = knight; break;
150 case 'S': piece = silver; break;
151 case 'G': piece = gold; break;
152 case 'B': piece = bishop; break;
153 case 'R': piece = rook; break;
155 sprintf(out, "00%c%c%s", 'a'+'9'-toX, '1'+'9'-toY, astr_table_piece[piece]);
156 } else { // board move (need to figure out moved piece)
157 int from = ('9' - fromY)*9 + (fromX - 'a');
158 int flag = (promo == '+' ? FLAG_PROMO : 0);
159 piece = abs( BOARD[from] ); // this only works when not searching!
160 printf("# piece from board: %d\n", piece);fflush(stdout);
161 if( game_status & ( flag_pondering | flag_puzzling | flag_thinking ) ) {
162 int i, to = ('9' - toY)*9 + (toX - 'a');
163 piece = 0; // kludge to force illegal CSA move
164 for( i = 0; i < root_nmove; i++ ) { // determine the piece from the move list
165 int move = root_move_list[i].move;
166 if( I2To(move) != to ) continue;
167 if( I2From(move) != from ) continue;
168 if( (move & FLAG_PROMO) != flag ) continue;
169 piece = I2PieceMove( move ); // we found the move; take the piece from it
172 printf("# piece corrected to %d\n", piece);fflush(stdout);
174 if( promo ) piece += promote;
175 sprintf(out, "%c%c%c%c%s", 'a'+'9'-fromX, '1'+'9'-fromY, 'a'+'9'-toX, '1'+'9'-toY, astr_table_piece[piece]);
181 { // set white and black times from own and opponent time.
183 if(movesPerSession <= 0) moves = 35; else {
185 while(moves <= 0) moves += movesPerSession;
187 time_limit = (myTime-inc-30)/(moves+2) + inc;
188 time_max_limit = 3*time_limit;
189 if(time_max_limit > myTime - 30)time_max_limit = myTime - 30; // keep 0.3 sec margin, as Bonanza reads the clock infrequently
190 time_limit *= 10; // msec
191 time_max_limit *= 10;
192 Out("# moves=%d, time=%d inc=%d t=%d, max=%d\n", moves, myTime, inc, time_limit, time_max_limit);
196 proce_xboard(char *line, const char *command, tree_t * restrict ptree)
197 { // [HGM] added to make Bonanza.exe a native WinBoard engine
199 static char forceMode = 0;
200 sscanf(line + strlen(command) + 1, "%d", &value);
201 Out("# command = '%s'\n", line);
205 Out("feature option=\"MultiPV -spin 1 1 100\"\n");
206 Out("feature option=\"centi-Pawn margin -spin 200 0 25000\"\n");
208 Out("feature variants=\"shogi\" usermove=1 myname=\"Bonanza " BNZ_VER
209 "\" memory=1 smp=1 debug=1 colors=0 setboard=1 ping=1 done=1\n");
211 IF("new") { forceMode = plyNr = 0; SetTimes(); return 0; }
212 IF("easy") { strcpy(line, "ponder off"); return 0; }
213 IF("hard") { strcpy(line, "ponder on"); return 0; }
216 IF("time") { sscanf(line+5, "%d", &myTime); }
217 IF("otim") { sscanf(line+5, "%d", &hisTime); }
218 IF("force") { forceMode = 1; }
219 IF("go") { forceMode = 0; SetTimes(); plyNr++; strcpy(line, "move"); return 0; }
221 IF("cores") { sprintf(line, "tlp num %d", value); return 0; }
222 IF("sd") { sprintf(line, "limit depth %d", value); return 0; }
224 IF("quit") { return 0; }
225 IF("analyze") { return 0; }
226 IF("exit") { return 0; }
227 IF("variant") { /* ignore, since it must be Shogi */; }
230 if(sscanf(line+7, "MultiPV=%d", &value) == 1) { sprintf(line, "mpv num %d", value); return 0; }
231 if(sscanf(line+7, "centi-Pawn margin=%d", &value) == 1) { sprintf(line, "mpv width %d", value); return 0; }
233 IF("level") { int min, sec; float fsec=0.;
234 if(sscanf(line+6, "%d %d:%d %f", &movesPerSession, &min, &sec, &fsec) != 4)
235 sscanf(line+6, "%d %d %f", &movesPerSession, &min, &fsec);
236 min = 60*min + sec; myTime = hisTime = 100*min; inc = 100 * fsec;
238 IF("usermove") { char buf[20];
239 xboard_to_CSA( ptree, line+9, buf );
240 if(forceMode || analyze_mode) strcpy(line, "move "), line += 5; else plyNr++, SetTimes();
245 IF("undo") { return 0; }
247 IF("ping") { Out("pong %d\n", value); }
252 static int CONV proce_cui( tree_t * restrict ptree )
257 token = strtok_r( str_cmdline, str_delimiters, &last );
259 if ( token == NULL || *token == '#' ) { return 1; }
263 if( proce_xboard(str_cmdline, token, ptree) ) return 1; // command already processed
264 Out("# translated command '%s'\n", str_cmdline); // command translated for processing by Bonanza
265 token = strtok_r( str_cmdline, str_delimiters, &last ); // redo parsing
267 if ( ! strcmp( token, "xboard" ) ) { xboard_mode = 1; game_status |= flag_noprompt; return 1; }
270 if ( ! strcmp( token, "analyze" ) ) { return cmd_analyze( ptree ); } // [HGM] analyze
271 if ( ! strcmp( token, "exit" ) ) { return cmd_exit(); } // [HGM] analyze
272 if ( ! strcmp( token, "move" ) ) { return cmd_move( ptree, &last ); }
273 if ( ! strcmp( token, "undo" ) ) { return cmd_undo( ptree ); } // [HGM] undo
275 if ( ! strcmp( token, "mpv" ) ) { return cmd_mpv( ptree, &last ); }
277 analyze_mode = 0; // [HGM] analyze: all other commands terminate analysis
278 if ( is_move( token ) ) { return cmd_usrmove( ptree, token, &last ); }
279 if ( ! strcmp( token, "s" ) ) { return cmd_move_now(); }
280 if ( ! strcmp( token, "beep" ) ) { return cmd_beep( &last); }
281 if ( ! strcmp( token, "book" ) ) { return CmdBook( ptree, &last ); }
282 if ( ! strcmp( token, "display" ) ) { return cmd_display( ptree, &last ); }
283 if ( ! strcmp( token, "hash" ) ) { return cmd_hash( &last ); }
284 if ( ! strcmp( token, "limit" ) ) { return cmd_limit( &last ); }
285 if ( ! strcmp( token, "new" ) ) { return cmd_new( ptree, &last ); }
286 if ( ! strcmp( token, "outmove" ) ) { return cmd_outmove( ptree ); }
287 if ( ! strcmp( token, "peek" ) ) { return cmd_peek( &last ); }
288 if ( ! strcmp( token, "stdout" ) ) { return cmd_stdout( &last ); }
289 if ( ! strcmp( token, "ping" ) ) { return cmd_ping(); }
290 if ( ! strcmp( token, "ponder" ) ) { return cmd_ponder( &last ); }
291 if ( ! strcmp( token, "problem" ) ) { return cmd_problem( ptree, &last ); }
292 if ( ! strcmp( token, "quit" ) ) { return cmd_quit(); }
293 if ( ! strcmp( token, "read" ) ) { return cmd_read( ptree, &last ); }
294 if ( ! strcmp( token, "resign" ) ) { return cmd_resign( ptree, &last ); }
295 if ( ! strcmp( token, "suspend" ) ) { return cmd_suspend(); }
296 if ( ! strcmp( token, "time" ) ) { return cmd_time( &last ); }
297 if ( ! strcmp( token, "newlog" ) ) { return cmd_newlog( &last ); }
299 if ( ! strcmp( token, "connect" ) ) { return cmd_connect( ptree, &last ); }
300 if ( ! strcmp( token, "sendpv" ) ) { return cmd_sendpv( &last ); }
303 if ( ! strcmp( token, "mnj" ) ) { return cmd_mnj( &last ); }
306 if ( ! strcmp( token, "dfpn" ) ) { return cmd_dfpn( ptree, &last ); }
308 #if defined(DFPN_CLIENT)
309 if ( ! strcmp( token, "dfpn_client")) { return cmd_dfpn_client( ptree,
313 if ( ! strcmp( token, "tlp" ) ) { return cmd_thread( &last ); }
315 #if ! defined(NO_STDOUT)
316 if ( ! strcmp( token, "stress" ) ) { return cmd_stress( &last ); }
318 #if ! defined(MINIMUM)
319 if ( ! strcmp( token, "learn" ) ) { return cmd_learn( ptree, &last ); }
322 str_error = str_bad_cmdline;
328 static int CONV proce_csalan( tree_t * restrict ptree )
333 token = strtok_r( str_cmdline, str_delimiters, &last );
335 if ( token == NULL ) { return 1; }
336 if ( *token == ach_turn[client_turn] && is_move( token+1 ) )
341 token = strtok_r( NULL, str_delimiters, &last );
342 if ( token == NULL || *token != 'T' )
344 str_error = str_bad_cmdline;
348 l = strtol( token+1, &ptr, 0 );
349 if ( token+1 == ptr || l == LONG_MAX || l < 1 )
351 str_error = str_bad_cmdline;
355 adjust_time( (unsigned int)l, client_turn );
356 Out( " elapsed: b%u, w%u\n", sec_b_total, sec_w_total );
359 if ( *token == ach_turn[Flip(client_turn)] && is_move( token+1 ) )
361 return cmd_usrmove( ptree, token+1, &last );
363 if ( ! strcmp( token, str_resign ) ) { return cmd_resign( ptree, &last ); }
364 if ( ! strcmp( token, "#WIN" )
365 || ! strcmp( token, "#LOSE" )
366 || ! strcmp( token, "#DRAW" )
367 || ! strcmp( token, "#CHUDAN" ) )
369 if ( game_status & ( flag_thinking | flag_pondering | flag_puzzling ) )
371 game_status |= flag_suspend;
375 if ( sckt_out( sckt_csa, "LOGOUT\n" ) < 0 ) { return -1; }
376 if ( sckt_recv_all( sckt_csa ) < 0 ) { return -1; }
380 if ( client_ngame == client_max_game ) { return cmd_quit(); }
382 return client_next_game( ptree, client_str_addr, (int)client_port );
391 static int CONV proce_mnj( tree_t * restrict ptree )
397 token = strtok_r( str_cmdline, str_delimiters, &last );
398 if ( token == NULL ) { return 1; }
400 if ( ! strcmp( token, "new" ) )
402 iret = cmd_suspend();
403 if ( iret != 1 ) { return iret; }
406 iret = cmd_new( ptree, &last );
407 if ( iret < 0 ) { return iret; }
409 moves_ignore[0] = MOVE_NA;
410 return analyze( ptree );
412 if ( ! strcmp( token, "ignore" ) ) { return cmd_mnjignore( ptree, &last ); }
413 if ( ! strcmp( token, "idle" ) ) { return cmd_suspend(); }
414 if ( ! strcmp( token, "alter" ) ) { return cmd_mnjmove( ptree, &last, 1 ); }
415 if ( ! strcmp( token, "retract" ) )
419 const char *str = strtok_r( NULL, str_delimiters, &last );
422 str_error = str_bad_cmdline;
425 l = strtol( str, &ptr, 0 );
426 if ( ptr == str || (long)NUM_UNMAKE < l )
428 str_error = str_bad_cmdline;
432 return cmd_mnjmove( ptree, &last, (int)l );
434 if ( ! strcmp( token, "move" ) ) { return cmd_mnjmove( ptree, &last, 0 ); }
436 str_error = str_bad_cmdline;
442 cmd_mnjignore( tree_t *restrict ptree, char **lasts )
451 token = strtok_r( NULL, str_delimiters, lasts );
454 str_error = str_bad_cmdline;
457 lid = strtol( token, &ptr, 0 );
458 if ( ptr == token || lid == LONG_MAX || lid < 1 )
460 str_error = str_bad_cmdline;
464 AbortDifficultCommand;
466 for ( i = 0; ; i += 1 )
468 token = strtok_r( NULL, str_delimiters, lasts );
469 if ( token == NULL ) { break; }
471 if ( interpret_CSA_move( ptree, &move, token ) < 0 ) { return -1; }
473 moves_ignore[i] = move;
477 str_error = str_bad_cmdline;
480 mnj_posi_id = (int)lid;
481 moves_ignore[i] = MOVE_NA;
483 return analyze( ptree );
488 cmd_mnjmove( tree_t * restrict ptree, char **lasts, int num_alter )
490 const char *str1 = strtok_r( NULL, str_delimiters, lasts );
491 const char *str2 = strtok_r( NULL, str_delimiters, lasts );
497 if ( sckt_mnj == SCKT_NULL || str1 == NULL || str2 == NULL )
499 str_error = str_bad_cmdline;
503 lid = strtol( str2, &ptr, 0 );
504 if ( ptr == str2 || lid == LONG_MAX || lid < 1 )
506 str_error = str_bad_cmdline;
510 AbortDifficultCommand;
514 iret = unmake_move_root( ptree );
515 if ( iret < 0 ) { return iret; }
520 iret = interpret_CSA_move( ptree, &move, str1 );
521 if ( iret < 0 ) { return iret; }
523 iret = get_elapsed( &time_turn_start );
524 if ( iret < 0 ) { return iret; }
526 mnj_posi_id = (int)lid;
528 iret = make_move_root( ptree, move, ( flag_time | flag_rep
529 | flag_detect_hang ) );
530 if ( iret < 0 ) { return iret; }
532 # if ! defined(NO_STDOUT)
533 iret = out_board( ptree, stdout, 0, 0 );
534 if ( iret < 0 ) { return iret; }
537 moves_ignore[0] = MOVE_NA;
538 return analyze( ptree );
544 do_analyze( tree_t * restrict ptree )
545 { // [HGM] analyze: do a ponder search on the current position
547 if ( get_elapsed( &time_start ) < 0 ) { return -1; }
548 time_limit = time_max_limit = 1e9; // kludge: use huge time to mimic infinity
550 if(xboard_mode) Out("1 0 0 0 New Search\n"); // make sure lower depth is emitted, so XBoard undestand new search started
552 game_status |= flag_pondering;
553 iret = iterate( ptree );
554 game_status &= ~flag_pondering;
560 cmd_undo( tree_t * restrict ptree )
561 { // [HGM] undo: restart the game, and feed all moves except the last
562 int i, last = move_ptr;
563 char *p = start_data;
564 if( move_ptr <= 0 ) {
565 str_error = "undo past start of game ignored";
569 AbortDifficultCommand;
572 cmd_new( ptree, &p );
573 for(i=0; i<last; i++) {
574 make_move_root( ptree, move_list[i], 0);
577 if ( analyze_mode ) return do_analyze ( ptree ); // [HGM] analyze: analysis should continue after undo
584 cmd_analyze( tree_t * restrict ptree )
585 { // [HGM] analyze: switch on analyze mode, and start analyzing
586 AbortDifficultCommand;
589 return do_analyze( ptree );
595 { // [HGM] analyze: switch off analysis mode
596 if ( !analyze_mode ) {
597 str_error = "was not analyzing";
601 if ( game_status & flag_pondering ) { game_status |= flag_quit_ponder; return 2; }
609 static int CONV proce_usi( tree_t * restrict ptree )
615 token = strtok_r( str_cmdline, str_delimiters, &lasts );
616 if ( token == NULL ) { return 1; }
618 if ( ! strcmp( token, "usi" ) )
620 USIOut( "id name %s\n", str_myname );
621 USIOut( "id author Kunihito Hoki\n" );
626 if ( ! strcmp( token, "isready" ) )
628 USIOut( "readyok\n", str_myname );
632 if ( ! strcmp( token, "echo" ) )
634 USIOut( "%s\n", lasts );
638 if ( ! strcmp( token, "ignore_moves" ) )
640 return usi_ignore( ptree, &lasts );
643 if ( ! strcmp( token, "genmove_probability" ) )
645 if ( get_elapsed( &time_start ) < 0 ) { return -1; }
646 return usi_root_list( ptree );
649 if ( ! strcmp( token, "go" ) )
651 iret = usi_go( ptree, &lasts );
652 moves_ignore[0] = MOVE_NA;
656 if ( ! strcmp( token, "stop" ) ) { return cmd_move_now(); }
657 if ( ! strcmp( token, "position" ) ) { return usi_posi( ptree, &lasts ); }
658 if ( ! strcmp( token, "quit" ) ) { return cmd_quit(); }
660 str_error = str_bad_cmdline;
666 usi_ignore( tree_t * restrict ptree, char **lasts )
673 AbortDifficultCommand;
675 for ( i = 0; ; i += 1 )
677 token = strtok_r( NULL, str_delimiters, lasts );
678 if ( token == NULL ) { break; }
680 if ( usi2csa( ptree, token, str_buf ) < 0 ) { return -1; }
681 if ( interpret_CSA_move( ptree, &move, str_buf ) < 0 ) { return -1; }
683 moves_ignore[i] = move;
686 moves_ignore[i] = MOVE_NA;
693 usi_go( tree_t * restrict ptree, char **lasts )
700 AbortDifficultCommand;
702 if ( game_status & mask_game_end )
704 str_error = str_game_ended;
708 token = strtok_r( NULL, str_delimiters, lasts );
710 if ( ! strcmp( token, "book" ) )
712 AbortDifficultCommand;
713 if ( usi_book( ptree ) < 0 ) { return -1; }
719 if ( ! strcmp( token, "infinite" ) )
721 usi_byoyomi = UINT_MAX;
722 depth_limit = PLY_MAX;
723 node_limit = UINT64_MAX;
724 sec_limit_depth = UINT_MAX;
726 else if ( ! strcmp( token, "byoyomi" ) )
728 token = strtok_r( NULL, str_delimiters, lasts );
731 str_error = str_bad_cmdline;
735 l = strtol( token, &ptr, 0 );
736 if ( ptr == token || l > UINT_MAX || l < 1 )
738 str_error = str_bad_cmdline;
742 usi_byoyomi = (unsigned int)l;
743 depth_limit = PLY_MAX;
744 node_limit = UINT64_MAX;
745 sec_limit_depth = UINT_MAX;
748 str_error = str_bad_cmdline;
753 if ( get_elapsed( &time_turn_start ) < 0 ) { return -1; }
755 iret = com_turn_start( ptree, 0 );
757 if ( str_error == str_no_legal_move ) { USIOut( "bestmove resign\n" ); }
766 usi_posi( tree_t * restrict ptree, char **lasts )
772 AbortDifficultCommand;
774 moves_ignore[0] = MOVE_NA;
776 token = strtok_r( NULL, str_delimiters, lasts );
777 if ( strcmp( token, "startpos" ) )
779 str_error = str_bad_cmdline;
783 if ( ini_game( ptree, &min_posi_no_handicap,
784 flag_history, NULL, NULL ) < 0 ) { return -1; }
786 token = strtok_r( NULL, str_delimiters, lasts );
787 if ( token == NULL ) { return 1; }
789 if ( strcmp( token, "moves" ) )
791 str_error = str_bad_cmdline;
797 token = strtok_r( NULL, str_delimiters, lasts );
798 if ( token == NULL ) { break; }
800 if ( usi2csa( ptree, token, str_buf ) < 0 ) { return -1; }
801 if ( interpret_CSA_move( ptree, &move, str_buf ) < 0 ) { return -1; }
802 if ( make_move_root( ptree, move, ( flag_history | flag_time
804 | flag_detect_hang ) ) < 0 )
810 if ( get_elapsed( &time_turn_start ) < 0 ) { return -1; }
817 static int CONV cmd_move_now( void )
819 if ( game_status & flag_thinking ) { game_status |= flag_move_now; }
826 cmd_usrmove( tree_t * restrict ptree, const char *str_move, char **lasts )
834 if ( game_status & mask_game_end )
836 str_error = str_game_ended;
840 if ( game_status & flag_thinking )
842 str_error = str_busy_think;
846 str = strtok_r( NULL, str_delimiters, lasts );
847 if ( str == NULL ) { lelapsed = 0; }
851 str_error = str_bad_cmdline;
855 lelapsed = strtol( str, &ptr, 0 );
856 if ( ptr == str || lelapsed == LONG_MAX || lelapsed < 1 )
858 str_error = str_bad_cmdline;
863 if ( game_status & ( flag_pondering | flag_puzzling ) )
867 for ( i = 0; i < ponder_nmove; i++ )
869 if ( ! strcmp( str_move, str_CSA_move(ponder_move_list[i]) ) )
874 if ( i == ponder_nmove )
877 if ( sckt_csa != SCKT_NULL ) { AbortDifficultCommand; }
880 #if defined(CSASHOGI)
881 AbortDifficultCommand;
883 str_error = str_illegal_move;
888 if ( ( game_status & flag_puzzling )
889 || strcmp( str_move, str_CSA_move(ponder_move) ) )
891 ponder_move = MOVE_PONDER_FAILED;
892 game_status |= flag_quit_ponder;
896 iret = update_time( Flip(root_turn) );
897 if ( iret < 0 ) { return iret; }
900 adjust_time( (unsigned int)lelapsed, Flip(root_turn) );
903 out_CSA( ptree, &record_game, ponder_move );
905 game_status &= ~flag_pondering;
906 game_status |= flag_thinking;
910 set_search_limit_time( root_turn );
912 OutCsaShogi( "info ponder end\n" );
914 str = str_time_symple( time_turn_start - time_start );
915 Out( " %6s MOVE PREDICTION HIT\n"
916 " elapsed: b%u, w%u\n", str, sec_b_total, sec_w_total );
921 iret = interpret_CSA_move( ptree, &move, str_move );
922 if ( iret < 0 ) { return iret; }
923 move_evasion_pchk = 0;
924 iret = make_move_root( ptree, move, ( flag_rep | flag_history | flag_time
925 | flag_detect_hang ) );
930 if ( sckt_csa != SCKT_NULL )
932 if ( move_evasion_pchk )
934 str = str_CSA_move( move_evasion_pchk );
935 iret = sckt_out( sckt_csa, "%c%s\n",
936 ach_turn[Flip(root_turn)], str );
937 if ( iret < 0 ) { return iret; }
939 return cmd_suspend();
943 if ( move_evasion_pchk )
945 str = str_CSA_move( move_evasion_pchk );
946 #if defined(CSASHOGI)
947 OutCsaShogi( "move%s\n", str );
948 return cmd_suspend();
950 snprintf( str_message, SIZE_MESSAGE, "perpetual check (%c%s)",
951 ach_turn[Flip(root_turn)], str );
952 str_error = str_message;
960 if ( lelapsed ) { adjust_time( (unsigned int)lelapsed, Flip(root_turn) ); }
961 Out( " elapsed: b%u, w%u\n", sec_b_total, sec_w_total );
964 if ( sckt_csa != SCKT_NULL && ( game_status & flag_mated ) )
966 iret = sckt_out( sckt_csa, "%%TORYO\n" );
967 if ( iret < 0 ) { return iret; }
971 if ( ! ( game_status & mask_game_end ) )
973 iret = com_turn_start( ptree, 0 );
974 if ( iret < 0 ) { return iret; }
981 static int CONV cmd_beep( char **lasts )
983 const char *str = strtok_r( NULL, str_delimiters, lasts );
986 str_error = str_bad_cmdline;
990 if ( ! strcmp( str, str_on ) ) { game_status &= ~flag_nobeep; }
991 else if ( ! strcmp( str, str_off ) ) { game_status |= flag_nobeep; }
993 str_error = str_bad_cmdline;
1001 static int CONV cmd_peek( char **lasts )
1003 const char *str = strtok_r( NULL, str_delimiters, lasts );
1007 str_error = str_bad_cmdline;
1011 if ( ! strcmp( str, str_on ) ) { game_status &= ~flag_nopeek; }
1012 else if ( ! strcmp( str, str_off ) ) { game_status |= flag_nopeek; }
1014 str_error = str_bad_cmdline;
1022 static int CONV cmd_stdout( char **lasts )
1024 const char *str = strtok_r( NULL, str_delimiters, lasts );
1028 str_error = str_bad_cmdline;
1032 if ( ! strcmp( str, str_on ) ) { game_status &= ~flag_nostdout; }
1033 else if ( ! strcmp( str, str_off ) ) { game_status |= flag_nostdout; }
1035 str_error = str_bad_cmdline;
1043 static int CONV cmd_newlog( char **lasts )
1045 const char *str = strtok_r( NULL, str_delimiters, lasts );
1049 str_error = str_bad_cmdline;
1053 if ( ! strcmp( str, str_on ) ) { game_status &= ~flag_nonewlog; }
1054 else if ( ! strcmp( str, str_off ) ) { game_status |= flag_nonewlog; }
1056 str_error = str_bad_cmdline;
1064 static int CONV cmd_ponder( char **lasts )
1066 const char *str = strtok_r( NULL, str_delimiters, lasts );
1070 str_error = str_bad_cmdline;
1074 if ( ! strcmp( str, str_on ) ) { game_status &= ~flag_noponder; }
1075 else if ( ! strcmp( str, str_off ) )
1077 if ( game_status & ( flag_pondering | flag_puzzling ) )
1079 game_status |= flag_quit_ponder;
1081 game_status |= flag_noponder;
1084 str_error = str_bad_cmdline;
1092 #if ! defined(NO_STDOUT)
1093 static int CONV cmd_stress( char **lasts )
1095 const char *str = strtok_r( NULL, str_delimiters, lasts );
1099 str_error = str_bad_cmdline;
1103 if ( ! strcmp( str, str_on ) ) { game_status &= ~flag_nostress; }
1104 else if ( ! strcmp( str, str_off ) ) { game_status |= flag_nostress; }
1106 str_error = str_bad_cmdline;
1116 #if defined(MINIMUM)
1117 cmd_book( char **lasts )
1119 cmd_book( tree_t * restrict ptree, char **lasts )
1122 const char *str = strtok_r( NULL, str_delimiters, lasts );
1127 str_error = str_bad_cmdline;
1130 if ( ! strcmp( str, str_on ) ) { iret = book_on(); }
1131 else if ( ! strcmp( str, str_off ) ) { iret = book_off(); }
1132 else if ( ! strcmp( str, "narrow" ) ) { game_status |= flag_narrow_book; }
1133 else if ( ! strcmp( str, "wide" ) ) { game_status &= ~flag_narrow_book; }
1134 #if ! defined(MINIMUM)
1135 else if ( ! strcmp( str, "create" ) )
1137 AbortDifficultCommand;
1139 iret = book_create( ptree );
1140 if ( iret < 0 ) { return iret; }
1142 iret = ini_game( ptree, &min_posi_no_handicap, flag_history,
1144 if ( iret < 0 ) { return iret; }
1146 iret = get_elapsed( &time_turn_start );
1150 str_error = str_bad_cmdline;
1158 static int CONV cmd_display( tree_t * restrict ptree, char **lasts )
1160 const char *str = strtok_r( NULL, str_delimiters, lasts );
1167 l = strtol( str, &ptr, 0 );
1170 str_error = str_bad_cmdline;
1173 if ( l == 1 ) { game_status &= ~flag_reverse; }
1174 else if ( l == 2 ) { game_status |= flag_reverse; }
1176 str_error = str_bad_cmdline;
1182 iret = out_board( ptree, stdout, 0, 0 );
1183 if ( iret < 0 ) { return iret; }
1184 #if ! defined(NO_LOGGING)
1185 iret = out_board( ptree, pf_log, 0, 0 );
1186 if ( iret < 0 ) { return iret; }
1194 static int CONV cmd_ping( void )
1196 OutCsaShogi( "pong\n" );
1202 static int CONV cmd_hash( char **lasts )
1204 const char *str = strtok_r( NULL, str_delimiters, lasts );
1210 str_error = str_bad_cmdline;
1214 l = strtol( str, &ptr, 0 );
1215 if ( ptr == str || l == LONG_MAX || l < 1 || l > 31 )
1217 str_error = str_bad_cmdline;
1221 AbortDifficultCommand;
1223 log2_ntrans_table = (int)l;
1224 memory_free( (void *)ptrans_table_orig );
1225 return ini_trans_table();
1229 static int CONV cmd_limit( char **lasts )
1231 const char *str = strtok_r( NULL, str_delimiters, lasts );
1237 str_error = str_bad_cmdline;
1241 AbortDifficultCommand;
1243 if ( ! strcmp( str, "depth" ) )
1245 str = strtok_r( NULL, str_delimiters, lasts );
1248 str_error = str_bad_cmdline;
1251 l1 = strtol( str, &ptr, 0 );
1252 if ( ptr == str || l1 == LONG_MAX || l1 < 1 )
1254 str_error = str_bad_cmdline;
1257 sec_limit_up = UINT_MAX;
1258 node_limit = UINT64_MAX;
1259 depth_limit = (int)l1;
1261 else if ( ! strcmp( str, "nodes" ) )
1263 str = strtok_r( NULL, str_delimiters, lasts );
1266 str_error = str_bad_cmdline;
1269 l1 = strtol( str, &ptr, 0 );
1270 if ( ptr == str || l1 == LONG_MAX || l1 < 1 )
1272 str_error = str_bad_cmdline;
1275 sec_limit_up = UINT_MAX;
1276 depth_limit = PLY_MAX;
1277 node_limit = (uint64_t)l1;
1279 else if ( ! strcmp( str, "time" ) )
1281 str = strtok_r( NULL, str_delimiters, lasts );
1284 str_error = str_bad_cmdline;
1288 if ( ! strcmp( str, "extendable" ) )
1290 game_status |= flag_time_extendable;
1292 else if ( ! strcmp( str, "strict" ) )
1294 game_status &= ~flag_time_extendable;
1297 l1 = strtol( str, &ptr, 0 );
1298 if ( ptr == str || l1 == LONG_MAX || l1 < 0 )
1300 str_error = str_bad_cmdline;
1304 str = strtok_r( NULL, str_delimiters, lasts );
1307 str_error = str_bad_cmdline;
1310 l2 = strtol( str, &ptr, 0 );
1311 if ( ptr == str || l2 == LONG_MAX || l2 < 0 )
1313 str_error = str_bad_cmdline;
1317 str = strtok_r( NULL, str_delimiters, lasts );
1318 if ( ! str ) { l3 = -1; }
1320 l3 = strtol( str, &ptr, 0 );
1321 if ( ptr == str || l3 >= PLY_MAX || l3 < -1 )
1323 str_error = str_bad_cmdline;
1328 if ( ! ( l1 | l2 ) ) { l2 = 1; }
1330 depth_limit = PLY_MAX;
1331 node_limit = UINT64_MAX;
1332 sec_limit = (unsigned int)l1 * 60U;
1333 sec_limit_up = (unsigned int)l2;
1334 if ( l3 == -1 ) { sec_limit_depth = UINT_MAX; }
1335 else { sec_limit_depth = (unsigned int)l3; }
1339 str_error = str_bad_cmdline;
1348 cmd_read( tree_t * restrict ptree, char **lasts )
1350 const char *str1 = strtok_r( NULL, str_delimiters, lasts );
1351 const char *str2 = strtok_r( NULL, str_delimiters, lasts );
1352 const char *str3 = strtok_r( NULL, str_delimiters, lasts );
1353 const char *str_tmp;
1354 FILE *pf_src, *pf_dest;
1355 char str_file[SIZE_FILENAME];
1361 flag = flag_history | flag_rep | flag_detect_hang;
1367 str_error = str_bad_cmdline;
1373 if ( ! strcmp( str2, "t" ) ) { flag |= flag_time; }
1374 else if ( strcmp( str2, "nil" ) )
1376 str_error = str_bad_cmdline;
1383 l = strtol( str3, &ptr, 0 );
1384 if ( ptr == str3 || l == LONG_MAX || l < 1 )
1386 str_error = str_bad_cmdline;
1389 moves = (unsigned int)l - 1U;
1392 AbortDifficultCommand;
1394 if ( ! strcmp( str1, "." ) )
1396 str_tmp = "game.cs_";
1398 #if defined(NO_LOGGING)
1399 strncpy( str_file, "game.csa", SIZE_FILENAME-1 );
1401 snprintf( str_file, SIZE_FILENAME, "%s/game%03d.csa",
1402 str_dir_logs, record_num );
1404 pf_dest = file_open( str_tmp, "w" );
1405 if ( pf_dest == NULL ) { return -2; }
1407 pf_src = file_open( str_file, "r" );
1408 if ( pf_src == NULL )
1410 file_close( pf_dest );
1414 while ( ( c = getc(pf_src) ) != EOF ) { putc( c, pf_dest ); }
1416 iret = file_close( pf_src );
1419 file_close( pf_dest );
1423 iret = file_close( pf_dest );
1424 if ( iret < 0 ) { return iret; }
1430 iret = read_record( ptree, str1, moves, flag );
1431 if ( iret < 0 ) { return iret; }
1433 iret = get_elapsed( &time_turn_start );
1434 if ( iret < 0 ) { return iret; }
1436 if ( str_tmp && remove( str_tmp ) )
1438 out_warning( "remove() failed." );
1446 static int CONV cmd_resign( tree_t * restrict ptree, char **lasts )
1448 const char *str = strtok_r( NULL, str_delimiters, lasts );
1452 if ( str == NULL || *str == 'T' )
1454 AbortDifficultCommand;
1456 if ( game_status & mask_game_end ) { return 1; }
1458 game_status |= flag_resigned;
1459 update_time( root_turn );
1460 out_CSA( ptree, &record_game, MOVE_RESIGN );
1463 l = strtol( str, &ptr, 0 );
1464 if ( ptr == str || l == LONG_MAX || l < MT_CAP_PAWN )
1466 str_error = str_bad_cmdline;
1469 resign_threshold = (int)l;
1476 static int CONV cmd_move( tree_t * restrict ptree, char **lasts )
1478 const char *str = strtok_r( NULL, str_delimiters, lasts );
1484 if ( game_status & mask_game_end )
1486 str_error = str_game_ended;
1490 AbortDifficultCommand;
1494 if ( analyze_mode ) // [HGM] analyze: in analysis mode we cannot set the engine thinking (but perhaps play PV move?)
1496 str_error = str_bad_cmdline;
1500 iret = get_elapsed( &time_turn_start );
1501 if ( iret < 0 ) { return iret; }
1503 return com_turn_start( ptree, 0 );
1506 l = strtol( str, &ptr, 0 );
1507 if ( str != ptr && l != LONG_MAX && l >= 1 && *ptr == '\0' )
1509 if ( analyze_mode ) // [HGM] analyze: in analysis mode we cannot set the engine thinking
1511 str_error = str_bad_cmdline;
1515 for ( i = 0; i < l; i += 1 )
1517 if ( game_status & ( flag_move_now | mask_game_end ) ) { break; }
1519 iret = get_elapsed( &time_turn_start );
1520 if ( iret < 0 ) { return iret; }
1522 iret = com_turn_start( ptree, 0 );
1523 if ( iret < 0 ) { return iret; }
1530 iret = interpret_CSA_move( ptree, &move, str );
1531 if ( iret < 0 ) { return iret; }
1533 iret = get_elapsed( &time_turn_start );
1534 if ( iret < 0 ) { return iret; }
1536 iret = make_move_root( ptree, move,
1537 ( flag_history | flag_time | flag_rep
1538 | flag_detect_hang ) );
1539 if ( iret < 0 ) { return iret; }
1541 str = strtok_r( NULL, str_delimiters, lasts );
1543 } while ( str != NULL );
1545 if ( analyze_mode ) return do_analyze ( ptree ); // [HGM] analyze: analysis should continue after feeding moves
1551 static int CONV cmd_new( tree_t * restrict ptree, char **lasts )
1553 const char *str1 = strtok_r( NULL, str_delimiters, lasts );
1554 const char *str2 = strtok_r( NULL, str_delimiters, lasts );
1555 const min_posi_t *pmp;
1556 min_posi_t min_posi;
1559 AbortDifficultCommand;
1561 start_pos = *lasts; move_ptr = 0; // [HGM] undo: remember start position
1565 strncpy(start_data, str1, 511); // [HGM] undo: remember start position
1566 memset( &min_posi.asquare, empty, nsquare );
1567 min_posi.hand_black = min_posi.hand_white = 0;
1568 iret = read_board_rep1( str1, &min_posi );
1569 if ( iret < 0 ) { return iret; }
1573 if ( ! strcmp( str2, "-" ) ) { min_posi.turn_to_move = white; }
1574 else if ( ! strcmp( str2, "+" ) ) { min_posi.turn_to_move = black; }
1576 str_error = str_bad_cmdline;
1580 else { min_posi.turn_to_move = black; }
1584 else { pmp = &min_posi_no_handicap; }
1586 iret = ini_game( ptree, pmp, flag_history, NULL, NULL );
1587 if ( iret < 0 ) { return iret; }
1589 return get_elapsed( &time_turn_start );
1593 static int CONV cmd_outmove( tree_t * restrict ptree )
1595 const char *str_move;
1597 unsigned int move_list[ MAX_LEGAL_MOVES ];
1600 AbortDifficultCommand;
1602 if ( game_status & mask_game_end )
1604 Out( "NO LEGAL MOVE\n" );
1605 DFPNOut( "NO LEGAL MOVE\n" );
1609 n = gen_legal_moves( ptree, move_list, 0 );
1612 for ( c = i = 0; i < n; i += 1 )
1614 str_move = str_CSA_move(move_list[i]);
1616 if ( i && ( i % 10 ) == 0 )
1618 Out( "%s\n", buffer );
1619 DFPNOut( "%s ", buffer );
1620 memcpy( buffer, str_move, 6 );
1626 memcpy( buffer + c + 1, str_move, 6 );
1630 memcpy( buffer + c, str_move, 6 );
1635 Out( "%s\n", buffer );
1636 DFPNOut( "%s\n", buffer );
1642 static int CONV cmd_problem( tree_t * restrict ptree, char **lasts )
1644 const char *str = strtok_r( NULL, str_delimiters, lasts );
1647 unsigned int nposition;
1653 AbortDifficultCommand;
1658 if ( str != NULL && ! strcmp( str, "mate" ) )
1661 str = strtok_r( NULL, str_delimiters, lasts );
1667 l = strtol( str, &ptr, 0 );
1668 if ( ptr == str || l == LONG_MAX || l < 1 )
1670 str_error = str_bad_cmdline;
1673 nposition = (unsigned int)l;
1675 else { nposition = UINT_MAX; }
1678 iret = record_open( &record_problems, "problem.csa", mode_read, NULL, NULL );
1679 if ( iret < 0 ) { return iret; }
1682 iret = is_mate ? solve_mate_problems( ptree, nposition )
1683 : solve_problems( ptree, nposition );
1685 iret = solve_problems( ptree, nposition );
1690 record_close( &record_problems );
1694 iret = record_close( &record_problems );
1695 if ( iret < 0 ) { return iret; }
1697 return get_elapsed( &time_turn_start );
1701 static int CONV cmd_quit( void )
1703 game_status |= flag_quit;
1708 static int CONV cmd_suspend( void )
1710 if ( game_status & ( flag_pondering | flag_puzzling ) )
1712 game_status |= flag_quit_ponder;
1716 game_status |= flag_suspend;
1721 static int CONV cmd_time( char **lasts )
1723 const char *str = strtok_r( NULL, str_delimiters, lasts );
1728 str_error = str_bad_cmdline;
1731 else if ( ! strcmp( str, "response" ) )
1734 str = strtok_r( NULL, str_delimiters, lasts );
1737 str_error = str_bad_cmdline;
1740 l = strtol( str, &ptr, 0 );
1741 if ( ptr == str || l == LONG_MAX || l < 0 || l > 1000 )
1743 str_error = str_bad_cmdline;
1746 time_response = (unsigned int)l;
1749 else if ( ! strcmp( str, "remain" ) )
1753 str = strtok_r( NULL, str_delimiters, lasts );
1756 str_error = str_bad_cmdline;
1759 l1 = strtol( str, &ptr, 0 );
1760 if ( ptr == str || l1 == LONG_MAX || l1 < 0 )
1762 str_error = str_bad_cmdline;
1766 str = strtok_r( NULL, str_delimiters, lasts );
1769 str_error = str_bad_cmdline;
1772 l2 = strtol( str, &ptr, 0 );
1773 if ( ptr == str || l2 == LONG_MAX || l2 < 0 )
1775 str_error = str_bad_cmdline;
1779 if ( sec_limit_up == UINT_MAX )
1781 str_error = str_bad_cmdline;
1785 return reset_time( (unsigned int)l1, (unsigned int)l2 );
1788 str_error = str_bad_cmdline;
1793 #if !defined(MINIMUM)
1794 /* learn (ini|no-ini) steps games iterations tlp1 tlp2 */
1795 static int CONV cmd_learn( tree_t * restrict ptree, char **lasts )
1797 const char *str1 = strtok_r( NULL, str_delimiters, lasts );
1798 const char *str2 = strtok_r( NULL, str_delimiters, lasts );
1799 const char *str3 = strtok_r( NULL, str_delimiters, lasts );
1800 const char *str4 = strtok_r( NULL, str_delimiters, lasts );
1802 const char *str5 = strtok_r( NULL, str_delimiters, lasts );
1803 const char *str6 = strtok_r( NULL, str_delimiters, lasts );
1807 unsigned int max_games;
1808 int is_ini, nsteps, max_iterations, nworker1, nworker2, iret;
1812 str_error = str_bad_cmdline;
1815 if ( ! strcmp( str1, "ini" ) ) { is_ini = 1; }
1816 else if ( ! strcmp( str1, "no-ini" ) ) { is_ini = 0; }
1818 str_error = str_bad_cmdline;
1822 max_games = UINT_MAX;
1823 max_iterations = INT_MAX;
1824 nworker1 = nworker2 = nsteps = 1;
1828 l = strtol( str2, &ptr, 0 );
1829 if ( ptr == str2 || l == LONG_MAX || l < 1 )
1831 str_error = str_bad_cmdline;
1839 l = strtol( str3, &ptr, 0 );
1840 if ( ptr == str3 || l == LONG_MAX || l == LONG_MIN )
1842 str_error = str_bad_cmdline;
1845 if ( l > 0 ) { max_games = (unsigned int)l; }
1850 l = strtol( str4, &ptr, 0 );
1851 if ( ptr == str4 || l == LONG_MAX || l == LONG_MIN )
1853 str_error = str_bad_cmdline;
1856 if ( l > 0 ) { max_iterations = (int)l; }
1862 l = strtol( str5, &ptr, 0 );
1863 if ( ptr == str5 || l > TLP_MAX_THREADS || l < 1 )
1865 str_error = str_bad_cmdline;
1873 l = strtol( str6, &ptr, 0 );
1874 if ( ptr == str6 || l > TLP_MAX_THREADS || l < 1 )
1876 str_error = str_bad_cmdline;
1883 AbortDifficultCommand;
1885 log2_ntrans_table = 12;
1887 memory_free( (void *)ptrans_table_orig );
1889 iret = ini_trans_table();
1890 if ( iret < 0 ) { return iret; }
1892 iret = learn( ptree, is_ini, nsteps, max_games, max_iterations,
1893 nworker1, nworker2 );
1894 if ( iret < 0 ) { return -1; }
1896 iret = ini_game( ptree, &min_posi_no_handicap, flag_history, NULL, NULL );
1897 if ( iret < 0 ) { return -1; }
1899 iret = get_elapsed( &time_turn_start );
1900 if ( iret < 0 ) { return iret; }
1904 #endif /* MINIMUM */
1908 static int CONV cmd_mpv( tree_t * restrict ptree, char **lasts )
1910 const char *str = strtok_r( NULL, str_delimiters, lasts );
1916 str_error = str_bad_cmdline;
1919 else if ( ! strcmp( str, "num" ) )
1921 str = strtok_r( NULL, str_delimiters, lasts );
1924 str_error = str_bad_cmdline;
1927 l = strtol( str, &ptr, 0 );
1928 if ( ptr == str || l == LONG_MAX || l < 1 || l > MPV_MAX_PV )
1930 str_error = str_bad_cmdline;
1934 AbortDifficultCommand;
1938 if ( analyze_mode ) return do_analyze ( ptree ); // [HGM] analyze: analysis should continue changing num
1942 else if ( ! strcmp( str, "width" ) )
1944 str = strtok_r( NULL, str_delimiters, lasts );
1947 str_error = str_bad_cmdline;
1950 l = strtol( str, &ptr, 0 );
1951 if ( ptr == str || l == LONG_MAX || l < MT_CAP_PAWN )
1953 str_error = str_bad_cmdline;
1957 AbortDifficultCommand;
1961 if ( analyze_mode ) return do_analyze ( ptree ); // [HGM] analyze: analysis should continue after changing width
1966 str_error = str_bad_cmdline;
1973 static int CONV cmd_dfpn( tree_t * restrict ptree, char **lasts )
1975 const char *str = strtok_r( NULL, str_delimiters, lasts );
1979 str_error = str_bad_cmdline;
1982 else if ( ! strcmp( str, "hash" ) )
1987 str = strtok_r( NULL, str_delimiters, lasts );
1990 str_error = str_bad_cmdline;
1993 l = strtol( str, &ptr, 0 );
1994 if ( ptr == str || l == LONG_MAX || l < 1 )
1996 str_error = str_bad_cmdline;
2000 AbortDifficultCommand;
2002 dfpn_hash_log2 = (unsigned int)l;
2003 return dfpn_ini_hash();
2005 else if ( ! strcmp( str, "go" ) )
2007 AbortDifficultCommand;
2009 return dfpn( ptree, root_turn, 1 );
2011 else if ( ! strcmp( str, "connect" ) )
2019 str = strtok_r( NULL, str_delimiters, lasts );
2020 if ( ! str || ! strcmp( str, "." ) ) { str = "127.0.0.1"; }
2021 strncpy( str_addr, str, 255 );
2022 str_addr[255] = '\0';
2024 str = strtok_r( NULL, str_delimiters, lasts );
2025 if ( ! str || ! strcmp( str, "." ) ) { str = "4083"; }
2026 l = strtol( str, &ptr, 0 );
2027 if ( ptr == str || l == LONG_MAX || l < 0 || l > USHRT_MAX )
2029 str_error = str_bad_cmdline;
2034 str = strtok_r( NULL, str_delimiters, lasts );
2035 if ( ! str || ! strcmp( str, "." ) ) { str = "bonanza1"; }
2036 strncpy( str_id, str, 255 );
2039 AbortDifficultCommand;
2041 dfpn_sckt = sckt_connect( str_addr, port );
2042 if ( dfpn_sckt == SCKT_NULL ) { return -2; }
2044 str_buffer_cmdline[0] = '\0';
2045 DFPNOut( "Worker: %s\n", str_id );
2050 str_error = str_bad_cmdline;
2057 static int CONV cmd_thread( char **lasts )
2059 const char *str = strtok_r( NULL, str_delimiters, lasts );
2063 str_error = str_bad_cmdline;
2066 else if ( ! strcmp( str, "num" ) )
2071 str = strtok_r( NULL, str_delimiters, lasts );
2074 str_error = str_bad_cmdline;
2077 l = strtol( str, &ptr, 0 );
2078 if ( ptr == str || l == LONG_MAX || l < 1 || l > TLP_MAX_THREADS )
2080 str_error = str_bad_cmdline;
2088 if ( game_status & ( flag_thinking | flag_pondering | flag_puzzling ) )
2095 str_error = str_bad_cmdline;
2101 #if defined(DFPN_CLIENT)
2102 static int CONV cmd_dfpn_client( tree_t * restrict ptree, char **lasts )
2108 AbortDifficultCommand;
2110 str = strtok_r( NULL, str_delimiters, lasts );
2111 if ( ! str || ! strcmp( str, "." ) ) { str = "127.0.0.1"; }
2112 strncpy( dfpn_client_str_addr, str, 255 );
2113 dfpn_client_str_addr[255] = '\0';
2115 str = strtok_r( NULL, str_delimiters, lasts );
2116 if ( ! str || ! strcmp( str, "." ) ) { str = "4083"; }
2117 dfpn_client_port = strtol( str, &ptr, 0 );
2118 if ( ptr == str || dfpn_client_port == LONG_MAX || dfpn_client_port < 0
2119 || dfpn_client_port > USHRT_MAX )
2121 str_error = str_bad_cmdline;
2125 Out( "DFPN Server: %s %d\n", dfpn_client_str_addr, dfpn_client_port );
2127 iret = ini_game( ptree, &min_posi_no_handicap, flag_history, NULL, NULL );
2128 if ( iret < 0 ) { return iret; }
2130 if ( dfpn_client_sckt == SCKT_NULL )
2132 str_error = "Check network status.";
2136 return get_elapsed( &time_turn_start );
2141 #if defined(CSA_LAN)
2142 static int CONV cmd_connect( tree_t * restrict ptree, char **lasts )
2148 str = strtok_r( NULL, str_delimiters, lasts );
2149 if ( ! str || ! strcmp( str, "." ) ) { str = "gserver.computer-shogi.org"; }
2150 strncpy( client_str_addr, str, 255 );
2151 client_str_addr[255] = '\0';
2153 str = strtok_r( NULL, str_delimiters, lasts );
2154 if ( ! str || ! strcmp( str, "." ) ) { str = "4081"; }
2155 client_port = strtol( str, &ptr, 0 );
2156 if ( ptr == str || client_port == LONG_MAX || client_port < 0
2157 || client_port > USHRT_MAX )
2159 str_error = str_bad_cmdline;
2163 str = strtok_r( NULL, str_delimiters, lasts );
2164 if ( ! str || ! strcmp( str, "." ) ) { str = "bonanza_test"; }
2165 strncpy( client_str_id, str, 255 );
2166 client_str_id[255] = '\0';
2168 str = strtok_r( NULL, " \t", lasts );
2169 if ( ! str || ! strcmp( str, "." ) ) { str = "bonanza_test"; }
2170 strncpy( client_str_pwd, str, 255 );
2171 client_str_pwd[255] = '\0';
2173 str = strtok_r( NULL, str_delimiters, lasts );
2174 if ( ! str || ! strcmp( str, "." ) ) { client_max_game = INT_MAX; }
2176 max_games = strtol( str, &ptr, 0 );
2177 if ( ptr == str || max_games == LONG_MAX || max_games < 1 )
2179 str_error = str_bad_cmdline;
2182 client_max_game = max_games;
2185 AbortDifficultCommand;
2189 return client_next_game( ptree, client_str_addr, (int)client_port );
2193 static int CONV cmd_sendpv( char **lasts )
2195 const char *str = strtok_r( NULL, str_delimiters, lasts );
2199 str_error = str_bad_cmdline;
2203 if ( ! strcmp( str, str_off ) ) { game_status &= ~flag_sendpv; }
2204 else if ( ! strcmp( str, str_on ) ) { game_status |= flag_sendpv; }
2206 str_error = str_bad_cmdline;
2215 #if defined(MNJ_LAN)
2216 /* mnj sd seed addr port name factor stable_depth */
2217 static int CONV cmd_mnj( char **lasts )
2219 char client_str_addr[256];
2220 char client_str_id[256];
2225 int client_port, sd;
2228 str = strtok_r( NULL, str_delimiters, lasts );
2231 str_error = str_bad_cmdline;
2234 l = strtol( str, &ptr, 0 );
2235 if ( ptr == str || l == LONG_MAX || l < 0 )
2237 str_error = str_bad_cmdline;
2243 str = strtok_r( NULL, str_delimiters, lasts );
2246 str_error = str_bad_cmdline;
2249 l = strtol( str, &ptr, 0 );
2250 if ( ptr == str || l == LONG_MAX || l < 0 )
2252 str_error = str_bad_cmdline;
2255 seed = (unsigned int)l;
2258 str = strtok_r( NULL, str_delimiters, lasts );
2259 if ( ! str || ! strcmp( str, "." ) ) { str = "localhost"; }
2260 strncpy( client_str_addr, str, 255 );
2261 client_str_addr[255] = '\0';
2264 str = strtok_r( NULL, str_delimiters, lasts );
2265 if ( ! str || ! strcmp( str, "." ) ) { str = "4082"; }
2266 l = strtol( str, &ptr, 0 );
2267 if ( ptr == str || l == LONG_MAX || l < 0 || l > USHRT_MAX )
2269 str_error = str_bad_cmdline;
2272 client_port = (int)l;
2275 str = strtok_r( NULL, str_delimiters, lasts );
2276 if ( ! str || ! strcmp( str, "." ) ) { str = "bonanza1"; }
2277 strncpy( client_str_id, str, 255 );
2278 client_str_id[255] = '\0';
2280 str = strtok_r( NULL, str_delimiters, lasts );
2281 if ( ! str || ! strcmp( str, "." ) ) { str = "1.0"; }
2282 factor = strtod( str, &ptr );
2283 if ( ptr == str || factor < 0.0 )
2285 str_error = str_bad_cmdline;
2289 str = strtok_r( NULL, str_delimiters, lasts );
2290 if ( ! str || ! strcmp( str, "." ) ) { l = -1; }
2292 l = strtol( str, &ptr, 0 );
2293 if ( ptr == str || l == LONG_MAX )
2295 str_error = str_bad_cmdline;
2299 if ( l <= 0 ) { mnj_depth_stable = INT_MAX; }
2300 else { mnj_depth_stable = (int)l; }
2302 AbortDifficultCommand;
2304 resign_threshold = 65535;
2305 game_status |= ( flag_noponder | flag_noprompt );
2306 if ( mnj_reset_tbl( sd, seed ) < 0 ) { return -1; }
2308 sckt_mnj = sckt_connect( client_str_addr, (int)client_port );
2309 if ( sckt_mnj == SCKT_NULL ) { return -2; }
2311 str_buffer_cmdline[0] = '\0';
2313 Out( "Sending my name %s", client_str_id );
2314 MnjOut( "%s %g final%s\n", client_str_id, factor,
2315 ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
2317 return cmd_suspend();