Update codebase to remove clang warnings (and a couple of legit errors
[typhoon.git] / src / command.c
1 /**
2
3 Copyright (c) Scott Gasch
4
5 Module Name:
6
7     command.c
8
9 Abstract:
10
11     Process commands received by the input thread.  Note: the COMMAND
12     macro is defined in chess.h and used heavily in this module to
13     build function declarations.  It hides four parameters:
14
15         CHAR *szInput : the full line of input
16         ULONG argc    : number of argument chunks
17         CHAR *argv[]  : array of ptrs to each argument chunk
18         POSITION *pos : a POSITION pointer to operate on
19
20 Author:
21
22     Scott Gasch ([email protected]) 13 May 2004
23
24 Revision History:
25
26     $Id: command.c 354 2008-06-30 05:10:08Z scott $
27
28 **/
29
30 #include "chess.h"
31
32 #define MAX_ARGS 32
33 int g_eModeBeforeAnalyze = -1;
34
35 typedef void (COMMAND_PARSER_FUNCTION)(CHAR *szInput,
36                                        ULONG argc, 
37                                        CHAR *argv[], 
38                                        POSITION *pos);
39 typedef struct _COMMAND_PARSER_ENTRY
40 {
41     CHAR *szOpcode;
42     COMMAND_PARSER_FUNCTION *pFunction;
43     FLAG fHandleOnTheFly;
44     FLAG fInvisible;
45     FLAG fWinBoard;
46     CHAR *szSimpleHelp;
47 }
48 COMMAND_PARSER_ENTRY;
49
50
51 COMMAND(AnalyzeCommand)
52 /**
53
54 Routine description:
55
56     This function implements the 'analyze' engine command.  
57
58     Usage:
59
60         analyze
61
62         This command takes no arguments and causes the engine to enter
63         analyze mode.  See also: exit
64     
65 Parameters:
66
67     The COMMAND macro hides four arguments from the input parser:
68
69         CHAR *szInput : the full line of input
70         ULONG argc    : number of argument chunks
71         CHAR *argv[]  : array of ptrs to each argument chunk
72         POSITION *pos : a POSITION pointer to operate on
73
74 Return value:
75
76     void
77
78 **/
79 {
80     if (g_Options.ePlayMode != ANALYZE_MODE)
81     {
82         g_eModeBeforeAnalyze = g_Options.ePlayMode;
83         g_Options.ePlayMode = ANALYZE_MODE;
84     }
85 }    
86
87 COMMAND(AnalyzeProgressCommand)
88 /**
89
90 Routine description:
91
92     This function implements the 'analyzeprogressreport' engine
93     command.
94
95     Usage:
96
97         analyzeprogressreport
98
99         This command takes no arguments and causes the engine to dump
100         the current analysis.
101     
102 Parameters:
103
104     The COMMAND macro hides four arguments from the input parser:
105
106         CHAR *szInput : the full line of input
107         ULONG argc    : number of argument chunks
108         CHAR *argv[]  : array of ptrs to each argument chunk
109         POSITION *pos : a POSITION pointer to operate on
110
111 Return value:
112
113     void
114
115 **/
116 {
117     if (g_Options.ePlayMode == ANALYZE_MODE)
118     {
119         Trace("%s\n", g_Options.szAnalyzeProgressReport);
120     }
121 }
122
123 COMMAND(BlackCommand)
124 /**
125
126 Routine description:
127
128     This function implements the 'black' engine command.
129
130     Usage:
131
132         black
133
134         This command takes no arguments and causes the engine to play
135         white and set black to move.
136     
137 Parameters:
138
139     The COMMAND macro hides four arguments from the input parser:
140
141         CHAR *szInput : the full line of input
142         ULONG argc    : number of argument chunks
143         CHAR *argv[]  : array of ptrs to each argument chunk
144         POSITION *pos : a POSITION pointer to operate on
145
146 Return value:
147
148     void
149
150 **/
151 {
152     TellGamelistThatIPlayColor(WHITE);
153     g_Options.ePlayMode = I_PLAY_WHITE;
154     pos->uToMove = BLACK;
155     pos->u64NonPawnSig = ComputeSig(pos);
156 }
157
158
159 COMMAND(BoardCommand)
160 /**
161
162 Routine description:
163
164     This function implements the 'board' engine command.  
165
166     Usage:
167
168         board
169
170         This command takes no arguments and displays the current board
171         position on stdout and in the log.
172     
173 Parameters:
174
175     The COMMAND macro hides four arguments from the input parser:
176
177         CHAR *szInput : the full line of input
178         ULONG argc    : number of argument chunks
179         CHAR *argv[]  : array of ptrs to each argument chunk
180         POSITION *pos : a POSITION pointer to operate on
181
182 Return value:
183
184     void
185
186 **/
187 {
188     DumpPosition(pos);
189 }
190
191 COMMAND(ComputerCommand)
192 /**
193
194 Routine description:
195
196     This function implements the 'computer' engine command.  
197
198     Usage:
199
200         computer
201
202         This command takes no argument and informs the engine that it
203         is playing against another computer.
204     
205 Parameters:
206
207     The COMMAND macro hides four arguments from the input parser:
208
209         CHAR *szInput : the full line of input
210         ULONG argc    : number of argument chunks
211         CHAR *argv[]  : array of ptrs to each argument chunk
212         POSITION *pos : a POSITION pointer to operate on
213
214 Return value:
215
216     void
217
218 **/
219 {
220     g_Options.fOpponentIsComputer = TRUE;
221     Trace("tellics +alias whisper kib\n");
222 }
223
224 COMMAND(DrawCommand)
225 {
226     //if (g_iNumDrawScoresInARow > 4)
227     //{
228     //    ToXboard("tellopponent I accept your draw offer.\n");
229     //    ToXboard("tellics draw\n");
230     //}
231     //else
232     //{
233     //Trace("tellopponent Sorry I do not accept your draw offer at "
234     //      "this time.\n");
235     //Trace("tellics decline draw\n");
236     //}
237 }
238
239
240 //
241 // TODO: timestamp command
242 //
243
244 void 
245 DumpSizes(void)
246 /**
247
248 Routine description:
249
250     Dump the sizes of some internal data structures on stdout.
251
252 Parameters:
253
254     void
255
256 Return value:
257
258     void
259
260 **/
261 {
262     Trace("sizeof(PAWN_HASH_ENTRY). . . . . . . . . %u bytes\n"
263           "sizeof(HASH_ENTRY) . . . . . . . . . . . %u bytes\n"
264           "sizeof(MOVE) . . . . . . . . . . . . . . %u bytes\n"
265           "sizeof(ATTACK_BITV). . . . . . . . . . . %u bytes\n"
266           "sizeof(SQUARE) . . . . . . . . . . . . . %u bytes\n"
267           "sizeof(POSITION) . . . . . . . . . . . . %u bytes\n"
268           "sizeof(MOVE_STACK) . . . . . . . . . . . %u bytes\n"
269           "sizeof(PLY_INFO) . . . . . . . . . . . . %u bytes\n"
270           "sizeof(COUNTERS) . . . . . . . . . . . . %u bytes\n"
271           "sizeof(SEARCHER_THREAD_CONTEXT). . . . . %u bytes\n"
272           "sizeof(GAME_OPTIONS) . . . . . . . . . . %u bytes\n"
273           "sizeof(MOVE_TIMER) . . . . . . . . . . . %u bytes\n"
274           "sizeof(PIECE_DATA) . . . . . . . . . . . %u bytes\n"
275           "sizeof(VECTOR_DELTA) . . . . . . . . . . %u bytes\n"
276           "sizeof(GAME_PLAYER). . . . . . . . . . . %u bytes\n"
277           "sizeof(GAME_HEADER). . . . . . . . . . . %u bytes\n"
278           "sizeof(GAME_MOVE). . . . . . . . . . . . %u bytes\n"
279           "sizeof(GAME_DATA). . . . . . . . . . . . %u bytes\n"
280           "sizeof(SEE_LIST) . . . . . . . . . . . . %u bytes\n"
281           "sizeof(BOOK_ENTRY) . . . . . . . . . . . %u bytes\n"
282           "-------------------------------------------------\n"
283           "Current main hash table size . . . . . . %u bytes (~%u Mb)\n",
284           sizeof(PAWN_HASH_ENTRY), sizeof(HASH_ENTRY), sizeof(MOVE),
285           sizeof(ATTACK_BITV), sizeof(SQUARE), sizeof(POSITION),
286           sizeof(MOVE_STACK), sizeof(PLY_INFO), sizeof(COUNTERS),
287           sizeof(SEARCHER_THREAD_CONTEXT), sizeof(GAME_OPTIONS),
288           sizeof(MOVE_TIMER), sizeof(PIECE_DATA), sizeof(VECTOR_DELTA),
289           sizeof(GAME_PLAYER), sizeof(GAME_HEADER), sizeof(GAME_MOVE),
290           sizeof(GAME_DATA), sizeof(SEE_LIST), sizeof(BOOK_ENTRY),
291           (g_uHashTableSizeEntries * sizeof(HASH_ENTRY)),
292           ((g_uHashTableSizeEntries * sizeof(HASH_ENTRY)) / MB));
293     ASSERT_ASM_ASSUMPTIONS;
294 }
295
296
297 COMMAND(DumpCommand)
298 /**
299
300 Routine description:
301
302     This function implements the 'dump' engine command.  
303
304     Usage:
305
306         dump board
307         dump moves
308         dump pgn
309         dump sizes
310         dump eval [optional coor]
311         dump evaldna
312
313         This command is used to dump internal information to the
314         stdout.  
315
316         When used with the 'board' argument, a dump of the internal
317         representation of the current board position is produced.
318
319         When used with the 'moves' argument, a list of the moves played
320         thus far in the current game is produced in list format.
321
322         When used with the 'pgn' argument, a list of the moves played 
323         thus far in the current game is produced in PGN format.
324
325         When used with the 'sizes' argument, a dump of internal data
326         structure sizes is produced.
327
328         When used with the 'eval' argument and no optional coordinate
329         a dump of all eval terms from the last time the eval function
330         was invoked is produced.  If the optional coordinate is
331         provided then the eval terms DIRECTLY affected by the piece at
332         the supplied coordinate is produced.  Note: to use dump eval
333         the engine must have been built with -DEVAL_DUMP.
334     
335 Parameters:
336
337     The COMMAND macro hides four arguments from the input parser:
338
339         CHAR *szInput : the full line of input
340         ULONG argc    : number of argument chunks
341         CHAR *argv[]  : array of ptrs to each argument chunk
342         POSITION *pos : a POSITION pointer to operate on
343
344 Return value:
345
346     void
347
348 **/
349 {
350 #ifdef EVAL_DUMP
351     COOR c;
352 #endif
353
354     if (argc < 2)
355     {
356         Trace("Error (missing argument)\n");
357         return;
358     }
359     if (!STRCMPI(argv[1], "board"))
360     {
361         DumpPosition(pos);
362     }
363     else if (!STRCMPI(argv[1], "moves"))
364     {
365         DumpGameList();
366     }
367     else if (!STRCMPI(argv[1], "pgn"))
368     {
369         DumpPgn();
370     }
371     else if (!STRCMPI(argv[1], "sizes"))
372     {
373         DumpSizes();
374     }
375     else if (!STRCMPI(argv[1], "evaldna")) 
376     {
377         char *p = ExportEvalDNA();
378         Trace("EvalDNA: %s\n", p);
379         free(p);
380     }
381 #ifdef EVAL_DUMP
382     else if (!STRCMPI(argv[1], "eval"))
383     {
384         if (argc < 3)
385         {
386             EvalTraceReport();
387         }
388         else
389         {
390             if (!STRCMPI(argv[2], "terms"))
391             {
392                 EvalTraceReport();
393             } else {
394                 if (LooksLikeCoor(argv[2]))
395                 {
396                     c = FILE_RANK_TO_COOR((tolower(argv[2][0]) - 'a'),
397                                           (tolower(argv[2][1]) - '0'));
398                     (void)EvalSigmaForPiece(pos, c);
399                 } else {
400                     (void)EvalSigmaForPiece(pos, ILLEGAL_COOR);
401                 }
402             }
403         }
404     }
405 #endif
406 }
407
408 COMMAND(EasyCommand)
409 /**
410
411 Routine description:
412
413     This function implements the 'easy' engine command.  
414
415     Usage:
416
417         easy
418
419         This command takes no arguments and causes the engine not to
420         think on the opponent's time (i.e. not to ponder)
421     
422 Parameters:
423
424     The COMMAND macro hides four arguments from the input parser:
425
426         CHAR *szInput : the full line of input
427         ULONG argc    : number of argument chunks
428         CHAR *argv[]  : array of ptrs to each argument chunk
429         POSITION *pos : a POSITION pointer to operate on
430
431 Return value:
432
433     void
434
435 **/
436 {
437     g_Options.fShouldPonder = FALSE;
438 }
439
440 COMMAND(EditCommand)
441 /**
442
443 Routine description:
444
445     This function implements the 'edit' engine command.  
446
447     Usage:
448
449         This command is deprecated and should not be used.
450     
451 Parameters:
452
453     The COMMAND macro hides four arguments from the input parser:
454
455         CHAR *szInput : the full line of input
456         ULONG argc    : number of argument chunks
457         CHAR *argv[]  : array of ptrs to each argument chunk
458         POSITION *pos : a POSITION pointer to operate on
459
460 Return value:
461
462     void
463
464 **/
465 {
466     Trace("Error (obsolete command): %s\n", argv[0]);
467     Trace("\nPlease upgrade your version of xboard at "
468           "http://www.timmann.org/\n");
469 }
470
471 COMMAND(EvalCommand)
472 /**
473
474 Routine description:
475
476     This function implements the 'eval' engine command.  
477
478     Usage:
479
480         eval
481
482         This command takes no arguments and causes the engine to print
483         out a static evaluation of the current board position.
484     
485 Parameters:
486
487     The COMMAND macro hides four arguments from the input parser:
488
489         CHAR *szInput : the full line of input
490         ULONG argc    : number of argument chunks
491         CHAR *argv[]  : array of ptrs to each argument chunk
492         POSITION *pos : a POSITION pointer to operate on
493
494 Return value:
495
496     void
497
498 **/
499 {
500     SEARCHER_THREAD_CONTEXT *ctx;
501     SCORE i;
502
503     ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
504     if (NULL != ctx) 
505     {
506         InitializeSearcherContext(pos, ctx);
507         i = Eval(ctx, -INFINITY, +INFINITY);
508         Trace("Static eval: %s\n", ScoreToString(i));
509         SystemFreeMemory(ctx);
510     } else {
511         Trace("Out of memory.\n");
512     }
513 }
514
515
516 COMMAND(EvalDnaCommand)
517 /**
518
519 Routine description:
520
521     This function implements the 'evaldna' engine command.  
522
523     Usage:
524
525         evaldna write <filename>
526         evaldna read <filename>
527         evaldna dump
528
529 Parameters:
530
531     The COMMAND macro hides four arguments from the input parser:
532
533         CHAR *szInput : the full line of input
534         ULONG argc    : number of argument chunks
535         CHAR *argv[]  : array of ptrs to each argument chunk
536         POSITION *pos : a POSITION pointer to operate on
537
538 Return value:
539
540     void
541
542 **/
543 {
544     char *p;
545     if (argc < 2)
546     {
547         Trace("Usage: evaldna <read | write> <filename>\n"
548               "       evaldna dump\n");
549         return;
550     }
551     if (!STRCMPI(argv[1], "write"))
552     {
553         if (argc < 3) {
554             Trace("Error (missing argument)\n");
555             return;
556         }
557         if (!WriteEvalDNA(argv[2])) 
558         {
559             Trace("Error writing dna file.\n");
560         } else {
561             Trace("DNA file written.\n");
562         }
563     }
564     else if (!STRCMPI(argv[1], "read") ||
565              !STRCMPI(argv[1], "load"))
566     {
567         if (argc < 3) {
568             Trace("Error (missing argument)\n");
569             return;
570         }
571         if (!ReadEvalDNA(argv[2])) 
572         {
573             Trace("Error reading dna file.\n");
574         } else {
575             Trace("Loaded dna file \"%s\"\n", argv[2]);
576             p = ExportEvalDNA();
577             Log("(New) dna: %s\n", p);
578             free(p);
579         }
580     }
581     else if (!STRCMPI(argv[1], "dump"))
582     {
583         p = ExportEvalDNA();
584         Trace("EvalDNA: %s\n", p);
585         free(p);
586     }
587 }
588
589
590 COMMAND(ExitCommand)
591 /**
592
593 Routine description:
594
595     This function implements the 'exit' engine command.  
596
597     Usage:
598
599         exit
600
601         This command takes no arguments and causes the engine to leave
602         analyze mode.  The engine reverts to the mode it was in prior
603         to entering analyze mode.  See also: analyze
604     
605 Parameters:
606
607     The COMMAND macro hides four arguments from the input parser:
608
609         CHAR *szInput : the full line of input
610         ULONG argc    : number of argument chunks
611         CHAR *argv[]  : array of ptrs to each argument chunk
612         POSITION *pos : a POSITION pointer to operate on
613
614 Return value:
615
616     void
617
618 **/
619 {
620     if (g_Options.ePlayMode == ANALYZE_MODE)
621     {
622         ASSERT(g_eModeBeforeAnalyze != ANALYZE_MODE);
623         g_Options.ePlayMode = g_eModeBeforeAnalyze;
624     }
625 }
626
627 COMMAND(ForceCommand)
628 /**
629
630 Routine description:
631
632     This function implements the 'force' engine command.  
633
634     Usage:
635
636         force
637
638         This command takes no arguments and causes the engine to enter
639         'force mode'.  In this mode it will play neither side.
640     
641 Parameters:
642
643     The COMMAND macro hides four arguments from the input parser:
644
645         CHAR *szInput : the full line of input
646         ULONG argc    : number of argument chunks
647         CHAR *argv[]  : array of ptrs to each argument chunk
648         POSITION *pos : a POSITION pointer to operate on
649
650 Return value:
651
652     void
653
654 **/
655 {
656     TellGamelistThatIPlayColor(BLACK);
657     g_Options.ePlayMode = FORCE_MODE;
658 }
659
660 COMMAND(GenerateCommand)
661 /**
662
663 Routine description:
664
665     This function is not directly callable.  See 'test generate'
666     instead.
667     
668 Parameters:
669
670     The COMMAND macro hides four arguments from the input parser:
671
672         CHAR *szInput : the full line of input
673         ULONG argc    : number of argument chunks
674         CHAR *argv[]  : array of ptrs to each argument chunk
675         POSITION *pos : a POSITION pointer to operate on
676
677 Return value:
678
679     void
680
681 **/
682 {
683     SEARCHER_THREAD_CONTEXT *ctx;
684     MOVE mv;
685     ULONG u, uLegal = 0;
686
687     ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
688     if (NULL != ctx)
689     {
690         memcpy(&(ctx->sPosition), pos, sizeof(POSITION));
691         mv.uMove = 0;
692         GenerateMoves(ctx, mv, (InCheck(pos, pos->uToMove) ? GENERATE_ESCAPES :
693                                                              GENERATE_ALL_MOVES));
694         ASSERT(ctx->uPly == 0);
695         for (u = ctx->sMoveStack.uBegin[0];
696              u < ctx->sMoveStack.uEnd[0];
697              u++)
698         {
699             mv = ctx->sMoveStack.mvf[u].mv;
700             if (MakeMove(ctx, mv))
701             {
702                 ASSERT(!InCheck(&(ctx->sPosition), GET_COLOR(mv.pMoved)));
703                 uLegal++;
704                 UnmakeMove(ctx, mv);
705                 Trace("%2u. %s (%d)\t", 
706                       uLegal, 
707                       MoveToSan(mv, &(ctx->sPosition)),
708                       ctx->sMoveStack.mvf[u].iValue);
709                 if (uLegal % 3 == 0)
710                 {
711                     Trace("\n");
712                 }
713             }
714         }
715         Trace("\n%u legal move(s).\n", uLegal);
716         SystemFreeMemory(ctx);
717     }
718 }
719
720 COMMAND(PlayOtherCommand)
721 /**
722
723 Routine description:
724
725     This function implements the '' engine command.  
726
727     Usage:
728     
729 Parameters:
730
731     The COMMAND macro hides four arguments from the input parser:
732
733         CHAR *szInput : the full line of input
734         ULONG argc    : number of argument chunks
735         CHAR *argv[]  : array of ptrs to each argument chunk
736         POSITION *pos : a POSITION pointer to operate on
737
738 Return value:
739
740     void
741
742 **/
743 {
744     if (pos->uToMove == WHITE)
745     {
746         TellGamelistThatIPlayColor(BLACK);
747         g_Options.ePlayMode = I_PLAY_BLACK;
748     } else {
749         ASSERT(pos->uToMove == BLACK);
750         TellGamelistThatIPlayColor(WHITE);
751         g_Options.ePlayMode = I_PLAY_WHITE;
752     }
753 }
754
755
756 COMMAND(GoCommand)
757 /**
758
759 Routine description:
760
761     This function implements the 'go' engine command.  
762
763     Usage:
764     
765 Parameters:
766
767     The COMMAND macro hides four arguments from the input parser:
768
769         CHAR *szInput : the full line of input
770         ULONG argc    : number of argument chunks
771         CHAR *argv[]  : array of ptrs to each argument chunk
772         POSITION *pos : a POSITION pointer to operate on
773
774 Return value:
775
776     void
777
778 **/
779 {
780     if (pos->uToMove == WHITE)
781     {
782         TellGamelistThatIPlayColor(WHITE);
783         g_Options.ePlayMode = I_PLAY_WHITE;
784     } else {
785         ASSERT(pos->uToMove == BLACK);
786         TellGamelistThatIPlayColor(BLACK);
787         g_Options.ePlayMode = I_PLAY_BLACK;
788     }
789 }
790
791 COMMAND(HardCommand)
792 {
793     g_Options.fShouldPonder = TRUE;
794 }
795
796 COMMAND(HelpCommand);
797
798 COMMAND(HintCommand)
799 /**
800
801 Routine description:
802
803     This function implements the '' engine command.  
804
805     Usage:
806     
807 Parameters:
808
809     The COMMAND macro hides four arguments from the input parser:
810
811         CHAR *szInput : the full line of input
812         ULONG argc    : number of argument chunks
813         CHAR *argv[]  : array of ptrs to each argument chunk
814         POSITION *pos : a POSITION pointer to operate on
815
816 Return value:
817
818     void
819
820 **/
821 {
822     Trace("Error (not implemented): %s\n", argv[0]);
823 }
824
825 CHAR *OnlyDigits(CHAR *sz)
826 {
827     static CHAR out[SMALL_STRING_LEN_CHAR];
828     CHAR *p = out;
829     ULONG uCount = 0;
830     
831     while((*sz) && (uCount < SMALL_STRING_LEN_CHAR))
832     {
833         if (isdigit(*sz))
834         {
835             uCount++;
836             *p++ = *sz++;
837         }
838     }
839     *p++ = '\0';
840     return(out);
841 }
842
843 COMMAND(LevelCommand)
844 /**
845
846 Routine description:
847
848     This function implements the '' engine command.  
849
850     Usage:
851     
852 Parameters:
853
854     The COMMAND macro hides four arguments from the input parser:
855
856         CHAR *szInput : the full line of input
857         ULONG argc    : number of argument chunks
858         CHAR *argv[]  : array of ptrs to each argument chunk
859         POSITION *pos : a POSITION pointer to operate on
860
861 Return value:
862
863     void
864
865 **/
866 {
867     ULONG x;
868
869     if (argc < 4)
870     {
871         Trace("Error (syntax): %s\n", argv[0]);
872     } else {
873         g_Options.uMovesPerTimePeriod = atoi(OnlyDigits(argv[1]));
874         g_Options.uMyClock = atoi(OnlyDigits(argv[2]));
875         g_Options.uMyIncrement = atoi(OnlyDigits(argv[3]));
876
877         g_Options.eClock = CLOCK_NORMAL;
878         if (g_Options.uMyIncrement)
879         {
880             g_Options.eClock = CLOCK_INCREMENT;
881         }
882         
883         x = (g_Options.uMyClock + ((g_Options.uMyIncrement * 2) / 3));
884         g_Options.uMyClock *= 60;
885         
886         Trace("etime = %u (clock %u and inc %u)\n", x,
887               g_Options.uMyClock, g_Options.uMyIncrement);
888         if (x <= 6)
889         {
890             Trace("bullet game\n");
891             g_Options.eGameType = GAME_BULLET;
892         }
893         else if (x < 15)
894         {
895             Trace("blitz game\n");
896             g_Options.eGameType = GAME_BLITZ;
897         } else {
898             Trace("standard game\n");
899             g_Options.eGameType = GAME_STANDARD;
900         }
901     }
902 }
903
904 COMMAND(MoveNowCommand)
905 /**
906
907 Routine description:
908
909     This function implements the '' engine command.  
910
911     Usage:
912     
913 Parameters:
914
915     The COMMAND macro hides four arguments from the input parser:
916
917         CHAR *szInput : the full line of input
918         ULONG argc    : number of argument chunks
919         CHAR *argv[]  : array of ptrs to each argument chunk
920         POSITION *pos : a POSITION pointer to operate on
921
922 Return value:
923
924     void
925
926 **/
927 {
928     Trace("MOVE NOW COMMAND --> stop searching now\n");
929     g_MoveTimer.bvFlags |= TIMER_STOPPING;
930 }
931
932 COMMAND(MovesCommand)
933 /**
934
935 Routine description:
936
937     This function implements the '' engine command.  
938
939     Usage:
940     
941 Parameters:
942
943     The COMMAND macro hides four arguments from the input parser:
944
945         CHAR *szInput : the full line of input
946         ULONG argc    : number of argument chunks
947         CHAR *argv[]  : array of ptrs to each argument chunk
948         POSITION *pos : a POSITION pointer to operate on
949
950 Return value:
951
952     void
953
954 **/
955 {
956     DumpGameList();
957 }
958
959 COMMAND(XboardCommand);
960 COMMAND(NameCommand)
961 /**
962
963 Routine description:
964
965     This function implements the '' engine command.  
966
967     Usage:
968     
969 Parameters:
970
971     The COMMAND macro hides four arguments from the input parser:
972
973         CHAR *szInput : the full line of input
974         ULONG argc    : number of argument chunks
975         CHAR *argv[]  : array of ptrs to each argument chunk
976         POSITION *pos : a POSITION pointer to operate on
977
978 Return value:
979
980     void
981
982 **/
983 {
984     if (argc < 2)
985     {
986         XboardCommand(szInput, argc, argv, pos);
987     } else {
988         SetOpponentsName(argv[1]);
989     }
990 }
991
992 COMMAND(NewCommand)
993 /**
994
995 Routine description:
996
997     This function implements the '' engine command.  
998
999     Usage:
1000     
1001 Parameters:
1002
1003     The COMMAND macro hides four arguments from the input parser:
1004
1005         CHAR *szInput : the full line of input
1006         ULONG argc    : number of argument chunks
1007         CHAR *argv[]  : array of ptrs to each argument chunk
1008         POSITION *pos : a POSITION pointer to operate on
1009
1010 Return value:
1011
1012     void
1013
1014 **/
1015 {
1016     Trace("tellics -alias whisp*\n");
1017     PreGameReset(TRUE);
1018     TellGamelistThatIPlayColor(BLACK);
1019     g_Options.ePlayMode = I_PLAY_BLACK;
1020     g_Options.uMaxDepth = MAX_PLY_PER_SEARCH - 1;
1021 }
1022
1023 COMMAND(NoPostCommand)
1024 /**
1025
1026 Routine description:
1027
1028     This function implements the '' engine command.  
1029
1030     Usage:
1031     
1032 Parameters:
1033
1034     The COMMAND macro hides four arguments from the input parser:
1035
1036         CHAR *szInput : the full line of input
1037         ULONG argc    : number of argument chunks
1038         CHAR *argv[]  : array of ptrs to each argument chunk
1039         POSITION *pos : a POSITION pointer to operate on
1040
1041 Return value:
1042
1043     void
1044
1045 **/
1046 {
1047     g_Options.fShouldPost = FALSE;
1048 }
1049
1050 COMMAND(OtimCommand)
1051 /**
1052
1053 Routine description:
1054
1055     This function implements the '' engine command.  
1056
1057     Usage:
1058     
1059 Parameters:
1060
1061     The COMMAND macro hides four arguments from the input parser:
1062
1063         CHAR *szInput : the full line of input
1064         ULONG argc    : number of argument chunks
1065         CHAR *argv[]  : array of ptrs to each argument chunk
1066         POSITION *pos : a POSITION pointer to operate on
1067
1068 Return value:
1069
1070     void
1071
1072 **/
1073 {
1074     ULONG x;
1075     
1076     if (argc < 2)
1077     {
1078         Trace("My opponent's clock stands at %u sec remaining.\n",
1079               g_Options.uOpponentsClock);
1080         
1081         switch (g_Options.eClock)
1082         {
1083             case CLOCK_FIXED:
1084                 Trace("The move timer is fixed, %u sec / move.\n",
1085                       g_Options.uMyIncrement);
1086                 break;
1087             case CLOCK_NORMAL:
1088                 if (g_Options.uMovesPerTimePeriod != 0)
1089                 {
1090                     Trace("The move timer is normal, %u moves / time "
1091                           "period.\n",
1092                           g_Options.uMovesPerTimePeriod);
1093                 } else {
1094                     Trace("The move timer is normal, finish entire "
1095                           "game in allotted time.\n");
1096                 }
1097                 break;
1098             case CLOCK_INCREMENT:
1099                 Trace("The move timer is increment, additional %u sec "
1100                       "/ move.\n",
1101                       g_Options.uMyIncrement);
1102                 break;
1103             case CLOCK_NONE:
1104             default:
1105                 Trace("The clock and move timer are disabled.\n");
1106                 break;
1107         }
1108     } else {
1109         x = atoi(argv[1]);
1110         if (x >= 0)
1111         {
1112             g_Options.uOpponentsClock = x / 100; // convert to seconds
1113         } else {
1114             Trace("Error (invalid time): %d\n", x);
1115         }
1116     }
1117 }
1118
1119 COMMAND(PingCommand)
1120 /**
1121
1122 Routine description:
1123
1124     This function implements the '' engine command.  
1125
1126     Usage:
1127     
1128 Parameters:
1129
1130     The COMMAND macro hides four arguments from the input parser:
1131
1132         CHAR *szInput : the full line of input
1133         ULONG argc    : number of argument chunks
1134         CHAR *argv[]  : array of ptrs to each argument chunk
1135         POSITION *pos : a POSITION pointer to operate on
1136
1137 Return value:
1138
1139     void
1140
1141 **/
1142 {
1143     if (argc > 1)
1144     {
1145         Trace("pong %s\n", argv[1]);
1146     }
1147 }
1148
1149 COMMAND(PostCommand)
1150 /**
1151
1152 Routine description:
1153
1154     This function implements the '' engine command.  
1155
1156     Usage:
1157     
1158 Parameters:
1159
1160     The COMMAND macro hides four arguments from the input parser:
1161
1162         CHAR *szInput : the full line of input
1163         ULONG argc    : number of argument chunks
1164         CHAR *argv[]  : array of ptrs to each argument chunk
1165         POSITION *pos : a POSITION pointer to operate on
1166
1167 Return value:
1168
1169     void
1170
1171 **/
1172 {
1173     g_Options.fShouldPost = TRUE;
1174 }
1175
1176 COMMAND(ProtoverCommand)
1177 /**
1178
1179 Routine description:
1180
1181     This function implements the '' engine command.  
1182
1183     Usage:
1184     
1185 Parameters:
1186
1187     The COMMAND macro hides four arguments from the input parser:
1188
1189         CHAR *szInput : the full line of input
1190         ULONG argc    : number of argument chunks
1191         CHAR *argv[]  : array of ptrs to each argument chunk
1192         POSITION *pos : a POSITION pointer to operate on
1193
1194 Return value:
1195
1196     void
1197
1198 **/
1199 {
1200     Trace("feature sigint=0 sigterm=0 myname=\"typhoon %s\" ping=1 "
1201           "setboard=1 playother=1 colors=0 time=1 analyze=1 pause=1 "
1202           "reuse=1 done=1\n", VERSION);
1203 }
1204
1205 COMMAND(QuitCommand)
1206 /**
1207
1208 Routine description:
1209
1210     This function implements the 'quit' engine command.  
1211
1212     Usage: quit
1213     
1214 Parameters:
1215
1216     The COMMAND macro hides four arguments from the input parser:
1217
1218         CHAR *szInput : the full line of input
1219         ULONG argc    : number of argument chunks
1220         CHAR *argv[]  : array of ptrs to each argument chunk
1221         POSITION *pos : a POSITION pointer to operate on
1222
1223 Return value:
1224
1225     void
1226
1227 **/
1228 {
1229 #ifdef MP
1230     ULONG u = 0;
1231 #endif
1232
1233     //
1234     // Stop searching; if we are on an MP box wait until all helper
1235     // threads return to the idle state and exit.
1236     //
1237     g_MoveTimer.bvFlags |= TIMER_STOPPING;
1238 #ifdef MP
1239     u = 0;
1240     do
1241     {
1242         SystemDeferExecution(100);
1243         if (++u == 5) break;
1244     }
1245     while(g_uNumHelpersAvailable != g_uNumHelperThreads);
1246 #endif
1247
1248     // 
1249     // We should be the last thread in the process now.
1250     //
1251 }
1252
1253 COMMAND(RatedCommand)
1254 /**
1255
1256 Routine description:
1257
1258     This function implements the '' engine command.  
1259
1260     Usage:
1261     
1262 Parameters:
1263
1264     The COMMAND macro hides four arguments from the input parser:
1265
1266         CHAR *szInput : the full line of input
1267         ULONG argc    : number of argument chunks
1268         CHAR *argv[]  : array of ptrs to each argument chunk
1269         POSITION *pos : a POSITION pointer to operate on
1270
1271 Return value:
1272
1273     void
1274
1275 **/
1276 {
1277     g_Options.fGameIsRated = TRUE;
1278 }
1279
1280 COMMAND(RatingCommand)
1281 /**
1282
1283 Routine description:
1284
1285     This function implements the '' engine command.  
1286
1287     Usage:
1288     
1289 Parameters:
1290
1291     The COMMAND macro hides four arguments from the input parser:
1292
1293         CHAR *szInput : the full line of input
1294         ULONG argc    : number of argument chunks
1295         CHAR *argv[]  : array of ptrs to each argument chunk
1296         POSITION *pos : a POSITION pointer to operate on
1297
1298 Return value:
1299
1300     void
1301
1302 **/
1303 {
1304     ULONG x;
1305     
1306     if (argc < 3)
1307     {
1308         Trace("Error (bad usage): %s\n", argv[0]);
1309     } else {
1310         x = atoi(argv[1]);
1311         if (x >= 0) 
1312         {
1313             SetMyRating(x);
1314         }
1315         x = atoi(argv[2]);
1316         if (x >= 0) 
1317         {
1318             SetOpponentsRating(x);
1319         }
1320     }
1321 }
1322
1323 COMMAND(RandomCommand)
1324 /**
1325
1326 Routine description:
1327
1328     This function implements the '' engine command.  
1329
1330     Usage:
1331     
1332 Parameters:
1333
1334     The COMMAND macro hides four arguments from the input parser:
1335
1336         CHAR *szInput : the full line of input
1337         ULONG argc    : number of argument chunks
1338         CHAR *argv[]  : array of ptrs to each argument chunk
1339         POSITION *pos : a POSITION pointer to operate on
1340
1341 Return value:
1342
1343     void
1344
1345 **/
1346 {
1347     Trace("%u\n", rand());
1348 }
1349
1350 COMMAND(RemoveCommand)
1351 /**
1352
1353 Routine description:
1354
1355     This function implements the '' engine command.  
1356
1357     Usage:
1358     
1359 Parameters:
1360
1361     The COMMAND macro hides four arguments from the input parser:
1362
1363         CHAR *szInput : the full line of input
1364         ULONG argc    : number of argument chunks
1365         CHAR *argv[]  : array of ptrs to each argument chunk
1366         POSITION *pos : a POSITION pointer to operate on
1367
1368 Return value:
1369
1370     void
1371
1372 **/
1373 {
1374     if (TRUE == OfficiallyTakebackMove())
1375     {
1376         if (TRUE == OfficiallyTakebackMove())
1377         {
1378             return;
1379         }
1380     }
1381     Trace("Error (unable to takeback move)\n");    
1382 }
1383
1384 COMMAND(ResultCommand)
1385 /**
1386
1387 Routine description:
1388
1389     This function implements the '' engine command.  
1390
1391     Usage:
1392     
1393 Parameters:
1394
1395     The COMMAND macro hides four arguments from the input parser:
1396
1397         CHAR *szInput : the full line of input
1398         ULONG argc    : number of argument chunks
1399         CHAR *argv[]  : array of ptrs to each argument chunk
1400         POSITION *pos : a POSITION pointer to operate on
1401
1402 Return value:
1403
1404     void
1405
1406 **/
1407 {
1408     GAME_RESULT result;
1409     result.eResult = RESULT_UNKNOWN;
1410     result.szDescription[0] = '\0';
1411     
1412     if (argc < 2)
1413     {
1414         Trace("Argc was %u\n", argc);
1415         Trace("Usage: result <result> [optional comment]\n");
1416     } else {
1417         if (!STRNCMPI("1-0", argv[1], 3))
1418         {
1419             result.eResult = RESULT_WHITE_WON;
1420         }
1421         else if (!STRNCMPI("0-1", argv[1], 3))
1422         {
1423             result.eResult = RESULT_BLACK_WON;
1424         }
1425         else if ((!STRNCMPI("1/2", argv[1], 3)) ||
1426                  (!STRNCMPI("=", argv[1], 1)))
1427         {
1428             result.eResult = RESULT_DRAW;
1429         }
1430         if (argc < 2) {
1431           strncpy(result.szDescription, argv[2], 256);
1432         }
1433         SetGameResultAndDescription(result);
1434         if (g_Options.ePlayMode != FORCE_MODE)
1435         {
1436             DumpPgn();
1437             TellGamelistThatIPlayColor(BLACK);
1438             g_Options.ePlayMode = FORCE_MODE;
1439         }
1440     }
1441 }
1442
1443 COMMAND(SearchDepthCommand)
1444 /**
1445
1446 Routine description:
1447
1448     This function implements the '' engine command.  
1449
1450     Usage:
1451     
1452 Parameters:
1453
1454     The COMMAND macro hides four arguments from the input parser:
1455
1456         CHAR *szInput : the full line of input
1457         ULONG argc    : number of argument chunks
1458         CHAR *argv[]  : array of ptrs to each argument chunk
1459         POSITION *pos : a POSITION pointer to operate on
1460
1461 Return value:
1462
1463     void
1464
1465 **/
1466 {
1467     ULONG x;
1468     
1469     if (argc < 2)
1470     {
1471         Trace("Current maximum depth limit is %u ply.\n"
1472               "The largest depth the engine can search to is %u ply.\n",
1473               g_Options.uMaxDepth,
1474               MAX_PLY_PER_SEARCH);
1475     } else {
1476         x = atoi(argv[1]);
1477         if (x <= 0)
1478         {
1479             Trace("Error (illegal depth): %d\n", x);
1480         }
1481         else if (x >= MAX_PLY_PER_SEARCH)
1482         {
1483             Trace("Error (my max depth is %u): %u\n", 
1484                   MAX_PLY_PER_SEARCH - 1, x);
1485         } else {
1486             g_Options.uMaxDepth = x;
1487         }
1488     }
1489 }
1490
1491 COMMAND(SearchNodesCommand)
1492 /**
1493
1494 Routine description:
1495
1496     This function implements the '' engine command.  
1497
1498     Usage:
1499     
1500 Parameters:
1501
1502     The COMMAND macro hides four arguments from the input parser:
1503
1504         CHAR *szInput : the full line of input
1505         ULONG argc    : number of argument chunks
1506         CHAR *argv[]  : array of ptrs to each argument chunk
1507         POSITION *pos : a POSITION pointer to operate on
1508
1509 Return value:
1510
1511     void
1512
1513 **/
1514 {
1515     UINT64 x;
1516     
1517     if (argc < 2)
1518     {
1519         g_Options.u64MaxNodeCount = 0;
1520         Trace("Search nodecount limit disabled.\n");
1521     } else {
1522         x = strtoull(argv[1], NULL, 10);
1523         if (x >= 0)
1524         {
1525             g_Options.u64MaxNodeCount = x;
1526             Trace("Search node limit set to %llu.\n", x);
1527         } else {
1528             g_Options.u64MaxNodeCount = 0;
1529             Trace("Search nodecount limit disabled.\n");
1530         }
1531     }
1532 }
1533
1534
1535 COMMAND(SearchTimeCommand)
1536 /**
1537
1538 Routine description:
1539
1540     This function implements the '' engine command.  
1541
1542     Usage:
1543     
1544 Parameters:
1545
1546     The COMMAND macro hides four arguments from the input parser:
1547
1548         CHAR *szInput : the full line of input
1549         ULONG argc    : number of argument chunks
1550         CHAR *argv[]  : array of ptrs to each argument chunk
1551         POSITION *pos : a POSITION pointer to operate on
1552
1553 Return value:
1554
1555     void
1556
1557 **/
1558 {
1559     ULONG x;
1560     
1561     if (argc < 2)
1562     {
1563         Trace("My clock stands at %u sec remaining.\n",
1564               g_Options.uMyClock);
1565         switch (g_Options.eClock)
1566         {
1567             case CLOCK_FIXED:
1568                 Trace("The move timer is fixed, %u sec / move.\n",
1569                       g_Options.uMyIncrement);
1570                 break;
1571             case CLOCK_NORMAL:
1572                 if (g_Options.uMovesPerTimePeriod != 0)
1573                 {
1574                     Trace("The move timer is normal, %u moves / "
1575                           "time period.\n",
1576                           g_Options.uMovesPerTimePeriod);
1577                 } else {
1578                     Trace("The move timer is normal, finish entire game in "
1579                           "allotted time.\n");
1580                 }
1581                 break;
1582             case CLOCK_INCREMENT:
1583                 Trace("The move timer is increment, additional %u sec "
1584                       "/ move.\n",
1585                       g_Options.uMyIncrement);
1586                 break;
1587             case CLOCK_NONE:
1588             default:
1589                 Trace("The clock and move timer are disabled.\n");
1590                 break;
1591         }
1592     } else {
1593         x = atoi(argv[1]);
1594         if (x >= 0)
1595         {
1596             g_Options.uMyIncrement = x;
1597             g_Options.eClock = CLOCK_FIXED;
1598         } else {
1599             Trace("Error (illegal time per move): %u\n", x);
1600         }
1601     }
1602 }
1603
1604 COMMAND(SetBoardCommand)
1605 /**
1606
1607 Routine description:
1608
1609     This function implements the '' engine command.  
1610
1611     Usage:
1612     
1613 Parameters:
1614
1615     The COMMAND macro hides four arguments from the input parser:
1616
1617         CHAR *szInput : the full line of input
1618         ULONG argc    : number of argument chunks
1619         CHAR *argv[]  : array of ptrs to each argument chunk
1620         POSITION *pos : a POSITION pointer to operate on
1621
1622 Return value:
1623
1624     void
1625
1626 **/
1627 {
1628     char *p;
1629
1630     if (argc < 2)
1631     {
1632         if (NULL != (p = PositionToFen(pos)))
1633         {
1634             Trace("Current board FEN is: %s\n", p);
1635             SystemFreeMemory(p);
1636         }
1637     } else {
1638         p = szInput + (argv[1] - argv[0]);
1639         if (FALSE == SetRootPosition(p))
1640         {
1641             Trace("Error (malformed FEN): %s\n", p);
1642             return;
1643         }
1644         VERIFY(PreGameReset(FALSE));
1645         g_Options.ePlayMode = FORCE_MODE;
1646     }
1647 }
1648
1649 COMMAND(SEECommand)
1650 {
1651     MOVE mv;
1652     SCORE s;
1653
1654     if (argc < 3)
1655     {
1656         Trace("Usage: test see <required-move>\n");
1657         return;
1658     }
1659     switch(LooksLikeMove(argv[2]))
1660     {
1661         case MOVE_SAN:
1662             mv = ParseMoveSan(argv[2], pos);
1663             break;
1664         case MOVE_ICS:
1665             mv = ParseMoveIcs(argv[2], pos);
1666             break;
1667         default:
1668             mv.uMove = 0;
1669     }
1670     if (!mv.uMove)
1671     {
1672         Trace("Error (invalid move): '%s'\n", argv[2]);
1673         return;
1674     }
1675     s = SEE(pos, mv);
1676     Trace("SEE says that the value of move '%s' is %d\n", argv[2], s);
1677 }
1678
1679
1680 COMMAND(TestCommand)
1681 /**
1682
1683 Routine description:
1684
1685     This function implements the 'test' engine command.
1686
1687     Usage:
1688
1689 Parameters:
1690
1691     The COMMAND macro hides four arguments from the input parser:
1692
1693         CHAR *szInput : the full line of input
1694         ULONG argc    : number of argument chunks
1695         CHAR *argv[]  : array of ptrs to each argument chunk
1696         POSITION *pos : a POSITION pointer to operate on
1697
1698 Return value:
1699
1700     void
1701
1702 **/
1703 {
1704     if (argc < 2)
1705     {
1706         Trace("Error (missing argument)\n");
1707         return;
1708     }
1709
1710     if (!STRCMPI(argv[1], "generate"))
1711     {
1712         GenerateCommand(szInput, argc, argv, pos);
1713     }
1714     else if (!STRCMPI(argv[1], "draw"))
1715     {
1716         Trace("drawcount = %u\n",
1717               CountOccurrancesOfSigInOfficialGameList(pos->u64NonPawnSig ^
1718                                                       pos->u64PawnSig));
1719     }
1720     else if (!STRCMPI(argv[1], "see"))
1721     {
1722         SEECommand(szInput, argc, argv, pos);
1723     }
1724 #ifdef EVAL_DUMP
1725     else if (!STRCMPI(argv[1], "eval"))
1726     {
1727         TestEvalWithSymmetry();
1728     }
1729 #endif
1730
1731     //
1732     // TODO: #ifdef TEST allow individual tests to be run here.
1733     //
1734 }
1735
1736 COMMAND(TimeCommand)
1737 /**
1738
1739 Routine description:
1740
1741     This function implements the '' engine command.
1742
1743     Usage:
1744
1745 Parameters:
1746
1747     The COMMAND macro hides four arguments from the input parser:
1748
1749         CHAR *szInput : the full line of input
1750         ULONG argc    : number of argument chunks
1751         CHAR *argv[]  : array of ptrs to each argument chunk
1752         POSITION *pos : a POSITION pointer to operate on
1753
1754 Return value:
1755
1756     void
1757
1758 **/
1759 {
1760     ULONG x;
1761     
1762     if (argc < 2)
1763     {
1764         Trace("My clock stands at %u sec remaining.\n",
1765               g_Options.uMyClock);
1766         
1767         switch (g_Options.eClock)
1768         {
1769             case CLOCK_FIXED:
1770                 Trace("The move timer is fixed, %u sec / move.\n",
1771                       g_Options.uMyIncrement);
1772                 break;
1773             case CLOCK_NORMAL:
1774                 if (g_Options.uMovesPerTimePeriod != 0)
1775                 {
1776                     Trace("The move timer is normal, %u moves / time "
1777                           "period.\n",
1778                           g_Options.uMovesPerTimePeriod);
1779                 } else {
1780                     Trace("The move timer is normal, finish entire "
1781                           "game in allotted time.\n");
1782                 }
1783                 break;
1784             case CLOCK_INCREMENT:
1785                 Trace("The move timer is increment, additional %u sec "
1786                       "/ move.\n",
1787                       g_Options.uMyIncrement);
1788                 break;
1789             case CLOCK_NONE:
1790             default:
1791                 Trace("The clock and move timer are disabled.\n");
1792                 break;
1793         }
1794     } else {
1795         x = atoi(argv[1]);
1796         if (x >= 0)
1797         {
1798             g_Options.uMyClock = x / 100; // convert to seconds
1799         } else {
1800             Trace("Error (illegal time): %d\n", x);
1801         }
1802     }
1803 }
1804
1805 COMMAND(UndoCommand)
1806 /**
1807
1808 Routine description:
1809
1810     This function implements the '' engine command.  
1811
1812     Usage:
1813     
1814 Parameters:
1815
1816     The COMMAND macro hides four arguments from the input parser:
1817
1818         CHAR *szInput : the full line of input
1819         ULONG argc    : number of argument chunks
1820         CHAR *argv[]  : array of ptrs to each argument chunk
1821         POSITION *pos : a POSITION pointer to operate on
1822
1823 Return value:
1824
1825     void
1826
1827 **/
1828 {
1829     if (FALSE == OfficiallyTakebackMove())
1830     {
1831         Trace("Error (can't undo): %s\n", argv[0]);
1832     }
1833 }
1834
1835 COMMAND(UnratedCommand)
1836 /**
1837
1838 Routine description:
1839
1840     This function implements the '' engine command.  
1841
1842     Usage:
1843     
1844 Parameters:
1845
1846     The COMMAND macro hides four arguments from the input parser:
1847
1848         CHAR *szInput : the full line of input
1849         ULONG argc    : number of argument chunks
1850         CHAR *argv[]  : array of ptrs to each argument chunk
1851         POSITION *pos : a POSITION pointer to operate on
1852
1853 Return value:
1854
1855     void
1856
1857 **/
1858 {
1859     g_Options.fGameIsRated = FALSE;
1860 }
1861
1862
1863 COMMAND(VariantCommand)
1864 /**
1865
1866 Routine description:
1867
1868     This function implements the '' engine command.  
1869
1870     Usage:
1871     
1872 Parameters:
1873
1874     The COMMAND macro hides four arguments from the input parser:
1875
1876         CHAR *szInput : the full line of input
1877         ULONG argc    : number of argument chunks
1878         CHAR *argv[]  : array of ptrs to each argument chunk
1879         POSITION *pos : a POSITION pointer to operate on
1880
1881 Return value:
1882
1883     void
1884
1885 **/
1886 {
1887     Trace("Error (not implemented): %s\n", argv[0]);
1888     Trace("tellics abort\n");
1889     ASSERT(FALSE);
1890 }
1891
1892 COMMAND(VersionCommand)
1893 /**
1894
1895 Routine description:
1896
1897     This function implements the '' engine command.  
1898
1899     Usage:
1900     
1901 Parameters:
1902
1903     The COMMAND macro hides four arguments from the input parser:
1904
1905         CHAR *szInput : the full line of input
1906         ULONG argc    : number of argument chunks
1907         CHAR *argv[]  : array of ptrs to each argument chunk
1908         POSITION *pos : a POSITION pointer to operate on
1909
1910 Return value:
1911
1912     void
1913
1914 **/
1915 {
1916     Banner();
1917 }
1918
1919 COMMAND(WhiteCommand)
1920 /**
1921
1922 Routine description:
1923
1924     This function implements the '' engine command.  
1925
1926     Usage:
1927     
1928 Parameters:
1929
1930     The COMMAND macro hides four arguments from the input parser:
1931
1932         CHAR *szInput : the full line of input
1933         ULONG argc    : number of argument chunks
1934         CHAR *argv[]  : array of ptrs to each argument chunk
1935         POSITION *pos : a POSITION pointer to operate on
1936
1937 Return value:
1938
1939     void
1940
1941 **/
1942 {
1943     TellGamelistThatIPlayColor(BLACK);
1944     g_Options.ePlayMode = I_PLAY_BLACK;
1945     pos->uToMove = WHITE;
1946     pos->u64NonPawnSig = ComputeSig(pos);
1947 }
1948
1949
1950 COMMAND(XboardCommand)
1951 /**
1952
1953 Routine description:
1954
1955     This function implements the '' engine command.  
1956
1957     Usage:
1958     
1959 Parameters:
1960
1961     The COMMAND macro hides four arguments from the input parser:
1962
1963         CHAR *szInput : the full line of input
1964         ULONG argc    : number of argument chunks
1965         CHAR *argv[]  : array of ptrs to each argument chunk
1966         POSITION *pos : a POSITION pointer to operate on
1967
1968 Return value:
1969
1970     void
1971
1972 **/
1973 {
1974     g_Options.fRunningUnderXboard = TRUE;
1975     Trace("\n\n");
1976 }
1977
1978 COMMAND(AcceptedCommand) 
1979 {
1980     ;;
1981 }
1982
1983
1984 // HEREHERE
1985 COMMAND_PARSER_ENTRY g_ParserTable[] = 
1986 {
1987     { "?",
1988       MoveNowCommand,
1989       TRUE,
1990       FALSE,
1991       TRUE,
1992       "Stop thinking and move immediately" },
1993     { ".",
1994       AnalyzeProgressCommand,
1995       TRUE,
1996       FALSE,
1997       TRUE,
1998       "Show engine's current best line when in analyze mode" },
1999     { "accepted",
2000       AcceptedCommand,
2001       TRUE,
2002       TRUE,
2003       TRUE,
2004       "Internal, part of the WinBoard protocol" },
2005     { "analyze",
2006       AnalyzeCommand,
2007       FALSE,
2008       FALSE,
2009       TRUE,
2010       "Enter analyze mode" },
2011     { "avoid",
2012       AvoidCommand,
2013       FALSE,
2014       FALSE,
2015       FALSE,
2016       "Set a move to avoid (up to three)" },
2017     { "bench",
2018       BenchCommand,
2019       FALSE,
2020       FALSE,
2021       FALSE,
2022       "Run a crafty benchmark and show results" },
2023     { "bestmove",
2024       GeneratePositionAndBestMoveSuite,
2025       FALSE,
2026       TRUE,
2027       FALSE,
2028       "Generate a best move suite from a PGN file" },
2029     { "black",
2030       BlackCommand,
2031       FALSE,
2032       FALSE,
2033       TRUE,
2034       "Sets black to move and computer to play white" },
2035     { "book",
2036       BookCommand,
2037       FALSE,
2038       FALSE,
2039       FALSE,
2040       "Manage the opening book" },
2041     { "computer",
2042       ComputerCommand,
2043       TRUE,
2044       FALSE,
2045       FALSE,
2046       "Informs the engine that it is playing another computer" },
2047     { "dump",
2048       DumpCommand,
2049       TRUE,
2050       FALSE,
2051       FALSE,
2052       "Dumps a structure, position, moves, or pgn" },
2053     { "easy",
2054       EasyCommand,
2055       FALSE,
2056       FALSE,
2057       TRUE,
2058       "Disable pondering" },
2059     { "draw",
2060       DrawCommand,
2061       TRUE,
2062       FALSE,
2063       FALSE,
2064       "Offer the engine a draw" },
2065     { "edit",
2066       EditCommand,
2067       FALSE,
2068       TRUE,
2069       TRUE,
2070       "Depreciated command, do not use" },
2071     { "eval",
2072       EvalCommand,
2073       FALSE,
2074       FALSE,
2075       FALSE,
2076       "Run a static eval" },
2077     { "evaldna",
2078       EvalDnaCommand,
2079       FALSE,
2080       FALSE,
2081       FALSE,
2082       "Read or write the DNA from the eval code." },
2083     { "exit",
2084       ExitCommand,
2085       FALSE,
2086       FALSE,
2087       TRUE,
2088       "Leave analyze mode" },
2089     { "force",
2090       ForceCommand,
2091       FALSE,
2092       FALSE,
2093       TRUE,
2094       "Enter force mode, engine plays neither side" },
2095     { "go",
2096       GoCommand,
2097       FALSE,
2098       FALSE,
2099       TRUE,
2100       "Sets engine to play side on move, begin thinking" },
2101     { "hard",
2102       HardCommand,
2103       FALSE,
2104       FALSE,
2105       TRUE,
2106       "Enable pondering" },
2107     { "help",
2108       HelpCommand,
2109       TRUE,
2110       FALSE,
2111       FALSE,
2112       "Show a list of commands available" },
2113     { "hint",
2114       HintCommand,
2115       FALSE,
2116       FALSE,
2117       TRUE,
2118       "Ask the engine for a hint" },
2119     { "id",
2120       IdCommand,
2121       TRUE,
2122       FALSE,
2123       FALSE,
2124       "Set a problem id name" },
2125     { "level",
2126       LevelCommand,
2127       FALSE,
2128       FALSE,
2129       TRUE,
2130       "Sets game time controls" },
2131     { "name",
2132       NameCommand,
2133       TRUE,
2134       FALSE,
2135       FALSE,
2136       "Tell the engine your name" },
2137     { "new",
2138       NewCommand,
2139       FALSE,
2140       FALSE,
2141       TRUE,
2142       "Start a new game" },
2143     { "nopost",
2144       NoPostCommand,
2145       TRUE,
2146       FALSE,
2147       TRUE,
2148       "Do not show thinking" },
2149     { "otim",
2150       OtimCommand,
2151       TRUE,
2152       FALSE,
2153       TRUE,
2154       "Inform the engine about opponent's clock" },
2155     { "perft",
2156       PerftCommand,
2157       FALSE,
2158       FALSE,
2159       FALSE,
2160       "Run a perft test on the move generator code." },
2161     { "ping",
2162       PingCommand,
2163       TRUE,
2164       TRUE,
2165       TRUE,
2166       "Internal part of the WinBoard protocol" },
2167     { "playother",
2168       PlayOtherCommand,
2169       FALSE,
2170       FALSE,
2171       TRUE,
2172       "Play the other side" },
2173     { "post",
2174       PostCommand,
2175       TRUE,
2176       FALSE,
2177       TRUE,
2178       "Show thinking" },    
2179     { "protover",
2180       ProtoverCommand,
2181       TRUE,
2182       TRUE,
2183       TRUE,
2184       "Internal part of the WinBoard protocol" },
2185     { "psqt",
2186       LearnPsqtFromPgn,
2187       FALSE,
2188       TRUE,
2189       FALSE,
2190       "Learn a set of PSQT settings from a PGN file" },
2191     { "quit",
2192       QuitCommand,
2193       TRUE,
2194       FALSE,
2195       FALSE,
2196       "Exit the engine" },
2197     { "random",
2198       RandomCommand,
2199       TRUE,
2200       TRUE,
2201       TRUE,
2202       "no-op" },
2203     { "rated",
2204       RatedCommand,
2205       TRUE,
2206       FALSE,
2207       FALSE,
2208       "Inform the engine that this is a rated game" },
2209     { "rating",
2210       RatingCommand,
2211       TRUE,
2212       FALSE,
2213       TRUE,
2214       "Inform the engine ratings" },
2215     { "remove",
2216       RemoveCommand,
2217       FALSE,
2218       FALSE,
2219       TRUE,
2220       "Take back a full move" },
2221     { "result",
2222       ResultCommand,
2223       FALSE,
2224       FALSE,
2225       TRUE,
2226       "Inform the engine about a game result" },
2227     { "script",
2228       ScriptCommand,
2229       FALSE,
2230       FALSE,
2231       FALSE,
2232       "Run a script" },
2233     { "sd",
2234       SearchDepthCommand, 
2235       TRUE,
2236       FALSE,
2237       TRUE,
2238       "Set engine maximum search depth" },
2239     { "set",
2240       SetCommand,
2241       TRUE,
2242       FALSE,
2243       FALSE,
2244       "View or change an engine variable" },
2245     { "setboard",
2246       SetBoardCommand,
2247       FALSE,
2248       FALSE,
2249       TRUE,
2250       "Load a board position" },
2251     { "solution",
2252       SolutionCommand,
2253       FALSE,
2254       FALSE,
2255       FALSE,
2256       "Set a solution move (up to three)" },
2257     { "sn",
2258       SearchNodesCommand,
2259       FALSE,
2260       FALSE,
2261       TRUE,
2262       "Set the engine max nodes per search limit" },
2263     { "st",
2264       SearchTimeCommand,
2265       FALSE,
2266       FALSE,
2267       TRUE,
2268       "Set the engine search time" },
2269     { "test",
2270       TestCommand,
2271       FALSE,
2272       FALSE,
2273       FALSE,
2274       "Run an internal debugging command" },
2275     { "time",
2276       TimeCommand,
2277       TRUE,
2278       FALSE,
2279       TRUE,
2280       "Tell the engine how its clock stands" },
2281     { "undo",
2282       UndoCommand,
2283       FALSE,
2284       FALSE,
2285       TRUE,
2286       "Take back a halfmove" },
2287     { "unrated",
2288       UnratedCommand,
2289       TRUE,
2290       FALSE,
2291       FALSE,
2292       "Tell the engine that the game is unrated" },
2293     { "variant",
2294       VariantCommand,
2295       FALSE,
2296       FALSE,
2297       TRUE,
2298       "Tell the engine what variant the game is" },    
2299     { "version",
2300       VersionCommand,
2301       TRUE,
2302       FALSE,
2303       FALSE,
2304       "Display current version number and build options" },
2305     { "white",
2306       WhiteCommand,
2307       FALSE,
2308       FALSE,
2309       TRUE,
2310       "Sets white to move, engine plays black" },
2311     { "winboard",
2312       XboardCommand,
2313       TRUE,
2314       TRUE,
2315       TRUE,
2316       "Internal part of the WinBoard protocol" },
2317     { "xboard",
2318       XboardCommand,
2319       TRUE,
2320       TRUE,
2321       TRUE,
2322       "Internal part of the WinBoard protocol" },
2323 };
2324
2325
2326 COMMAND(HelpCommand)
2327 {
2328     char *command = NULL;
2329     ULONG u;
2330
2331     //
2332     // If passed an argument, give help only about that command.
2333     // TODO: divert to a more specific help page here if available.
2334     //
2335     if (argc > 1) 
2336     {
2337         command = argv[1];
2338         for (u = 0; u < ARRAY_LENGTH(g_ParserTable); u++) 
2339         {
2340             if ((!g_ParserTable[u].fInvisible) &&
2341                 (!STRCMPI(command, g_ParserTable[u].szOpcode))) 
2342             {
2343                 Trace("%-13s: %s\n",
2344                       g_ParserTable[u].szOpcode,
2345                       g_ParserTable[u].szSimpleHelp);
2346             }
2347         }
2348         return;
2349     }
2350
2351     //
2352     // Otherwise general help about all commands.
2353     //
2354     Trace("xboard/WinBoard protocol support commands:\n"
2355           "------------------------------------------\n");
2356     for (u = 0; u < ARRAY_LENGTH(g_ParserTable); u++) 
2357     {
2358         if ((g_ParserTable[u].fWinBoard) && (!g_ParserTable[u].fInvisible)) {
2359             Trace("%-13s: %s\n",
2360                   g_ParserTable[u].szOpcode,
2361                   g_ParserTable[u].szSimpleHelp);
2362         }
2363     }
2364     Trace("\nInternal engine commands:\n"
2365           "-------------------------\n");
2366     for (u = 0; u < ARRAY_LENGTH(g_ParserTable); u++) 
2367     {
2368         if ((!g_ParserTable[u].fWinBoard) && (!g_ParserTable[u].fInvisible)) {
2369             Trace("%-13s: %s\n", 
2370                   g_ParserTable[u].szOpcode,
2371                   g_ParserTable[u].szSimpleHelp);
2372         }
2373     }
2374 }
2375
2376
2377 void 
2378 ParseUserInput(FLAG fSearching)
2379 /**
2380
2381 Routine description:
2382
2383 Parameters:
2384
2385     FLAG fSearching
2386
2387 Return value:
2388
2389     void
2390
2391 **/
2392 {
2393     CHAR *pCapturedInput = NULL;
2394     CHAR *pFreeThis = NULL;
2395     CHAR *pDontFree;
2396     CHAR *p, *q;
2397     ULONG u;
2398     CHAR *argv[MAX_ARGS];
2399     ULONG argc = 0;
2400     FLAG fInQuote = FALSE;
2401     MOVE mv;
2402     POSITION *pos = GetRootPosition();
2403 #if 0
2404     static ULONG uHeapAllocated = 0;
2405
2406     if (0 == uHeapAllocated)
2407     {
2408         uHeapAllocated = GetHeapMemoryUsage();
2409     } else {
2410         ASSERT(uHeapAllocated == GetHeapMemoryUsage());
2411         uHeapAllocated = GetHeapMemoryUsage();
2412     }
2413 #endif
2414     //
2415     // If we are in batch mode and there is no waiting input, exit.
2416     //
2417     if (g_Options.fNoInputThread && (0 == NumberOfPendingInputEvents()))
2418     {
2419         Trace("Exhausted input in batch mode, exiting...\n");
2420         exit(-1);
2421     }
2422     
2423         //
2424         // By the time we see this the input thread is likely already
2425         // exited so don't try to read from the queue...
2426         //
2427     if (g_fExitProgram == TRUE) 
2428     {
2429                 QuitCommand("quit", 1, NULL, pos);
2430                 return;
2431         }
2432     
2433     //
2434     // If we are searching, don't actually read the input event yet. 
2435     // Just peek and leave it there until we know whether we can do 
2436     // it or not.
2437     //
2438     if (TRUE == fSearching)
2439     {
2440         ASSERT(g_Options.fPondering || g_Options.fThinking);
2441         p = pDontFree = PeekNextInput();
2442     } else {
2443         p = pFreeThis = BlockingReadInput();
2444     }
2445     if (NULL == p) 
2446     {
2447         goto end;
2448     }
2449     
2450     //
2451     // Skip over leading whitespace and do not parse comment lines
2452     //
2453     while((*p) && (isspace(*p))) p++;
2454     if (((*p) && (*p == '#')) ||
2455         ((*p) && (*(p+1)) && (*p == '/') && (*(p+1) == '/')))
2456     {
2457         goto consume_if_searching;
2458     }
2459
2460     //
2461     // Chop the last \n out of the string
2462     //
2463     q = p;
2464     while(*q)
2465     {
2466         if (*q == '\n') 
2467         {
2468             *q = '\0';
2469             break;
2470         }
2471         q++;
2472     }
2473
2474     //
2475     // Break it up into chunks for the COMMAND functions.
2476     //
2477     pCapturedInput = STRDUP(p);
2478     memset(argv, 0, sizeof(argv));
2479     do
2480     {
2481         while(*p && isspace(*p)) p++;
2482         if (!*p) break;
2483         argv[argc++] = p;
2484         fInQuote = FALSE;
2485         while (*p)
2486         {
2487             if (*p == '"')
2488             {
2489                 fInQuote = !fInQuote;
2490             }
2491             else if (*p == '{')
2492             {
2493                 fInQuote = TRUE;
2494             }
2495             else if (*p == '}')
2496             {
2497                 fInQuote = FALSE;
2498             }
2499             else if (isspace(*p) && (FALSE == fInQuote))
2500             {
2501                 break;
2502             }
2503             p++;
2504         }
2505         if (!*p) break;
2506         *p = '\0';
2507         p++;
2508     }
2509     while(argc < MAX_ARGS);
2510     if (argc == 0) 
2511     {
2512         goto consume_if_searching;
2513     }
2514     
2515     //
2516     // Does it look like a move?
2517     //
2518     mv.uMove = 0;
2519     switch(LooksLikeMove(argv[0]))
2520     {
2521         case MOVE_SAN:
2522             mv = ParseMoveSan(argv[0], pos);
2523             break;
2524         case MOVE_ICS:
2525             mv = ParseMoveIcs(argv[0], pos);
2526             break;
2527         case NOT_MOVE:
2528             for (u = 0; u < ARRAY_LENGTH(g_ParserTable); u++)
2529             {
2530                 if (!STRCMPI(g_ParserTable[u].szOpcode, argv[0]))
2531                 {
2532                     if (TRUE == fSearching) 
2533                     {
2534                         if (TRUE == g_ParserTable[u].fHandleOnTheFly)
2535                         {
2536                             //
2537                             // We can do that command on the fly in
2538                             // the middle of the search.  Note: these
2539                             // commands MUST NOT affect anything that
2540                             // the search is doing or you'll get
2541                             // corruption.
2542                             //
2543                             (*g_ParserTable[u].pFunction)
2544                                 (pCapturedInput, argc, argv, pos);
2545                             goto consume_if_searching;
2546                         } else {
2547                             //
2548                             // We can't handle that input without
2549                             // unrolling the search first.
2550                             //
2551                             Trace("COMPLEX INPUT --> stop searching now\n");
2552                             ASSERT(pDontFree);
2553                             strcpy(pDontFree, pCapturedInput);
2554                             g_MoveTimer.bvFlags |= TIMER_STOPPING;
2555                             goto end;
2556                         }
2557                     } else {
2558                         //
2559                         // We were called from the main loop or from
2560                         // the script parser.  No one is searching.
2561                         // Just do the command.
2562                         //
2563                         (*g_ParserTable[u].pFunction)
2564                             (pCapturedInput, argc, argv, pos);
2565                         goto end;
2566                     }
2567                 }
2568             }
2569             if ((TRUE == LooksLikeFen(pCapturedInput)) &&
2570                 (TRUE == SetRootPosition(pCapturedInput)))
2571             {
2572                 goto end;
2573             }
2574             break;
2575 #ifdef DEBUG
2576         default:
2577             UtilPanic(SHOULD_NOT_GET_HERE,
2578                       NULL, NULL, NULL, NULL, 
2579                       __FILE__, __LINE__);
2580             break;
2581 #endif
2582     }
2583     
2584     //
2585     // Was it a move?
2586     //
2587     if (mv.uMove)
2588     {
2589         if (fSearching == TRUE)
2590         {
2591             //
2592             // No one should move (my pieces) while I'm thinking!
2593             //
2594             ASSERT(g_Options.fPondering == TRUE);
2595             ASSERT(g_Options.fThinking == FALSE);
2596             if (IS_SAME_MOVE(mv, g_Options.mvPonder))
2597             {
2598                 Trace("PREDICTED MOVE PLAYED --> converting to search\n");
2599                 g_Options.fSuccessfulPonder = TRUE;
2600                 g_Options.fPondering = FALSE;
2601                 g_Options.fThinking = TRUE;
2602                 SetMoveTimerForSearch(TRUE, FLIP(GET_COLOR(mv.pMoved)));
2603                 goto consume_if_searching;
2604             } else {
2605                 g_MoveTimer.bvFlags |= TIMER_STOPPING;
2606                 if (TRUE == OfficiallyMakeMove(mv, 0, FALSE))
2607                 {
2608                     Trace("NONPREDICTED MOVE PLAYED --> stop pondering now\n");
2609                     goto end;
2610                 } else {
2611                     UtilPanic(GOT_ILLEGAL_MOVE_WHILE_PONDERING,
2612                               GetRootPosition(),
2613                               (void *)mv.uMove,
2614                               NULL,
2615                               NULL,
2616                               __FILE__, __LINE__);
2617                 }
2618             }
2619         } else {
2620             if (FALSE == OfficiallyMakeMove(mv, 0, FALSE))
2621             {
2622                 UtilPanic(CANNOT_OFFICIALLY_MAKE_MOVE,
2623                           GetRootPosition(),
2624                           (void *)mv.uMove,
2625                           NULL,
2626                           NULL,
2627                           __FILE__, __LINE__);
2628             }
2629         }
2630     } else {
2631         Trace("Unknown/illegal move/command: \"%s\"\n", pCapturedInput);
2632     }
2633
2634  consume_if_searching:
2635     if (TRUE == fSearching)
2636     {
2637         ASSERT(NULL == pFreeThis);
2638         ASSERT(NumberOfPendingInputEvents() > 0);
2639         pFreeThis = BlockingReadInput();
2640     }
2641     // fall through
2642     
2643  end:
2644     if (NULL != pFreeThis)
2645     {
2646         SystemFreeMemory(pFreeThis);
2647         pFreeThis = NULL;
2648     }
2649     if (NULL != pCapturedInput)
2650     {
2651         SystemFreeMemory(pCapturedInput);
2652         pCapturedInput = NULL;
2653     }
2654 //    ASSERT(uHeapAllocated == GetHeapMemoryUsage());
2655 }