#include
<iostream>
#include
"defines.h"
#include
"extglobals.h"
#include
"protos.h"
U64 perft(int
depth)
{
// Raw node count, up to depth, doing a
full tree search.
// perft is very similar to the search
algorithm - instead of evaluating the leaves, we count them.
//
// Be carefull when calling this
function with depths > 7, because it can take a very long
// time before the result is returned:
the average branching factor in chess is 35, so every
// increment in depth will require 35x
more computer time.
//
// perft is a good way of verifying
correctness of the movegenerator and (un)makeMove,
// because you can compare the results
with published results for certain test positions.
//
// perft is also used to measure the
performance of the move generator and (un)makeMove in terms
// of speed, and to compare different
implementations of generating, storing and (un)making moves.
U64 retVal = 0;
int i;
// count this node
if
(depth == 0)
{
#ifdef
WINGLET_DEBUG_EVAL
int
before = board.eval();
board.mirror();
int
after = board.eval();
board.mirror();
if
(before != after)
{
std::cout <<
"evaluation is not symmetrical! "
<< before << std::endl;
for (int j = 0 ; j <
board.endOfSearch ; j++)
{
std::cout << j+1
<< ". ";
displayMove(board.gameLine[j].move);
std::cout <<std::endl;
}
board.display();
}
#endif
return
1;
}
// generate moves from this position
board.ply++;
movegen();
// loop over moves:
for (i =
board.moveBufLen[board.ply]; i < board.moveBufLen[board.ply+1]; i++)
{
makeMove(board.moveBuffer[i]);
{
if (!isOtherKingAttacked())
{
// recursively call perft
retVal += perft(depth-1);
#ifdef WINGLET_DEBUG_PERFT
if
(depth == 1)
{
if (board.moveBuffer[i].isCapture())
ICAPT++;
if (board.moveBuffer[i].isEnpassant())
IEP++;
if (board.moveBuffer[i].isPromotion())
IPROM++;
if (board.moveBuffer[i].isCastleOO())
ICASTLOO++;
if (board.moveBuffer[i].isCastleOOO())
ICASTLOOO++;
if (isOwnKingAttacked())
ICHECK++;
}
#endif
}
}
unmakeMove(board.moveBuffer[i]);
}
board.ply--;
return
retVal;
}
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE 1
#endif
#include
<iostream>
#include
"defines.h"
#include
"protos.h"
#include
"extglobals.h"
#include
"board.h"
#include
"timer.h"
void readCommands()
{
int nextc;
if (board.nextMove
== WHITE_MOVE)
{
std::cout
<< "wt> ";
}
else
{
std::cout
<< "bl> ";
}
std::cout.flush();
//
===========================================================================
// Read a command and call doCommand:
//
===========================================================================
while ((nextc
= getc(stdin)) != EOF)
{
if (nextc
== '\n')
{
CMD_BUFF[CMD_BUFF_COUNT] = '\0';
while
(CMD_BUFF_COUNT)
{
if
(!doCommand(CMD_BUFF)) return;
}
if
(board.nextMove == WHITE_MOVE)
{
std::cout << "wt> ";
}
else
{
std::cout << "bl> ";
}
std::cout.flush();
}
else
{
if (CMD_BUFF_COUNT
>= MAX_CMD_BUFF-1)
{
std::cout << "Warning: command
buffer full !! " << std::endl;
CMD_BUFF_COUNT = 0;
}
CMD_BUFF[CMD_BUFF_COUNT++] =
nextc;
}
}
}
BOOLTYPE doCommand(const
char
*buf)
{
Move move;
Timer timer;
U64 msStart;
U64 msStop;
U64 perftcount;
char
userinput[80];
int i,
number;
//
=================================================================
// return when command buffer is empty
//
=================================================================
if (!strcmp(buf,
""))
{
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// help, h, or ?: show this help
//
=================================================================
if ((!strcmp(buf,
"help"))
|| (!strcmp(buf, "h"))
|| (!strcmp(buf, "?")))
{
std::cout <<
std::endl << "help:"
<< std::endl;
std::cout <<
"black : BLACK to
move" << std::endl;
std::cout <<
"cc : play
computer-to-computer " << std::endl;
std::cout <<
"d : display
board " << std::endl;
std::cout <<
"exit : exit
program " << std::endl;
std::cout <<
"eval : show
static evaluation of this position" <<
std::endl;
std::cout <<
"game : show game
moves " << std::endl;
std::cout <<
"go : computer
next move " << std::endl;
std::cout <<
"help, h, or ? : show this
help " << std::endl;
std::cout <<
"info : display
variables (for testing purposes)" <<
std::endl;
std::cout <<
"move e2e4, or h7h8q : enter a
move (use this format)" << std::endl;
std::cout <<
"moves : show all
legal moves" << std::endl;
std::cout <<
"new : start new
game" << std::endl;
std::cout <<
"perf : benchmark
a number of key functions" << std::endl;
std::cout <<
"perft n : calculate
raw number of nodes from here, depth n "
<< std::endl;
std::cout <<
"quit : exit
program " << std::endl;
std::cout <<
"r : rotate
board " << std::endl;
std::cout <<
"readfen filename n : reads #-th
FEN position from filename" <<
std::endl;
std::cout <<
"sd n : set the
search depth to n" << std::endl;
std::cout <<
"setup : setup
board... " << std::endl;
std::cout <<
"undo : take back
last move" << std::endl;
std::cout <<
"white : WHITE to
move" << std::endl;
std::cout << std::endl;
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// black: black to move
//
=================================================================
if (!strcmp(buf,
"black"))
{
board.nextMove = BLACK_MOVE;
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// d: display board
//
=================================================================
if (!strcmp(buf,
"d"))
{
board.display();
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// eval (do a static evaluation of the
board)
//
=================================================================
if (!strcmp(buf,
"eval"))
{
number = board.eval();
std::cout <<
"eval score = " << number <<
std::endl;
#ifdef
WINGLET_DEBUG_EVAL
board.mirror();
board.display();
i = board.eval();
std::cout <<
"eval score = " << i << std::endl;
board.mirror();
if
(number != i) std::cout << "evaluation
is not symmetrical! " << number << std::endl;
else
std::cout << "evaluation is symmetrical"
<< std::endl;
#endif
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// exit or quit: exit program
//
=================================================================
if ((!strcmp(buf,
"exit"))
|| (!strcmp(buf, "quit")))
{
CMD_BUFF_COUNT =
'\0';
return
false;
}
//
=================================================================
// game: show game moves
//
=================================================================
if (!strcmp(buf,
"game"))
{
if (board.endOfGame)
{
for (i = 0
; i < board.endOfGame ; i++)
{
std::cout << i+1 << ". ";
displayMove(board.gameLine[i].move);
std::cout <<std::endl;
}
}
else
{
std::cout
<< "there are no game moves"
<< std::endl;
}
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// moves: show all legal moves
//
=================================================================
if (!strcmp(buf,
"moves"))
{
i = 0;
board.ply = 0;
movegen();
std::cout <<
std::endl << "moves from this
position:" << std::endl;
for
(number = board.moveBufLen[board.ply]; number <
board.moveBufLen[board.ply+1]; number++)
{
makeMove(board.moveBuffer[number]);
if (isOtherKingAttacked())
{
unmakeMove(board.moveBuffer[number]);
}
else
{
std::cout << i + 1 << ". "
;
displayMove(board.moveBuffer[number]);
std::cout << std::endl;
unmakeMove(board.moveBuffer[number]);
i++;
}
}
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// move (do a move) [console mode only]
//
=================================================================
if (!strncmp(buf,
"move",
4))
{
sscanf(buf+4,"%s",userinput);
// generate the pseudo-legal move list
board.ply = 0;
movegen();
if (isValidTextMove(userinput,
move)) // check to see if
the user move is also found in the pseudo-legal move list
{
makeMove(move);
if (isOtherKingAttacked())
// post-move check to see if we
are leaving our king in check
{
unmakeMove(move);
std::cout << " invalid move,
leaving king in check: " << userinput
<< std::endl;
}
else
{
board.endOfGame++;
board.endOfSearch =
board.endOfGame;
board.display();
}
}
else
{
std::cout
<< " move is invalid or not
recognized: " << userinput << std::endl;
}
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// info: display variables (for testing purposes)
//
=================================================================
if (!strcmp(buf,
"info"))
{
info();
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// new: start new game
//
=================================================================
if (!strcmp(buf,
"new"))
{
dataInit();
board.init();
board.display();
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// perft n : calculate raw number of nodes from here, depth n
//
=================================================================
if (!strncmp(buf,
"perft",
5))
{
sscanf(buf+5,"%d",
&number);
std::cout <<
" starting perft "
<< number << "..."
<< std::endl;
timer.init();
board.ply = 0;
#ifdef WINGLET_DEBUG_PERFT
ICAPT = 0;
IEP = 0;
IPROM = 0;
ICASTLOO = 0;
ICASTLOOO = 0;
ICHECK = 0;
#endif
msStart = timer.getms();
perftcount = perft(number);
msStop = timer.getms();
std::cout <<
"nodes = "
<< perftcount << ", "
<< msStop - msStart << " ms, ";
if ((msStop
- msStart) > 0)
std::cout
<< (perftcount/(msStop - msStart)) <<
" knods/s";
std::cout << std::endl;
CMD_BUFF_COUNT =
'\0';
#ifdef WINGLET_DEBUG_PERFT
std::cout <<
"captures = "
<< ICAPT << std::endl;
std::cout <<
"en-passant = "
<< IEP << std::endl;
std::cout <<
"castlings = "
<< ICASTLOO + ICASTLOOO << std::endl;
std::cout <<
"promotions = "
<< IPROM << std::endl;
std::cout <<
"checks = "
<< ICHECK << std::endl;
#endif
return
true;
}
//
=================================================================
// r: rotate board
//
=================================================================
if (!strcmp(buf,
"r"))
{
board.viewRotated = !board.viewRotated;
board.display();
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// readfen filename n : reads #-th FEN position from filename
//
=================================================================
if (!strncmp(buf,
"readfen",
7))
{
sscanf(buf+7,"%s
%d", userinput, &number);
board.init();
readFen(userinput, number);
board.display();
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// setup : setup board...
//
=================================================================
if (!strncmp(buf,
"setup",
5))
{
setup();
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// undo: take back last move
//
=================================================================
if (!strcmp(buf,
"undo"))
{
if (board.endOfGame)
{
unmakeMove(board.gameLine[--board.endOfGame].move);
board.endOfSearch =
board.endOfGame;
board.display();
}
else
{
std::cout
<< "already at start of game"
<< std::endl;
}
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// white: white to move
//
=================================================================
if (!strcmp(buf,
"white"))
{
board.nextMove = WHITE_MOVE;
CMD_BUFF_COUNT =
'\0';
return
true;
}
//
=================================================================
// unknown command
//
=================================================================
std::cout <<
" command not implemented: "
<< buf << ", type 'help' for
more info" << std::endl;
CMD_BUFF_COUNT =
'\0';
return
true;
}
|