Computer Chess Club Archives


Search

Terms

Messages

Subject: my support winboard code (long,will be happy to get productive comments)

Author: Uri Blass

Date: 11:22:54 09/29/02


void ponder()
{
	/*this function is going to start by make_expected_move and
	later choosemove,my idea is that there is going also to be
	a function continue_to_ponder and this function is going to be called
	during searching when the opponent makes a move.

	The function continue_to_ponder may simply continue the search
	if the opponent make the expected move or stop the search
	in case of unexpected move

	I think that an interface should not tell the engine how to ponder
	and this is the reason that I do not think to include it in a general
	winboard function

	I plan in the near future to ponder in the normal way but
	I want to design the program in order to give me an option also
	to do it in a different way without too many changes*/
}
void new_command()
{
	/*we use book when there is a new game*/
	UseBook=1;
	/*setup set up position in FEN notation*/
	setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
	computer_side = DARK;
}

void sd_command()
{
	sscanf(buffer, "sd %d", &max_depth);
			max_time = 1 << 25;
}
void st_command()
{
	/*today movei does not support the st command*/
}
void time_command()
{
	//max_time is the time in centiseconds
	sscanf(buffer, "time %d", &max_time);
	/*handletime should calculate the target time and the maximal time
	based on the variables max_time and num_moves and increasment
	opponent time and the time that already wasted in pondering*/
	handletime();
}

void hint_command()
{
	/*if the opponent ask for a hint calculate
			for the opponent and give a hint*/
			choosemove(0);
			if (pv[0][0].u)
				printf("Hint: %s\n", move_str(pv[0][0].b));
			else
				printf("mistake");
			fflush(stdout);
}
void level_command()
{
	sscanf(buffer,"level%d %d %d",&num_moves,&max_time,&increasement);
			/*-1 is only a flag that says that we do not know the
			ply of first move*/
			starting_ply=-1;
			if (num_moves>0)
				firstnum_moves=num_moves;
			else
			{
				firstnum_moves=INFINIT;
				num_moves=INFINIT;
			}
}
void setboard_command()
{
	char position[256];
	char str2[10],str3[10],str4[10],str5[10],str6[10];

	UseBook=0;
	sscanf(buffer,"setboard%s %s %s %s %s
%s",&position,&str2,&str3,&str4,&str5,&str6);
	strcat(position," ");
	strcat(position,str2);
	strcat(position," ");
	strcat(position,str3);
	strcat(position," ");
	strcat(position,str4);
	strcat(position," ");
	strcat(position,str5);
	strcat(position," ");
	strcat(position,str6);
	/*a function that help the computer to setup FEN*/
	setup(position);
	/*we do not know which side is the computer so we set computer_side to
	EMPTY*/
	computer_side = EMPTY;
}

void remove_command()
{
	if (hply<2)
	{
		unmakemove();
		unmakemove();
	}
}
void result_command()
{
	/*we stop the game when we get the result,learning from the value
	is going to be done later*/
	computer_side=EMPTY;
/*	sscanf(buffer,"result %s ",);*/
}
void analyze_command()
{
	UseBook=0;
	analyze=ANALYSIS_MODE;
	computer_side=EMPTY;
	/*wait_flag is changed to 1 only if search is not
	needed. It means in mate or stalemate position or if the search
	is finished when the program found mate or got maximal depth*/
	wait_flag=0;
	do
	{
		if (mateorstalemate())
			wait_flag=1;
		if (wait_flag==0)
			choosemove(YES);
		if (wait_flag==1)
			fgets(buffer, 256, stdin);
			wait_flag=0;
			sscanf(buffer, "%s", command);
			/*making the move if it is legal*/
			makeusermove(buffer);
			switch(command[0])
			{
			case 'u':if (!strcmp(command, "undo"))
					 {
						unmakemove();
						continue;
					 }
				break;
			case 'n':if (!strcmp(command, "new"))
					{
			/*we do not use book when we analyze*/
						UseBook=0;
						setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0

1");
						continue;
					}
				break;
			case 's':
				if (!strcmp(command, "setboard"))
				{
					setboard_command();
					continue;
				}
				break;
			case 'e':
				if (!strcmp(command, "exit"))
				{
					analyze=PLAY_MODE;
					continue;
				}
				break;
			case '.':
				if (!strcmp(command, "."))
				//today last commands are ignored
				continue;
				break;
			case 'b':if (!strcmp(command, "bk"))
						 continue;
				break;
			case 'h':if (!strcmp(command, "hint"))
						 continue;
			}
	}
	while (analyze==ANALYSIS_MODE);
}

void xboard()
{
	int i;
	signal(SIGINT, SIG_IGN);
	printf("\n");
	/*input_init called only one time at start_up*/
	input_init();
	/*computer_side can get only 3 values
	LIGHT if the computer is white,DARK if the computer is black
	and EMPTY if the game is finished or it is analyzed mode*/
	computer_side = EMPTY;
	/*analyze can get 3 values ANALYSIS_MODE when the computer analyze
	ponder_mode when the computer ponders and PLAY_MODE in other cases*/
	analyze=PLAY_MODE;
	for (;;)
	{
		if (side == computer_side)
		{
		/*printing the result in case that the game is finished*/
			if (gamefinished())
			{
				computer_side=EMPTY;
				/*print_result prints with printf the following informatuion based on the
result
				"0-1 {Black mates}\n" or
				"1-0 {White mates}\n" or
				"1/2-1/2 {Stalemate}\n" or
				"1/2-1/2 {Draw by insufficient material}\n" or
				"1/2-1/2 {Draw by repetition}\n"
				"1/2-1/2 {Draw by fifty move rule}\n"*/
				print_result();
				fflush(stdout);
			}
			else
			{
				/*choosemove is the function that choose the move of
				the program,it get the move and decides based on the
				value of post if to print main lines*/
				choosemove(post);
				/*num_moves give the number of moves until the
				next time control
				if the time control is fisher time control
				the first value is 999999 moves
				so num_moves is very high and is not important
				for time allocation
				*/
				if (computer_side==side)
				{
					num_moves--;
					/*firstnum_moves is the number of moves in level
					of x minutes/y moves*/

					if (num_moves==0)
						num_moves=firstnum_moves;
				/*this function make and print the move using printf*/
					makeandprintpvmove();
					if (gamefinished())
						print_result();
					else
					{
						if (ponder_flag==1)
							ponder();
					}
					fflush(stdout);
				}
			}
		}
		if (!fgets(buffer, 256, stdin))
			return;
		if (buffer[0] == '\n')
			continue;
		sscanf(buffer, "%s", command);
		switch(command[0])
		{
			/*we are not in analysis mode so we can know that
			we do not get the exit command so I ignored it*/
		case'a':if (!strcmp(command, "analyze"))
				{
					/*analyze_commands takes us to a different loop
					when we get out of it only by exit command*/
					analyze_command();
					continue;
				}
			break;
		case'e':if (!strcmp(command, "easy"))
				{
					 ponder_flag=0;
					 continue;
				}
			break;
		case 'f':if (!strcmp(command, "force"))
				 {
					 computer_side=EMPTY;
					 continue;
				 }
			break;
		case 'g':if (!strcmp(command, "go"))
				 {
					 /*side is the side to move and computer_side is the side
			that the the computer plays*/
					 computer_side=side;
					 continue;
				 }
			break;
		case 'h':switch (command[1])
				 {
		            case 'a':if (!strcmp(command, "hard"))
							 {
								 ponder_flag=1;
								 continue;
							 }
			        break;
		            case 'i':if (!strcmp(command, "hint"))
							 {
								 hint_command();
								 continue;
							 }
				 }
			break;
		case 'l':if (!strcmp(command, "level"))
				 {
					 level_command();
					 continue;
				 }
			break;
		case 'n':switch (command[1])
				 {
		            case 'e':if (!strcmp(command, "new"))
							 {
								 new_command();
								 continue;
							 }
			        break;
		            case 'o':if (!strcmp(command, "nopost"))
							 {
								 post=NO;
								 continue;
							 }
				 }
			break;
		case 'o':if (!strcmp(command, "otim"))
				 {
					 /*should be
					 sscanf(buffer, "opptime %d", &max_time);
					 when I use it but today I ignore it*/
					 continue;
				 }
				break;
		case 'p':switch (command[1])
				 {
		            case 'o':if (!strcmp(command, "post"))
							 {
								 post=YES;
								 continue;
							 }
						break;
					case 'r':if (!strcmp(command, "protover"))
							 {
								 printf("feature setboard=1 draw=0 done=1

analyze=1\n");
								 fflush(stdout);
								 continue;
							 }
				 }
			break;
		case 'q':if (!strcmp(command, "quit"))
					 return;
			break;
		case 'r':if (command[1]=='e')
				 switch (command[2])
				 {
		            case 'm':if (!strcmp(command, "remove"))
							 {
								 remove_command();
								 continue;
							 }
						break;
					case 's':if (!strcmp(command, "result"))
							 {
								 result_command();
								 continue;
							 }
				 }
			break;
		case 's':switch (command[1])
			   {
				   case 'd':if (!strcmp(command, "sd"))
							 {
								 sscanf(buffer, "sd %d", &max_depth);
								 max_time = 1 << 25;
								 continue;
							 }
						break;
					case 'e':if (!strcmp(command, "setboard"))
							 {
								 setboard_command();
								 continue;
							 }
						break;
					case 't':if(!strcmp(command, "st"))
							 {
								 //need to add
								 continue;
							 }
			   }
			break;
		case 't':if(!strcmp(command, "time"))
				 {
					 time_command();
					 continue;
				 }
			break;
		case 'u':if(!strcmp(command, "undo"))
				 {/*unmakemove is a function that undo move unless
			it is the beginning of the game*/
					 unmakemove();
					 computer_side=EMPTY;
					 continue;
				 }
			break;
		case 'x':if(!strcmp(command, "xboard"))
					 continue;
			break;
		}
		/*makeusermove make the move of the player to move
		and returen 0 only if the move is illegal*/
		i=makeusermove(buffer);
		if (i==0)
		{
			printf("Error (unknown command): %s\n", command);
			fflush(stdout);
		}
		else
			print_result();
	}
}





loop when searching





static int is_pipe;
static HANDLE input_handle;

/* Call once at startup. thanks to Dieter for this function and the
same for input_available and part of readwbinput*/
void input_init(void)
{
	DWORD dw;
	input_handle = GetStdHandle(STD_INPUT_HANDLE);
	is_pipe = !GetConsoleMode(input_handle, &dw);
}


int input_available(void)
{
	DWORD nchars;
/* When using Standard C input functions, also check if there
is anything in the buffer. After a call to such functions,
the input waiting in the pipe will be copied to the buffer,
and the call to PeekNamedPipe can indicate no input available.
Setting stdin to unbuffered was not enough, IIRC */
//input_init();
	if (stdin->_cnt > 0)
		return 1;
	if (is_pipe)
	{
/* When running under a GUI, you will end here. */
		if (!PeekNamedPipe(input_handle, NULL, 0, NULL, &nchars, NULL))
			return 1;
/* Something went wrong. Probably the parent program exited.
Could call exit() here. Returning 1 will make the next call
to the input function return EOF, where this should be
catched then. */
		return nchars != 0;
	}
	else
		return _kbhit(); /* In "text-mode" without GUI */
}


jmp_buf env;

void readwbinput(void)
{
	char command[256];
	if (input_available())
	{
		if (fgets(buffer, sizeof buffer, stdin) == NULL)
		{
			printf("probably broken pipe");
			exit(1);
		}
/* Now you have the command as a string in buf. */
/* Do something with the contents of buf */
		if (sscanf(buffer, "%s", command))
		{
			/*we have command that we want to read and our actions
			can be different in analysis mode,ponder_mode or play_mode*/

			switch(analyze)
			{
			case PLAY_MODE:
				switch (command[0])
				{
					/*we jump to the beginning of the search
					undo the moves and go back to the passive loop
					if we are asked to move now*/
				case'?':if (!strcmp(command, "?"))
						{
							stop_search=1;
							longjmp(env,0);
						}
					break;
				case 'e':if (!strcmp(command, "easy"))
							 ponder_flag=0;
					break;
				case 'h':if (!strcmp(command, "hard"))
					ponder_flag=1;
				break;

				case 'r':if (!strcmp(command,"result"))
						 {
							 stop_search=1;
							 longjmp(env,0);
						 }
					break;
				case 'f':computer_side=EMPTY;
					stop_search=1;
					longjmp(env,0);
					break;
				}
				break;
			case ANALYSIS_MODE:
				/*if command tell us to stop the search
				we first stop the search and later
				continue process the command*/
				if ((!strcmp(command, "undo"))||
					(!strcmp(command, "new"))||
					(!strcmp(command, "setboard"))||
					(!strcmp(command, "exit")))

				{
					stop_search=1;
					longjmp(env, 0);
				}
				/*maybe the user entered a move
			it is also a reason to stop the search and continue later*/
				if (legal(command))
				{
					stop_search=1;
					longjmp(env,0);
				}
				break;
			case PONDER_MODE:
				switch (command[0])
				{
				case 't':if(!strcmp(command, "time"))
							 time_command();
					break;
				case 'o':if (!strcmp(command,"otim"));
					break;
				case 'e':if(!strcmp(command, "easy"))
						 {
							 stop_search=1;
							 longjmp(env,0);
						 }
				}
			break;
			}
		}

/* For example in ponder mode, the string might be "time 500\n", which you
     must process immediately. It may contain a move, which may mean, if it
     is your predicted ponder move, that you just change from "ponder mode" to
     "search mode". You will probably want to check the clocks at this time,
     and decide, if you actually want to search on, or to return immediately
     the sofar best move */
	}
}

void checkup(void)
{
	if ((analyze==PLAY_MODE)&&(get_ms()>=stop_time))
	{
		stop_search = 1;
		longjmp(env, 0);
	}
	else
	{
		/*NodesFrequency is 2^n-1*/
		if (((nodes&Nodes_Frequency)==0)&&input_available)
			readwbinput();
	}
}



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.