⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interface.cpp

📁 超强国际象棋引擎
💻 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 + -