This part of the engine deals with the communication with the GUI. The supported GUI formats are Xboard and UCI Protocol.
In the initialization process, if the engine is started through a program using one of these protocols, they identify themselves with "xboard" and "uci" respectively. In the com() function the variable mode is then set to store the protocol we communicate with.
com() is always called when the engine wants to check whether there is any new user input. gets(command) copies the input into command and returns true in case there has been a message.
The next step is that the commands get executed. This is now either done in com_xboard() or com_uci() depending on the GUI we are communicating with. Should we be running the engine without any GUI (e.g. through the command window for debugging), that means mode is set to 0, some basic commands get executed in the com() function.
Code
#include "stdafx.h"#include "transposition.h"#include <windows.h>enum etask {
TASK_NOTHING,
TASK_SEARCH,
TASK_PONDER
} task = TASK_NOTHING;enum eproto {
PROTO_NOTHING,
PROTO_XBOARD,
PROTO_UCI
} mode = PROTO_NOTHING;int debug =0;int pipe;
HANDLE hstdin;int com_init(){unsignedlong dw;
hstdin = GetStdHandle(STD_INPUT_HANDLE);
pipe =!GetConsoleMode(hstdin, &dw);if(!pipe){
SetConsoleMode(hstdin,dw&~(ENABLE_MOUSE_INPUT|ENABLE_WINDOW_INPUT));
FlushConsoleInputBuffer(hstdin);}else{setvbuf(stdin,NULL,_IONBF,0);setvbuf(stdout,NULL,_IONBF,0);}/* default search settings */
chronos.movetime=5000;
chronos.flags= FMOVETIME;
printWelcome();return0;}int input(){unsignedlong dw=0;if(task == TASK_NOTHING)return1;if(stdin->_cnt >0)return1;if(pipe){if(!PeekNamedPipe(hstdin, 0, 0, 0, &dw, 0))return1;return dw;}else{
GetNumberOfConsoleInputEvents(hstdin, &dw);if(dw >1) task = TASK_NOTHING;}return0;}int com(){char command[65536];if(!input())return0;/* unwind the search-stack first */if(task == TASK_SEARCH){
task = TASK_NOTHING;return0;}gets(command);switch(mode){case PROTO_XBOARD : com_xboard(command);break;case PROTO_UCI : com_uci(command);break;case PROTO_NOTHING: com_nothing(command);break;}return0;}int com_nothing(char* command){if(!strcmp(command, "xboard")) com_xboard(command);elseif(!strcmp(command, "uci")) com_uci(command);elseif(!strncmp(command,"perft", 5)) perft_start(command);elseif(!strncmp(command,"bench", 5)) util_bench(command);elseif(!strcmp(command, "eval")) printEval();elseif(!strcmp(command, "stat")) printStats();elseif(!strcmp(command, "d")) board_display();elseif(!strcmp(command, "new")) board_loadFromFen(STARTFEN);elseif(!strncmp(command, "pos", 3)) board_loadFromFen(command+4);elseif(!strcmp(command, "go")) time_nothing_go();elseif(!strcmp(command, "quit"))exit(0);elseif(!strcmp(command, "help")) printHelp();elseif(com_ismove(command)){if( algebraic_moves(command))
time_nothing_go();elseprintf("Sorry, this is not a legal move\n");}elseif(!strncmp(command, "st", 2)){sscanf(command, "st %d", &chronos.movetime);
chronos.movetime*=1000;
chronos.flags= FMOVETIME;}elseif(!strncmp(command, "sd", 2)){sscanf(command, "sd %d", &chronos.depth);
chronos.flags= FDEPTH;}elseif(command[0]=='\n'){}else{strcat(command, " - UNKNOWN COMMAND (type 'help' for a list of commands)");
com_send(command);}return0;}int com_xboard(char* command){if(!strcmp(command, "xboard"))
mode = PROTO_XBOARD;if(!strcmp(command, "new"))
board_loadFromFen(STARTFEN);elseif(!strcmp(command, "force"))
task = TASK_NOTHING;elseif(!strcmp(command, "white"))
sd.myside= WHITE;elseif(!strcmp(command, "black"))
sd.myside= BLACK;elseif(!strncmp(command, "st", 2)){sscanf(command, "st %d", &chronos.movetime);
chronos.movetime*=1000;
chronos.flags= FMOVETIME;}elseif(!strncmp(command, "sd", 2)){sscanf(command, "sd %d", &chronos.depth);
chronos.flags= FDEPTH;}elseif(!strncmp(command, "time", 4)){sscanf(command, "time %d", &chronos.time[sd.myside]);
chronos.flags= FTIME;}elseif(!strncmp(command, "otim", 4)){sscanf(command, "otim %d", &chronos.time[!sd.myside]);
chronos.flags= FTIME;}elseif(!strcmp(command, "go"))
time_xboard_go();elseif(!strcmp(command, "hint")){// hint}elseif(!strcmp(command, "undo")){// undo}elseif(!strcmp(command, "remove")){// remove}elseif(!strcmp(command, "post")){// post}elseif(!strcmp(command, "nopost")){// nopost}elseif(!strcmp(command, "quit")){exit(0);}elseif(com_ismove(command)){
algebraic_moves(command);
time_xboard_go();}return0;}int com_uci(char* command){if(!strcmp(command, "uci")){
mode = PROTO_UCI;
com_send("id name CPW-Engine 1.1");
com_send("id author Computer Chess Wiki");printf("option name Hash type spin default 64 min 1 max 1024\n");// send options
com_send("uciok");}if(!strcmp(command, "isready"))
com_send("readyok");if(!strncmp(command, "setoption", 9)){char name[256];char value[256];sscanf(command, "setoption name %s value %s", &name, &value);if(!strcmp(name, "Hash")){int val;sscanf(value, "%d", &val);
tt_setsize(val<<20);
ttpawn_setsize(val<<18);}}if(!strcmp(command, "ucinewgame")){}if(!strncmp(command, "position", 8)){//position [fen | startpos] [moves ...]if(!strncmp(command,"position fen",12)){
board_loadFromFen(command +13);}else{
board_loadFromFen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");}char* moves =strstr(command, "moves");if(moves) algebraic_moves(moves+6);}if(!strncmp(command, "go", 2))
time_uci_go(command);if(!strncmp(command, "debug", 5))
debug =strcmp(command,"debug off");if(!strcmp(command, "ponderhit"))
time_uci_ponderhit();if(!strcmp(command, "stop"))
task = TASK_NOTHING;if(!strcmp(command, "quit"))exit(0);return0;}int com_send(char* command){printf("%s\n",command);return0;}int com_sendmove(smove m){int promotion =0;char parray[5]={0,'q','r','b','n'};char command[20];char move[6];switch(mode){case PROTO_XBOARD:strcpy(command,"move ");break;case PROTO_UCI:strcpy(command,"bestmove ");break;default:strcpy(command,"CPW: ");}
convert_0x88_a(m.from, move);
convert_0x88_a(m.to, move+2);//Promotion pieceif(m.piece_to!= m.piece_from){
promotion = m.piece_to;}
move[4]= parray[promotion];
move[5]=0;strcat(command, move);
com_send(command);/* in xboard and nothing actually do the move on the board */if(mode == PROTO_XBOARD || mode == PROTO_NOTHING)
move_make(m);return0;}int com_ismove(char* command){return(command[0]>='a'&& command[0]<='h'&&
command[1]>='1'&& command[1]<='8'&&
command[2]>='a'&& command[2]<='h'&&
command[3]>='1'&& command[3]<='8'&&( command[4]==' '|| command[4]=='\n'|| command[4]==0||
command[4]=='-'||
command[4]=='q'|| command[4]=='r'|| command[4]=='b'|| command[4]=='n'));/***************************************************************
* command[4] might be: *
* *
* (a) any kind of a blank space *
* (b) '-' or any other mark used in opening book processing *
* (c) first letter of a name of a promoted piece *
***************************************************************/}
Table of Contents
Description
This part of the engine deals with the communication with the GUI. The supported GUI formats are Xboard and UCI Protocol.In the initialization process, if the engine is started through a program using one of these protocols, they identify themselves with "xboard" and "uci" respectively. In the com() function the variable mode is then set to store the protocol we communicate with.
com() is always called when the engine wants to check whether there is any new user input. gets(command) copies the input into command and returns true in case there has been a message.
The next step is that the commands get executed. This is now either done in com_xboard() or com_uci() depending on the GUI we are communicating with. Should we be running the engine without any GUI (e.g. through the command window for debugging), that means mode is set to 0, some basic commands get executed in the com() function.
Code
What links here?
Up one Level