3 Copyright (c) Scott Gasch
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:
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
26 $Id: command.c 354 2008-06-30 05:10:08Z scott $
33 int g_eModeBeforeAnalyze = -1;
35 typedef void (COMMAND_PARSER_FUNCTION)(CHAR *szInput,
39 typedef struct _COMMAND_PARSER_ENTRY
42 COMMAND_PARSER_FUNCTION *pFunction;
51 COMMAND(AnalyzeCommand)
56 This function implements the 'analyze' engine command.
62 This command takes no arguments and causes the engine to enter
63 analyze mode. See also: exit
67 The COMMAND macro hides four arguments from the input parser:
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
80 if (g_Options.ePlayMode != ANALYZE_MODE)
82 g_eModeBeforeAnalyze = g_Options.ePlayMode;
83 g_Options.ePlayMode = ANALYZE_MODE;
87 COMMAND(AnalyzeProgressCommand)
92 This function implements the 'analyzeprogressreport' engine
99 This command takes no arguments and causes the engine to dump
100 the current analysis.
104 The COMMAND macro hides four arguments from the input parser:
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
117 if (g_Options.ePlayMode == ANALYZE_MODE)
119 Trace("%s\n", g_Options.szAnalyzeProgressReport);
123 COMMAND(BlackCommand)
128 This function implements the 'black' engine command.
134 This command takes no arguments and causes the engine to play
135 white and set black to move.
139 The COMMAND macro hides four arguments from the input parser:
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
152 TellGamelistThatIPlayColor(WHITE);
153 g_Options.ePlayMode = I_PLAY_WHITE;
154 pos->uToMove = BLACK;
155 pos->u64NonPawnSig = ComputeSig(pos);
159 COMMAND(BoardCommand)
164 This function implements the 'board' engine command.
170 This command takes no arguments and displays the current board
171 position on stdout and in the log.
175 The COMMAND macro hides four arguments from the input parser:
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
191 COMMAND(ComputerCommand)
196 This function implements the 'computer' engine command.
202 This command takes no argument and informs the engine that it
203 is playing against another computer.
207 The COMMAND macro hides four arguments from the input parser:
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
220 g_Options.fOpponentIsComputer = TRUE;
221 Trace("tellics +alias whisper kib\n");
226 //if (g_iNumDrawScoresInARow > 4)
228 // ToXboard("tellopponent I accept your draw offer.\n");
229 // ToXboard("tellics draw\n");
233 //Trace("tellopponent Sorry I do not accept your draw offer at "
235 //Trace("tellics decline draw\n");
241 // TODO: timestamp command
250 Dump the sizes of some internal data structures on stdout.
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;
302 This function implements the 'dump' engine command.
310 dump eval [optional coor]
313 This command is used to dump internal information to the
316 When used with the 'board' argument, a dump of the internal
317 representation of the current board position is produced.
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.
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.
325 When used with the 'sizes' argument, a dump of internal data
326 structure sizes is produced.
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.
337 The COMMAND macro hides four arguments from the input parser:
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
356 Trace("Error (missing argument)\n");
359 if (!STRCMPI(argv[1], "board"))
363 else if (!STRCMPI(argv[1], "moves"))
367 else if (!STRCMPI(argv[1], "pgn"))
371 else if (!STRCMPI(argv[1], "sizes"))
375 else if (!STRCMPI(argv[1], "evaldna"))
377 char *p = ExportEvalDNA();
378 Trace("EvalDNA: %s\n", p);
382 else if (!STRCMPI(argv[1], "eval"))
390 if (!STRCMPI(argv[2], "terms"))
394 if (LooksLikeCoor(argv[2]))
396 c = FILE_RANK_TO_COOR((tolower(argv[2][0]) - 'a'),
397 (tolower(argv[2][1]) - '0'));
398 (void)EvalSigmaForPiece(pos, c);
400 (void)EvalSigmaForPiece(pos, ILLEGAL_COOR);
413 This function implements the 'easy' engine command.
419 This command takes no arguments and causes the engine not to
420 think on the opponent's time (i.e. not to ponder)
424 The COMMAND macro hides four arguments from the input parser:
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
437 g_Options.fShouldPonder = FALSE;
445 This function implements the 'edit' engine command.
449 This command is deprecated and should not be used.
453 The COMMAND macro hides four arguments from the input parser:
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
466 Trace("Error (obsolete command): %s\n", argv[0]);
467 Trace("\nPlease upgrade your version of xboard at "
468 "http://www.timmann.org/\n");
476 This function implements the 'eval' engine command.
482 This command takes no arguments and causes the engine to print
483 out a static evaluation of the current board position.
487 The COMMAND macro hides four arguments from the input parser:
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
500 SEARCHER_THREAD_CONTEXT *ctx;
503 ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
506 InitializeSearcherContext(pos, ctx);
507 i = Eval(ctx, -INFINITY, +INFINITY);
508 Trace("Static eval: %s\n", ScoreToString(i));
509 SystemFreeMemory(ctx);
511 Trace("Out of memory.\n");
516 COMMAND(EvalDnaCommand)
521 This function implements the 'evaldna' engine command.
525 evaldna write <filename>
526 evaldna read <filename>
531 The COMMAND macro hides four arguments from the input parser:
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
547 Trace("Usage: evaldna <read | write> <filename>\n"
551 if (!STRCMPI(argv[1], "write"))
554 Trace("Error (missing argument)\n");
557 if (!WriteEvalDNA(argv[2]))
559 Trace("Error writing dna file.\n");
561 Trace("DNA file written.\n");
564 else if (!STRCMPI(argv[1], "read") ||
565 !STRCMPI(argv[1], "load"))
568 Trace("Error (missing argument)\n");
571 if (!ReadEvalDNA(argv[2]))
573 Trace("Error reading dna file.\n");
575 Trace("Loaded dna file \"%s\"\n", argv[2]);
577 Log("(New) dna: %s\n", p);
581 else if (!STRCMPI(argv[1], "dump"))
584 Trace("EvalDNA: %s\n", p);
595 This function implements the 'exit' engine command.
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
607 The COMMAND macro hides four arguments from the input parser:
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
620 if (g_Options.ePlayMode == ANALYZE_MODE)
622 ASSERT(g_eModeBeforeAnalyze != ANALYZE_MODE);
623 g_Options.ePlayMode = g_eModeBeforeAnalyze;
627 COMMAND(ForceCommand)
632 This function implements the 'force' engine command.
638 This command takes no arguments and causes the engine to enter
639 'force mode'. In this mode it will play neither side.
643 The COMMAND macro hides four arguments from the input parser:
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
656 TellGamelistThatIPlayColor(BLACK);
657 g_Options.ePlayMode = FORCE_MODE;
660 COMMAND(GenerateCommand)
665 This function is not directly callable. See 'test generate'
670 The COMMAND macro hides four arguments from the input parser:
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
683 SEARCHER_THREAD_CONTEXT *ctx;
687 ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
690 memcpy(&(ctx->sPosition), pos, sizeof(POSITION));
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];
699 mv = ctx->sMoveStack.mvf[u].mv;
700 if (MakeMove(ctx, mv))
702 ASSERT(!InCheck(&(ctx->sPosition), GET_COLOR(mv.pMoved)));
705 Trace("%2u. %s (%d)\t",
707 MoveToSan(mv, &(ctx->sPosition)),
708 ctx->sMoveStack.mvf[u].iValue);
715 Trace("\n%u legal move(s).\n", uLegal);
716 SystemFreeMemory(ctx);
720 COMMAND(PlayOtherCommand)
725 This function implements the '' engine command.
731 The COMMAND macro hides four arguments from the input parser:
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
744 if (pos->uToMove == WHITE)
746 TellGamelistThatIPlayColor(BLACK);
747 g_Options.ePlayMode = I_PLAY_BLACK;
749 ASSERT(pos->uToMove == BLACK);
750 TellGamelistThatIPlayColor(WHITE);
751 g_Options.ePlayMode = I_PLAY_WHITE;
761 This function implements the 'go' engine command.
767 The COMMAND macro hides four arguments from the input parser:
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
780 if (pos->uToMove == WHITE)
782 TellGamelistThatIPlayColor(WHITE);
783 g_Options.ePlayMode = I_PLAY_WHITE;
785 ASSERT(pos->uToMove == BLACK);
786 TellGamelistThatIPlayColor(BLACK);
787 g_Options.ePlayMode = I_PLAY_BLACK;
793 g_Options.fShouldPonder = TRUE;
796 COMMAND(HelpCommand);
803 This function implements the '' engine command.
809 The COMMAND macro hides four arguments from the input parser:
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
822 Trace("Error (not implemented): %s\n", argv[0]);
825 CHAR *OnlyDigits(CHAR *sz)
827 static CHAR out[SMALL_STRING_LEN_CHAR];
831 while((*sz) && (uCount < SMALL_STRING_LEN_CHAR))
843 COMMAND(LevelCommand)
848 This function implements the '' engine command.
854 The COMMAND macro hides four arguments from the input parser:
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
871 Trace("Error (syntax): %s\n", argv[0]);
873 g_Options.uMovesPerTimePeriod = atoi(OnlyDigits(argv[1]));
874 g_Options.uMyClock = atoi(OnlyDigits(argv[2]));
875 g_Options.uMyIncrement = atoi(OnlyDigits(argv[3]));
877 g_Options.eClock = CLOCK_NORMAL;
878 if (g_Options.uMyIncrement)
880 g_Options.eClock = CLOCK_INCREMENT;
883 x = (g_Options.uMyClock + ((g_Options.uMyIncrement * 2) / 3));
884 g_Options.uMyClock *= 60;
886 Trace("etime = %u (clock %u and inc %u)\n", x,
887 g_Options.uMyClock, g_Options.uMyIncrement);
890 Trace("bullet game\n");
891 g_Options.eGameType = GAME_BULLET;
895 Trace("blitz game\n");
896 g_Options.eGameType = GAME_BLITZ;
898 Trace("standard game\n");
899 g_Options.eGameType = GAME_STANDARD;
904 COMMAND(MoveNowCommand)
909 This function implements the '' engine command.
915 The COMMAND macro hides four arguments from the input parser:
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
928 Trace("MOVE NOW COMMAND --> stop searching now\n");
929 g_MoveTimer.bvFlags |= TIMER_STOPPING;
932 COMMAND(MovesCommand)
937 This function implements the '' engine command.
943 The COMMAND macro hides four arguments from the input parser:
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
959 COMMAND(XboardCommand);
965 This function implements the '' engine command.
971 The COMMAND macro hides four arguments from the input parser:
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
986 XboardCommand(szInput, argc, argv, pos);
988 SetOpponentsName(argv[1]);
997 This function implements the '' engine command.
1003 The COMMAND macro hides four arguments from the input parser:
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
1016 Trace("tellics -alias whisp*\n");
1018 TellGamelistThatIPlayColor(BLACK);
1019 g_Options.ePlayMode = I_PLAY_BLACK;
1020 g_Options.uMaxDepth = MAX_PLY_PER_SEARCH - 1;
1023 COMMAND(NoPostCommand)
1026 Routine description:
1028 This function implements the '' engine command.
1034 The COMMAND macro hides four arguments from the input parser:
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
1047 g_Options.fShouldPost = FALSE;
1050 COMMAND(OtimCommand)
1053 Routine description:
1055 This function implements the '' engine command.
1061 The COMMAND macro hides four arguments from the input parser:
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
1078 Trace("My opponent's clock stands at %u sec remaining.\n",
1079 g_Options.uOpponentsClock);
1081 switch (g_Options.eClock)
1084 Trace("The move timer is fixed, %u sec / move.\n",
1085 g_Options.uMyIncrement);
1088 if (g_Options.uMovesPerTimePeriod != 0)
1090 Trace("The move timer is normal, %u moves / time "
1092 g_Options.uMovesPerTimePeriod);
1094 Trace("The move timer is normal, finish entire "
1095 "game in allotted time.\n");
1098 case CLOCK_INCREMENT:
1099 Trace("The move timer is increment, additional %u sec "
1101 g_Options.uMyIncrement);
1105 Trace("The clock and move timer are disabled.\n");
1112 g_Options.uOpponentsClock = x / 100; // convert to seconds
1114 Trace("Error (invalid time): %d\n", x);
1119 COMMAND(PingCommand)
1122 Routine description:
1124 This function implements the '' engine command.
1130 The COMMAND macro hides four arguments from the input parser:
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
1145 Trace("pong %s\n", argv[1]);
1149 COMMAND(PostCommand)
1152 Routine description:
1154 This function implements the '' engine command.
1160 The COMMAND macro hides four arguments from the input parser:
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
1173 g_Options.fShouldPost = TRUE;
1176 COMMAND(ProtoverCommand)
1179 Routine description:
1181 This function implements the '' engine command.
1187 The COMMAND macro hides four arguments from the input parser:
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
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);
1205 COMMAND(QuitCommand)
1208 Routine description:
1210 This function implements the 'quit' engine command.
1216 The COMMAND macro hides four arguments from the input parser:
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
1234 // Stop searching; if we are on an MP box wait until all helper
1235 // threads return to the idle state and exit.
1237 g_MoveTimer.bvFlags |= TIMER_STOPPING;
1242 SystemDeferExecution(100);
1243 if (++u == 5) break;
1245 while(g_uNumHelpersAvailable != g_uNumHelperThreads);
1249 // We should be the last thread in the process now.
1253 COMMAND(RatedCommand)
1256 Routine description:
1258 This function implements the '' engine command.
1264 The COMMAND macro hides four arguments from the input parser:
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
1277 g_Options.fGameIsRated = TRUE;
1280 COMMAND(RatingCommand)
1283 Routine description:
1285 This function implements the '' engine command.
1291 The COMMAND macro hides four arguments from the input parser:
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
1308 Trace("Error (bad usage): %s\n", argv[0]);
1318 SetOpponentsRating(x);
1323 COMMAND(RandomCommand)
1326 Routine description:
1328 This function implements the '' engine command.
1334 The COMMAND macro hides four arguments from the input parser:
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
1347 Trace("%u\n", rand());
1350 COMMAND(RemoveCommand)
1353 Routine description:
1355 This function implements the '' engine command.
1361 The COMMAND macro hides four arguments from the input parser:
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
1374 if (TRUE == OfficiallyTakebackMove())
1376 if (TRUE == OfficiallyTakebackMove())
1381 Trace("Error (unable to takeback move)\n");
1384 COMMAND(ResultCommand)
1387 Routine description:
1389 This function implements the '' engine command.
1395 The COMMAND macro hides four arguments from the input parser:
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
1409 result.eResult = RESULT_UNKNOWN;
1410 result.szDescription[0] = '\0';
1414 Trace("Argc was %u\n", argc);
1415 Trace("Usage: result <result> [optional comment]\n");
1417 if (!STRNCMPI("1-0", argv[1], 3))
1419 result.eResult = RESULT_WHITE_WON;
1421 else if (!STRNCMPI("0-1", argv[1], 3))
1423 result.eResult = RESULT_BLACK_WON;
1425 else if ((!STRNCMPI("1/2", argv[1], 3)) ||
1426 (!STRNCMPI("=", argv[1], 1)))
1428 result.eResult = RESULT_DRAW;
1431 strncpy(result.szDescription, argv[2], 256);
1433 SetGameResultAndDescription(result);
1434 if (g_Options.ePlayMode != FORCE_MODE)
1437 TellGamelistThatIPlayColor(BLACK);
1438 g_Options.ePlayMode = FORCE_MODE;
1443 COMMAND(SearchDepthCommand)
1446 Routine description:
1448 This function implements the '' engine command.
1454 The COMMAND macro hides four arguments from the input parser:
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
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);
1479 Trace("Error (illegal depth): %d\n", x);
1481 else if (x >= MAX_PLY_PER_SEARCH)
1483 Trace("Error (my max depth is %u): %u\n",
1484 MAX_PLY_PER_SEARCH - 1, x);
1486 g_Options.uMaxDepth = x;
1491 COMMAND(SearchNodesCommand)
1494 Routine description:
1496 This function implements the '' engine command.
1502 The COMMAND macro hides four arguments from the input parser:
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
1519 g_Options.u64MaxNodeCount = 0;
1520 Trace("Search nodecount limit disabled.\n");
1522 x = strtoull(argv[1], NULL, 10);
1525 g_Options.u64MaxNodeCount = x;
1526 Trace("Search node limit set to %llu.\n", x);
1528 g_Options.u64MaxNodeCount = 0;
1529 Trace("Search nodecount limit disabled.\n");
1535 COMMAND(SearchTimeCommand)
1538 Routine description:
1540 This function implements the '' engine command.
1546 The COMMAND macro hides four arguments from the input parser:
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
1563 Trace("My clock stands at %u sec remaining.\n",
1564 g_Options.uMyClock);
1565 switch (g_Options.eClock)
1568 Trace("The move timer is fixed, %u sec / move.\n",
1569 g_Options.uMyIncrement);
1572 if (g_Options.uMovesPerTimePeriod != 0)
1574 Trace("The move timer is normal, %u moves / "
1576 g_Options.uMovesPerTimePeriod);
1578 Trace("The move timer is normal, finish entire game in "
1579 "allotted time.\n");
1582 case CLOCK_INCREMENT:
1583 Trace("The move timer is increment, additional %u sec "
1585 g_Options.uMyIncrement);
1589 Trace("The clock and move timer are disabled.\n");
1596 g_Options.uMyIncrement = x;
1597 g_Options.eClock = CLOCK_FIXED;
1599 Trace("Error (illegal time per move): %u\n", x);
1604 COMMAND(SetBoardCommand)
1607 Routine description:
1609 This function implements the '' engine command.
1615 The COMMAND macro hides four arguments from the input parser:
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
1632 if (NULL != (p = PositionToFen(pos)))
1634 Trace("Current board FEN is: %s\n", p);
1635 SystemFreeMemory(p);
1638 p = szInput + (argv[1] - argv[0]);
1639 if (FALSE == SetRootPosition(p))
1641 Trace("Error (malformed FEN): %s\n", p);
1644 VERIFY(PreGameReset(FALSE));
1645 g_Options.ePlayMode = FORCE_MODE;
1656 Trace("Usage: test see <required-move>\n");
1659 switch(LooksLikeMove(argv[2]))
1662 mv = ParseMoveSan(argv[2], pos);
1665 mv = ParseMoveIcs(argv[2], pos);
1672 Trace("Error (invalid move): '%s'\n", argv[2]);
1676 Trace("SEE says that the value of move '%s' is %d\n", argv[2], s);
1680 COMMAND(TestCommand)
1683 Routine description:
1685 This function implements the 'test' engine command.
1691 The COMMAND macro hides four arguments from the input parser:
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
1706 Trace("Error (missing argument)\n");
1710 if (!STRCMPI(argv[1], "generate"))
1712 GenerateCommand(szInput, argc, argv, pos);
1714 else if (!STRCMPI(argv[1], "draw"))
1716 Trace("drawcount = %u\n",
1717 CountOccurrancesOfSigInOfficialGameList(pos->u64NonPawnSig ^
1720 else if (!STRCMPI(argv[1], "see"))
1722 SEECommand(szInput, argc, argv, pos);
1725 else if (!STRCMPI(argv[1], "eval"))
1727 TestEvalWithSymmetry();
1732 // TODO: #ifdef TEST allow individual tests to be run here.
1736 COMMAND(TimeCommand)
1739 Routine description:
1741 This function implements the '' engine command.
1747 The COMMAND macro hides four arguments from the input parser:
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
1764 Trace("My clock stands at %u sec remaining.\n",
1765 g_Options.uMyClock);
1767 switch (g_Options.eClock)
1770 Trace("The move timer is fixed, %u sec / move.\n",
1771 g_Options.uMyIncrement);
1774 if (g_Options.uMovesPerTimePeriod != 0)
1776 Trace("The move timer is normal, %u moves / time "
1778 g_Options.uMovesPerTimePeriod);
1780 Trace("The move timer is normal, finish entire "
1781 "game in allotted time.\n");
1784 case CLOCK_INCREMENT:
1785 Trace("The move timer is increment, additional %u sec "
1787 g_Options.uMyIncrement);
1791 Trace("The clock and move timer are disabled.\n");
1798 g_Options.uMyClock = x / 100; // convert to seconds
1800 Trace("Error (illegal time): %d\n", x);
1805 COMMAND(UndoCommand)
1808 Routine description:
1810 This function implements the '' engine command.
1816 The COMMAND macro hides four arguments from the input parser:
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
1829 if (FALSE == OfficiallyTakebackMove())
1831 Trace("Error (can't undo): %s\n", argv[0]);
1835 COMMAND(UnratedCommand)
1838 Routine description:
1840 This function implements the '' engine command.
1846 The COMMAND macro hides four arguments from the input parser:
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
1859 g_Options.fGameIsRated = FALSE;
1863 COMMAND(VariantCommand)
1866 Routine description:
1868 This function implements the '' engine command.
1874 The COMMAND macro hides four arguments from the input parser:
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
1887 Trace("Error (not implemented): %s\n", argv[0]);
1888 Trace("tellics abort\n");
1892 COMMAND(VersionCommand)
1895 Routine description:
1897 This function implements the '' engine command.
1903 The COMMAND macro hides four arguments from the input parser:
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
1919 COMMAND(WhiteCommand)
1922 Routine description:
1924 This function implements the '' engine command.
1930 The COMMAND macro hides four arguments from the input parser:
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
1943 TellGamelistThatIPlayColor(BLACK);
1944 g_Options.ePlayMode = I_PLAY_BLACK;
1945 pos->uToMove = WHITE;
1946 pos->u64NonPawnSig = ComputeSig(pos);
1950 COMMAND(XboardCommand)
1953 Routine description:
1955 This function implements the '' engine command.
1961 The COMMAND macro hides four arguments from the input parser:
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
1974 g_Options.fRunningUnderXboard = TRUE;
1978 COMMAND(AcceptedCommand)
1985 COMMAND_PARSER_ENTRY g_ParserTable[] =
1992 "Stop thinking and move immediately" },
1994 AnalyzeProgressCommand,
1998 "Show engine's current best line when in analyze mode" },
2004 "Internal, part of the WinBoard protocol" },
2010 "Enter analyze mode" },
2016 "Set a move to avoid (up to three)" },
2022 "Run a crafty benchmark and show results" },
2024 GeneratePositionAndBestMoveSuite,
2028 "Generate a best move suite from a PGN file" },
2034 "Sets black to move and computer to play white" },
2040 "Manage the opening book" },
2046 "Informs the engine that it is playing another computer" },
2052 "Dumps a structure, position, moves, or pgn" },
2058 "Disable pondering" },
2064 "Offer the engine a draw" },
2070 "Depreciated command, do not use" },
2076 "Run a static eval" },
2082 "Read or write the DNA from the eval code." },
2088 "Leave analyze mode" },
2094 "Enter force mode, engine plays neither side" },
2100 "Sets engine to play side on move, begin thinking" },
2106 "Enable pondering" },
2112 "Show a list of commands available" },
2118 "Ask the engine for a hint" },
2124 "Set a problem id name" },
2130 "Sets game time controls" },
2136 "Tell the engine your name" },
2142 "Start a new game" },
2148 "Do not show thinking" },
2154 "Inform the engine about opponent's clock" },
2160 "Run a perft test on the move generator code." },
2166 "Internal part of the WinBoard protocol" },
2172 "Play the other side" },
2184 "Internal part of the WinBoard protocol" },
2190 "Learn a set of PSQT settings from a PGN file" },
2196 "Exit the engine" },
2208 "Inform the engine that this is a rated game" },
2214 "Inform the engine ratings" },
2220 "Take back a full move" },
2226 "Inform the engine about a game result" },
2238 "Set engine maximum search depth" },
2244 "View or change an engine variable" },
2250 "Load a board position" },
2256 "Set a solution move (up to three)" },
2262 "Set the engine max nodes per search limit" },
2268 "Set the engine search time" },
2274 "Run an internal debugging command" },
2280 "Tell the engine how its clock stands" },
2286 "Take back a halfmove" },
2292 "Tell the engine that the game is unrated" },
2298 "Tell the engine what variant the game is" },
2304 "Display current version number and build options" },
2310 "Sets white to move, engine plays black" },
2316 "Internal part of the WinBoard protocol" },
2322 "Internal part of the WinBoard protocol" },
2326 COMMAND(HelpCommand)
2328 char *command = NULL;
2332 // If passed an argument, give help only about that command.
2333 // TODO: divert to a more specific help page here if available.
2338 for (u = 0; u < ARRAY_LENGTH(g_ParserTable); u++)
2340 if ((!g_ParserTable[u].fInvisible) &&
2341 (!STRCMPI(command, g_ParserTable[u].szOpcode)))
2343 Trace("%-13s: %s\n",
2344 g_ParserTable[u].szOpcode,
2345 g_ParserTable[u].szSimpleHelp);
2352 // Otherwise general help about all commands.
2354 Trace("xboard/WinBoard protocol support commands:\n"
2355 "------------------------------------------\n");
2356 for (u = 0; u < ARRAY_LENGTH(g_ParserTable); u++)
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);
2364 Trace("\nInternal engine commands:\n"
2365 "-------------------------\n");
2366 for (u = 0; u < ARRAY_LENGTH(g_ParserTable); u++)
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);
2378 ParseUserInput(FLAG fSearching)
2381 Routine description:
2393 CHAR *pCapturedInput = NULL;
2394 CHAR *pFreeThis = NULL;
2398 CHAR *argv[MAX_ARGS];
2400 FLAG fInQuote = FALSE;
2402 POSITION *pos = GetRootPosition();
2404 static ULONG uHeapAllocated = 0;
2406 if (0 == uHeapAllocated)
2408 uHeapAllocated = GetHeapMemoryUsage();
2410 ASSERT(uHeapAllocated == GetHeapMemoryUsage());
2411 uHeapAllocated = GetHeapMemoryUsage();
2415 // If we are in batch mode and there is no waiting input, exit.
2417 if (g_Options.fNoInputThread && (0 == NumberOfPendingInputEvents()))
2419 Trace("Exhausted input in batch mode, exiting...\n");
2424 // By the time we see this the input thread is likely already
2425 // exited so don't try to read from the queue...
2427 if (g_fExitProgram == TRUE)
2429 QuitCommand("quit", 1, NULL, pos);
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
2438 if (TRUE == fSearching)
2440 ASSERT(g_Options.fPondering || g_Options.fThinking);
2441 p = pDontFree = PeekNextInput();
2443 p = pFreeThis = BlockingReadInput();
2451 // Skip over leading whitespace and do not parse comment lines
2453 while((*p) && (isspace(*p))) p++;
2454 if (((*p) && (*p == '#')) ||
2455 ((*p) && (*(p+1)) && (*p == '/') && (*(p+1) == '/')))
2457 goto consume_if_searching;
2461 // Chop the last \n out of the string
2475 // Break it up into chunks for the COMMAND functions.
2477 pCapturedInput = STRDUP(p);
2478 memset(argv, 0, sizeof(argv));
2481 while(*p && isspace(*p)) p++;
2489 fInQuote = !fInQuote;
2499 else if (isspace(*p) && (FALSE == fInQuote))
2509 while(argc < MAX_ARGS);
2512 goto consume_if_searching;
2516 // Does it look like a move?
2519 switch(LooksLikeMove(argv[0]))
2522 mv = ParseMoveSan(argv[0], pos);
2525 mv = ParseMoveIcs(argv[0], pos);
2528 for (u = 0; u < ARRAY_LENGTH(g_ParserTable); u++)
2530 if (!STRCMPI(g_ParserTable[u].szOpcode, argv[0]))
2532 if (TRUE == fSearching)
2534 if (TRUE == g_ParserTable[u].fHandleOnTheFly)
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
2543 (*g_ParserTable[u].pFunction)
2544 (pCapturedInput, argc, argv, pos);
2545 goto consume_if_searching;
2548 // We can't handle that input without
2549 // unrolling the search first.
2551 Trace("COMPLEX INPUT --> stop searching now\n");
2553 strcpy(pDontFree, pCapturedInput);
2554 g_MoveTimer.bvFlags |= TIMER_STOPPING;
2559 // We were called from the main loop or from
2560 // the script parser. No one is searching.
2561 // Just do the command.
2563 (*g_ParserTable[u].pFunction)
2564 (pCapturedInput, argc, argv, pos);
2569 if ((TRUE == LooksLikeFen(pCapturedInput)) &&
2570 (TRUE == SetRootPosition(pCapturedInput)))
2577 UtilPanic(SHOULD_NOT_GET_HERE,
2578 NULL, NULL, NULL, NULL,
2579 __FILE__, __LINE__);
2589 if (fSearching == TRUE)
2592 // No one should move (my pieces) while I'm thinking!
2594 ASSERT(g_Options.fPondering == TRUE);
2595 ASSERT(g_Options.fThinking == FALSE);
2596 if (IS_SAME_MOVE(mv, g_Options.mvPonder))
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;
2605 g_MoveTimer.bvFlags |= TIMER_STOPPING;
2606 if (TRUE == OfficiallyMakeMove(mv, 0, FALSE))
2608 Trace("NONPREDICTED MOVE PLAYED --> stop pondering now\n");
2611 UtilPanic(GOT_ILLEGAL_MOVE_WHILE_PONDERING,
2616 __FILE__, __LINE__);
2620 if (FALSE == OfficiallyMakeMove(mv, 0, FALSE))
2622 UtilPanic(CANNOT_OFFICIALLY_MAKE_MOVE,
2627 __FILE__, __LINE__);
2631 Trace("Unknown/illegal move/command: \"%s\"\n", pCapturedInput);
2634 consume_if_searching:
2635 if (TRUE == fSearching)
2637 ASSERT(NULL == pFreeThis);
2638 ASSERT(NumberOfPendingInputEvents() > 0);
2639 pFreeThis = BlockingReadInput();
2644 if (NULL != pFreeThis)
2646 SystemFreeMemory(pFreeThis);
2649 if (NULL != pCapturedInput)
2651 SystemFreeMemory(pCapturedInput);
2652 pCapturedInput = NULL;
2654 // ASSERT(uHeapAllocated == GetHeapMemoryUsage());