📄 interface.cpp
字号:
// protocol.cpp
// includes
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "board.h"
#include "evaluate.h"
#include "fen.h"
#include "material.h"
#include "move.h"
#include "make_move.h"
#include "move_gen.h"
#include "config.h"
#include "pawn.h"
#include "input.h"
#include "probe.h"
#include "interface.h"
#include "position.h"
#include "search.h"
#include "search_root.h"
#include "transposition.h"
#include "values.h"
// variables
static bool searching;
static bool Infinite;
static bool delay;
static bool option_ponder = false;
int option_searchdepth = 0;
int option_searchtime = 0;
int option_threads = 0;
// prototypes
void process_input();
static void parse_go(char string []);
static void parse_position(char string []);
static void parse_setoption(char string []);
static void send_best_move();
static bool string_equal(const char s1 [], const char s2 []);
static bool string_start_with(const char s1 [], const char s2 []);
// functions
// process_input()
void process_input()
{
char string[65536];
int thread_id;
// read a line
get(string, 65536);
// parse
if(false) { }
else if(string_start_with(string, "debug ")) {
// dummy
}
else if(string_start_with(string, "go "))
{
if(!searching && !delay)
{
parse_go(string);
}
else { }
}
else if(string_equal(string, "isready"))
{
if(!searching && !delay) { }
send("readyok"); // no need to wait when searching (dixit SMK)
}
else if(string_equal(string, "ponderhit"))
{
if(searching)
{
search_input->infinite = false;
Infinite = false;
}
else if(delay)
{
send_best_move();
delay = false;
}
else { }
}
else if(string_start_with(string, "position "))
{
if(!searching && !delay)
{
parse_position(string);
}
else { }
}
else if(string_equal(string, "quit"))
{
exit(EXIT_SUCCESS);
}
else if(string_start_with(string, "setoption "))
{
if(!searching && !delay)
{
parse_setoption(string);
}
else { }
}
else if(string_equal(string, "stop"))
{
if(searching)
{
for ( thread_id = 0; thread_id < number_threads; thread_id++ )
{
search_info[thread_id]->stop = true;
}
Infinite = false;
}
else if(delay)
{
send_best_move();
delay = false;
}
}
else if(string_equal(string, "uci"))
{
send("id name Cyclone " VERSION);
send("id author Kranium");
option_list();
send("uciok");
}
else if(string_equal(string, "ucinewgame"))
{
if(!searching && !delay)
{
trans_clear(Trans);
}
else { }
}
}
// parse_go()
static void parse_go(char string [])
{
const char *ptr;
bool infinite, ponder;
int depth, mate, movestogo;
sint64 nodes;
double binc, btime, movetime, winc, wtime;
double time, inc;
double time_max, alloc;
int thread_id;
// init
infinite = false;
ponder = false;
depth = -1;
mate = -1;
movestogo = -1;
nodes = -1;
binc = -1.0;
btime = -1.0;
movetime = -1.0;
winc = -1.0;
wtime = -1.0;
// parse
ptr = strtok(string, " "); // skip "go"
for ( ptr = strtok(NULL, " "); ptr != NULL; ptr = strtok(NULL, " ") )
{
if(false) { }
else if(string_equal(ptr, "binc"))
{
ptr = strtok(NULL, " ");
binc = double(atoi(ptr)) / 1000.0;
}
else if(string_equal(ptr, "btime"))
{
ptr = strtok(NULL, " ");
btime = double(atoi(ptr)) / 1000.0;
}
else if(string_equal(ptr, "depth"))
{
ptr = strtok(NULL, " ");
depth = atoi(ptr);
}
else if(string_equal(ptr, "infinite"))
{
infinite = true;
}
else if(string_equal(ptr, "mate"))
{
ptr = strtok(NULL, " ");
mate = atoi(ptr);
}
else if(string_equal(ptr, "movestogo"))
{
ptr = strtok(NULL, " ");
movestogo = atoi(ptr);
}
else if(string_equal(ptr, "movetime"))
{
ptr = strtok(NULL, " ");
movetime = double(atoi(ptr)) / 1000.0;
}
else if(string_equal(ptr, "nodes"))
{
ptr = strtok(NULL, " ");
nodes = atoll(ptr);
}
else if(string_equal(ptr, "ponder"))
{
ponder = true;
}
else if(string_equal(ptr, "searchmoves")) {
// dummy
}
else if(string_equal(ptr, "winc"))
{
ptr = strtok(NULL, " ");
winc = double(atoi(ptr)) / 1000.0;
}
else if(string_equal(ptr, "wtime"))
{
ptr = strtok(NULL, " ");
wtime = double(atoi(ptr)) / 1000.0;
}
}
// init
search_clear();
// depth limit
if(option_searchdepth > 0)
{
depth = option_searchdepth;
}
if(depth >= 0)
{
search_input->depth_is_limited = true;
search_input->depth_limit = depth;
}
else if(mate >= 0)
{
search_input->depth_is_limited = true;
search_input->depth_limit = mate * 2 - 1;
}
// time limit
if(COLOUR_IS_WHITE(search_input->board->turn))
{
time = wtime;
inc = winc;
}
else
{
time = btime;
inc = binc;
}
if(movestogo <= 0 || movestogo > 30)
movestogo = 30;
if(inc < 0.0)
inc = 0.0;
if(option_searchtime > 0)
{
movetime = double(option_searchtime);
}
if(movetime >= 0.0)
{
// fixed time
search_input->time_is_limited = true;
search_input->time_limit_1 = movetime * 5.0;
search_input->time_limit_2 = movetime;
}
else if(time >= 0.0)
{
// dynamic allocation
time_max = time * 0.95 - 1.0;
if(time_max < 0.0)
time_max = 0.0;
search_input->time_is_limited = true;
alloc = (time_max + inc * double(movestogo - 1)) / double(movestogo);
alloc *= (option_ponder ? 1.25 : 1);
if(alloc > time_max)
alloc = time_max;
search_input->time_limit_1 = alloc;
alloc = (time_max + inc * double(movestogo - 1)) * 0.5;
if(alloc < search_input->time_limit_1)
alloc = search_input->time_limit_1;
if(alloc > time_max)
alloc = time_max;
search_input->time_limit_2 = alloc;
}
if(infinite || ponder)
search_input->infinite = true;
// search
searching = true;
Infinite = infinite || ponder;
delay = false;
search();
for ( thread_id = 0; thread_id < number_threads; thread_id++ )
{
search_update_current(thread_id);
}
searching = false;
delay = Infinite;
if(!delay)
send_best_move();
}
// parse_position()
static void parse_position(char string [])
{
const char *fen;
char *moves;
const char *ptr;
char move_string[256];
int move;
undo_t undo[1];
// init
fen = strstr(string, "fen ");
moves = strstr(string, "moves ");
// start position
if(fen != NULL)
{
if(moves != NULL)
{
moves[-1] = '\0';
}
board_from_fen(search_input->board, fen + 4);
}
else
{
board_from_fen(search_input->board, start_fen);
}
// moves
if(moves != NULL)
{ // "moves" present
ptr = moves + 6;
while(*ptr != '\0')
{
move_string[0] = *ptr++;
move_string[1] = *ptr++;
move_string[2] = *ptr++;
move_string[3] = *ptr++;
if(*ptr == '\0' || *ptr == ' ')
{
move_string[4] = '\0';
}
else
{ // promote
move_string[4] = *ptr++;
move_string[5] = '\0';
}
move = move_from_string(move_string, search_input->board);
move_do(search_input->board, move, undo);
while(*ptr == ' ')
ptr++;
}
}
}
// parse_setoption()
static void parse_setoption(char string [])
{
const char *name;
char *value;
// init
name = strstr(string, "name ");
value = strstr(string, "value ");
if(name == NULL || value == NULL || name >= value)
return;
value[-1] = '\0';
name += 5;
value += 6;
// update
option_set(name, value);
// update bitbase config
if(string_equals(name, "Bitbases") || string_equals(name, "Bitbase Path") || string_equals(name, "Bitbase Cache"))
{
bitbase_init();
}
// update ponder parameter
if(string_equals(name, "Ponder"))
{
option_ponder = (option_get_bool("Ponder"));
}
// update search depth parameter
if(string_equals(name, "Search Depth"))
{
option_searchdepth = (option_get_int("Search Depth"));
}
// update thread number parameter
if(string_equals(name, "Threads"))
{
option_threads = (option_get_int("Threads"));
if (option_threads != number_threads)
{
material_free();
pawn_free();
number_threads = option_threads;
material_alloc();
pawn_alloc();
}
}
// update search time parameter
if(string_equals(name, "Search Time"))
{
option_searchtime = (option_get_int("Search Time"));
}
// update transposition-table config
if(string_equals(name, "Dynamic Hash") || string_equals(name, "Nodes Per Second")
|| string_equals(name, "Seconds Per Move") || string_equals(name, "Manual Hash")
|| string_equals(name, "Manual Hash Size"))
{
trans_parameter();
}
}
// send_best_move()
static void send_best_move()
{
double time, speed;
sint64 node_nb;
char move_string[256];
char ponder_string[256];
int move;
int thread_id, bestThreadId;
mv_t *pv;
// info
time = search_current[0]->time;
speed = 0;
for ( thread_id = 0; thread_id < number_threads; thread_id++ )
{
speed += search_current[thread_id]->speed;
}
node_nb = 0;
for ( thread_id = 0; thread_id < number_threads; thread_id++ )
{
node_nb += search_current[thread_id]->node_nb;
}
send("info time %.0f nodes " S64_FORMAT " nps %.0f",time*1000.0,node_nb,speed);
trans_stats(Trans);
bestThreadId = 0;
for ( thread_id = 1; thread_id < number_threads; thread_id++ )
{
if(search_best[bestThreadId][0].depth < search_best[thread_id][0].depth
|| (search_best[bestThreadId][0].depth == search_best[thread_id][0].depth
&& search_best[bestThreadId][0].value < search_best[thread_id][0].value))
{
bestThreadId = thread_id;
}
}
move = search_best[bestThreadId][0].move;
pv = search_best[bestThreadId][0].pv;
move_to_string(move, move_string, 256);
if(pv[0] == move && move_is_ok(pv[1]))
{
move_to_string(pv[1], ponder_string, 256);
send("bestmove %s ponder %s", move_string, ponder_string);
}
else
{
send("bestmove %s", move_string);
}
}
// search_init()
void search_init()
{
searching = false;
Infinite = false;
delay = false;
search_clear();
board_from_fen(search_input->board, start_fen);
}
// event()
void event()
{
while(!search_info[0]->stop && input_available())
process_input();
}
// get()
void get(char string [], int size)
{
if(!file_read_line(stdin, string, size))
{ // EOF
exit(EXIT_SUCCESS);
}
}
// string_equal()
static bool string_equal(const char s1 [], const char s2 [])
{
return strcmp(s1, s2) == 0;
}
// string_start_with()
static bool string_start_with(const char s1 [], const char s2 [])
{
return strstr(s1, s2) == s1;
}
// end of protocol.cpp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -