#include <iostream>
#include <sstream>
#include <string.h>
#include <set>
#include "Uci.h"
#include "DebugTest.h"
#include "DebugBench.h"
#include "Move.h"
using namespace std;
Uci::Uci()
{
//engine = eng;
if(!ChessEngine.debugMode)
cout << ChessEngine.GetEngineInfo() << endl;
}
Uci::~Uci(void)
{
}
int Uci::loop(){
string cmd, token;
while (token != "quit")
{
//Threads.DisplayStatus();
if (!getline(cin, cmd)) // Block here waiting for input
cmd = "quit";
istringstream is(cmd);
is >> skipws >> token;
if (token == "quit" || token == "stop")
{
ChessEngine.Stop();
}
else if (token == "ponderhit")
{
// // TODO: implement PonderMode
//
// // The opponent has played the expected move. GUI sends "ponderhit" if
// // we were told to ponder on the same move the opponent has played. We
// // should continue searching but switching from pondering to normal search.
// //Search::Limits.ponder = false;
// //ChessEngine.SetPonderLimit(false);
// // Search::Signals.stopOnPonderhit)
// //if (ChessEngine.IsStopOnPonderHit())
// //ChessEngine.StopThinking();
// //ChessEngine.Stop();
}
else if (token == "go") {
go(is);
}
else if (token == "ucinewgame"){
//pos.from_fen(StartFEN, false);
ChessEngine.SetStartPosition();
}
else if (token == "isready")
{
cout << "readyok" << endl;
}
else if (token == "position")
{
set_position(is);
}
else if (token == "setoption")
{
set_option(is);
}
/*
else if (token == "perft")
{
perft(pos, is);
}
*/
else if (token == "d")
{
// pos.DebugDisplay();
}
else if (token == "flip")
{
// // TODO: implement this method
// int toBeImplemented=1;
// //pos.flip_me();
// //ChessEngine.FlipBoard();
}
else if (token == "eval")
{
// // TODO: implement this method
// int toBeImplemented=1;
// //read_evaluation_uci_options(pos.side_to_move());
// //ChessEngine.ReadEvaluation();
//
// //cout << trace_evaluate(pos) << endl;
// //ChessEngine.TraceEvaluate();
}
else if (token == "key")
{
// cout << "key: " << hex << pos.key()
// << "\nmaterial key: " << pos.material_key()
// << "\npawn key: " << pos.pawn_key() << endl;
}
else if (token == "uci")
{
cout << ChessEngine.GetEngineInfo()
<< ChessEngine.GetEngineOptions()
<< "uciok" << endl;
}
else if ( token == "test" )
{
DebugTest test;
test.LaunchTests();
token = "dummy";
}
else if ( token == "bench" )
{
DebugBench bench;
bench.LaunchBench();
token = "dummy";
}
else if ( token == "dummy" )
{
// do nothing
}
else
{
cout << "Unknown command: " << cmd << endl;
}
}
return 0;
}
const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
void Uci::set_position(istringstream& is) {
Move m;
string token, fen;
is >> token;
if (token == "startpos")
{
fen = StartFEN;
is >> token; // Consume "moves" token if any
}
else if (token == "fen")
while (is >> token && token != "moves")
fen += token + " ";
else
return;
//pos.from_fen(fen, Options["UCI_Chess960"]);
ChessEngine.SetPosition(fen);
// Parse move list (if any)
//while (is >> token && (m = string_to_move(ChessEngine.currentPosition, token)) != MOVE_NONE)
while (is >> token && (m = string_to_move(/*ChessEngine.currentPosition,*/ token)) != MOVE_NONE)
{
//TODO: take current position in consideration for stringToMove method (cPiece and cColor are missing in generated move)
//m = move_from_uci(pos, token);
//m = stringToMove(token);
//pos.do_move(m, *SetupState);
//ChessEngine.DoMove(m, *SetupState);
ChessEngine.Play(m);
/*
// Increment pointer to StateRingBuf circular buffer
if (++SetupState - StateRingBuf >= 102)
SetupState = StateRingBuf;
*/
}
}
// set_option() is called when engine receives the "setoption" UCI command. The
// function updates the UCI option ("name") to the given value ("value").
void Uci::set_option(istringstream& is) {
string token, name, value;
is >> token; // Consume "name" token
// Read option name (can contain spaces)
while (is >> token && token != "value")
name += string(" ", !name.empty()) + token;
// Read option value (can contain spaces)
while (is >> token)
value += string(" ", !value.empty()) + token;
/*
//if (!Options.size()(name))
if (!ChessEngine.IsValidOption(name))
cout << "No such option: " << name << endl;
else if (value.empty()) // UCI buttons don't have a value
Options[name] = true;
else
Options[name] = value;
else */
ChessEngine.SetOption(name,value);
}
// go() is called when engine receives the "go" UCI command. The function sets
// the thinking time and other parameters from the input string, and then starts
// the main searching thread.
void Uci::go(istringstream& is) {
string token;
//LimitsType limits;
std::set<Move> searchMoves;
int time[] = { 0, 0 }, inc[] = { 0, 0 };
while (is >> token)
{
if (token == "infinite") {
//ChessEngine.SetLimitsInfinite(true);//limits.infinite = true;
ChessEngine.brainMode = INFINITE_MODE;
}
else if (token == "ponder") {
//ChessEngine.SetLimitsPonder(true);//limits.ponder = true;
ChessEngine.SetPonderMode();
}
else if (token == "wtime"){
is >> time[WHITE];
//is >> ChessEngine.wtime;
}
else if (token == "btime"){
is >> time[BLACK];
//is >> ChessEngine.btime;
}
else if (token == "winc"){
is >> inc[WHITE];
//is >> ChessEngine.winc;
}
else if (token == "binc"){
is >> inc[BLACK];
//is >> ChessEngine.binc;
}
else if (token == "movestogo"){
//is >> limits.movestogo;
int movesToGo;
is >> movesToGo;
ChessEngine.SetMovestogo(movesToGo);
}
else if (token == "depth"){
//is >> limits.depth;
//ChessEngine.brainMode = DEPTH_MODE;
int depth;
is >> depth;
ChessEngine.SetDepthMode(depth);
}
else if (token == "nodes"){
//is >> limits.maxNodes;
//ChessEngine.brainMode = NODES_MODE;
int maxNodes;
is >> maxNodes;
ChessEngine.SetNodesMode(maxNodes);
}
else if (token == "movetime"){
//is >> limits.maxTime;
//is >> ChessEngine.thinkDelay;
//ChessEngine.brainMode = MOVETIME_MODE;
int movetime;
is >> movetime;
ChessEngine.SetMovetimeMode(movetime);
}
else if (token == "searchmoves"){
// TODO: refactor this part
//while (is >> token)
// searchMoves.insert(move_from_uci(pos, token));
}
}
//limits.time = time[pos.side_to_move() pos.turn?0:1];
//limits.increment = inc[pos.side_to_move() pos.turn?0:1];
//Threads.start_thinking(pos, limits, searchMoves, true);
//ChessEngine.StartThinking(pos, limits, searchMoves, true);
ChessEngine.Start();
}
// perft() is called when engine receives the "perft" command. The function
// calls perft() with the required search depth then prints counted leaf nodes
// and elapsed time.
/*
void Uci::perft(istringstream& is) {
int depth, time;
if (!(is >> depth))
return;
// TODO: use watch (to be improved)
Watch w;
w.Start();
//time = system_time();
//int64_t n = Search::perft(pos, depth * ONE_PLY); long ???
long long n = perft(pos, depth * ONE_PLY);
// TODO: use watch
w.Stop();
time = w.GetElapsedTime();
//time = system_time() - time;
std::cout << "\nNodes " << n
<< "\nTime (ms) " << time
<< "\nNodes/second " << int(n / (time / 1000.0)) << std::endl;
}
*/
///// Search::perft() is our utility to verify move generation. All the leaf nodes
///// up to the given depth are generated and counted and the sum returned.
//
////int64_t
//long long perft(Position& pos, int depth) {
//
// //StateInfo st;
// //int64_t cnt = 0;
// long long cnt = 0;
// /*
//
// Movevector<MV_LEGAL> ml(pos);
//
// // At the last ply just return the number of moves (leaf nodes)
// if (depth == ONE_PLY)
// return ml.size();
//
// CheckInfo ci(pos);
// for ( ; !ml.end(); ++ml)
// {
// pos.do_move(ml.move(), st, ci, pos.move_gives_check(ml.move(), ci));
// cnt += perft(pos, depth - ONE_PLY);
// pos.undo_move(ml.move());
// }
// */
// return cnt;
//}
/*
/// move_from_uci() takes a position and a string representing a move in
/// simple coordinate notation and returns an equivalent Move if any.
/// Moves are guaranteed to be legal.
Move Uci::move_from_uci(const Position& pos, const string& str) {
for (Movevector<MV_LEGAL> ml(pos); !ml.end(); ++ml)
if (str == move_to_uci(ml.move(), pos.is_chess960()))
return ml.move();
return MOVE_NONE;
return NULL;
}
*/
void Uci::bench(std::istringstream &is){
string partToBench;
if (!(is >> partToBench))
return;
//ChessEngine.Bench(partToBench);
}
void Uci::test(std::istringstream &is){
string partToTest;
if (!(is >> partToTest))
return;
//ChessEngine.Test(partToTest);
}