From c3159e453dfc6d056c14a86dd7aa908b0963f4e3 Mon Sep 17 00:00:00 2001 From: Fabian Fichter Date: Sun, 12 Jan 2020 01:00:53 +0100 Subject: [PATCH] Rewrite bughouse partner communication - Support playing moves requested by partner. - Extend help. --- src/Makefile | 2 +- src/partner.cpp | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/partner.h | 41 ++++++++++++++++++++++++++ src/search.cpp | 8 ++++- src/xboard.cpp | 26 +++++++---------- 5 files changed, 144 insertions(+), 18 deletions(-) create mode 100644 src/partner.cpp create mode 100644 src/partner.h diff --git a/src/Makefile b/src/Makefile index 9b93f17..98ee074 100644 --- a/src/Makefile +++ b/src/Makefile @@ -37,7 +37,7 @@ PGOBENCH = ./$(EXE) bench ### Object files OBJS = benchmark.o bitbase.o bitboard.o endgame.o evaluate.o main.o \ - material.o misc.o movegen.o movepick.o parser.o pawns.o piece.o position.o psqt.o \ + material.o misc.o movegen.o movepick.o partner.o parser.o pawns.o piece.o position.o psqt.o \ search.o thread.o timeman.o tt.o uci.o ucioption.o variant.o xboard.o syzygy/tbprobe.o ### Establish the operating system name diff --git a/src/partner.cpp b/src/partner.cpp new file mode 100644 index 0000000..c1f533e --- /dev/null +++ b/src/partner.cpp @@ -0,0 +1,85 @@ +/* + Fairy-Stockfish, a UCI chess variant playing engine derived from Stockfish + Copyright (C) 2018-2019 Fabian Fichter + + Fairy-Stockfish is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fairy-Stockfish is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include + +#include "partner.h" +#include "thread.h" +#include "uci.h" + +PartnerHandler Partner; // Global object + +void PartnerHandler::parse_partner(std::istringstream& is) { + std::string token; + if (is >> token) + sync_cout << "tellics ptell partner Fairy-Stockfish is an engine. Ask it 'help' for supported commands." << sync_endl; + else + isFairy = false; +} + +void PartnerHandler::parse_ptell(std::istringstream& is, const Position& pos) { + std::string token; + is >> token; + if (token == "partner") + { + if (is >> token && token == "Fairy-Stockfish") + isFairy = true; + } + else if (token == "help") + { + if (!(is >> token)) + sync_cout << "tellics ptell I listen to the commands help, sit, go, and move. Ptell 'help sit', etc. for details." << sync_endl; + else if (token == "sit") + sync_cout << "tellics ptell After receiving 'sit', I stop moving. Also see 'go'." << sync_endl; + else if (token == "go") + sync_cout << "tellics ptell After receiving 'go', I will no longer sit." << sync_endl; + else if (token == "move") + { + sync_cout << "tellics ptell After receiving 'move', I will move immediately." << sync_endl; + sync_cout << "tellics ptell If you specify a valid move, e.g., 'move e2e4', I will play it." << sync_endl; + } + } + else if (!pos.two_boards()) + return; + else if (token == "sit") + { + sitRequested = true; + sync_cout << "tellics ptell I sit, tell me 'go' to continue" << sync_endl; + } + else if (token == "go") + { + sitRequested = false; + Threads.stop = true; + } + else if (token == "move") + { + if (is >> token) + { + // if the given move is valid and we can still abort the search, play it + Move move = UCI::to_move(pos, token); + if (move && !Threads.abort.exchange(true)) + moveRequested = move; + else + sync_cout << "tellics ptell sorry, not possible" << sync_endl; + } + else + Threads.stop = true; + } +} diff --git a/src/partner.h b/src/partner.h new file mode 100644 index 0000000..def5797 --- /dev/null +++ b/src/partner.h @@ -0,0 +1,41 @@ +/* + Fairy-Stockfish, a UCI chess variant playing engine derived from Stockfish + Copyright (C) 2018-2019 Fabian Fichter + + Fairy-Stockfish is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fairy-Stockfish is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PARTNER_H_INCLUDED +#define PARTNER_H_INCLUDED + +#include +#include + +#include "position.h" + +/// PartnerHandler manages the communication with the partner +/// in games played on two boards, such as bughouse. + +struct PartnerHandler { + void parse_partner(std::istringstream& is); + void parse_ptell(std::istringstream& is, const Position& pos); + + std::atomic isFairy; + std::atomic sitRequested; + Move moveRequested; +}; + +extern PartnerHandler Partner; + +#endif // #ifndef PARTNER_H_INCLUDED \ No newline at end of file diff --git a/src/search.cpp b/src/search.cpp index 3393e29..2c218ef 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -29,6 +29,7 @@ #include "misc.h" #include "movegen.h" #include "movepick.h" +#include "partner.h" #include "position.h" #include "search.h" #include "thread.h" @@ -260,7 +261,7 @@ void MainThread::search() { // GUI sends a "stop" or "ponderhit" command. We therefore simply wait here // until the GUI sends one of those commands. - while (!Threads.stop && (ponder || Limits.infinite || (rootPos.two_boards() && (Threads.sit || this->rootMoves[0].score <= VALUE_MATED_IN_MAX_PLY) && Time.elapsed() < Limits.time[us] - 1000))) + while (!Threads.stop && (ponder || Limits.infinite || (rootPos.two_boards() && (Partner.sitRequested || this->rootMoves[0].score <= VALUE_MATED_IN_MAX_PLY) && Time.elapsed() < Limits.time[us] - 1000))) {} // Busy wait for a stop or a ponder reset // Stop the threads if not already stopped (also raise the stop if @@ -558,7 +559,7 @@ void Thread::search() { // keep pondering until the GUI sends "ponderhit" or "stop". if (mainThread->ponder) mainThread->stopOnPonderhit = true; - else if (!Threads.sit && !(rootPos.two_boards() && bestValue <= VALUE_MATED_IN_MAX_PLY)) + else if (!(rootPos.two_boards() && (Partner.sitRequested || bestValue <= VALUE_MATED_IN_MAX_PLY))) Threads.stop = true; } } @@ -1746,6 +1747,9 @@ void MainThread::check_time() { if (ponder) return; + if (Partner.sitRequested) + return; + if ( (Limits.use_time_management() && (elapsed > Time.maximum() - 10 || stopOnPonderhit)) || (Limits.movetime && elapsed >= Limits.movetime) || (Limits.nodes && Threads.nodes_searched() >= (uint64_t)Limits.nodes)) diff --git a/src/xboard.cpp b/src/xboard.cpp index 9972169..2e2b378 100644 --- a/src/xboard.cpp +++ b/src/xboard.cpp @@ -20,6 +20,7 @@ #include #include "evaluate.h" +#include "partner.h" #include "search.h" #include "thread.h" #include "types.h" @@ -234,25 +235,20 @@ void StateMachine::process_command(Position& pos, std::string token, std::istrin } } // Bughouse commands - else if (token == "partner") {} // ignore for now + else if (token == "partner") + Partner.parse_partner(is); else if (token == "ptell") { - // parse requests by partner - is >> token; - if (token == "help") - sync_cout << "tellics ptell I listen to the commands help, sit, and go." << sync_endl; - else if (token == "hi" || token == "hello") - sync_cout << "tellics ptell hi" << sync_endl; - else if (token == "sit") + Partner.parse_ptell(is, pos); + // play move requested by partner + if (moveAfterSearch && Partner.moveRequested) { - Threads.stop = false; - Threads.sit = true; - sync_cout << "tellics ptell I sit, tell me 'go' to continue" << sync_endl; - } - else if (token == "go") - { - Threads.sit = false; Threads.stop = true; + Threads.main()->wait_for_search_finished(); + sync_cout << "move " << UCI::move(pos, Partner.moveRequested) << sync_endl; + do_move(pos, moveList, states, Partner.moveRequested); + moveAfterSearch = false; + Partner.moveRequested = MOVE_NONE; } } else if (token == "holding") -- 1.7.0.4