📄 cmd.c
字号:
/* GNU Chess 5.0 - cmd.c - command parser Copyright (c) 1999-2002 Free Software Foundation, Inc. GNU Chess is based on the two research programs Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft. GNU Chess is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Chess is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Chess; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Contact Info: bug-gnu-chess@gnu.org cracraft@ai.mit.edu, cracraft@stanfordalumni.org, cracraft@earthlink.net*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <ctype.h>#include <errno.h>#include "version.h"#include "common.h"#include "eval.h"static char logfile[MAXSTR];static char gamefile[MAXSTR];/* * Splitting input is actually not neccessary, but we find * tokens separated by whitespace and put pointers on them. * How many do we need? We just take 3 for now. Check if the * fact that tokens are not 0-terminated but whitespace-terminated * generates bugs. (Already killed one bug in move.c) * We also kill trailing whitespace. (The trailing '\n' might * be really annoying otherwise.) */#define TOKENS 3static char *token[TOKENS];char *endptr;static void split_input(void){ /* r points to the last non-space character */ char *s, *r; int k; for (k = 0, s = r = inputstr; k < TOKENS; ++k) { /* Skip leading whitespace */ while (isspace(*s)) s++; token[k] = s; /* Skip token */ while (*s && !isspace(*s)) r = s++; } while (*s) { while (isspace(*s)) s++; while (*s && !isspace(*s)) r = s++; } r[1] = '\0';}/* * Compares two tokens, returns 1 on equality. Tokens * are separated by whitespace. */static int tokeneq(const char *s, const char *t){ while (*s && *t && !isspace(*s) && !isspace(*t)) { if (*s++ != *t++) return 0; } return (!*s || isspace(*s)) && (!*t || isspace(*t));} void cmd_accepted(void) {}void cmd_activate(void) { CLEAR (flags, TIMEOUT); CLEAR (flags, ENDED);} void cmd_analyze(void){ /* * "analyze" mode is similar to force, hard and post together * in that it produces a text output like post, but must * think indefinitely like ponder. * * Some additional output is expected in command ".\n" but if ignored * this should not be sent any more *//* TODO correct output, add fail high low */ if (!(flags & ANALYZE)){ preanalyze_flags=flags; /* save these flags for exit */ SET (flags, ANALYZE); cmd_post(); cmd_force(); cmd_hard(); }}void cmd_bk(void){ /* Print moves from Open Book for Xboard/WinBoard */ /* Lines must start with " " and end with blank line */ /* No need to test for xboard as it is generally useful */ BookQuery(1); printf("\n"); /* Blank line */ fflush(stdout);}void cmd_black(void) { /* * No longer used by Xboard but requested as a feature */ NewPosition(); /* Reset some flags and settings */ CLEAR ( flags, THINK); CLEAR ( flags, MANUAL); CLEAR (flags, TIMEOUT); computer = white; if ( board.side == white ) { board.side = black; board.ep = -1; }}void cmd_book(void){ if (tokeneq(token[1], "add")) { if (access(token[2], F_OK) < 0) { printf("The syntax to add a new book is:\n\n\tbook add file.pgn\n"); } else { BookPGNReadFromFile (token[2]); } } else if (tokeneq (token[1], "on") || tokeneq(token[1], "prefer")) { bookmode = BOOKPREFER; printf("book now on.\n"); } else if (tokeneq (token[1], "off")) { bookmode = BOOKOFF; printf("book now off.\n"); } else if (tokeneq (token[1], "best")) { bookmode = BOOKBEST; printf("book now best.\n"); } else if (tokeneq (token[1], "worst")) { bookmode = BOOKWORST; printf("book now worst.\n"); } else if (tokeneq (token[1], "random")) { bookmode = BOOKRAND; printf("book now random.\n"); }}/* Our opponent is a computer */void cmd_computer(void) {}void cmd_depth(void){ SearchDepth = atoi (token[1]); printf("Search to a depth of %d\n",SearchDepth);}/* Ignore draw offers */void cmd_draw(void) {}void cmd_easy(void) { CLEAR (flags, HARD); }/* Predecessor to setboard */void cmd_edit(void) { if ( flags & XBOARD ) { printf("tellusererror command 'edit' not implemented\n"); fflush(stdout); }}void cmd_epd(void){ ParseEPD (token[1]); NewPosition(); ShowBoard(); printf ("\n%s : Best move = %s\n", id, solution); }void cmd_exit(void) { /* * "exit" is a synonym for quit except in engine mode * when it means leave analyze mode */ if ( flags & ANALYZE ){ flags = preanalyze_flags ; /* this implicitly clears ANALYZE flag */ } else { cmd_quit(); } }void cmd_force(void) { SET (flags, MANUAL); }void cmd_go(void){ SET (flags, THINK); CLEAR (flags, MANUAL); CLEAR (flags, TIMEOUT); CLEAR (flags, ENDED); computer = board.side;}void cmd_hard(void) { SET (flags, HARD); }void cmd_hash(void){ if (tokeneq (token[1], "off")) CLEAR (flags, USEHASH); else if (tokeneq (token[1], "on")) SET (flags, USEHASH); printf ("Hashing %s\n", flags & USEHASH ? "on" : "off");}void cmd_hashsize(void){ if (token[1][0] == 0) { printf("Current HashSize is %d slots\n", HashSize); } else { int i; /* i = atoi (token[1]); */ errno = 0; i = strtol (token[1], &endptr, 10); if ( errno != 0 || *endptr != '\0' ){ printf("Hashsize out of Range or Invalid\n"); } else { CalcHashSize(i); InitHashTable (); } }}/* Give a possible move for the player to play */void cmd_hint(void){ if ( flags & ENDED ){ printf("The game is over.\n"); } else { int HintMove; HintMove = TreePtr[1]->move; /* Pick first move in tree */ if (IsLegalMove(HintMove)){ GenMoves(1); SANMove(TreePtr[1]->move,1); printf("Hint: %s\n", SANmv); } else { printf("No hint available at this time\n"); } } fflush(stdout);}void cmd_level(void){ SearchDepth = 0; sscanf (token[1], "%d %f %d", &TCMove, &TCTime, &TCinc); if (TCMove == 0) { TCMove = 35 /* MIN((5*(GameCnt+1)/2)+1,60) */; printf("TCMove = %d\n",TCMove); suddendeath = 1; } else suddendeath = 0; if (TCTime == 0) { SET (flags, TIMECTL); SearchTime = TCinc / 2.0f ; printf("Fischer increment of %d seconds\n",TCinc); } else { SET (flags, TIMECTL); MoveLimit[white] = MoveLimit[black] = TCMove - (GameCnt+1)/2; TimeLimit[white] = TimeLimit[black] = TCTime * 60; if (!(flags & XBOARD)) { printf ("Time Control: %d moves in %.2f secs\n", MoveLimit[white], TimeLimit[white]); printf("Fischer increment of %d seconds\n",TCinc); } }}void cmd_list(void){ if (token[1][0] == '?') { printf("name - list known players alphabetically\n"); printf("score - list by GNU best result first \n"); printf("reverse - list by GNU worst result first\n"); } else { if (token[1][0] == '\0') DBListPlayer("rscore"); else DBListPlayer(token[1]); }}void cmd_load(void){ LoadEPD (token[1]); if (!ValidateBoard()) { SET (flags, ENDED); printf ("Board is wrong!\n"); }}void cmd_manual(void) { SET (flags, MANUAL); }/* Move now, not applicable */void cmd_movenow(void) {}/* * TODO: Add a logpath variable or macro, not always dump into current * dir. Again, how does one handle paths portably across Unix/Windows? * -- Lukas */void cmd_name(void){ int suffix = 0; /* name[sizeof name - 1] should always be 0 */ strncpy(name, token[1], sizeof name - 1); for (suffix = 0; suffix < 1000; suffix++) { sprintf(logfile,"log.%03d",suffix); sprintf(gamefile,"game.%03d",suffix); /* * There is an obvious race condition here but who cares, we just * bail out in case of failure... --Lukas */ if (access(logfile,F_OK) < 0) { ofp = fopen(logfile,"w"); if (ofp == NULL) { ofp = stdout; fprintf(stderr, "Failed to open %s for writing: %s\n", logfile, strerror(errno)); } return; } } fprintf(stderr, "Could not create logfile, all slots occupied.\n"); fprintf(stderr, "You may consider deleting or renaming your existing logfiles.\n");}void cmd_new(void){ InitVars (); NewPosition (); /* Protocol specification for ANALYZE says "new" does not end analysis */ if (!(flags & ANALYZE)) CLEAR (flags, MANUAL); CLEAR (flags, THINK); myrating = opprating = 0;}void cmd_nopost(void) { CLEAR (flags, POST); }void cmd_null(void){ if (tokeneq (token[1], "off")) CLEAR (flags, USENULL); else if (tokeneq (token[1], "on")) SET (flags, USENULL); printf ("Null moves %s\n", flags & USENULL ? "on" : "off");}void cmd_otim(void) {}void cmd_pgnload(void) { PGNReadFromFile (token[1]); }/* * XXX - Filenames with spaces will break here, * do we want to support them? I vote for "no" * - Lukas */void cmd_pgnsave(void){ if ( strlen(token[1]) > 0 ) PGNSaveToFile (token[1], ""); else printf("Invalid filename.\n");} void cmd_ping(void){ /* If ping is received when we are on move, we are supposed to reply only after moving. In this version of GNU Chess, we never read commands while we are on move, so we don't have to worry about that here. */ printf("pong %s\n", token[1]); fflush(stdout);} void cmd_post(void) { SET (flags, POST); }void cmd_protover(void){ if (flags & XBOARD) { /* Note: change this if "draw" command is added, etc. */ printf("feature setboard=1 analyze=1 ping=1 draw=0 sigint=0" " variants=\"normal\" myname=\"%s %s\" done=1\n", PROGRAM, VERSION); fflush(stdout); }}void cmd_quit(void) { SET (flags, QUIT); }void cmd_random(void) {}void cmd_rating(void){ myrating = atoi(token[1]); opprating = atoi(token[2]); fprintf(ofp,"my rating = %d, opponent rating = %d\n",myrating,opprating); /* Change randomness of book based on opponent rating. */ /* Basically we play narrower book the higher the opponent */ if (opprating >= 1700) bookfirstlast = 2; else if (opprating >= 1700) bookfirstlast = 2; else bookfirstlast = 2;}void cmd_rejected(void) {}void cmd_remove(void){ if (GameCnt >= 0) { CLEAR (flags, ENDED); CLEAR (flags, TIMEOUT); UnmakeMove (board.side, &Game[GameCnt].move); if (GameCnt >= 0) { UnmakeMove (board.side, &Game[GameCnt].move); if (!(flags & XBOARD)) ShowBoard (); } PGNSaveToFile ("game.log",""); } else printf ("No moves to undo! \n");}void cmd_result(void){ if (ofp != stdout) { fprintf(ofp, "result: %s\n",token[1]); fclose(ofp); ofp = stdout; printf("Save to %s\n",gamefile); PGNSaveToFile (gamefile, token[1]); DBUpdatePlayer (name, token[1]); }} void cmd_save(void){ if ( strlen(token[1]) > 0 ) SaveEPD (token[1]); else printf("Invalid filename.\n");}void cmd_setboard(void){ /* setboard uses FEN, not EPD, but ParseEPD will accept FEN too */ ParseEPD (token[1]); NewPosition();}void cmd_solve(void) { Solve (token[1]); }/* Set total time for move to be N seconds is "st N" */void cmd_st(void) { /* Approximately level 1 0 N */ sscanf(token[1],"%d",&TCinc); suddendeath = 0 ; /* Allow a little fussiness for failing low etc */ SearchTime = TCinc * 0.90f ; CLEAR (flags, TIMECTL);}void cmd_switch(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -