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