Make multi-PV mode accessible from XBoard protocol
[bonanza.git] / proce.c
1 #include <ctype.h>
2 #include <limits.h>
3 #include <math.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "shogi.h"
8
9 /* unacceptable when the program is thinking, or quit pondering */
10 #define AbortDifficultCommand                                              \
11           if ( game_status & flag_thinking )                               \
12             {                                                              \
13               str_error = str_busy_think;                                  \
14               return -2;                                                   \
15             }                                                              \
16           else if ( game_status & ( flag_pondering | flag_puzzling ) )     \
17             {                                                              \
18               game_status |= flag_quit_ponder;                             \
19               return 2;                                                    \
20             }
21
22 #if defined(MINIMUM)
23 #  define CmdBook(x,y) cmd_book(y);
24 static int CONV cmd_book( char **lasts );
25 #else
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 );
29 #endif
30
31 #if ! defined(NO_STDOUT)
32 static int CONV cmd_stress( char **lasts );
33 #endif
34
35 #if defined(CSA_LAN)
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 );
39 #endif
40
41 #if defined(MNJ_LAN)
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,
46                              int num_alter );
47 #endif
48
49 #if defined(USI)
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 );
54 #endif
55
56 #if defined(TLP)
57 static int CONV cmd_thread( char **lasts );
58 #endif
59
60 #if defined(MPV)
61 static int CONV cmd_mpv( tree_t * restrict ptree, char **lasts );
62 #endif
63
64 #if defined(DFPN)
65 static int CONV cmd_dfpn( tree_t * restrict ptree, char **lasts );
66 #endif
67
68 #if defined(DFPN_CLIENT)
69 static int CONV cmd_dfpn_client( tree_t * restrict ptree, char **lasts );
70 #endif
71
72 static int CONV proce_cui( tree_t * restrict ptree );
73 static int CONV cmd_usrmove( tree_t * restrict ptree, const char *str_move,
74                              char **last );
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 );
98
99
100 int CONV is_move( const char *str )
101 {
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; }
106
107   return 0;
108 }
109
110
111 int CONV
112 procedure( tree_t * restrict ptree )
113 {
114 #if defined(CSA_LAN)
115   if ( sckt_csa != SCKT_NULL ) { return proce_csalan( ptree ); }
116 #endif
117
118 #if defined(MNJ_LAN)
119   if ( sckt_mnj != SCKT_NULL ) { return proce_mnj( ptree ); }
120 #endif
121
122 #if defined(USI)
123   if ( usi_mode != usi_off ) { return proce_usi( ptree ); }
124 #endif
125
126   return proce_cui( ptree );
127 }
128
129 char *start_pos, start_data[512]; // [HGM] undo: for remembering start position
130 int move_list[1024], move_ptr;
131
132 #ifdef XBOARD
133 #define IF(X) else if(!strcmp(command, X))
134
135 int myTime, hisTime, movesPerSession, inc, plyNr;
136 char xboard_mode;
137 char analyze_mode;
138
139 static void
140 SetTimes(void)
141 { // set white and black times from own and opponent time.
142   int moves;
143   if(movesPerSession <= 0) moves = 35; else {
144     moves = - plyNr/2;
145     while(moves <= 0) moves += movesPerSession;
146   }
147   time_limit = (myTime-inc-30)/(moves+2) + inc;
148   time_max_limit = 3*time_limit;
149   if(time_max_limit > myTime - 30)time_max_limit = myTime - 30; // keep 0.3 sec margin, as Bonanza reads the clock infrequently
150   time_limit *= 10; // msec
151   time_max_limit *= 10;
152 Out("# moves=%d, time=%d inc=%d t=%d, max=%d\n", moves, myTime, inc, time_limit, time_max_limit);
153 }
154
155 static int
156 proce_xboard(char *line, const char *command, tree_t * restrict ptree)
157 { // [HGM] added to make Bonanza.exe a native WinBoard engine
158   int value = -100000;
159   static char forceMode = 0;
160   sscanf(line + strlen(command) + 1, "%d", &value);
161 Out("# command = '%s'\n", line);
162   if(0) ;
163   IF("protover") {
164 #if defined(MPV)
165                    Out("feature option=\"MultiPV -spin 1 1 100\"\n");
166                    Out("feature option=\"centi-Pawn margin -spin 200 0 25000\"\n");
167 #endif
168                    Out("feature variants=\"shogi\" usermove=1 myname=\"Bonanza " BNZ_VER
169                        "\" memory=1 smp=1 debug=1 colors=0 setboard=1 ping=1 done=1\n");
170                  }
171   IF("new")      { forceMode = plyNr = 0; SetTimes(); return 0; }
172   IF("easy")     { strcpy(line, "ponder off"); return 0; }
173   IF("hard")     { strcpy(line, "ponder on");  return 0; }
174   IF("post")     { ; }
175   IF("nopost")   { ; }
176   IF("time")     { sscanf(line+5, "%d", &myTime); }
177   IF("otim")     { sscanf(line+5, "%d", &hisTime); }
178   IF("force")    { forceMode = 1; }
179   IF("go")       { forceMode = 0; SetTimes(); plyNr++; strcpy(line, "move"); return 0; }
180   IF("memory")   { ; }
181   IF("cores")    { sprintf(line, "tlp num %d", value); return 0; }
182   IF("sd")       { sprintf(line, "limit depth %d", value); return 0; }
183   IF("st")       { ; }
184   IF("quit")     { return 0; }
185   IF("analyze")  { return 0; }
186   IF("exit")     { return 0; }
187   IF("variant")  { /* ignore, since it must be Shogi */; }
188   IF("setboard") { ; }
189   IF("option")   {
190                    if(sscanf(line+7, "MultiPV=%d", &value) == 1) { sprintf(line, "mpv num %d", value); return 0; }
191                    if(sscanf(line+7, "centi-Pawn margin=%d", &value) == 1) { sprintf(line, "mpv width %d", value); return 0; }
192                  }
193   IF("level")    { int min, sec; float fsec=0.;
194                    if(sscanf(line+6, "%d %d:%d %f", &movesPerSession, &min, &sec, &fsec) != 4)
195                       sscanf(line+6, "%d %d %f", &movesPerSession, &min, &fsec);
196                    min = 60*min + sec; myTime = hisTime = 100*min; inc = 100 * fsec;
197                  }
198   IF("usermove") { char fromX=line[9], fromY=line[10], toX=line[11], toY=line[12], promo=line[13];
199                    int from;
200 {int i,j;for(i=0;i<81;i+=9){printf("# ");for(j=0;j<9;j++)printf(" %3d", BOARD[i+j]);printf("\n");}}
201                    if(forceMode || analyze_mode) strcpy(line, "move "), line += 5; else plyNr++, SetTimes();
202                    if(fromY == '@') { // drop
203                        if(fromX >= 'a') fromX += 'A' - 'a';
204                        switch(fromX) { // encode piece
205                          case 'P': fromX = pawn;   break;
206                          case 'L': fromX = lance;  break;
207                          case 'N': fromX = knight; break;
208                          case 'S': fromX = silver; break;
209                          case 'G': fromX = gold;   break;
210                          case 'B': fromX = bishop; break;
211                          case 'R': fromX = rook;   break;
212                        }
213                        sprintf(line, "00%c%c%s", 'a'+'9'-toX, '1'+'9'-toY, astr_table_piece[(int)fromX]);
214                    } else {
215                        from = ('9' - fromY)*9 + (fromX - 'a');
216 Out("# from=%d\n",from);
217                        sprintf(line, "%c%c%c%c%s", 'a'+'9'-fromX, '1'+'9'-fromY, 'a'+'9'-toX, '1'+'9'-toY,
218                                  astr_table_piece[abs(BOARD[from]) + (promo == '+' ? promote : 0)]);
219                    }
220                    plyNr++;
221                    return 0;
222                  }
223   IF("undo")     { return 0; }
224   IF("remove")   { ; }
225   IF("ping")     { Out("pong %d\n", value); }
226   return 1;
227 }
228 #endif
229
230 static int CONV proce_cui( tree_t * restrict ptree )
231 {
232   const char *token;
233   char *last;
234
235   token = strtok_r( str_cmdline, str_delimiters, &last );
236
237   if ( token == NULL || *token == '#' ) { return 1; }
238 #ifdef XBOARD
239   { 
240     if(xboard_mode) {
241       if( proce_xboard(str_cmdline, token, ptree) )  return 1; // command already processed
242       Out("# translated command '%s'\n", str_cmdline);         // command translated for processing by Bonanza
243       token = strtok_r( str_cmdline, str_delimiters, &last );  // redo parsing
244     } else
245     if ( ! strcmp( token, "xboard" ) )  { xboard_mode = 1; game_status |= flag_noprompt; return 1; }
246   }
247 #endif
248   if ( ! strcmp( token, "analyze" ) )   { return cmd_analyze( ptree ); } // [HGM] analyze
249   if ( ! strcmp( token, "exit" ) )      { return cmd_exit(); }           // [HGM] analyze
250   if ( ! strcmp( token, "move" ) )      { return cmd_move( ptree, &last ); }
251   if ( ! strcmp( token, "undo" ) )      { return cmd_undo( ptree ); }    // [HGM] undo
252 #if defined(MPV)
253   if ( ! strcmp( token, "mpv" ) )       { return cmd_mpv( ptree, &last ); }
254 #endif
255   analyze_mode = 0; // [HGM] analyze: all other commands terminate analysis
256   if ( is_move( token ) ) { return cmd_usrmove( ptree, token, &last ); }
257   if ( ! strcmp( token, "s" ) )         { return cmd_move_now(); }
258   if ( ! strcmp( token, "beep" ) )      { return cmd_beep( &last); }
259   if ( ! strcmp( token, "book" ) )      { return CmdBook( ptree, &last ); }
260   if ( ! strcmp( token, "display" ) )   { return cmd_display( ptree, &last ); }
261   if ( ! strcmp( token, "hash" ) )      { return cmd_hash( &last ); }
262   if ( ! strcmp( token, "limit" ) )     { return cmd_limit( &last ); }
263   if ( ! strcmp( token, "new" ) )       { return cmd_new( ptree, &last ); }
264   if ( ! strcmp( token, "outmove" ) )   { return cmd_outmove( ptree ); }
265   if ( ! strcmp( token, "peek" ) )      { return cmd_peek( &last ); }
266   if ( ! strcmp( token, "stdout" ) )    { return cmd_stdout( &last ); }
267   if ( ! strcmp( token, "ping" ) )      { return cmd_ping(); }
268   if ( ! strcmp( token, "ponder" ) )    { return cmd_ponder( &last ); }
269   if ( ! strcmp( token, "problem" ) )   { return cmd_problem( ptree, &last ); }
270   if ( ! strcmp( token, "quit" ) )      { return cmd_quit(); }
271   if ( ! strcmp( token, "read" ) )      { return cmd_read( ptree, &last ); }
272   if ( ! strcmp( token, "resign" ) )    { return cmd_resign( ptree, &last ); }
273   if ( ! strcmp( token, "suspend" ) )   { return cmd_suspend(); }
274   if ( ! strcmp( token, "time" ) )      { return cmd_time( &last ); }
275   if ( ! strcmp( token, "newlog" ) )    { return cmd_newlog( &last ); }
276 #if defined(CSA_LAN)
277   if ( ! strcmp( token, "connect" ) )   { return cmd_connect( ptree, &last ); }
278   if ( ! strcmp( token, "sendpv" ) )    { return cmd_sendpv( &last ); }
279 #endif
280 #if defined(MNJ_LAN)
281   if ( ! strcmp( token, "mnj" ) )       { return cmd_mnj( &last ); }
282 #endif
283 #if defined(DFPN)
284   if ( ! strcmp( token, "dfpn" ) )      { return cmd_dfpn( ptree, &last ); }
285 #endif
286 #if defined(DFPN_CLIENT)
287   if ( ! strcmp( token, "dfpn_client")) { return cmd_dfpn_client( ptree,
288                                                                   &last ); }
289 #endif
290 #if defined(TLP)
291   if ( ! strcmp( token, "tlp" ) )       { return cmd_thread( &last ); }
292 #endif
293 #if ! defined(NO_STDOUT)
294   if ( ! strcmp( token, "stress" ) )    { return cmd_stress( &last ); }
295 #endif
296 #if ! defined(MINIMUM)
297   if ( ! strcmp( token, "learn" ) )     { return cmd_learn( ptree, &last ); }
298 #endif
299
300   str_error = str_bad_cmdline;
301   return -2;
302 }
303
304
305 #if defined(CSA_LAN)
306 static int CONV proce_csalan( tree_t * restrict ptree )
307 {
308   const char *token;
309   char *last;
310
311   token = strtok_r( str_cmdline, str_delimiters, &last );
312     
313   if ( token == NULL ) { return 1; }
314   if ( *token == ach_turn[client_turn] && is_move( token+1 ) )
315     {
316       char *ptr;
317       long l;
318
319       token = strtok_r( NULL, str_delimiters, &last );
320       if ( token == NULL || *token != 'T' )
321         {
322           str_error = str_bad_cmdline;
323           return -1;
324         }
325       
326       l = strtol( token+1, &ptr, 0 );
327       if ( token+1 == ptr || l == LONG_MAX || l < 1 )
328         {
329           str_error = str_bad_cmdline;
330           return -1;
331         }
332
333       adjust_time( (unsigned int)l, client_turn );
334       Out( "  elapsed: b%u, w%u\n", sec_b_total, sec_w_total );
335       return 1;
336     }
337   if ( *token == ach_turn[Flip(client_turn)] && is_move( token+1 ) )
338     {
339       return cmd_usrmove( ptree, token+1, &last );
340     }
341   if ( ! strcmp( token, str_resign ) ) { return cmd_resign( ptree, &last ); }
342   if ( ! strcmp( token, "#WIN" )
343        || ! strcmp( token, "#LOSE" )
344        || ! strcmp( token, "#DRAW" )
345        || ! strcmp( token, "#CHUDAN" ) )
346     {
347       if ( game_status & ( flag_thinking | flag_pondering | flag_puzzling ) )
348         {
349           game_status |= flag_suspend;
350           return 2;
351         }
352
353       if ( sckt_out( sckt_csa, "LOGOUT\n" ) < 0 ) { return -1; }
354       if ( sckt_recv_all( sckt_csa )        < 0 ) { return -1; }
355
356       ShutdownAll();
357       
358       if ( client_ngame == client_max_game ) { return cmd_quit(); }
359
360       return client_next_game( ptree, client_str_addr, (int)client_port );
361     }
362   
363   return 1;
364 }
365 #endif
366
367
368 #if defined(MNJ_LAN)
369 static int CONV proce_mnj( tree_t * restrict ptree )
370 {
371   const char *token;
372   char *last;
373   int iret;
374
375   token = strtok_r( str_cmdline, str_delimiters, &last );
376   if ( token == NULL ) { return 1; }
377
378   if ( ! strcmp( token, "new" ) )
379     {
380       iret = cmd_suspend();
381       if ( iret != 1 ) { return iret; }
382
383       mnj_posi_id = 0;
384       iret = cmd_new( ptree, &last );
385       if ( iret < 0 ) { return iret; }
386
387       moves_ignore[0] = MOVE_NA;
388       return analyze( ptree );
389     }
390   if ( ! strcmp( token, "ignore" ) ) { return cmd_mnjignore( ptree, &last ); }
391   if ( ! strcmp( token, "idle" ) )   { return cmd_suspend(); }
392   if ( ! strcmp( token, "alter" ) )  { return cmd_mnjmove( ptree, &last, 1 ); }
393   if ( ! strcmp( token, "retract" ) )
394     {
395       long l;
396       char *ptr;
397       const char *str = strtok_r( NULL, str_delimiters, &last );
398       if ( str == NULL )
399         {
400           str_error = str_bad_cmdline;
401           return -1;
402         }
403       l = strtol( str, &ptr, 0 );
404       if ( ptr == str || (long)NUM_UNMAKE < l )
405         {
406           str_error = str_bad_cmdline;
407           return -1;
408         }
409       
410       return cmd_mnjmove( ptree, &last, (int)l );
411     }
412   if ( ! strcmp( token, "move" ) )  { return cmd_mnjmove( ptree, &last, 0 ); }
413
414   str_error = str_bad_cmdline;
415   return -2;
416 }
417
418
419 static int CONV
420 cmd_mnjignore( tree_t *restrict ptree, char **lasts )
421 {
422   const char *token;
423   char *ptr;
424   int i;
425   unsigned int move;
426   long lid;
427
428
429   token = strtok_r( NULL, str_delimiters, lasts );
430   if ( token == NULL )
431     {
432       str_error = str_bad_cmdline;
433       return -1;
434     }
435   lid = strtol( token, &ptr, 0 );
436   if ( ptr == token || lid == LONG_MAX || lid < 1 )
437     {
438       str_error = str_bad_cmdline;
439       return -1;
440     }
441
442   AbortDifficultCommand;
443
444   for ( i = 0; ; i += 1 )
445     {
446       token = strtok_r( NULL, str_delimiters, lasts );
447       if ( token == NULL ) { break; }
448
449       if ( interpret_CSA_move( ptree, &move, token ) < 0 ) { return -1; }
450
451       moves_ignore[i] = move;
452     }
453   if ( i == 0 )
454     {
455       str_error = str_bad_cmdline;
456       return -1;
457     }
458   mnj_posi_id     = (int)lid;
459   moves_ignore[i] = MOVE_NA;
460
461   return analyze( ptree );
462 }
463
464
465 static int CONV
466 cmd_mnjmove( tree_t * restrict ptree, char **lasts, int num_alter )
467 {
468   const char *str1 = strtok_r( NULL, str_delimiters, lasts );
469   const char *str2 = strtok_r( NULL, str_delimiters, lasts );
470   char *ptr;
471   long lid;
472   unsigned int move;
473   int iret;
474
475   if ( sckt_mnj == SCKT_NULL ||  str1 == NULL || str2 == NULL )
476     {
477       str_error = str_bad_cmdline;
478       return -1;
479     }
480
481   lid = strtol( str2, &ptr, 0 );
482   if ( ptr == str2 || lid == LONG_MAX || lid < 1 )
483     {
484       str_error = str_bad_cmdline;
485       return -1;
486     }
487
488   AbortDifficultCommand;
489  
490   while ( num_alter )
491     {
492       iret = unmake_move_root( ptree );
493       if ( iret < 0 ) { return iret; }
494
495       num_alter -= 1;
496     }
497
498   iret = interpret_CSA_move( ptree, &move, str1 );
499   if ( iret < 0 ) { return iret; }
500     
501   iret = get_elapsed( &time_turn_start );
502   if ( iret < 0 ) { return iret; }
503
504   mnj_posi_id = (int)lid;
505
506   iret = make_move_root( ptree, move, ( flag_time | flag_rep
507                                         | flag_detect_hang ) );
508   if ( iret < 0 ) { return iret; }
509   
510 #  if ! defined(NO_STDOUT)
511   iret = out_board( ptree, stdout, 0, 0 );
512   if ( iret < 0 ) { return iret; }
513 #  endif
514
515   moves_ignore[0] = MOVE_NA;
516   return analyze( ptree );
517 }
518 #endif
519
520
521 static int CONV
522 do_analyze( tree_t * restrict ptree )
523 { // [HGM] analyze: do a ponder search on the current position
524   int iret;
525   if ( get_elapsed( &time_start ) < 0 ) { return -1; }
526   time_limit = time_max_limit = 1e9; // kludge: use huge time to mimic infinity
527 #ifdef XBOARD
528   if(xboard_mode) Out("1 0 0 0 New Search\n"); // make sure lower depth is emitted, so XBoard undestand new search started
529 #endif
530   game_status |= flag_pondering;
531   iret         = iterate( ptree );
532   game_status &= ~flag_pondering;
533   return iret;
534 }
535
536
537 static int CONV
538 cmd_undo( tree_t * restrict ptree )
539 { // [HGM] undo: restart the game, and feed all moves except the last
540   int i, last = move_ptr;
541   char *p = start_data;
542   if( move_ptr <= 0 ) {
543     str_error = "undo past start of game ignored";
544     return -2;
545   }
546
547   AbortDifficultCommand;
548
549   last--;
550   cmd_new( ptree, &p );
551   for(i=0; i<last; i++) {
552     make_move_root( ptree, move_list[i], 0);
553   }
554
555   if ( analyze_mode ) return do_analyze ( ptree ); // [HGM] analyze: analysis should continue after undo
556
557   return 1;
558 }
559
560
561 static int CONV
562 cmd_analyze( tree_t * restrict ptree )
563 { // [HGM] analyze: switch on analyze mode, and start analyzing
564   AbortDifficultCommand;
565
566   analyze_mode = 1;
567   return do_analyze( ptree );
568 }
569
570
571 static int CONV
572 cmd_exit( void )
573 { // [HGM] analyze: switch off analysis mode
574   if ( !analyze_mode ) {
575     str_error = "was not analyzing";
576     return -2;
577   }
578
579   if ( game_status & flag_pondering ) { game_status |= flag_quit_ponder; return 2; }
580   analyze_mode = 0;
581
582   return 1;
583 }
584
585
586 #if defined(USI)
587 static int CONV proce_usi( tree_t * restrict ptree )
588 {
589   const char *token;
590   char *lasts;
591   int iret;
592
593   token = strtok_r( str_cmdline, str_delimiters, &lasts );
594   if ( token == NULL ) { return 1; }
595
596   if ( ! strcmp( token, "usi" ) )
597     {
598       USIOut( "id name %s\n", str_myname );
599       USIOut( "id author Kunihito Hoki\n" );
600       USIOut( "usiok\n" );
601       return 1;
602     }
603
604   if ( ! strcmp( token, "isready" ) )
605     {
606       USIOut( "readyok\n", str_myname );
607       return 1;
608     }
609
610   if ( ! strcmp( token, "echo" ) )
611     {
612       USIOut( "%s\n", lasts );
613       return 1;
614     }
615
616   if ( ! strcmp( token, "ignore_moves" ) )
617     {
618       return usi_ignore( ptree, &lasts );
619     }
620
621   if ( ! strcmp( token, "genmove_probability" ) )
622     {
623       if ( get_elapsed( &time_start ) < 0 ) { return -1; }
624       return usi_root_list( ptree );
625     }
626
627   if ( ! strcmp( token, "go" ) )
628     {
629       iret = usi_go( ptree, &lasts );
630       moves_ignore[0] = MOVE_NA;
631       return iret;
632     }
633
634   if ( ! strcmp( token, "stop" ) )     { return cmd_move_now(); }
635   if ( ! strcmp( token, "position" ) ) { return usi_posi( ptree, &lasts ); }
636   if ( ! strcmp( token, "quit" ) )     { return cmd_quit(); }
637   
638   str_error = str_bad_cmdline;
639   return -1;
640 }
641
642
643 static int CONV
644 usi_ignore( tree_t * restrict ptree, char **lasts )
645 {
646   const char *token;
647   char str_buf[7];
648   int i;
649   unsigned int move;
650
651   AbortDifficultCommand;
652
653   for ( i = 0; ; i += 1 )
654     {
655       token = strtok_r( NULL, str_delimiters, lasts );
656       if ( token == NULL ) { break; }
657       
658       if ( usi2csa( ptree, token, str_buf ) < 0 )            { return -1; }
659       if ( interpret_CSA_move( ptree, &move, str_buf ) < 0 ) { return -1; }
660
661       moves_ignore[i] = move;
662     }
663
664   moves_ignore[i] = MOVE_NA;
665
666   return 1;
667 }
668
669
670 static int CONV
671 usi_go( tree_t * restrict ptree, char **lasts )
672 {
673   const char *token;
674   char *ptr;
675   int iret;
676   long l;
677
678   AbortDifficultCommand;
679
680   if ( game_status & mask_game_end )
681     {
682       str_error = str_game_ended;
683       return -1;
684     }
685   
686   token = strtok_r( NULL, str_delimiters, lasts );
687
688   if ( ! strcmp( token, "book" ) )
689     {
690       AbortDifficultCommand;
691       if ( usi_book( ptree ) < 0 ) { return -1; }
692
693       return 1;
694     }
695
696
697   if ( ! strcmp( token, "infinite" ) )
698     {
699       usi_byoyomi     = UINT_MAX;
700       depth_limit     = PLY_MAX;
701       node_limit      = UINT64_MAX;
702       sec_limit_depth = UINT_MAX;
703     }
704   else if ( ! strcmp( token, "byoyomi" ) )
705     {
706       token = strtok_r( NULL, str_delimiters, lasts );
707       if ( token == NULL )
708         {
709           str_error = str_bad_cmdline;
710           return -1;
711         }
712
713       l = strtol( token, &ptr, 0 );
714       if ( ptr == token || l > UINT_MAX || l < 1 )
715         {
716           str_error = str_bad_cmdline;
717           return -1;
718         }
719       
720       usi_byoyomi     = (unsigned int)l;
721       depth_limit     = PLY_MAX;
722       node_limit      = UINT64_MAX;
723       sec_limit_depth = UINT_MAX;
724     }
725   else {
726     str_error = str_bad_cmdline;
727     return -1;
728   }
729
730       
731   if ( get_elapsed( &time_turn_start ) < 0 ) { return -1; }
732
733   iret = com_turn_start( ptree, 0 );
734   if ( iret < 0 ) {
735     if ( str_error == str_no_legal_move ) { USIOut( "bestmove resign\n" ); }
736     else                                  { return -1; }
737   }
738   
739   return 1;
740 }
741
742
743 static int CONV
744 usi_posi( tree_t * restrict ptree, char **lasts )
745 {
746   const char *token;
747   char str_buf[7];
748   unsigned int move;
749     
750   AbortDifficultCommand;
751     
752   moves_ignore[0] = MOVE_NA;
753
754   token = strtok_r( NULL, str_delimiters, lasts );
755   if ( strcmp( token, "startpos" ) )
756     {
757       str_error = str_bad_cmdline;
758       return -1;
759     }
760     
761   if ( ini_game( ptree, &min_posi_no_handicap,
762                  flag_history, NULL, NULL ) < 0 ) { return -1; }
763     
764   token = strtok_r( NULL, str_delimiters, lasts );
765   if ( token == NULL ) { return 1; }
766
767   if ( strcmp( token, "moves" ) )
768     {
769       str_error = str_bad_cmdline;
770       return -1;
771     }
772     
773   for ( ;; )  {
774
775     token = strtok_r( NULL, str_delimiters, lasts );
776     if ( token == NULL ) { break; }
777       
778     if ( usi2csa( ptree, token, str_buf ) < 0 )            { return -1; }
779     if ( interpret_CSA_move( ptree, &move, str_buf ) < 0 ) { return -1; }
780     if ( make_move_root( ptree, move, ( flag_history | flag_time
781                                         | flag_rep
782                                         | flag_detect_hang ) ) < 0 )
783       {
784         return -1;
785       }
786   }
787     
788   if ( get_elapsed( &time_turn_start ) < 0 ) { return -1; }
789   return 1;
790 }
791
792 #endif
793
794
795 static int CONV cmd_move_now( void )
796 {
797   if ( game_status & flag_thinking ) { game_status |= flag_move_now; }
798
799   return 1;
800 }
801
802
803 static int CONV
804 cmd_usrmove( tree_t * restrict ptree, const char *str_move, char **lasts )
805 {
806   const char *str;
807   char *ptr;
808   long lelapsed;
809   unsigned int move;
810   int iret;
811
812   if ( game_status & mask_game_end )
813     {
814       str_error = str_game_ended;
815       return -2;
816     }
817   
818   if ( game_status & flag_thinking )
819     {
820       str_error = str_busy_think;
821       return -2;
822     }
823
824   str = strtok_r( NULL, str_delimiters, lasts );
825   if ( str == NULL ) { lelapsed = 0; }
826   else {
827     if ( *str != 'T' )
828       {
829         str_error = str_bad_cmdline;
830         return -2;
831       }
832     str += 1;
833     lelapsed = strtol( str, &ptr, 0 );
834     if ( ptr == str || lelapsed == LONG_MAX || lelapsed < 1 )
835       {
836         str_error = str_bad_cmdline;
837         return -2;
838       }
839   }
840
841   if ( game_status & ( flag_pondering | flag_puzzling ) )
842     {
843       int i;
844
845       for ( i = 0; i < ponder_nmove; i++ )
846         {
847           if ( ! strcmp( str_move, str_CSA_move(ponder_move_list[i]) ) )
848             {
849               break;
850             }
851         }
852       if ( i == ponder_nmove )
853         {
854 #if defined(CSA_LAN)
855           if ( sckt_csa != SCKT_NULL ) { AbortDifficultCommand; }
856 #endif
857
858 #if defined(CSASHOGI)
859           AbortDifficultCommand;
860 #else
861           str_error = str_illegal_move;
862           return -2;
863 #endif
864         }
865
866       if ( ( game_status & flag_puzzling )
867            || strcmp( str_move, str_CSA_move(ponder_move) ) )
868         {
869           ponder_move  = MOVE_PONDER_FAILED;
870           game_status |= flag_quit_ponder;
871           return 2;
872         }
873       else {
874         iret = update_time( Flip(root_turn) );
875         if ( iret < 0 ) { return iret; }
876         if ( lelapsed )
877           {
878             adjust_time( (unsigned int)lelapsed, Flip(root_turn) );
879           }
880
881         out_CSA( ptree, &record_game, ponder_move );
882
883         game_status      &= ~flag_pondering;
884         game_status      |= flag_thinking;
885 #ifdef XBOARD
886       if(!xboard_mode)
887 #endif
888         set_search_limit_time( root_turn );
889
890         OutCsaShogi( "info ponder end\n" );
891
892         str = str_time_symple( time_turn_start - time_start );
893         Out( "    %6s          MOVE PREDICTION HIT\n"
894              "  elapsed: b%u, w%u\n", str, sec_b_total, sec_w_total );
895         return 1;
896       }
897     }
898
899   iret = interpret_CSA_move( ptree, &move, str_move );
900   if ( iret < 0 ) { return iret; }
901   move_evasion_pchk = 0;
902   iret = make_move_root( ptree, move, ( flag_rep | flag_history | flag_time
903                                         | flag_detect_hang ) );
904   if ( iret < 0 )
905       {
906
907 #if defined(CSA_LAN)
908         if ( sckt_csa != SCKT_NULL )
909           {
910             if ( move_evasion_pchk )
911               {
912                 str  = str_CSA_move( move_evasion_pchk );
913                 iret = sckt_out( sckt_csa, "%c%s\n",
914                                  ach_turn[Flip(root_turn)], str );
915                 if ( iret < 0 ) { return iret; }
916               }
917             return cmd_suspend();
918           }
919 #endif
920
921         if ( move_evasion_pchk )
922           {
923             str = str_CSA_move( move_evasion_pchk );
924 #if defined(CSASHOGI)
925             OutCsaShogi( "move%s\n", str );
926             return cmd_suspend();
927 #else
928             snprintf( str_message, SIZE_MESSAGE, "perpetual check (%c%s)",
929                       ach_turn[Flip(root_turn)], str );
930             str_error = str_message;
931             return -2;
932 #endif
933           }
934
935         return iret;
936       }
937
938   if ( lelapsed ) { adjust_time( (unsigned int)lelapsed, Flip(root_turn) ); }
939   Out( "  elapsed: b%u, w%u\n", sec_b_total, sec_w_total );
940
941 #if defined(CSA_LAN)
942   if ( sckt_csa != SCKT_NULL && ( game_status & flag_mated ) )
943     {
944       iret = sckt_out( sckt_csa, "%%TORYO\n" );
945       if ( iret < 0 ) { return iret; }
946     }
947 #endif
948
949   if ( ! ( game_status & mask_game_end ) )
950     {
951       iret = com_turn_start( ptree, 0 );
952       if ( iret < 0 ) { return iret; }
953     }
954
955   return 1;
956 }
957
958
959 static int CONV cmd_beep( char **lasts )
960 {
961   const char *str = strtok_r( NULL, str_delimiters, lasts );
962   if ( str == NULL )
963     {
964       str_error = str_bad_cmdline;
965       return -2;
966     }
967
968   if      ( ! strcmp( str, str_on )  ) {  game_status &= ~flag_nobeep; }
969   else if ( ! strcmp( str, str_off ) ) {  game_status |=  flag_nobeep; }
970   else {
971     str_error = str_bad_cmdline;
972     return -2;
973   }
974
975   return 1;
976 }
977
978
979 static int CONV cmd_peek( char **lasts )
980 {
981   const char *str = strtok_r( NULL, str_delimiters, lasts );
982
983   if ( str == NULL )
984     {
985       str_error = str_bad_cmdline;
986       return -2;
987     }
988
989   if      ( ! strcmp( str, str_on )  ) {  game_status &= ~flag_nopeek; }
990   else if ( ! strcmp( str, str_off ) ) {  game_status |=  flag_nopeek; }
991   else {
992     str_error = str_bad_cmdline;
993     return -2;
994   }
995
996   return 1;
997 }
998
999
1000 static int CONV cmd_stdout( char **lasts )
1001 {
1002   const char *str = strtok_r( NULL, str_delimiters, lasts );
1003
1004   if ( str == NULL )
1005     {
1006       str_error = str_bad_cmdline;
1007       return -2;
1008     }
1009
1010   if      ( ! strcmp( str, str_on )  ) {  game_status &= ~flag_nostdout; }
1011   else if ( ! strcmp( str, str_off ) ) {  game_status |=  flag_nostdout; }
1012   else {
1013     str_error = str_bad_cmdline;
1014     return -2;
1015   }
1016
1017   return 1;
1018 }
1019
1020
1021 static int CONV cmd_newlog( char **lasts )
1022 {
1023   const char *str = strtok_r( NULL, str_delimiters, lasts );
1024
1025   if ( str == NULL )
1026     {
1027       str_error = str_bad_cmdline;
1028       return -2;
1029     }
1030
1031   if      ( ! strcmp( str, str_on )  ) { game_status &= ~flag_nonewlog; }
1032   else if ( ! strcmp( str, str_off ) ) { game_status |=  flag_nonewlog; }
1033   else {
1034     str_error = str_bad_cmdline;
1035     return -2;
1036   }
1037
1038   return 1;
1039 }
1040
1041
1042 static int CONV cmd_ponder( char **lasts )
1043 {
1044   const char *str = strtok_r( NULL, str_delimiters, lasts );
1045
1046   if ( str == NULL )
1047     {
1048       str_error = str_bad_cmdline;
1049       return -2;
1050     }
1051
1052   if      ( ! strcmp( str, str_on )  ) { game_status &= ~flag_noponder; }
1053   else if ( ! strcmp( str, str_off ) )
1054     {
1055       if ( game_status & ( flag_pondering | flag_puzzling ) )
1056         {
1057           game_status |= flag_quit_ponder;
1058         }
1059       game_status |= flag_noponder;
1060     }
1061   else {
1062     str_error = str_bad_cmdline;
1063     return -2;
1064   }
1065
1066   return 1;
1067 }
1068
1069
1070 #if ! defined(NO_STDOUT)
1071 static int CONV cmd_stress( char **lasts )
1072 {
1073   const char *str = strtok_r( NULL, str_delimiters, lasts );
1074
1075   if ( str == NULL )
1076     {
1077       str_error = str_bad_cmdline;
1078       return -2;
1079     }
1080
1081   if      ( ! strcmp( str, str_on  ) ) { game_status &= ~flag_nostress; }
1082   else if ( ! strcmp( str, str_off ) ) { game_status |= flag_nostress; }
1083   else {
1084     str_error = str_bad_cmdline;
1085     return -2;
1086   }
1087
1088   return 1;
1089 }
1090 #endif
1091
1092
1093 static int CONV
1094 #if defined(MINIMUM)
1095 cmd_book( char **lasts )
1096 #else
1097 cmd_book( tree_t * restrict ptree, char **lasts )
1098 #endif
1099 {
1100   const char *str = strtok_r( NULL, str_delimiters, lasts );
1101   int iret = 1;
1102
1103   if ( str == NULL )
1104     {
1105       str_error = str_bad_cmdline;
1106       return -2;
1107     }
1108   if      ( ! strcmp( str, str_on ) )   { iret = book_on(); }
1109   else if ( ! strcmp( str, str_off ) )  { iret = book_off(); }
1110   else if ( ! strcmp( str, "narrow" ) ) { game_status |= flag_narrow_book; }
1111   else if ( ! strcmp( str, "wide" ) )   { game_status &= ~flag_narrow_book; }
1112 #if ! defined(MINIMUM)
1113   else if ( ! strcmp( str, "create" ) )
1114     {
1115       AbortDifficultCommand;
1116
1117       iret = book_create( ptree );
1118       if ( iret < 0 ) { return iret; }
1119
1120       iret = ini_game( ptree, &min_posi_no_handicap, flag_history,
1121                        NULL, NULL );
1122       if ( iret < 0 ) { return iret; }
1123
1124       iret = get_elapsed( &time_turn_start );
1125     }
1126 #endif
1127   else {
1128     str_error = str_bad_cmdline;
1129     iret = -2;
1130   }
1131
1132   return iret;
1133 }
1134
1135
1136 static int CONV cmd_display( tree_t * restrict ptree, char **lasts )
1137 {
1138   const char *str = strtok_r( NULL, str_delimiters, lasts );
1139   char *ptr;
1140   long l;
1141   int iret;
1142
1143   if ( str != NULL )
1144     {
1145       l = strtol( str, &ptr, 0 );
1146       if ( ptr == str )
1147         {
1148           str_error = str_bad_cmdline;
1149           return -2;
1150         }
1151       if      ( l == 1 ) { game_status &= ~flag_reverse; }
1152       else if ( l == 2 ) { game_status |= flag_reverse; }
1153       else {
1154         str_error = str_bad_cmdline;
1155         return -2;
1156       }
1157     }
1158   
1159   Out( "\n" );
1160   iret = out_board( ptree, stdout, 0, 0 );
1161   if ( iret < 0 ) { return iret; }
1162 #if ! defined(NO_LOGGING)
1163   iret = out_board( ptree, pf_log, 0, 0 );
1164   if ( iret < 0 ) { return iret; }
1165 #endif
1166   Out( "\n" );
1167
1168   return 1;
1169 }
1170
1171
1172 static int CONV cmd_ping( void )
1173 {
1174   OutCsaShogi( "pong\n" );
1175   Out( "pong\n" );
1176   return 1;
1177 }
1178
1179
1180 static int CONV cmd_hash( char **lasts )
1181 {
1182   const char *str = strtok_r( NULL, str_delimiters, lasts );
1183   char *ptr;
1184   long l;
1185
1186   if ( str == NULL )
1187     {
1188       str_error = str_bad_cmdline;
1189       return -2;
1190     }
1191
1192   l = strtol( str, &ptr, 0 );
1193   if ( ptr == str || l == LONG_MAX || l < 1 || l > 31 )
1194     {
1195       str_error = str_bad_cmdline;
1196       return -2;
1197     }
1198   
1199   AbortDifficultCommand;
1200   
1201   log2_ntrans_table = (int)l;
1202   memory_free( (void *)ptrans_table_orig );
1203   return ini_trans_table();
1204 }
1205
1206
1207 static int CONV cmd_limit( char **lasts )
1208 {
1209   const char *str = strtok_r( NULL, str_delimiters, lasts );
1210   char *ptr;
1211   long l1, l2, l3;
1212
1213   if ( str == NULL )
1214     {
1215       str_error = str_bad_cmdline;
1216       return -2;
1217     }
1218
1219   AbortDifficultCommand;
1220
1221   if ( ! strcmp( str, "depth" ) )
1222     {
1223       str = strtok_r( NULL, str_delimiters, lasts );
1224       if ( str == NULL )
1225         {
1226           str_error = str_bad_cmdline;
1227           return -2;
1228         }
1229       l1 = strtol( str, &ptr, 0 );
1230       if ( ptr == str || l1 == LONG_MAX || l1 < 1 )
1231         {
1232           str_error = str_bad_cmdline;
1233           return -2;
1234         }
1235       sec_limit_up = UINT_MAX;
1236       node_limit   = UINT64_MAX;
1237       depth_limit  = (int)l1;
1238     }
1239   else if ( ! strcmp( str, "nodes" ) )
1240     {
1241       str = strtok_r( NULL, str_delimiters, lasts );
1242       if ( str == NULL )
1243         {
1244           str_error = str_bad_cmdline;
1245           return -2;
1246         }
1247       l1 = strtol( str, &ptr, 0 );
1248       if ( ptr == str || l1 == LONG_MAX || l1 < 1 )
1249         {
1250           str_error = str_bad_cmdline;
1251           return -2;
1252         }
1253       sec_limit_up = UINT_MAX;
1254       depth_limit  = PLY_MAX;
1255       node_limit   = (uint64_t)l1;
1256     }
1257   else if ( ! strcmp( str, "time" ) )
1258     {
1259       str = strtok_r( NULL, str_delimiters, lasts );
1260       if ( str == NULL )
1261         {
1262           str_error = str_bad_cmdline;
1263           return -2;
1264         }
1265
1266       if ( ! strcmp( str, "extendable" ) )
1267         {
1268           game_status |= flag_time_extendable;
1269         }
1270       else if ( ! strcmp( str, "strict" ) )
1271         {
1272           game_status &= ~flag_time_extendable;
1273         }
1274       else {
1275         l1 = strtol( str, &ptr, 0 );
1276         if ( ptr == str || l1 == LONG_MAX || l1 < 0 )
1277           {
1278             str_error = str_bad_cmdline;
1279             return -2;
1280           }
1281
1282         str = strtok_r( NULL, str_delimiters, lasts );
1283         if ( str == NULL )
1284           {
1285             str_error = str_bad_cmdline;
1286             return -2;
1287           }
1288         l2 = strtol( str, &ptr, 0 );
1289         if ( ptr == str || l2 == LONG_MAX || l2 < 0 )
1290           {
1291             str_error = str_bad_cmdline;
1292             return -2;
1293           }
1294
1295         str = strtok_r( NULL, str_delimiters, lasts );
1296         if ( ! str ) { l3 = -1; }
1297         else {
1298           l3 = strtol( str, &ptr, 0 );
1299           if ( ptr == str || l3 >= PLY_MAX || l3 < -1 )
1300             {
1301               str_error = str_bad_cmdline;
1302               return -2;
1303             }
1304         }
1305
1306         if ( ! ( l1 | l2 ) ) { l2 = 1; }
1307
1308         depth_limit  = PLY_MAX;
1309         node_limit   = UINT64_MAX;
1310         sec_limit    = (unsigned int)l1 * 60U;
1311         sec_limit_up = (unsigned int)l2;
1312         if ( l3 == -1 ) { sec_limit_depth = UINT_MAX; }
1313         else            { sec_limit_depth = (unsigned int)l3; }
1314       }
1315     }
1316   else {
1317     str_error = str_bad_cmdline;
1318     return -2;
1319   }
1320
1321   return 1;
1322 }
1323
1324
1325 static int CONV
1326 cmd_read( tree_t * restrict ptree, char **lasts )
1327 {
1328   const char *str1 = strtok_r( NULL, str_delimiters, lasts );
1329   const char *str2 = strtok_r( NULL, str_delimiters, lasts );
1330   const char *str3 = strtok_r( NULL, str_delimiters, lasts );
1331   const char *str_tmp;
1332   FILE *pf_src, *pf_dest;
1333   char str_file[SIZE_FILENAME];
1334   char *ptr;
1335   unsigned int moves;
1336   long l;
1337   int iret, flag, c;
1338
1339   flag    = flag_history | flag_rep | flag_detect_hang;
1340   moves   = UINT_MAX;
1341   str_tmp = NULL;
1342
1343   if ( str1 == NULL )
1344     {
1345       str_error = str_bad_cmdline;
1346       return -2;
1347     }
1348
1349   if ( str2 != NULL )
1350     {
1351       if ( ! strcmp( str2, "t" ) ) { flag |= flag_time; }
1352       else if ( strcmp( str2, "nil" ) )
1353         {
1354           str_error = str_bad_cmdline;
1355           return -2;
1356         }
1357     }
1358
1359   if ( str3 != NULL )
1360     {
1361       l = strtol( str3, &ptr, 0 );
1362       if ( ptr == str3 || l == LONG_MAX || l < 1 )
1363         {
1364           str_error = str_bad_cmdline;
1365           return -2;
1366         }
1367       moves = (unsigned int)l - 1U;
1368     }
1369
1370   AbortDifficultCommand;
1371
1372   if ( ! strcmp( str1, "." ) )
1373     {
1374       str_tmp = "game.cs_";
1375
1376 #if defined(NO_LOGGING)
1377       strncpy( str_file, "game.csa", SIZE_FILENAME-1 );
1378 #else
1379       snprintf( str_file, SIZE_FILENAME, "%s/game%03d.csa",
1380                 str_dir_logs, record_num );
1381 #endif
1382       pf_dest = file_open( str_tmp, "w" );
1383       if ( pf_dest == NULL ) { return -2; }
1384
1385       pf_src = file_open( str_file, "r" );
1386       if ( pf_src == NULL )
1387         {
1388           file_close( pf_dest );
1389           return -2;
1390         }
1391
1392       while ( ( c = getc(pf_src) ) != EOF ) { putc( c, pf_dest ); }
1393
1394       iret = file_close( pf_src );
1395       if ( iret < 0 )
1396         {
1397           file_close( pf_dest );
1398           return iret;
1399         }
1400
1401       iret = file_close( pf_dest );
1402       if ( iret < 0 ) { return iret; }
1403
1404       flag |= flag_time;
1405       str1  = str_tmp;
1406     }
1407
1408   iret = read_record( ptree, str1, moves, flag );
1409   if ( iret < 0 ) { return iret; }
1410
1411   iret = get_elapsed( &time_turn_start );
1412   if ( iret < 0 ) { return iret; }
1413
1414   if ( str_tmp && remove( str_tmp ) )
1415     {
1416       out_warning( "remove() failed." );
1417       return -2;
1418     }
1419
1420   return 1;
1421 }
1422
1423
1424 static int CONV cmd_resign( tree_t * restrict ptree, char **lasts )
1425 {
1426   const char *str = strtok_r( NULL, str_delimiters, lasts );
1427   char *ptr;
1428   long l;
1429
1430   if ( str == NULL || *str == 'T' )
1431     {
1432       AbortDifficultCommand;
1433
1434       if ( game_status & mask_game_end ) { return 1; }
1435
1436       game_status |= flag_resigned;
1437       update_time( root_turn );
1438       out_CSA( ptree, &record_game, MOVE_RESIGN );
1439     }
1440   else {
1441     l = strtol( str, &ptr, 0 );
1442     if ( ptr == str || l == LONG_MAX || l < MT_CAP_PAWN )
1443       {
1444         str_error = str_bad_cmdline;
1445         return -2;
1446       }
1447     resign_threshold = (int)l;
1448   }
1449
1450   return 1;
1451 }
1452
1453
1454 static int CONV cmd_move( tree_t * restrict ptree, char **lasts )
1455 {
1456   const char *str = strtok_r( NULL, str_delimiters, lasts );
1457   char *ptr;
1458   long l;
1459   unsigned int move;
1460   int iret, i;
1461
1462   if ( game_status & mask_game_end )
1463     {
1464       str_error = str_game_ended;
1465       return -2;
1466     }
1467   
1468   AbortDifficultCommand;
1469
1470   if ( str == NULL )
1471     {
1472       if ( analyze_mode ) // [HGM] analyze: in analysis mode we cannot set the engine thinking (but perhaps play PV move?)
1473           {
1474             str_error = str_bad_cmdline;
1475             return -2;
1476           }
1477
1478       iret = get_elapsed( &time_turn_start );
1479       if ( iret < 0 ) { return iret; }
1480       
1481       return com_turn_start( ptree, 0 );
1482     }
1483
1484   l = strtol( str, &ptr, 0 );
1485   if ( str != ptr && l != LONG_MAX && l >= 1 && *ptr == '\0' )
1486     {
1487       if ( analyze_mode ) // [HGM] analyze: in analysis mode we cannot set the engine thinking
1488           {
1489             str_error = str_bad_cmdline;
1490             return -2;
1491           }
1492
1493       for ( i = 0; i < l; i += 1 )
1494         {
1495           if ( game_status & ( flag_move_now | mask_game_end ) ) { break; }
1496
1497           iret = get_elapsed( &time_turn_start );
1498           if ( iret < 0 ) { return iret; }
1499         
1500           iret = com_turn_start( ptree, 0 );
1501           if ( iret < 0 ) { return iret; }
1502         }
1503
1504       return 1;
1505     }
1506
1507   do {
1508     iret = interpret_CSA_move( ptree, &move, str );
1509     if ( iret < 0 ) { return iret; }
1510     
1511     iret = get_elapsed( &time_turn_start );
1512     if ( iret < 0 ) { return iret; }
1513     
1514     iret = make_move_root( ptree, move,
1515                            ( flag_history | flag_time | flag_rep
1516                              | flag_detect_hang ) );
1517     if ( iret < 0 ) { return iret; }
1518     
1519     str = strtok_r( NULL, str_delimiters, lasts );
1520
1521   } while ( str != NULL );
1522
1523   if ( analyze_mode ) return do_analyze ( ptree ); // [HGM] analyze: analysis should continue after feeding moves
1524   
1525   return 1;
1526 }
1527
1528
1529 static int CONV cmd_new( tree_t * restrict ptree, char **lasts )
1530 {
1531   const char *str1 = strtok_r( NULL, str_delimiters, lasts );
1532   const char *str2 = strtok_r( NULL, str_delimiters, lasts );
1533   const min_posi_t *pmp;
1534   min_posi_t min_posi;
1535   int iret;
1536
1537   AbortDifficultCommand;
1538
1539   start_pos = *lasts; move_ptr = 0; // [HGM] undo: remember start position
1540
1541   if ( str1 != NULL )
1542     {
1543       strncpy(start_data, str1, 511); // [HGM] undo: remember start position
1544       memset( &min_posi.asquare, empty, nsquare );
1545       min_posi.hand_black = min_posi.hand_white = 0;
1546       iret = read_board_rep1( str1, &min_posi );
1547       if ( iret < 0 ) { return iret; }
1548
1549       if ( str2 != NULL )
1550         {
1551           if      ( ! strcmp( str2, "-" ) ) { min_posi.turn_to_move = white; }
1552           else if ( ! strcmp( str2, "+" ) ) { min_posi.turn_to_move = black; }
1553           else {
1554             str_error = str_bad_cmdline;
1555             return -2;
1556           }
1557         }
1558       else { min_posi.turn_to_move = black; }
1559
1560       pmp = &min_posi;
1561     }
1562   else { pmp = &min_posi_no_handicap; }
1563
1564   iret = ini_game( ptree, pmp, flag_history, NULL, NULL );
1565   if ( iret < 0 ) { return iret; }
1566
1567   return get_elapsed( &time_turn_start );
1568 }
1569
1570
1571 static int CONV cmd_outmove( tree_t * restrict ptree )
1572 {
1573   const char *str_move;
1574   char buffer[256];
1575   unsigned int move_list[ MAX_LEGAL_MOVES ];
1576   int i, c, n;
1577
1578   AbortDifficultCommand;
1579
1580   if ( game_status & mask_game_end )
1581     {
1582       Out( "NO LEGAL MOVE\n" );
1583       DFPNOut( "NO LEGAL MOVE\n" );
1584       return 1;
1585     }
1586
1587   n = gen_legal_moves( ptree, move_list, 0 );
1588
1589   buffer[0]='\0';
1590   for ( c = i = 0; i < n; i += 1 )
1591     {
1592       str_move = str_CSA_move(move_list[i]);
1593
1594       if ( i && ( i % 10 ) == 0 )
1595         {
1596           Out( "%s\n", buffer );
1597           DFPNOut( "%s ", buffer );
1598           memcpy( buffer, str_move, 6 );
1599           c = 6;
1600         }
1601       else if ( i )
1602         {
1603           buffer[c] = ' ';
1604           memcpy( buffer + c + 1, str_move, 6 );
1605           c += 7;
1606         }
1607       else {
1608         memcpy( buffer + c, str_move, 6 );
1609         c += 6;
1610       }
1611       buffer[c] = '\0';
1612     }
1613   Out( "%s\n", buffer );
1614   DFPNOut( "%s\n", buffer );
1615
1616   return 1;
1617 }
1618
1619
1620 static int CONV cmd_problem( tree_t * restrict ptree, char **lasts )
1621 {
1622   const char *str = strtok_r( NULL, str_delimiters, lasts );
1623   char *ptr;
1624   long l;
1625   unsigned int nposition;
1626   int iret;
1627 #if defined(DFPN)
1628   int is_mate;
1629 #endif
1630
1631   AbortDifficultCommand;
1632
1633
1634 #if defined(DFPN)
1635   is_mate = 0;
1636   if ( str != NULL && ! strcmp( str, "mate" ) )
1637     {
1638       is_mate = 1;
1639       str     = strtok_r( NULL, str_delimiters, lasts );
1640     }
1641 #endif
1642
1643   if ( str != NULL )
1644     {
1645       l = strtol( str, &ptr, 0 );
1646       if ( ptr == str || l == LONG_MAX || l < 1 )
1647         {
1648           str_error = str_bad_cmdline;
1649           return -2;
1650         }
1651       nposition = (unsigned int)l;
1652     }
1653   else { nposition = UINT_MAX; }
1654
1655   
1656   iret = record_open( &record_problems, "problem.csa", mode_read, NULL, NULL );
1657   if ( iret < 0 ) { return iret; }
1658
1659 #if defined(DFPN)
1660   iret = is_mate ? solve_mate_problems( ptree, nposition )
1661                  : solve_problems( ptree, nposition );
1662 #else
1663   iret = solve_problems( ptree, nposition );
1664 #endif
1665
1666   if ( iret < 0 )
1667     {
1668       record_close( &record_problems );
1669       return iret;
1670     }
1671
1672   iret = record_close( &record_problems );
1673   if ( iret < 0 ) { return iret; }
1674
1675   return get_elapsed( &time_turn_start );
1676 }
1677
1678
1679 static int CONV cmd_quit( void )
1680 {
1681   game_status |= flag_quit;
1682   return 1;
1683 }
1684
1685
1686 static int CONV cmd_suspend( void )
1687 {
1688   if ( game_status & ( flag_pondering | flag_puzzling ) )
1689     {
1690       game_status |= flag_quit_ponder;
1691       return 2;
1692     }
1693   
1694   game_status |= flag_suspend;
1695   return 1;
1696 }
1697
1698
1699 static int CONV cmd_time( char **lasts )
1700 {
1701   const char *str = strtok_r( NULL, str_delimiters, lasts );
1702   char *ptr;
1703
1704   if ( str == NULL )
1705     {
1706       str_error = str_bad_cmdline;
1707       return -2;
1708     }
1709   else if ( ! strcmp( str, "response" ) )
1710     {
1711       long l;
1712       str = strtok_r( NULL, str_delimiters, lasts );
1713       if ( str == NULL )
1714         {
1715           str_error = str_bad_cmdline;
1716           return -2;
1717         }
1718       l = strtol( str, &ptr, 0 );
1719       if ( ptr == str || l == LONG_MAX || l < 0 || l > 1000 )
1720         {
1721           str_error = str_bad_cmdline;
1722           return -2;
1723         }
1724       time_response = (unsigned int)l;
1725       return 1;
1726     }
1727   else if ( ! strcmp( str, "remain" ) )
1728     {
1729       long l1, l2;
1730       
1731       str = strtok_r( NULL, str_delimiters, lasts );
1732       if ( str == NULL )
1733         {
1734           str_error = str_bad_cmdline;
1735           return -2;
1736         }
1737       l1 = strtol( str, &ptr, 0 );
1738       if ( ptr == str || l1 == LONG_MAX || l1 < 0 )
1739         {
1740           str_error = str_bad_cmdline;
1741           return -2;
1742         }
1743
1744       str = strtok_r( NULL, str_delimiters, lasts );
1745       if ( str == NULL )
1746         {
1747           str_error = str_bad_cmdline;
1748           return -2;
1749         }
1750       l2 = strtol( str, &ptr, 0 );
1751       if ( ptr == str || l2 == LONG_MAX || l2 < 0 )
1752         {
1753           str_error = str_bad_cmdline;
1754           return -2;
1755         }
1756
1757       if ( sec_limit_up == UINT_MAX )
1758         {
1759           str_error = str_bad_cmdline;
1760           return -2;
1761         }
1762
1763       return reset_time( (unsigned int)l1, (unsigned int)l2 );
1764     }
1765
1766   str_error = str_bad_cmdline;
1767   return -2;
1768 }
1769
1770
1771 #if !defined(MINIMUM)
1772 /* learn (ini|no-ini) steps games iterations tlp1 tlp2 */
1773 static int CONV cmd_learn( tree_t * restrict ptree, char **lasts )
1774 {
1775   const char *str1 = strtok_r( NULL, str_delimiters, lasts );
1776   const char *str2 = strtok_r( NULL, str_delimiters, lasts );
1777   const char *str3 = strtok_r( NULL, str_delimiters, lasts );
1778   const char *str4 = strtok_r( NULL, str_delimiters, lasts );
1779 #  if defined(TLP)
1780   const char *str5 = strtok_r( NULL, str_delimiters, lasts );
1781   const char *str6 = strtok_r( NULL, str_delimiters, lasts );
1782 #  endif
1783   char *ptr;
1784   long l;
1785   unsigned int max_games;
1786   int is_ini, nsteps, max_iterations, nworker1, nworker2, iret;
1787
1788   if ( str1 == NULL )
1789     {
1790       str_error = str_bad_cmdline;
1791       return -2;
1792     }
1793   if      ( ! strcmp( str1, "ini" ) )    { is_ini = 1; }
1794   else if ( ! strcmp( str1, "no-ini" ) ) { is_ini = 0; }
1795   else {
1796     str_error = str_bad_cmdline;
1797     return -2;
1798   }
1799
1800   max_games      = UINT_MAX;
1801   max_iterations = INT_MAX;
1802   nworker1 = nworker2 = nsteps = 1;
1803
1804   if ( str2 != NULL )
1805     {
1806       l = strtol( str2, &ptr, 0 );
1807       if ( ptr == str2 || l == LONG_MAX || l < 1 )
1808         {
1809           str_error = str_bad_cmdline;
1810           return -2;
1811         }
1812       nsteps = (int)l;
1813     }
1814
1815   if ( str3 != NULL )
1816     {
1817       l = strtol( str3, &ptr, 0 );
1818       if ( ptr == str3 || l == LONG_MAX || l == LONG_MIN )
1819         {
1820           str_error = str_bad_cmdline;
1821           return -2;
1822         }
1823       if ( l > 0 ) { max_games = (unsigned int)l; }
1824     }
1825
1826   if ( str4 != NULL )
1827     {
1828       l = strtol( str4, &ptr, 0 );
1829       if ( ptr == str4 || l == LONG_MAX || l == LONG_MIN )
1830         {
1831           str_error = str_bad_cmdline;
1832           return -2;
1833         }
1834       if ( l > 0 ) { max_iterations = (int)l; }
1835     }
1836
1837 #  if defined(TLP)
1838   if ( str5 != NULL )
1839     {
1840       l = strtol( str5, &ptr, 0 );
1841       if ( ptr == str5 || l > TLP_MAX_THREADS || l < 1 )
1842         {
1843           str_error = str_bad_cmdline;
1844           return -2;
1845         }
1846       nworker1 = (int)l;
1847     }
1848
1849   if ( str6 != NULL )
1850     {
1851       l = strtol( str6, &ptr, 0 );
1852       if ( ptr == str6 || l > TLP_MAX_THREADS || l < 1 )
1853         {
1854           str_error = str_bad_cmdline;
1855           return -2;
1856         }
1857       nworker2 = (int)l;
1858     }
1859 #  endif
1860
1861   AbortDifficultCommand;
1862
1863   log2_ntrans_table = 12;
1864
1865   memory_free( (void *)ptrans_table_orig );
1866
1867   iret = ini_trans_table();
1868   if ( iret < 0 ) { return iret; }
1869
1870   iret = learn( ptree, is_ini, nsteps, max_games, max_iterations,
1871                 nworker1, nworker2 );
1872   if ( iret < 0 ) { return -1; }
1873
1874   iret = ini_game( ptree, &min_posi_no_handicap, flag_history, NULL, NULL );
1875   if ( iret < 0 ) { return -1; }
1876
1877   iret = get_elapsed( &time_turn_start );
1878   if ( iret < 0 ) { return iret; }
1879
1880   return 1;
1881 }
1882 #endif /* MINIMUM */
1883
1884
1885 #if defined(MPV)
1886 static int CONV cmd_mpv( tree_t * restrict ptree, char **lasts )
1887 {
1888   const char *str = strtok_r( NULL, str_delimiters, lasts );
1889   char *ptr;
1890   long l;
1891
1892   if ( str == NULL )
1893     {
1894       str_error = str_bad_cmdline;
1895       return -2;
1896     }
1897   else if ( ! strcmp( str, "num" ) )
1898     {
1899       str = strtok_r( NULL, str_delimiters, lasts );
1900       if ( str == NULL )
1901         {
1902           str_error = str_bad_cmdline;
1903           return -2;
1904         }
1905       l = strtol( str, &ptr, 0 );
1906       if ( ptr == str || l == LONG_MAX || l < 1 || l > MPV_MAX_PV )
1907         {
1908           str_error = str_bad_cmdline;
1909           return -2;
1910         }
1911
1912       AbortDifficultCommand;
1913
1914       mpv_num = (int)l;
1915
1916       if ( analyze_mode ) return do_analyze ( ptree ); // [HGM] analyze: analysis should continue changing num
1917
1918       return 1;
1919     }
1920   else if ( ! strcmp( str, "width" ) )
1921     {
1922       str = strtok_r( NULL, str_delimiters, lasts );
1923       if ( str == NULL )
1924         {
1925           str_error = str_bad_cmdline;
1926           return -2;
1927         }
1928       l = strtol( str, &ptr, 0 );
1929       if ( ptr == str || l == LONG_MAX || l < MT_CAP_PAWN )
1930         {
1931           str_error = str_bad_cmdline;
1932           return -2;
1933         }
1934
1935       AbortDifficultCommand;
1936
1937       mpv_width = (int)l;
1938
1939       if ( analyze_mode ) return do_analyze ( ptree ); // [HGM] analyze: analysis should continue after changing width
1940
1941       return 1;
1942     }
1943
1944   str_error = str_bad_cmdline;
1945   return -2;
1946 }
1947 #endif
1948
1949
1950 #if defined(DFPN)
1951 static int CONV cmd_dfpn( tree_t * restrict ptree, char **lasts )
1952 {
1953   const char *str = strtok_r( NULL, str_delimiters, lasts );
1954
1955   if ( str == NULL )
1956     {
1957       str_error = str_bad_cmdline;
1958       return -2;
1959     }
1960   else if ( ! strcmp( str, "hash" ) )
1961     {
1962       char *ptr;
1963       long l;
1964
1965       str = strtok_r( NULL, str_delimiters, lasts );
1966       if ( str == NULL )
1967         {
1968           str_error = str_bad_cmdline;
1969           return -2;
1970         }
1971       l = strtol( str, &ptr, 0 );
1972       if ( ptr == str || l == LONG_MAX || l < 1 )
1973         {
1974           str_error = str_bad_cmdline;
1975           return -2;
1976         }
1977
1978       AbortDifficultCommand;
1979
1980       dfpn_hash_log2 = (unsigned int)l;
1981       return dfpn_ini_hash();
1982     }
1983   else if ( ! strcmp( str, "go" ) )
1984     {
1985       AbortDifficultCommand;
1986
1987       return dfpn( ptree, root_turn, 1 );
1988     }
1989   else if ( ! strcmp( str, "connect" ) )
1990     {
1991       char str_addr[256];
1992       char str_id[256];
1993       char *ptr;
1994       long l;
1995       int port;
1996
1997       str = strtok_r( NULL, str_delimiters, lasts );
1998       if ( ! str || ! strcmp( str, "." ) ) { str = "127.0.0.1"; }
1999       strncpy( str_addr, str, 255 );
2000       str_addr[255] = '\0';
2001
2002       str = strtok_r( NULL, str_delimiters, lasts );
2003       if ( ! str || ! strcmp( str, "." ) ) { str = "4083"; }
2004       l = strtol( str, &ptr, 0 );
2005       if ( ptr == str || l == LONG_MAX || l < 0 || l > USHRT_MAX )
2006         {
2007           str_error = str_bad_cmdline;
2008           return -2;
2009         }
2010       port = (int)l;
2011
2012       str = strtok_r( NULL, str_delimiters, lasts );
2013       if ( ! str || ! strcmp( str, "." ) ) { str = "bonanza1"; }
2014       strncpy( str_id, str, 255 );
2015       str_id[255] = '\0';
2016
2017       AbortDifficultCommand;
2018       
2019       dfpn_sckt = sckt_connect( str_addr, port );
2020       if ( dfpn_sckt == SCKT_NULL ) { return -2; }
2021
2022       str_buffer_cmdline[0] = '\0';
2023       DFPNOut( "Worker: %s\n", str_id );
2024
2025       return 1;
2026     }
2027
2028   str_error = str_bad_cmdline;
2029   return -2;
2030 }
2031 #endif
2032
2033
2034 #if defined(TLP)
2035 static int CONV cmd_thread( char **lasts )
2036 {
2037   const char *str = strtok_r( NULL, str_delimiters, lasts );
2038
2039   if ( str == NULL )
2040     {
2041       str_error = str_bad_cmdline;
2042       return -2;
2043     }
2044   else if ( ! strcmp( str, "num" ) )
2045     {
2046       char *ptr;
2047       long l;
2048
2049       str = strtok_r( NULL, str_delimiters, lasts );
2050       if ( str == NULL )
2051         {
2052           str_error = str_bad_cmdline;
2053           return -2;
2054         }
2055       l = strtol( str, &ptr, 0 );
2056       if ( ptr == str || l == LONG_MAX || l < 1 || l > TLP_MAX_THREADS )
2057         {
2058           str_error = str_bad_cmdline;
2059           return -2;
2060         }
2061
2062       TlpEnd();
2063
2064       tlp_max = (int)l;
2065
2066       if ( game_status & ( flag_thinking | flag_pondering | flag_puzzling ) )
2067         {
2068           return tlp_start();
2069         }
2070       return 1;
2071     }
2072
2073   str_error = str_bad_cmdline;
2074   return -2;
2075 }
2076 #endif
2077
2078
2079 #if defined(DFPN_CLIENT)
2080 static int CONV cmd_dfpn_client( tree_t * restrict ptree, char **lasts )
2081 {
2082   const char *str;
2083   char *ptr;
2084   int iret;
2085
2086   AbortDifficultCommand;
2087
2088   str = strtok_r( NULL, str_delimiters, lasts );
2089   if ( ! str || ! strcmp( str, "." ) ) { str = "127.0.0.1"; }
2090   strncpy( dfpn_client_str_addr, str, 255 );
2091   dfpn_client_str_addr[255] = '\0';
2092
2093   str = strtok_r( NULL, str_delimiters, lasts );
2094   if ( ! str || ! strcmp( str, "." ) ) { str = "4083"; }
2095   dfpn_client_port = strtol( str, &ptr, 0 );
2096   if ( ptr == str || dfpn_client_port == LONG_MAX || dfpn_client_port < 0
2097        || dfpn_client_port > USHRT_MAX )
2098     {
2099       str_error = str_bad_cmdline;
2100       return -2;
2101     }
2102
2103   Out( "DFPN Server: %s %d\n", dfpn_client_str_addr, dfpn_client_port );
2104
2105   iret = ini_game( ptree, &min_posi_no_handicap, flag_history, NULL, NULL );
2106   if ( iret < 0 ) { return iret; }
2107
2108   if ( dfpn_client_sckt == SCKT_NULL )
2109     {
2110       str_error = "Check network status.";
2111       return -1;
2112     }
2113
2114   return get_elapsed( &time_turn_start );
2115 }
2116 #endif
2117
2118
2119 #if defined(CSA_LAN)
2120 static int CONV cmd_connect( tree_t * restrict ptree, char **lasts )
2121 {
2122   const char *str;
2123   char *ptr;
2124   long max_games;
2125
2126   str = strtok_r( NULL, str_delimiters, lasts );
2127   if ( ! str || ! strcmp( str, "." ) ) { str = "gserver.computer-shogi.org"; }
2128   strncpy( client_str_addr, str, 255 );
2129   client_str_addr[255] = '\0';
2130
2131   str = strtok_r( NULL, str_delimiters, lasts );
2132   if ( ! str || ! strcmp( str, "." ) ) { str = "4081"; }
2133   client_port = strtol( str, &ptr, 0 );
2134   if ( ptr == str || client_port == LONG_MAX || client_port < 0
2135        || client_port > USHRT_MAX )
2136     {
2137       str_error = str_bad_cmdline;
2138       return -2;
2139     }
2140
2141   str = strtok_r( NULL, str_delimiters, lasts );
2142   if ( ! str || ! strcmp( str, "." ) ) { str = "bonanza_test"; }
2143   strncpy( client_str_id, str, 255 );
2144   client_str_id[255] = '\0';
2145
2146   str = strtok_r( NULL, " \t", lasts );
2147   if ( ! str || ! strcmp( str, "." ) ) { str = "bonanza_test"; }
2148   strncpy( client_str_pwd, str, 255 );
2149   client_str_pwd[255] = '\0';
2150
2151   str = strtok_r( NULL, str_delimiters, lasts );
2152   if ( ! str || ! strcmp( str, "." ) ) { client_max_game = INT_MAX; }
2153   else {
2154     max_games = strtol( str, &ptr, 0 );
2155     if ( ptr == str || max_games == LONG_MAX || max_games < 1 )
2156     {
2157       str_error = str_bad_cmdline;
2158       return -2;
2159     }
2160     client_max_game = max_games;
2161   }
2162
2163   AbortDifficultCommand;
2164
2165   client_ngame          = 0;
2166
2167   return client_next_game( ptree, client_str_addr, (int)client_port );
2168 }
2169
2170
2171 static int CONV cmd_sendpv( char **lasts )
2172 {
2173   const char *str = strtok_r( NULL, str_delimiters, lasts );
2174
2175   if ( str == NULL )
2176     {
2177       str_error = str_bad_cmdline;
2178       return -2;
2179     }
2180
2181   if      ( ! strcmp( str, str_off ) ) {  game_status &= ~flag_sendpv; }
2182   else if ( ! strcmp( str, str_on ) )  {  game_status |=  flag_sendpv; }
2183   else {
2184     str_error = str_bad_cmdline;
2185     return -2;
2186   }
2187
2188   return 1;
2189 }
2190 #endif
2191
2192
2193 #if defined(MNJ_LAN)
2194 /* mnj sd seed addr port name factor stable_depth */
2195 static int CONV cmd_mnj( char **lasts )
2196 {
2197   char client_str_addr[256];
2198   char client_str_id[256];
2199   const char *str;
2200   char *ptr;
2201   unsigned int seed;
2202   long l;
2203   int client_port, sd;
2204   double factor;
2205
2206   str = strtok_r( NULL, str_delimiters, lasts );
2207   if ( ! str )
2208     {
2209       str_error = str_bad_cmdline;
2210       return -2;
2211     }
2212   l = strtol( str, &ptr, 0 );
2213   if ( ptr == str || l == LONG_MAX || l < 0 )
2214     {
2215       str_error = str_bad_cmdline;
2216       return -2;
2217     }
2218   sd = (int)l;
2219
2220
2221   str = strtok_r( NULL, str_delimiters, lasts );
2222   if ( ! str )
2223     {
2224       str_error = str_bad_cmdline;
2225       return -2;
2226     }
2227   l = strtol( str, &ptr, 0 );
2228   if ( ptr == str || l == LONG_MAX || l < 0 )
2229     {
2230       str_error = str_bad_cmdline;
2231       return -2;
2232     }
2233   seed = (unsigned int)l;
2234
2235
2236   str = strtok_r( NULL, str_delimiters, lasts );
2237   if ( ! str || ! strcmp( str, "." ) ) { str = "localhost"; }
2238   strncpy( client_str_addr, str, 255 );
2239   client_str_addr[255] = '\0';
2240
2241
2242   str = strtok_r( NULL, str_delimiters, lasts );
2243   if ( ! str || ! strcmp( str, "." ) ) { str = "4082"; }
2244   l = strtol( str, &ptr, 0 );
2245   if ( ptr == str || l == LONG_MAX || l < 0 || l > USHRT_MAX )
2246     {
2247       str_error = str_bad_cmdline;
2248       return -2;
2249     }
2250   client_port = (int)l;
2251
2252
2253   str = strtok_r( NULL, str_delimiters, lasts );
2254   if ( ! str || ! strcmp( str, "." ) ) { str = "bonanza1"; }
2255   strncpy( client_str_id, str, 255 );
2256   client_str_id[255] = '\0';
2257
2258   str = strtok_r( NULL, str_delimiters, lasts );
2259   if ( ! str || ! strcmp( str, "." ) ) { str = "1.0"; }
2260   factor = strtod( str, &ptr );
2261   if ( ptr == str || factor < 0.0 )
2262     {
2263       str_error = str_bad_cmdline;
2264       return -2;
2265     }
2266
2267   str = strtok_r( NULL, str_delimiters, lasts );
2268   if ( ! str || ! strcmp( str, "." ) ) { l = -1; }
2269   else {
2270     l = strtol( str, &ptr, 0 );
2271     if ( ptr == str || l == LONG_MAX )
2272       {
2273         str_error = str_bad_cmdline;
2274         return -2;
2275       }
2276   }
2277   if ( l <= 0 ) { mnj_depth_stable = INT_MAX; }
2278   else          { mnj_depth_stable = (int)l; }
2279
2280   AbortDifficultCommand;
2281
2282   resign_threshold  = 65535;
2283   game_status      |= ( flag_noponder | flag_noprompt );
2284   if ( mnj_reset_tbl( sd, seed ) < 0 ) { return -1; }
2285
2286   sckt_mnj = sckt_connect( client_str_addr, (int)client_port );
2287   if ( sckt_mnj == SCKT_NULL ) { return -2; }
2288
2289   str_buffer_cmdline[0] = '\0';
2290
2291   Out( "Sending my name %s", client_str_id );
2292   MnjOut( "%s %g final%s\n", client_str_id, factor,
2293           ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
2294
2295   return cmd_suspend();
2296 }
2297 #endif
2298
2299