#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
#include
<conio.h>
#include
<stdio.h>
#include
<iostream>
#include
<iomanip>
#include
"defines.h"
#include
"extglobals.h"
#include
"protos.h"
#include
"board.h"
#include
"timer.h"
Move Board::think()
{
//
===========================================================================
// This is the entry point for search, it is intended to drive
iterative deepening
// The search stops if (whatever comes first):
// - there is no legal move (checkmate or stalemate)
// - there is only one legal move (in this case we don't need to
search)
// - time is up
// - the search is interrupted by the user, or by winboard
// - the search depth is reached
//
===========================================================================
int score,
legalmoves, currentdepth;
Move singlemove;
//
===========================================================================
// Check if the game has ended, or if there is only one legal
move,
// because then we don't need to search:
//
===========================================================================
if (isEndOfgame(legalmoves,
singlemove)) return
NOMOVE;
if (legalmoves
== 1)
{
std::cout <<
"forced move: ";
displayMove(singlemove); std::cout << std::endl;
if (XB_MODE
&& XB_POST)
{
printf("0
0 0 0 ");
displayMove(singlemove);
std::cout << std::endl;
}
return
singlemove;
}
//
===========================================================================
// There is more than legal 1 move, so prepare to search:
//
===========================================================================
if (XB_MODE)
timeControl();
lastPVLength = 0;
memset(lastPV, 0 ,
sizeof(lastPV));
memset(whiteHeuristics,
0, sizeof(whiteHeuristics));
memset(blackHeuristics,
0, sizeof(blackHeuristics));
inodes = 0;
countdown = UPDATEINTERVAL;
timedout =
false;
// display console header
displaySearchStats(1, 0, 0);
timer.init();
msStart = timer.getms();
// iterative deepening:
for (currentdepth
= 1; currentdepth <= searchDepth; currentdepth++)
{
// clear the buffers:
memset(moveBufLen, 0, sizeof(moveBufLen));
memset(moveBuffer, 0, sizeof(moveBuffer));
memset(triangularLength, 0,
sizeof(triangularLength));
memset(triangularArray, 0,
sizeof(triangularArray));
followpv =
true;
allownull =
true;
score = alphabetapvs(0, currentdepth,
-LARGE_NUMBER, LARGE_NUMBER);
// now check if time is up
// if not decide if it makes sense to
start another iteration:
if (timedout)
{
std::cout << std::endl;
return
(lastPV[0]);
}
else
{
if
(!XB_NO_TIME_LIMIT)
{
msStop = timer.getms();
if ((msStop - msStart) > (STOPFRAC * maxTime))
{
if (!XB_MODE) std::cout <<
" ok" << std::endl;
return (lastPV[0]);
}
}
}
displaySearchStats(2, currentdepth,
score);
// stop searching if the current depth
leads to a forced mate:
if ((score
> (CHECKMATESCORE-currentdepth)) || (score < -(CHECKMATESCORE-currentdepth)))
currentdepth = searchDepth;
}
return
(lastPV[0]);
}
(...)
void Board::displaySearchStats(int
mode, int
depth, int
score)
{
// displays various search statistics
// only to be used when ply = 0
// mode = 1 : display header
// mode = 2 : display full stats,
including score and latest PV
// mode = 3 : display current root move
that is being searched
// depth = ply,
score = loop counter in the search move list
char
sanMove[12], timestring[8];
U64 dt;
dt = timer.getms() - msStart;
switch
(mode)
{
case
1:
if (!XB_MODE) std::cout <<
"depth score nodes time knps PV" << std::endl;
break;
case
2:
if (XB_MODE && XB_POST)
{
printf("%5d
%6d %8d %9d ", depth, score, dt/10, inodes);
rememberPV();
displayPV();
}
else
{
// depth
printf("%5d
", depth);
// score
printf("%+6.2f
", float(score/100.0));
// nodes searched
if (inodes > 100000000) printf("%6.0f%c
", float(inodes/1000000.0),
'M');
else if
(inodes > 10000000) printf("%6.2f%c ",
float(inodes/1000000.0),
'M');
else if
(inodes > 1000000) printf("%6.0f%c ",
float(inodes/1000.0),
'K');
else if
(inodes > 100000) printf("%6.1f%c ",
float(inodes/1000.0),
'K');
else if
(inodes > 10000) printf("%6.2f%c ",
float(inodes/1000.0),
'K');
else
printf("%7d ", inodes);
// search time
mstostring(dt,
timestring);
printf("%8s
", timestring);
// search speed
if (dt > 0) std::cout <<
std::setw(5) << (inodes/dt) << " ";
else std::cout <<
" - ";
// store this PV:
rememberPV();
// display the PV
displayPV();
}
break;
case
3: // Note that the numbers refer to
pseudo-legal moves:
if (!TO_CONSOLE) break;
if (XB_MODE)
{
}
else
{
mstostring(dt,
timestring);
printf("
(%2d/%2d) %8s ", score+1, moveBufLen[depth+1]-moveBufLen[depth],
timestring);
unmakeMove(moveBuffer[score]);
toSan(moveBuffer[score], sanMove);
std::cout <<
sanMove;
makeMove(moveBuffer[score]);
printf("...
\r");
std::cout.flush();
}
break;
default:
break;
}
return;
}
(...)
void timeControl()
{
//
===========================================================================
// This routine is used to calculate
maxTime, the maximum time for this move
// in millisceonds. Based on:
// XB_CTIM = computer's time,
milliseconds
// XB_OTIM = opponents' time,
millseconds
// XB_INC = time increment,
milliseconds
//
===========================================================================
int xb_ctim,
movesLeft;
//
===========================================================================
// First build in a safety buffer of
2000 milliseconds:
//
===========================================================================
xb_ctim = XB_CTIM - 2000;
if (xb_ctim <
1) xb_ctim = 1;
//
===========================================================================
// Estimate the number of moves per
side that are left. Assume 80 half moves
// per game with a minimum of 10
half moves left to play, no matter how many moves are played:
//
===========================================================================
movesLeft = 80 - board.endOfSearch;
if (movesLeft
< 20) movesLeft = 20;
#ifdef
WINGLET_DEBUG_WINBOARD
std::cout <<
"#-winglet : in timecontrol, movesleft="
<< movesLeft << std::endl;
#endif
//
===========================================================================
// Use up part of the thinking time
advantage that we may have:
//
===========================================================================
if ((XB_OTIM
+ XB_INC) < xb_ctim)
board.maxTime = (xb_ctim / movesLeft)
+ XB_INC + (int)(0.80*(xb_ctim -
XB_OTIM - XB_INC));
else
board.maxTime = (xb_ctim / movesLeft);
//
===========================================================================
// If an XB_INC is defined, then
there is no reason to run out of time:
//
===========================================================================
if ((XB_INC)
&& (xb_ctim < XB_INC)) board.maxTime = xb_ctim;
//
===========================================================================
// Final checks, all moves should be
> something:
//
===========================================================================
if (board.maxTime
> xb_ctim) board.maxTime = (int)(0.8
* xb_ctim);
if (board.maxTime
< 1) board.maxTime = 1;
#ifdef
WINGLET_DEBUG_WINBOARD
std::cout <<
"#-winglet : in timecontrol, XB_CTIM="
<< XB_CTIM << std::endl;
std::cout <<
"#-winglet : in timecontrol, XB_OTIM="
<< XB_OTIM << std::endl;
std::cout <<
"#-winglet : in timecontrol, XB_INC ="
<< XB_INC << std::endl;
std::cout <<
"#-winglet : in timecontrol, maxtime="
<< board.maxTime << std::endl;
#endif
return;
}
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
#include <windows.h>
#include <iostream>
#include <conio.h>
#include "extglobals.h"
#include "protos.h"
#include "timer.h"
void Board::readClockAndInput()
{
// check if we need
to stop, because time is up, or because the user has hit the
keyboard.
// UPDATEINTERVAL
defines how often this check is done in terms of nodes searched.
// For example, if
the search speed is 1000 knods per second, then a value of
UPDATEINTERVAL = 100000
// will result in
10 checks per second (or 0.1s time intervals)
DWORD nchar;
char
command[80];
// reset countdown
countdown = UPDATEINTERVAL;
if ((!XB_NO_TIME_LIMIT
&& ((timer.getms() - msStart) > maxTime)) || (!XB_MODE && _kbhit()))
{
timedout =
true;
#ifdef
WINGLET_DEBUG_WINBOARD
if
(XB_MODE)
{
if (_kbhit())
{
std::cout <<
"#-winglet : timed out, kbhit" <<
std::endl;
}
else
{
std::cout <<
"#-winglet : timed out, time" <<
std::endl;
}
}
#endif
return;
}
noPonder:
if ((XB_MODE)
&& (PeekNamedPipe(GetStdHandle(STD_INPUT_HANDLE), NULL, 0, NULL, &nchar,
NULL)))
{
for (CMD_BUFF_COUNT
= 0; CMD_BUFF_COUNT < (int)nchar;
CMD_BUFF_COUNT++)
{
CMD_BUFF[CMD_BUFF_COUNT] =
getc(stdin);
//
sometimes we do not receive a newline character
if
(((CMD_BUFF_COUNT+1)==(int)nchar) ||
CMD_BUFF[CMD_BUFF_COUNT] == '\n')
// if (CMD_BUFF[CMD_BUFF_COUNT]
== '\n')
{
if (CMD_BUFF[CMD_BUFF_COUNT] ==
'\n') CMD_BUFF[CMD_BUFF_COUNT] =
'\0';
else CMD_BUFF[CMD_BUFF_COUNT+1] =
'\0';
//
CMD_BUFF[CMD_BUFF_COUNT] = '\0';
if (CMD_BUFF=="" || !CMD_BUFF_COUNT)
return;
sscanf(CMD_BUFF,
"%s", command);
#ifdef WINGLET_DEBUG_WINBOARD
std::cout <<
"#-winglet : in peek, CMD_BUFF="
<< CMD_BUFF << " command=" <<
command << std::endl;
#endif
// do not stop thinking/pondering/analyzing for any of the following
commands:
if (!strcmp(command, "."))
return;
if (!strcmp(command, "?"))
return;
if (!strcmp(command, "bk"))
return;
if (!strcmp(command, "easy"))
{
XB_PONDER =
false;
return;
}
if (!strcmp(command, "hint"))
return;
if (!strcmp(command, "nopost"))
{
XB_POST =
false;
return;
}
if (!strcmp(command, "otim"))
{
sscanf(CMD_BUFF,
"otim %d", &XB_OTIM);
XB_OTIM *= 10;
// convert centiseconds to miliseconds;
goto noPonder;
}
if (!strcmp(command, "post"))
{
XB_POST =
true;
return;
}
if (!strcmp(command, "time"))
{
sscanf(CMD_BUFF,"time
%d",&XB_CTIM);
XB_CTIM *= 10;
// convert centiseconds to milliseconds
goto noPonder;
}
timedout =
true;
CMD_BUFF_COUNT = (int)strlen(CMD_BUFF);
XB_DO_PENDING =
true;
return;
}
}
}
return;
}

√
You can use winboard to play games, experiment with the
code, or have winglet play matches against other winboard
engines.
|
|