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