- Support playing moves requested by partner.
- Extend help.
### 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
--- /dev/null
+/*
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#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;
+ }
+}
--- /dev/null
+/*
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PARTNER_H_INCLUDED
+#define PARTNER_H_INCLUDED
+
+#include <atomic>
+#include <sstream>
+
+#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<bool> isFairy;
+ std::atomic<bool> sitRequested;
+ Move moveRequested;
+};
+
+extern PartnerHandler Partner;
+
+#endif // #ifndef PARTNER_H_INCLUDED
\ No newline at end of file
#include "misc.h"
#include "movegen.h"
#include "movepick.h"
+#include "partner.h"
#include "position.h"
#include "search.h"
#include "thread.h"
// 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
// 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;
}
}
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))
#include <string>
#include "evaluate.h"
+#include "partner.h"
#include "search.h"
#include "thread.h"
#include "types.h"
}
}
// 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")