214c78b5e01b8538e16cdc5625d45dc31a972e89
[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 cmd_book( char **lasts );
25 #else
26 #  define CmdBook(x,y) cmd_book(x,y);
27 static int cmd_learn( tree_t * restrict ptree, char **lasts );
28 static int cmd_book( tree_t * restrict ptree, char **lasts );
29 #endif
30
31 #if ! defined(NO_STDOUT)
32 static int cmd_stress( char **lasts );
33 #endif
34
35 #if defined(DEKUNOBOU)
36 static int cmd_dek( char **lasts );
37 #endif
38
39 #if defined(CSA_LAN)
40 static int proce_csalan( tree_t * restrict ptree );
41 static int cmd_connect( tree_t * restrict ptree, char **lasts );
42 #endif
43
44 #if defined(MNJ_LAN)
45 static int proce_mnj( tree_t * restrict ptree );
46 static int cmd_mnj( tree_t * restrict ptree, char **lasts );
47 static int cmd_mnjmove( tree_t * restrict ptree, char **lasts, int is_alter );
48 #endif
49
50 #if defined(TLP)
51 static int cmd_thread( char **lasts );
52 #endif
53
54 #if defined(MPV)
55 static int cmd_mpv( char **lasts );
56 #endif
57
58 static int proce_cui( tree_t * restrict ptree );
59 static int cmd_usrmove( tree_t * restrict ptree, const char *str_move,
60                         char **last );
61 static int cmd_move_now( void );
62 static int cmd_ponder( char **lasts );
63 static int cmd_limit( char **lasts );
64 static int cmd_quit( void );
65 static int cmd_beep( char **lasts );
66 static int cmd_peek( char **lasts );
67 static int cmd_hash( char **lasts );
68 static int cmd_ping( void );
69 static int cmd_suspend( void );
70 static int cmd_problem( tree_t * restrict ptree, char **lasts );
71 static int cmd_display( tree_t * restrict ptree, char **lasts );
72 static int cmd_move( tree_t * restrict ptree, char **lasts );
73 static int cmd_new( tree_t * restrict ptree, char **lasts );
74 static int cmd_read( tree_t * restrict ptree, char **lasts );
75 static int cmd_resign( tree_t * restrict ptree, char **lasts );
76 static int cmd_time( char **lasts );
77 static int cmd_undo( tree_t * restrict ptree );    // [HGM] undo
78 static int is_move( const char *str );
79
80
81 int
82 procedure( tree_t * restrict ptree )
83 {
84 #if defined(CSA_LAN)
85   if ( sckt_csa != SCKT_NULL ) { return proce_csalan( ptree ); }
86 #endif
87 #if defined(MNJ_LAN)
88   if ( sckt_mnj != SCKT_NULL ) { return proce_mnj( ptree ); }
89 #endif
90
91   return proce_cui( ptree );
92 }
93
94 char *start_pos, start_data[512]; // [HGM] undo: for remembering start position
95 int move_list[1024], move_ptr;
96
97 #ifdef XBOARD
98 #define IF(X) else if(!strcmp(command, X))
99
100 int myTime, hisTime, movesPerSession, inc, plyNr;
101 char xboard_mode;
102
103 static void
104 SetTimes(void)
105 { // set white and black times from own and opponent time.
106   int moves;
107   if(movesPerSession <= 0) moves = 35; else {
108     moves = - plyNr/2;
109     while(moves <= 0) moves += movesPerSession;
110   }
111   time_limit = (myTime-inc-30)/(moves+2) + inc;
112   time_max_limit = 3*time_limit;
113   if(time_max_limit > myTime - 30)time_max_limit = myTime - 30; // keep 0.3 sec margin, as Bonanza reads the clock infrequently
114   time_limit *= 10; // msec
115   time_max_limit *= 10;
116 Out("# moves=%d, time=%d inc=%d t=%d, max=%d\n", moves, myTime, inc, time_limit, time_max_limit);
117 }
118
119 static int
120 proce_xboard(char *line, const char *command, tree_t * restrict ptree)
121 { // [HGM] added to make Bonanza.exe a native WinBoard engine
122   int value = -100000;
123   static char forceMode = 0;
124   sscanf(line + strlen(command) + 1, "%d", &value);
125 Out("# command = '%s'\n", line);
126   if(0) ;
127   IF("protover") { Out("feature variants=\"shogi\" usermove=1 myname=\"Bonanza " BNZ_VER
128                        "\" memory=1 smp=1 debug=1 colors=0 setboard=1 ping=1 done=1\n"); }
129   IF("new")      { forceMode = plyNr = 0; SetTimes(); return 0; }
130   IF("easy")     { strcpy(line, "ponder off"); return 0; }
131   IF("hard")     { strcpy(line, "ponder on");  return 0; }
132   IF("post")     { ; }
133   IF("nopost")   { ; }
134   IF("time")     { sscanf(line+5, "%d", &myTime); }
135   IF("otim")     { sscanf(line+5, "%d", &hisTime); }
136   IF("force")    { forceMode = 1; }
137   IF("go")       { forceMode = 0; SetTimes(); plyNr++; strcpy(line, "move"); return 0; }
138   IF("memory")   { ; }
139   IF("cores")    { sprintf(line, "tlp num %d", value); return 0; }
140   IF("sd")       { sprintf(line, "limit depth %d", value); return 0; }
141   IF("st")       { ; }
142   IF("quit")     { return 0; }
143   IF("analyze")  { ; }
144   IF("exit")     { ; }
145   IF("variant")  { /* ignore, since it must be Shogi */; }
146   IF("setboard") { ; }
147   IF("option")   { ; }
148   IF("level")    { int min, sec; float fsec=0.;
149                    if(sscanf(line+6, "%d %d:%d %f", &movesPerSession, &min, &sec, &fsec) != 4)
150                       sscanf(line+6, "%d %d %f", &movesPerSession, &min, &fsec);
151                    min = 60*min + sec; myTime = hisTime = 100*min; inc = 100 * fsec;
152                  }
153   IF("usermove") { char fromX=line[9], fromY=line[10], toX=line[11], toY=line[12], promo=line[13];
154                    int from;
155 {int i,j;for(i=0;i<81;i+=9){printf("# ");for(j=0;j<9;j++)printf(" %3d", BOARD[i+j]);printf("\n");}}
156                    if(forceMode) strcpy(line, "move "), line += 5; else plyNr++, SetTimes();
157                    if(fromY == '@') { // drop
158                        if(fromX >= 'a') fromX += 'A' - 'a';
159                        switch(fromX) { // encode piece
160                          case 'P': fromX = pawn;   break;
161                          case 'L': fromX = lance;  break;
162                          case 'N': fromX = knight; break;
163                          case 'S': fromX = silver; break;
164                          case 'G': fromX = gold;   break;
165                          case 'B': fromX = bishop; break;
166                          case 'R': fromX = rook;   break;
167                        }
168                        sprintf(line, "00%c%c%s", 'a'+'9'-toX, '1'+'9'-toY, astr_table_piece[(int)fromX]);
169                    } else {
170                        from = ('9' - fromY)*9 + (fromX - 'a');
171 Out("# from=%d\n",from);
172                        sprintf(line, "%c%c%c%c%s", 'a'+'9'-fromX, '1'+'9'-fromY, 'a'+'9'-toX, '1'+'9'-toY,
173                                  astr_table_piece[abs(BOARD[from]) + (promo == '+' ? promote : 0)]);
174                    }
175                    plyNr++;
176                    return 0;
177                  }
178   IF("undo")     { ; }
179   IF("remove")   { ; }
180   IF("ping")     { Out("pong %d\n", value); }
181   return 1;
182 }
183 #endif
184
185 static int
186 proce_cui( tree_t * restrict ptree )
187 {
188   const char *token;
189   char *last;
190
191   token = strtok_r( str_cmdline, str_delimiters, &last );
192
193   if ( token == NULL || *token == '#' ) { return 1; }
194 #ifdef XBOARD
195   { 
196     if(xboard_mode) {
197       if( proce_xboard(str_cmdline, token, ptree) )  return 1; // command already processed
198       Out("# translated command '%s'\n", str_cmdline);         // command translated for processing by Bonanza
199       token = strtok_r( str_cmdline, str_delimiters, &last );  // redo parsing
200     } else
201     if ( ! strcmp( token, "xboard" ) )  { xboard_mode = 1; game_status |= flag_noprompt; return 1; }
202   }
203 #endif
204   if ( is_move( token ) ) { return cmd_usrmove( ptree, token, &last ); }
205   if ( ! strcmp( token, "s" ) )         { return cmd_move_now(); }
206   if ( ! strcmp( token, "beep" ) )      { return cmd_beep( &last); }
207   if ( ! strcmp( token, "book" ) )      { return CmdBook( ptree, &last ); }
208   if ( ! strcmp( token, "display" ) )   { return cmd_display( ptree, &last ); }
209   if ( ! strcmp( token, "hash" ) )      { return cmd_hash( &last ); }
210   if ( ! strcmp( token, "limit" ) )     { return cmd_limit( &last ); }
211   if ( ! strcmp( token, "move" ) )      { return cmd_move( ptree, &last ); }
212   if ( ! strcmp( token, "new" ) )       { return cmd_new( ptree, &last ); }
213   if ( ! strcmp( token, "peek" ) )      { return cmd_peek( &last ); }
214   if ( ! strcmp( token, "ping" ) )      { return cmd_ping(); }
215   if ( ! strcmp( token, "ponder" ) )    { return cmd_ponder( &last ); }
216   if ( ! strcmp( token, "problem" ) )   { return cmd_problem( ptree, &last ); }
217   if ( ! strcmp( token, "quit" ) )      { return cmd_quit(); }
218   if ( ! strcmp( token, "read" ) )      { return cmd_read( ptree, &last ); }
219   if ( ! strcmp( token, "resign" ) )    { return cmd_resign( ptree, &last ); }
220   if ( ! strcmp( token, "suspend" ) )   { return cmd_suspend(); }
221   if ( ! strcmp( token, "time" ) )      { return cmd_time( &last ); }
222   if ( ! strcmp( token, "undo" ) )      { return cmd_undo( ptree ); }    // [HGM] undo
223 #if defined(CSA_LAN)
224   if ( ! strcmp( token, "connect" ) )   { return cmd_connect( ptree, &last ); }
225 #endif
226 #if defined(MNJ_LAN)
227   if ( ! strcmp( token, "mnj" ) )       { return cmd_mnj( ptree, &last ); }
228 #endif
229 #if defined(DEKUNOBOU)
230   if ( ! strcmp( token, "dekunobou" ) ) { return cmd_dek( &last ); }
231 #endif
232 #if defined(MPV)
233   if ( ! strcmp( token, "mpv" ) )       { return cmd_mpv( &last ); }
234 #endif
235 #if defined(TLP)
236   if ( ! strcmp( token, "tlp" ) )       { return cmd_thread( &last ); }
237 #endif
238 #if ! defined(NO_STDOUT)
239   if ( ! strcmp( token, "stress" ) )    { return cmd_stress( &last ); }
240 #endif
241 #if ! defined(MINIMUM)
242   if ( ! strcmp( token, "learn" ) )     { return cmd_learn( ptree, &last ); }
243 #endif
244
245   str_error = str_bad_cmdline;
246   return -2;
247 }
248
249
250 #if defined(CSA_LAN)
251 static int
252 proce_csalan( tree_t * restrict ptree )
253 {
254   const char *token;
255   char *last;
256
257   token = strtok_r( str_cmdline, str_delimiters, &last );
258     
259   if ( token == NULL ) { return 1; }
260   if ( *token == ach_turn[client_turn] && is_move( token+1 ) )
261     {
262       char *ptr;
263       long l;
264
265       token = strtok_r( NULL, str_delimiters, &last );
266       if ( token == NULL || *token != 'T' )
267         {
268           str_error = str_bad_cmdline;
269           return -1;
270         }
271       
272       l = strtol( token+1, &ptr, 0 );
273       if ( token+1 == ptr || l == LONG_MAX || l < 1 )
274         {
275           str_error = str_bad_cmdline;
276           return -1;
277         }
278
279       adjust_time( (unsigned int)l, client_turn );
280       Out( "  elapsed: b%u, w%u\n", sec_b_total, sec_w_total );
281       return 1;
282     }
283   if ( *token == ach_turn[Flip(client_turn)] && is_move( token+1 ) )
284     {
285       return cmd_usrmove( ptree, token+1, &last );
286     }
287   if ( ! strcmp( token, str_resign ) ) { return cmd_resign( ptree, &last ); }
288   if ( ! strcmp( token, "#WIN" )
289        || ! strcmp( token, "#LOSE" )
290        || ! strcmp( token, "#DRAW" )
291        || ! strcmp( token, "#CHUDAN" ) )
292     {
293       if ( game_status & ( flag_thinking | flag_pondering | flag_puzzling ) )
294         {
295           game_status |= flag_suspend;
296           return 2;
297         }
298       
299       ShutdownClient;
300       
301       if ( client_ngame == client_max_game ) { return cmd_quit(); }
302
303       return client_next_game( ptree, client_str_addr, (int)client_port );
304     }
305   
306   return 1;
307 }
308 #endif
309
310
311 #if defined(MNJ_LAN)
312 static int
313 proce_mnj( tree_t * restrict ptree )
314 {
315   const char *token;
316   char *last;
317   int iret;
318
319   token = strtok_r( str_cmdline, str_delimiters, &last );
320   if ( token == NULL ) { return 1; }
321
322   if ( ! strcmp( token, "new" ) )
323     {
324       iret = cmd_suspend();
325       if ( iret != 1 ) { return iret; }
326
327       mnj_posi_id = 0;
328       iret = cmd_new( ptree, &last );
329       if ( iret < 0 ) { return iret; }
330
331       return analyze( ptree );
332     }
333   if ( ! strcmp( token, "idle" ) )  { return cmd_suspend(); }
334   if ( ! strcmp( token, "alter" ) ) { return cmd_mnjmove( ptree, &last, 1 ); }
335   if ( ! strcmp( token, "move" ) )  { return cmd_mnjmove( ptree, &last, 0 ); }
336
337   str_error = str_bad_cmdline;
338   return -2;
339 }
340
341
342 static int
343 cmd_mnjmove( tree_t * restrict ptree, char **lasts, int is_alter )
344 {
345   const char *str1 = strtok_r( NULL, str_delimiters, lasts );
346   const char *str2 = strtok_r( NULL, str_delimiters, lasts );
347   char *ptr;
348   long lid;
349   unsigned int move;
350   int iret;
351
352   if ( sckt_mnj == SCKT_NULL ||  str1 == NULL || str2 == NULL )
353     {
354       str_error = str_bad_cmdline;
355       return -1;
356     }
357
358   lid = strtol( str2, &ptr, 0 );
359   if ( ptr == str2 || lid == LONG_MAX || lid < 1 )
360     {
361       str_error = str_bad_cmdline;
362       return -1;
363     }
364
365   AbortDifficultCommand;
366  
367   if ( is_alter ) { unmake_move_root( ptree, mnj_move_last ); };
368
369   iret = interpret_CSA_move( ptree, &move, str1 );
370   if ( iret < 0 ) { return iret; }
371     
372   iret = get_elapsed( &time_turn_start );
373   if ( iret < 0 ) { return iret; }
374
375   mnj_posi_id   = (int)lid;
376   mnj_move_last = move;
377
378   iret = make_move_root( ptree, move, ( flag_history | flag_time | flag_rep
379                                         | flag_detect_hang
380                                         | flag_rejections ) );
381   if ( iret < 0 ) { return iret; }
382   
383 #  if ! defined(NO_STDOUT)
384   iret = out_board( ptree, stdout, 0, 0 );
385   if ( iret < 0 ) { return iret; }
386 #  endif
387
388   return analyze( ptree );
389 }
390 #endif
391
392
393 static int
394 cmd_undo( tree_t * restrict ptree )
395 { // [HGM] undo: restart the game, and feed all moves except the last
396   int i, last = move_ptr;
397   char *p = start_data;
398   if( move_ptr <= 0 ) {
399     str_error = "undo past start of game ignored";
400     return -2;
401   }
402
403   AbortDifficultCommand;
404
405   last--;
406   cmd_new( ptree, &p );
407   for(i=0; i<last; i++) {
408     make_move_root( ptree, move_list[i], 0);
409   }
410   return 1;
411 }
412
413
414 static int
415 is_move( const char *str )
416 {
417   if ( isdigit( (int)str[0] ) && isdigit( (int)str[1] )
418        && isdigit( (int)str[2] ) && isdigit( (int)str[3] )
419        && isupper( (int)str[4] ) && isupper( (int)str[5] )
420        && str[6] == '\0' ) { return 1; }
421
422   return 0;
423 }
424
425
426 static int
427 cmd_move_now( void )
428 {
429   if ( game_status & flag_thinking ) { game_status |= flag_move_now; }
430
431   return 1;
432 }
433
434
435 static int
436 cmd_usrmove( tree_t * restrict ptree, const char *str_move, char **lasts )
437 {
438   const char *str;
439   char *ptr;
440   long lelapsed;
441   unsigned int move;
442   int iret;
443
444   if ( game_status & mask_game_end )
445     {
446       str_error = str_game_ended;
447       return -2;
448     }
449   
450   if ( game_status & flag_thinking )
451     {
452       str_error = str_busy_think;
453       return -2;
454     }
455
456   str = strtok_r( NULL, str_delimiters, lasts );
457   if ( str == NULL ) { lelapsed = 0; }
458   else {
459     if ( *str != 'T' )
460       {
461         str_error = str_bad_cmdline;
462         return -2;
463       }
464     str += 1;
465     lelapsed = strtol( str, &ptr, 0 );
466     if ( ptr == str || lelapsed == LONG_MAX || lelapsed < 1 )
467       {
468         str_error = str_bad_cmdline;
469         return -2;
470       }
471   }
472
473   if ( game_status & ( flag_pondering | flag_puzzling ) )
474     {
475       int i;
476
477       for ( i = 0; i < ponder_nmove; i++ )
478         {
479           if ( ! strcmp( str_move, str_CSA_move(ponder_move_list[i]) ) )
480             {
481               break;
482             }
483         }
484       if ( i == ponder_nmove )
485         {
486 #if defined(CSA_LAN)
487           if ( sckt_csa != SCKT_NULL ) { AbortDifficultCommand; }
488 #endif
489
490 #if defined(DEKUNOBOU)
491           if ( dek_ngame ) { AbortDifficultCommand; }
492 #endif
493
494 #if defined(CSASHOGI)
495           AbortDifficultCommand;
496 #else
497           str_error = str_illegal_move;
498           return -2;
499 #endif
500         }
501
502       if ( ( game_status & flag_puzzling )
503            || strcmp( str_move, str_CSA_move(ponder_move) ) )
504         {
505           ponder_move  = MOVE_PONDER_FAILED;
506           game_status |= flag_quit_ponder;
507           return 2;
508         }
509       else {
510         iret = renovate_time( Flip(root_turn) );
511         if ( iret < 0 ) { return iret; }
512         if ( lelapsed )
513           {
514             adjust_time( (unsigned int)lelapsed, Flip(root_turn) );
515           }
516
517         history_book_learn[ record_game.moves ].move_played = ponder_move;
518         history_book_learn[ record_game.moves ].hand_played
519           = ptree->rep_hand_list[ root_nrep-1 ];
520         history_book_learn[ record_game.moves ].key_played
521           = (unsigned int)ptree->rep_board_list[ root_nrep-1 ];
522
523         out_CSA( ptree, &record_game, ponder_move );
524
525         game_status      &= ~flag_pondering;
526         game_status      |= flag_thinking;
527         n_nobook_move    += 1;
528 #ifdef XBOARD
529       if(!xboard_mode)
530 #endif
531         set_search_limit_time( root_turn );
532
533         OutCsaShogi( "info ponder end\n" );
534
535         str = str_time_symple( time_turn_start - time_start );
536         Out( "    %6s          MOVE PREDICTION HIT\n"
537              "  elapsed: b%u, w%u\n", str, sec_b_total, sec_w_total );
538         return 1;
539       }
540     }
541
542   iret = interpret_CSA_move( ptree, &move, str_move );
543   if ( iret < 0 ) { return iret; }
544   move_evasion_pchk = 0;
545   iret = make_move_root( ptree, move, ( flag_rep | flag_history | flag_time
546                                         | flag_rejections
547                                         | flag_detect_hang ) );
548   if ( iret < 0 )
549       {
550
551 #if defined(CSA_LAN)
552         if ( sckt_csa != SCKT_NULL )
553           {
554             if ( move_evasion_pchk )
555               {
556                 str  = str_CSA_move( move_evasion_pchk );
557                 iret = sckt_out( sckt_csa, "%c%s\n",
558                                  ach_turn[Flip(root_turn)], str );
559                 if ( iret < 0 ) { return iret; }
560               }
561             return cmd_suspend();
562           }
563 #endif
564
565 #if defined(DEKUNOBOU)
566         if ( dek_ngame )
567           {
568             if ( move_evasion_pchk )
569               {
570                 dek_win += 1;
571                 OutDek( "%%TORYO\n" );
572               }
573             return cmd_suspend();
574           }
575 #endif
576
577         if ( move_evasion_pchk )
578           {
579             str = str_CSA_move( move_evasion_pchk );
580 #if defined(CSASHOGI)
581             OutCsaShogi( "move%s\n", str );
582             return cmd_suspend();
583 #else
584             snprintf( str_message, SIZE_MESSAGE, "perpetual check (%c%s)",
585                       ach_turn[Flip(root_turn)], str );
586             str_error = str_message;
587             return -2;
588 #endif
589           }
590
591         return iret;
592       }
593
594   if ( lelapsed ) { adjust_time( (unsigned int)lelapsed, Flip(root_turn) ); }
595   Out( "  elapsed: b%u, w%u\n", sec_b_total, sec_w_total );
596
597 #if defined(CSA_LAN)
598   if ( sckt_csa != SCKT_NULL && ( game_status & flag_mated ) )
599     {
600       iret = sckt_out( sckt_csa, "%%TORYO\n" );
601       if ( iret < 0 ) { return iret; }
602     }
603 #endif
604
605 #if defined(DEKUNOBOU)
606   if ( dek_ngame && ( game_status & flag_drawn ) ) { OutDek( "%%TORYO\n" ); }
607 #endif
608
609   if ( ! ( game_status & mask_game_end ) )
610     {
611       iret = com_turn_start( ptree, 0 );
612       if ( iret < 0 ) { return iret; }
613     }
614
615   return 1;
616 }
617
618
619 static int
620 cmd_beep( char **lasts )
621 {
622   const char *str = strtok_r( NULL, str_delimiters, lasts );
623   if ( str == NULL )
624     {
625       str_error = str_bad_cmdline;
626       return -2;
627     }
628
629   if      ( ! strcmp( str, str_on )  ) {  game_status &= ~flag_nobeep; }
630   else if ( ! strcmp( str, str_off ) ) {  game_status |=  flag_nobeep; }
631   else {
632     str_error = str_bad_cmdline;
633     return -2;
634   }
635
636   return 1;
637 }
638
639
640 static int
641 cmd_peek( char **lasts )
642 {
643   const char *str = strtok_r( NULL, str_delimiters, lasts );
644
645   if ( str == NULL )
646     {
647       str_error = str_bad_cmdline;
648       return -2;
649     }
650
651   if      ( ! strcmp( str, str_on )  ) {  game_status &= ~flag_nopeek; }
652   else if ( ! strcmp( str, str_off ) ) {  game_status |=  flag_nopeek; }
653   else {
654     str_error = str_bad_cmdline;
655     return -2;
656   }
657
658   return 1;
659 }
660
661
662 static int
663 cmd_ponder( char **lasts )
664 {
665   const char *str = strtok_r( NULL, str_delimiters, lasts );
666
667   if ( str == NULL )
668     {
669       str_error = str_bad_cmdline;
670       return -2;
671     }
672
673   if      ( ! strcmp( str, str_on )  ) {  game_status &= ~flag_noponder; }
674   else if ( ! strcmp( str, str_off ) )
675     {
676       if ( game_status & ( flag_pondering | flag_puzzling ) )
677         {
678           game_status |= flag_quit_ponder;
679         }
680       game_status |= flag_noponder;
681     }
682   else {
683     str_error = str_bad_cmdline;
684     return -2;
685   }
686
687   return 1;
688 }
689
690
691 #if ! defined(NO_STDOUT)
692 static int
693 cmd_stress( char **lasts )
694 {
695   const char *str = strtok_r( NULL, str_delimiters, lasts );
696
697   if ( str == NULL )
698     {
699       str_error = str_bad_cmdline;
700       return -2;
701     }
702
703   if      ( ! strcmp( str, str_on  ) ) { game_status &= ~flag_nostress; }
704   else if ( ! strcmp( str, str_off ) ) { game_status |= flag_nostress; }
705   else {
706     str_error = str_bad_cmdline;
707     return -2;
708   }
709
710   return 1;
711 }
712 #endif
713
714
715 static int
716 #if defined(MINIMUM)
717 cmd_book( char **lasts )
718 #else
719 cmd_book( tree_t * restrict ptree, char **lasts )
720 #endif
721 {
722   const char *str = strtok_r( NULL, str_delimiters, lasts );
723   int iret = 1;
724
725   if ( str == NULL )
726     {
727       str_error = str_bad_cmdline;
728       return -2;
729     }
730   if      ( ! strcmp( str, str_on ) )   { iret = book_on(); }
731   else if ( ! strcmp( str, str_off ) )  { iret = book_off(); }
732   else if ( ! strcmp( str, "narrow" ) ) { game_status |= flag_narrow_book; }
733   else if ( ! strcmp( str, "wide" ) )   { game_status &= ~flag_narrow_book; }
734 #if ! defined(MINIMUM)
735   else if ( ! strcmp( str, "create" ) )
736     {
737       AbortDifficultCommand;
738
739       iret = book_create( ptree );
740       if ( iret < 0 ) { return iret; }
741
742       iret = ini_game( ptree, &min_posi_no_handicap, flag_history,
743                        NULL, NULL );
744       if ( iret < 0 ) { return iret; }
745
746       iret = get_elapsed( &time_turn_start );
747     }
748 #endif
749   else {
750     str_error = str_bad_cmdline;
751     iret = -2;
752   }
753
754   return iret;
755 }
756
757
758 static int
759 cmd_display( tree_t * restrict ptree, char **lasts )
760 {
761   const char *str = strtok_r( NULL, str_delimiters, lasts );
762   char *ptr;
763   long l;
764   int iret;
765
766   if ( str != NULL )
767     {
768       l = strtol( str, &ptr, 0 );
769       if ( ptr == str )
770         {
771           str_error = str_bad_cmdline;
772           return -2;
773         }
774       if      ( l == 1 ) { game_status &= ~flag_reverse; }
775       else if ( l == 2 ) { game_status |= flag_reverse; }
776       else {
777         str_error = str_bad_cmdline;
778         return -2;
779       }
780     }
781   
782   Out( "\n" );
783   iret = out_board( ptree, stdout, 0, 0 );
784   if ( iret < 0 ) { return iret; }
785 #if ! defined(NO_LOGGING)
786   iret = out_board( ptree, pf_log, 0, 0 );
787   if ( iret < 0 ) { return iret; }
788 #endif
789   Out( "\n" );
790
791   return 1;
792 }
793
794
795 static int
796 cmd_ping( void )
797 {
798   OutCsaShogi( "pong\n" );
799   Out( "pong\n" );
800   return 1;
801 }
802
803
804 static int
805 cmd_hash( char **lasts )
806 {
807   const char *str = strtok_r( NULL, str_delimiters, lasts );
808   char *ptr;
809   long l;
810
811   if ( str == NULL )
812     {
813       str_error = str_bad_cmdline;
814       return -2;
815     }
816
817   if ( ! strcmp( str, "learn" ) )
818     {
819       str = strtok_r( NULL, str_delimiters, lasts );
820       if ( str != NULL && ! strcmp( str, str_on ) )
821         {
822           return hash_learn_on();
823         }
824       else if ( str != NULL && ! strcmp( str, str_off ) )
825         {
826           return hash_learn_off();
827         }
828 #if ! defined(MINIMUM)
829       else if ( str != NULL && ! strcmp( str, "create" ) )
830         {
831           return hash_learn_create();
832         }
833 #endif
834       else {
835         str_error = str_bad_cmdline;
836         return -2;
837       }
838     }
839
840   l = strtol( str, &ptr, 0 );
841   if ( ptr == str || l == LONG_MAX || l < 1 || l > 31 )
842     {
843       str_error = str_bad_cmdline;
844       return -2;
845     }
846   
847   AbortDifficultCommand;
848   
849   log2_ntrans_table = (int)l;
850   memory_free( (void *)ptrans_table_orig );
851   return ini_trans_table();
852 }
853
854
855 static int
856 cmd_limit( char **lasts )
857 {
858   const char *str = strtok_r( NULL, str_delimiters, lasts );
859   char *ptr;
860   long l1, l2, l3;
861
862   if ( str == NULL )
863     {
864       str_error = str_bad_cmdline;
865       return -2;
866     }
867
868   AbortDifficultCommand;
869
870   if ( ! strcmp( str, "depth" ) )
871     {
872       str = strtok_r( NULL, str_delimiters, lasts );
873       if ( str == NULL )
874         {
875           str_error = str_bad_cmdline;
876           return -2;
877         }
878       l1 = strtol( str, &ptr, 0 );
879       if ( ptr == str || l1 == LONG_MAX || l1 < 1 )
880         {
881           str_error = str_bad_cmdline;
882           return -2;
883         }
884       sec_limit_up = UINT_MAX;
885       node_limit   = UINT64_MAX;
886       depth_limit  = (int)l1;
887     }
888   else if ( ! strcmp( str, "nodes" ) )
889     {
890       str = strtok_r( NULL, str_delimiters, lasts );
891       if ( str == NULL )
892         {
893           str_error = str_bad_cmdline;
894           return -2;
895         }
896       l1 = strtol( str, &ptr, 0 );
897       if ( ptr == str || l1 == LONG_MAX || l1 < 1 )
898         {
899           str_error = str_bad_cmdline;
900           return -2;
901         }
902       sec_limit_up = UINT_MAX;
903       depth_limit  = PLY_MAX;
904       node_limit   = (uint64_t)l1;
905     }
906   else if ( ! strcmp( str, "time" ) )
907     {
908       str = strtok_r( NULL, str_delimiters, lasts );
909       if ( str == NULL )
910         {
911           str_error = str_bad_cmdline;
912           return -2;
913         }
914
915       if ( ! strcmp( str, "extendable" ) )
916         {
917           game_status |= flag_time_extendable;
918         }
919       else if ( ! strcmp( str, "strict" ) )
920         {
921           game_status &= ~flag_time_extendable;
922         }
923       else {
924         l1 = strtol( str, &ptr, 0 );
925         if ( ptr == str || l1 == LONG_MAX || l1 < 0 )
926           {
927             str_error = str_bad_cmdline;
928             return -2;
929           }
930
931         str = strtok_r( NULL, str_delimiters, lasts );
932         if ( str == NULL )
933           {
934             str_error = str_bad_cmdline;
935             return -2;
936           }
937         l2 = strtol( str, &ptr, 0 );
938         if ( ptr == str || l2 == LONG_MAX || l2 < 0 )
939           {
940             str_error = str_bad_cmdline;
941             return -2;
942           }
943
944         str = strtok_r( NULL, str_delimiters, lasts );
945         if ( ! str ) { l3 = -1; }
946         else {
947           l3 = strtol( str, &ptr, 0 );
948           if ( ptr == str || l3 >= PLY_MAX || l3 < -1 )
949             {
950               str_error = str_bad_cmdline;
951               return -2;
952             }
953         }
954
955         if ( ! ( l1 | l2 ) ) { l2 = 1; }
956
957         depth_limit  = PLY_MAX;
958         node_limit   = UINT64_MAX;
959         sec_limit    = (unsigned int)l1 * 60U;
960         sec_limit_up = (unsigned int)l2;
961         if ( l3 == -1 ) { sec_limit_depth = UINT_MAX; }
962         else            { sec_limit_depth = (unsigned int)l3; }
963       }
964     }
965   else {
966     str_error = str_bad_cmdline;
967     return -2;
968   }
969
970   return 1;
971 }
972
973
974 static int
975 cmd_read( tree_t * restrict ptree, char **lasts )
976 {
977   const char *str1 = strtok_r( NULL, str_delimiters, lasts );
978   const char *str2 = strtok_r( NULL, str_delimiters, lasts );
979   const char *str3 = strtok_r( NULL, str_delimiters, lasts );
980   const char *str_tmp;
981   FILE *pf_src, *pf_dest;
982   char str_file[SIZE_FILENAME];
983   char *ptr;
984   unsigned int moves;
985   long l;
986   int iret, flag, c;
987
988   flag    = flag_history | flag_rep | flag_detect_hang | flag_rejections;
989   moves   = UINT_MAX;
990   str_tmp = NULL;
991
992   if ( str1 == NULL )
993     {
994       str_error = str_bad_cmdline;
995       return -2;
996     }
997
998   if ( str2 != NULL )
999     {
1000       if ( ! strcmp( str2, "t" ) ) { flag |= flag_time; }
1001       else if ( strcmp( str2, "nil" ) )
1002         {
1003           str_error = str_bad_cmdline;
1004           return -2;
1005         }
1006     }
1007
1008   if ( str3 != NULL )
1009     {
1010       l = strtol( str3, &ptr, 0 );
1011       if ( ptr == str3 || l == LONG_MAX || l < 1 )
1012         {
1013           str_error = str_bad_cmdline;
1014           return -2;
1015         }
1016       moves = (unsigned int)l - 1U;
1017     }
1018
1019   AbortDifficultCommand;
1020
1021   if ( ! strcmp( str1, "." ) )
1022     {
1023       str_tmp = "game.cs_";
1024
1025 #if defined(NO_LOGGING)
1026       strncpy( str_file, "game.csa", SIZE_FILENAME-1 );
1027 #else
1028       snprintf( str_file, SIZE_FILENAME, "%s/game%03d.csa",
1029                 str_dir_logs, irecord_game );
1030 #endif
1031       pf_dest = file_open( str_tmp, "w" );
1032       if ( pf_dest == NULL ) { return -2; }
1033
1034       pf_src = file_open( str_file, "r" );
1035       if ( pf_src == NULL )
1036         {
1037           file_close( pf_dest );
1038           return -2;
1039         }
1040
1041       while ( ( c = getc(pf_src) ) != EOF ) { putc( c, pf_dest ); }
1042
1043       iret = file_close( pf_src );
1044       if ( iret < 0 )
1045         {
1046           file_close( pf_dest );
1047           return iret;
1048         }
1049
1050       iret = file_close( pf_dest );
1051       if ( iret < 0 ) { return iret; }
1052
1053       flag |= flag_time;
1054       str1  = str_tmp;
1055     }
1056
1057   iret = read_record( ptree, str1, moves, flag );
1058   if ( iret < 0 ) { return iret; }
1059
1060   iret = get_elapsed( &time_turn_start );
1061   if ( iret < 0 ) { return iret; }
1062
1063   if ( str_tmp && remove( str_tmp ) )
1064     {
1065       out_warning( "remove() failed." );
1066       return -2;
1067     }
1068
1069   return 1;
1070 }
1071
1072
1073 static int
1074 cmd_resign( tree_t * restrict ptree, char **lasts )
1075 {
1076   const char *str = strtok_r( NULL, str_delimiters, lasts );
1077   char *ptr;
1078   long l;
1079
1080   if ( str == NULL || *str == 'T' )
1081     {
1082       AbortDifficultCommand;
1083
1084       if ( game_status & mask_game_end ) { return 1; }
1085
1086 #if defined(DEKUNOBOU)
1087       if ( dek_ngame && record_game.moves < 2 )
1088         {
1089           str_error = "ignore resignation";
1090           return -2;
1091         }
1092 #endif
1093
1094       game_status |= flag_resigned;
1095       renovate_time( root_turn );
1096       out_CSA( ptree, &record_game, MOVE_RESIGN );
1097     }
1098   else {
1099     l = strtol( str, &ptr, 0 );
1100     if ( ptr == str || l == LONG_MAX || l < MT_CAP_PAWN )
1101       {
1102         str_error = str_bad_cmdline;
1103         return -2;
1104       }
1105     resign_threshold = (int)l;
1106   }
1107
1108   return 1;
1109 }
1110
1111
1112 static int
1113 cmd_move( tree_t * restrict ptree, char **lasts )
1114 {
1115   const char *str = strtok_r( NULL, str_delimiters, lasts );
1116   unsigned int move;
1117   int iret;
1118
1119   if ( game_status & mask_game_end )
1120     {
1121       str_error = str_game_ended;
1122       return -2;
1123     }
1124   
1125   AbortDifficultCommand;
1126
1127   if ( str == NULL )
1128     {
1129       iret = get_elapsed( &time_turn_start );
1130       if ( iret < 0 ) { return iret; }
1131       
1132       iret = com_turn_start( ptree, 0 );
1133       if ( iret < 0 ) { return iret; }
1134     }
1135   else if ( ! strcmp( str, "restraint" ) )
1136     {
1137       iret = get_elapsed( &time_turn_start );
1138       if ( iret < 0 ) { return iret; }
1139       
1140       iret = com_turn_start( ptree, flag_refer_rest );
1141       if ( iret < 0 ) { return iret; }
1142     }
1143   else {
1144
1145     iret = interpret_CSA_move( ptree, &move, str );
1146     if ( iret < 0 ) { return iret; }
1147     
1148     iret = get_elapsed( &time_turn_start );
1149     if ( iret < 0 ) { return iret; }
1150     
1151 #if defined(MNJ_LAN)
1152     if ( sckt_mnj != SCKT_NULL )
1153       {
1154         const char *str2 = strtok_r( NULL, str_delimiters, lasts );
1155         char *ptr;
1156         long l;
1157         if ( str2 ) { l = strtol( str2, &ptr, 0 ); }
1158         if ( ! str2 || ptr == str || l == LONG_MAX || l < 1 )
1159           {
1160             str_error = str_bad_cmdline;
1161             return -2;
1162           }
1163         mnj_posi_id   = (int)l;
1164         mnj_move_last = move;
1165       }
1166 #endif
1167
1168     iret = make_move_root( ptree, move, ( flag_history | flag_time | flag_rep
1169                                           | flag_detect_hang
1170                                           | flag_rejections ) );
1171     if ( iret < 0 ) { return iret; }
1172   }
1173   
1174   return 1;
1175 }
1176
1177
1178 static int
1179 cmd_new( tree_t * restrict ptree, char **lasts )
1180 {
1181   const char *str1 = strtok_r( NULL, str_delimiters, lasts );
1182   const char *str2 = strtok_r( NULL, str_delimiters, lasts );
1183   const min_posi_t *pmp;
1184   min_posi_t min_posi;
1185   int iret;
1186
1187   AbortDifficultCommand;
1188
1189   start_pos = *lasts; move_ptr = 0; // [HGM] undo: remember start position
1190
1191   if ( str1 != NULL )
1192     {
1193       strncpy(start_data, str1, 511); // [HGM] undo: remember start position
1194       memset( &min_posi.asquare, empty, nsquare );
1195       min_posi.hand_black = min_posi.hand_white = 0;
1196       iret = read_board_rep1( str1, &min_posi );
1197       if ( iret < 0 ) { return iret; }
1198
1199       if ( str2 != NULL )
1200         {
1201           if      ( ! strcmp( str2, "-" ) ) { min_posi.turn_to_move = white; }
1202           else if ( ! strcmp( str2, "+" ) ) { min_posi.turn_to_move = black; }
1203           else {
1204             str_error = str_bad_cmdline;
1205             return -2;
1206           }
1207         }
1208       else { min_posi.turn_to_move = black; }
1209
1210       pmp = &min_posi;
1211     }
1212   else { pmp = &min_posi_no_handicap; }
1213
1214   iret = ini_game( ptree, pmp, flag_history, NULL, NULL );
1215   if ( iret < 0 ) { return iret; }
1216
1217   return get_elapsed( &time_turn_start );
1218 }
1219
1220
1221 static int
1222 cmd_problem( tree_t * restrict ptree, char **lasts )
1223 {
1224   const char *str = strtok_r( NULL, str_delimiters, lasts );
1225   char *ptr;
1226   long l;
1227   unsigned int nposition;
1228   int iret;
1229
1230   if ( str != NULL )
1231     {
1232       l = strtol( str, &ptr, 0 );
1233       if ( ptr == str || l == LONG_MAX || l < 1 )
1234         {
1235           str_error = str_bad_cmdline;
1236           return -2;
1237         }
1238       nposition = (unsigned int)l;
1239     }
1240   else { nposition = UINT_MAX; }
1241
1242   AbortDifficultCommand;
1243
1244   iret = record_open( &record_problems, "problem.csa", mode_read, NULL, NULL );
1245   if ( iret < 0 ) { return iret; }
1246
1247   iret = solve_problems( ptree, nposition );
1248   if ( iret < 0 )
1249     {
1250       record_close( &record_problems );
1251       return iret;
1252     }
1253
1254   iret = record_close( &record_problems );
1255   if ( iret < 0 ) { return iret; }
1256
1257   iret = ini_game( ptree, &min_posi_no_handicap, flag_history, NULL, NULL );
1258   if ( iret < 0 ) { return iret; }
1259
1260   return get_elapsed( &time_turn_start );
1261 }
1262
1263
1264 static int
1265 cmd_quit( void )
1266 {
1267   game_status |= flag_quit;
1268   return 1;
1269 }
1270
1271
1272 static int
1273 cmd_suspend( void )
1274 {
1275   if ( game_status & ( flag_pondering | flag_puzzling ) )
1276     {
1277       game_status |= flag_quit_ponder;
1278       return 2;
1279     }
1280   
1281   game_status |= flag_suspend;
1282   return 1;
1283 }
1284
1285
1286 static int
1287 cmd_time( char **lasts )
1288 {
1289   const char *str = strtok_r( NULL, str_delimiters, lasts );
1290   char *ptr;
1291
1292   if ( str == NULL )
1293     {
1294       str_error = str_bad_cmdline;
1295       return -2;
1296     }
1297   else if ( ! strcmp( str, "response" ) )
1298     {
1299       long l;
1300       str = strtok_r( NULL, str_delimiters, lasts );
1301       if ( str == NULL )
1302         {
1303           str_error = str_bad_cmdline;
1304           return -2;
1305         }
1306       l = strtol( str, &ptr, 0 );
1307       if ( ptr == str || l == LONG_MAX || l < 0 || l > 1000 )
1308         {
1309           str_error = str_bad_cmdline;
1310           return -2;
1311         }
1312       time_response = (unsigned int)l;
1313       return 1;
1314     }
1315   else if ( ! strcmp( str, "remain" ) )
1316     {
1317       long l1, l2;
1318       
1319       str = strtok_r( NULL, str_delimiters, lasts );
1320       if ( str == NULL )
1321         {
1322           str_error = str_bad_cmdline;
1323           return -2;
1324         }
1325       l1 = strtol( str, &ptr, 0 );
1326       if ( ptr == str || l1 == LONG_MAX || l1 < 0 )
1327         {
1328           str_error = str_bad_cmdline;
1329           return -2;
1330         }
1331
1332       str = strtok_r( NULL, str_delimiters, lasts );
1333       if ( str == NULL )
1334         {
1335           str_error = str_bad_cmdline;
1336           return -2;
1337         }
1338       l2 = strtol( str, &ptr, 0 );
1339       if ( ptr == str || l2 == LONG_MAX || l2 < 0 )
1340         {
1341           str_error = str_bad_cmdline;
1342           return -2;
1343         }
1344
1345       if ( sec_limit_up == UINT_MAX )
1346         {
1347           str_error = str_bad_cmdline;
1348           return -2;
1349         }
1350
1351       return reset_time( (unsigned int)l1, (unsigned int)l2 );
1352     }
1353
1354   str_error = str_bad_cmdline;
1355   return -2;
1356 }
1357
1358
1359 #if !defined(MINIMUM)
1360 /* learn (ini|no-ini) steps games iterations tlp1 tlp2 */
1361 static int
1362 cmd_learn( tree_t * restrict ptree, char **lasts )
1363 {
1364   const char *str1 = strtok_r( NULL, str_delimiters, lasts );
1365   const char *str2 = strtok_r( NULL, str_delimiters, lasts );
1366   const char *str3 = strtok_r( NULL, str_delimiters, lasts );
1367   const char *str4 = strtok_r( NULL, str_delimiters, lasts );
1368 #  if defined(TLP)
1369   const char *str5 = strtok_r( NULL, str_delimiters, lasts );
1370   const char *str6 = strtok_r( NULL, str_delimiters, lasts );
1371 #  endif
1372   char *ptr;
1373   long l;
1374   unsigned int max_games;
1375   int is_ini, nsteps, max_iterations, nworker1, nworker2, iret;
1376
1377   if ( str1 == NULL )
1378     {
1379       str_error = str_bad_cmdline;
1380       return -2;
1381     }
1382   if      ( ! strcmp( str1, "ini" ) )    { is_ini = 1; }
1383   else if ( ! strcmp( str1, "no-ini" ) ) { is_ini = 0; }
1384   else {
1385     str_error = str_bad_cmdline;
1386     return -2;
1387   }
1388
1389   max_games      = UINT_MAX;
1390   max_iterations = INT_MAX;
1391   nworker1 = nworker2 = nsteps = 1;
1392
1393   if ( str2 != NULL )
1394     {
1395       l = strtol( str2, &ptr, 0 );
1396       if ( ptr == str2 || l == LONG_MAX || l < 1 )
1397         {
1398           str_error = str_bad_cmdline;
1399           return -2;
1400         }
1401       nsteps = (int)l;
1402     }
1403
1404   if ( str3 != NULL )
1405     {
1406       l = strtol( str3, &ptr, 0 );
1407       if ( ptr == str3 || l == LONG_MAX || l == LONG_MIN )
1408         {
1409           str_error = str_bad_cmdline;
1410           return -2;
1411         }
1412       if ( l > 0 ) { max_games = (unsigned int)l; }
1413     }
1414
1415   if ( str4 != NULL )
1416     {
1417       l = strtol( str4, &ptr, 0 );
1418       if ( ptr == str4 || l == LONG_MAX || l == LONG_MIN )
1419         {
1420           str_error = str_bad_cmdline;
1421           return -2;
1422         }
1423       if ( l > 0 ) { max_iterations = (int)l; }
1424     }
1425
1426 #  if defined(TLP)
1427   if ( str5 != NULL )
1428     {
1429       l = strtol( str5, &ptr, 0 );
1430       if ( ptr == str5 || l > TLP_MAX_THREADS || l < 1 )
1431         {
1432           str_error = str_bad_cmdline;
1433           return -2;
1434         }
1435       nworker1 = (int)l;
1436     }
1437
1438   if ( str6 != NULL )
1439     {
1440       l = strtol( str6, &ptr, 0 );
1441       if ( ptr == str6 || l > TLP_MAX_THREADS || l < 1 )
1442         {
1443           str_error = str_bad_cmdline;
1444           return -2;
1445         }
1446       nworker2 = (int)l;
1447     }
1448 #  endif
1449
1450   AbortDifficultCommand;
1451
1452   log2_ntrans_table = 12;
1453
1454   memory_free( (void *)ptrans_table_orig );
1455
1456   iret = ini_trans_table();
1457   if ( iret < 0 ) { return iret; }
1458
1459   iret = learn( ptree, is_ini, nsteps, max_games, max_iterations,
1460                 nworker1, nworker2 );
1461   if ( iret < 0 ) { return -1; }
1462
1463   iret = ini_game( ptree, &min_posi_no_handicap, flag_history, NULL, NULL );
1464   if ( iret < 0 ) { return -1; }
1465
1466   iret = get_elapsed( &time_turn_start );
1467   if ( iret < 0 ) { return iret; }
1468
1469   return 1;
1470 }
1471 #endif /* MINIMUM */
1472
1473
1474 #if defined(MPV)
1475 static int
1476 cmd_mpv( char **lasts )
1477 {
1478   const char *str = strtok_r( NULL, str_delimiters, lasts );
1479   char *ptr;
1480   long l;
1481
1482   if ( str == NULL )
1483     {
1484       str_error = str_bad_cmdline;
1485       return -2;
1486     }
1487   else if ( ! strcmp( str, "num" ) )
1488     {
1489       str = strtok_r( NULL, str_delimiters, lasts );
1490       if ( str == NULL )
1491         {
1492           str_error = str_bad_cmdline;
1493           return -2;
1494         }
1495       l = strtol( str, &ptr, 0 );
1496       if ( ptr == str || l == LONG_MAX || l < 1 || l > MPV_MAX_PV )
1497         {
1498           str_error = str_bad_cmdline;
1499           return -2;
1500         }
1501
1502       AbortDifficultCommand;
1503
1504       mpv_num = (int)l;
1505
1506       return 1;
1507     }
1508   else if ( ! strcmp( str, "width" ) )
1509     {
1510       str = strtok_r( NULL, str_delimiters, lasts );
1511       if ( str == NULL )
1512         {
1513           str_error = str_bad_cmdline;
1514           return -2;
1515         }
1516       l = strtol( str, &ptr, 0 );
1517       if ( ptr == str || l == LONG_MAX || l < MT_CAP_PAWN )
1518         {
1519           str_error = str_bad_cmdline;
1520           return -2;
1521         }
1522
1523       AbortDifficultCommand;
1524
1525       mpv_width = (int)l;
1526
1527       return 1;
1528     }
1529
1530   str_error = str_bad_cmdline;
1531   return -2;
1532 }
1533 #endif
1534
1535
1536 #if defined(TLP)
1537 static int
1538 cmd_thread( char **lasts )
1539 {
1540   const char *str = strtok_r( NULL, str_delimiters, lasts );
1541
1542   if ( str == NULL )
1543     {
1544       str_error = str_bad_cmdline;
1545       return -2;
1546     }
1547   else if ( ! strcmp( str, "num" ) )
1548     {
1549       char *ptr;
1550       long l;
1551
1552       str = strtok_r( NULL, str_delimiters, lasts );
1553       if ( str == NULL )
1554         {
1555           str_error = str_bad_cmdline;
1556           return -2;
1557         }
1558       l = strtol( str, &ptr, 0 );
1559       if ( ptr == str || l == LONG_MAX || l < 1 || l > TLP_MAX_THREADS )
1560         {
1561           str_error = str_bad_cmdline;
1562           return -2;
1563         }
1564
1565       TlpEnd();
1566
1567       tlp_max = (int)l;
1568
1569       if ( game_status & ( flag_thinking | flag_pondering | flag_puzzling ) )
1570         {
1571           return tlp_start();
1572         }
1573       return 1;
1574     }
1575
1576   str_error = str_bad_cmdline;
1577   return -2;
1578 }
1579 #endif
1580
1581
1582 #if defined(CSA_LAN)
1583 static int
1584 cmd_connect( tree_t * restrict ptree, char **lasts )
1585 {
1586   const char *str;
1587   char *ptr;
1588   long max_games;
1589
1590   str = strtok_r( NULL, str_delimiters, lasts );
1591   if ( ! str || ! strcmp( str, "." ) ) { str = "gserver.computer-shogi.org"; }
1592   strncpy( client_str_addr, str, 255 );
1593   client_str_addr[255] = '\0';
1594
1595   str = strtok_r( NULL, str_delimiters, lasts );
1596   if ( ! str || ! strcmp( str, "." ) ) { str = "4081"; }
1597   client_port = strtol( str, &ptr, 0 );
1598   if ( ptr == str || client_port == LONG_MAX || client_port < 0
1599        || client_port > USHRT_MAX )
1600     {
1601       str_error = str_bad_cmdline;
1602       return -2;
1603     }
1604
1605   str = strtok_r( NULL, str_delimiters, lasts );
1606   if ( ! str || ! strcmp( str, "." ) ) { str = "bonanza_test"; }
1607   strncpy( client_str_id, str, 255 );
1608   client_str_id[255] = '\0';
1609
1610   str = strtok_r( NULL, " \t", lasts );
1611   if ( ! str || ! strcmp( str, "." ) ) { str = "bonanza_test"; }
1612   strncpy( client_str_pwd, str, 255 );
1613   client_str_pwd[255] = '\0';
1614
1615   str = strtok_r( NULL, str_delimiters, lasts );
1616   if ( ! str || ! strcmp( str, "." ) ) { client_max_game = INT_MAX; }
1617   else {
1618     max_games = strtol( str, &ptr, 0 );
1619     if ( ptr == str || max_games == LONG_MAX || max_games < 1 )
1620     {
1621       str_error = str_bad_cmdline;
1622       return -2;
1623     }
1624     client_max_game = max_games;
1625   }
1626
1627   AbortDifficultCommand;
1628
1629   client_ngame          = 0;
1630
1631   return client_next_game( ptree, client_str_addr, (int)client_port );
1632 }
1633 #endif
1634
1635
1636 #if defined(MNJ_LAN)
1637 static int
1638 cmd_mnj( tree_t * restrict ptree, char **lasts )
1639 {
1640   char client_str_addr[256];
1641   char client_str_id[256];
1642   const char *str;
1643   char *ptr;
1644   unsigned int seed;
1645   int sd;
1646   long l;
1647   int client_port;
1648
1649   str = strtok_r( NULL, str_delimiters, lasts );
1650   if ( ! str )
1651     {
1652       str_error = str_bad_cmdline;
1653       return -2;
1654     }
1655   l = strtol( str, &ptr, 0 );
1656   if ( ptr == str || l == LONG_MAX || l < 0 )
1657     {
1658       str_error = str_bad_cmdline;
1659       return -2;
1660     }
1661   sd = (int)l;
1662
1663
1664   str = strtok_r( NULL, str_delimiters, lasts );
1665   if ( ! str )
1666     {
1667       str_error = str_bad_cmdline;
1668       return -2;
1669     }
1670   l = strtol( str, &ptr, 0 );
1671   if ( ptr == str || l == LONG_MAX || l < 0 )
1672     {
1673       str_error = str_bad_cmdline;
1674       return -2;
1675     }
1676   seed = (unsigned int)l;
1677
1678
1679   str = strtok_r( NULL, str_delimiters, lasts );
1680   if ( ! str || ! strcmp( str, "." ) ) { str = "localhost"; }
1681   strncpy( client_str_addr, str, 255 );
1682   client_str_addr[255] = '\0';
1683
1684
1685   str = strtok_r( NULL, str_delimiters, lasts );
1686   if ( ! str || ! strcmp( str, "." ) ) { str = "4082"; }
1687   l = strtol( str, &ptr, 0 );
1688   if ( ptr == str || l == LONG_MAX || l < 0 || l > USHRT_MAX )
1689     {
1690       str_error = str_bad_cmdline;
1691       return -2;
1692     }
1693   client_port = (int)l;
1694
1695
1696   str = strtok_r( NULL, str_delimiters, lasts );
1697   if ( ! str || ! strcmp( str, "." ) ) { str = "bonanza1"; }
1698   strncpy( client_str_id, str, 255 );
1699   client_str_id[255] = '\0';
1700
1701   AbortDifficultCommand;
1702
1703   resign_threshold  = 65535;
1704   game_status      |= ( flag_noponder | flag_noprompt );
1705   if ( mnj_reset_tbl( sd, seed ) < 0 ) { return -1; }
1706
1707   sckt_mnj = sckt_connect( client_str_addr, (int)client_port );
1708   if ( sckt_mnj == SCKT_NULL ) { return -2; }
1709
1710   str_buffer_cmdline[0] = '\0';
1711
1712   Out( "Sending my name %s", client_str_id );
1713   sckt_out( sckt_mnj, "%s\n", client_str_id );
1714
1715   return analyze( ptree );
1716 }
1717 #endif
1718
1719
1720 #if defined(DEKUNOBOU)
1721
1722 static int
1723 cmd_dek( char **lasts )
1724 {
1725   const char *str = strtok_r( NULL, str_delimiters, lasts );
1726   char *ptr;
1727   long l1, l2;
1728   int iret;
1729
1730   if ( str == NULL )
1731     {
1732       str_error = str_bad_cmdline;
1733       return -2;
1734     }
1735   strncpy( str_message, str, SIZE_MESSAGE-1 );
1736   str_message[SIZE_MESSAGE-1] = '\0';
1737   dek_ul_addr = inet_addr( str );
1738
1739   str = strtok_r( NULL, str_delimiters, lasts );
1740   if ( str == NULL )
1741     {
1742       str_error = str_bad_cmdline;
1743       return -2;
1744     }
1745   l1 = strtol( str, &ptr, 0 );
1746   if ( ptr == str || l1 == LONG_MAX || l1 < 0 || l1 > USHRT_MAX )
1747     {
1748       str_error = str_bad_cmdline;
1749       return -2;
1750     }
1751
1752   str = strtok_r( NULL, str_delimiters, lasts );
1753   if ( str == NULL )
1754     {
1755       str_error = str_bad_cmdline;
1756       return -2;
1757     }
1758   l2 = strtol( str, &ptr, 0 );
1759   if ( ptr == str || l2 == LONG_MAX || l2 < 0 || l2 > USHRT_MAX )
1760     {
1761       str_error = str_bad_cmdline;
1762       return -2;
1763     }
1764
1765   AbortDifficultCommand;
1766
1767   iret = dek_start( str_message, (int)l1, (int)l2 );
1768   if ( iret < 0 ) { return iret; }
1769
1770   Out( "\n- in communication with Dekunobou...\n" );
1771
1772   str_buffer_cmdline[0] = '\0';
1773   dek_ngame    = 1;
1774   dek_lost     = 0;
1775   dek_win      = 0;
1776   dek_turn     = 1;
1777   game_status |= flag_resigned;
1778   
1779   return 1;
1780 }
1781
1782 #endif
1783