From 4b7f54b77db1803b4d03bed848540dada37e7a0b Mon Sep 17 00:00:00 2001
From: Danny Jelsma <73849717+Dannyj1@users.noreply.github.com>
Date: Sat, 4 May 2024 19:10:45 +0200
Subject: [PATCH 01/91] Remove all code so we can start the rewrite
---
CMakeLists.txt | 42 +-
senjo/BackgroundCommand.cpp | 277 ---------
senjo/BackgroundCommand.h | 173 ------
senjo/CMakeLists.txt | 9 -
senjo/ChessEngine.cpp | 74 ---
senjo/ChessEngine.h | 279 ---------
senjo/EngineOption.cpp | 157 -----
senjo/EngineOption.h | 223 -------
senjo/GoParams.h | 45 --
senjo/Output.cpp | 58 --
senjo/Output.h | 134 -----
senjo/Parameters.cpp | 112 ----
senjo/Parameters.h | 144 -----
senjo/Platform.h | 140 -----
senjo/README.md | 112 ----
senjo/SearchStats.h | 56 --
senjo/Thread.cpp | 75 ---
senjo/Thread.h | 102 ----
senjo/UCIAdapter.cpp | 667 ---------------------
senjo/UCIAdapter.h | 88 ---
src/bitboard.cpp | 891 ----------------------------
src/bitboard.h | 438 --------------
src/bitwise.cpp | 338 -----------
src/bitwise.h | 125 ----
src/constants.h | 92 ---
src/engine.cpp | 256 --------
src/engine.h | 123 ----
src/evaluate.cpp | 773 ------------------------
src/evaluate.h | 72 ---
src/features.cpp | 181 ------
src/features.h | 187 ------
src/magics.cpp | 450 --------------
src/magics.h | 92 ---
src/main.cpp | 227 +------
src/movegen.cpp | 572 ------------------
src/movelist_pool.cpp | 72 ---
src/movelist_pool.h | 49 --
src/movepicker.cpp | 48 --
src/movepicker.h | 50 --
src/pst.cpp | 314 ----------
src/pst.h | 44 --
src/search.cpp | 538 -----------------
src/search.h | 59 --
src/timemanager.cpp | 103 ----
src/timemanager.h | 33 --
src/tt.cpp | 168 ------
src/tt.h | 106 ----
src/tuner.cpp | 400 -------------
src/tuner.h | 59 --
src/types.h | 185 ------
tests/tests_main.cpp => src/uci.cpp | 14 -
src/{movegen.h => uci.h} | 14 +-
src/utils.cpp | 72 ---
src/utils.h | 97 ---
tests/ep_tests.cpp | 44 --
tests/eval_tests.cpp | 174 ------
tests/perft_tests.cpp | 109 ----
tests/see_tests.cpp | 125 ----
58 files changed, 24 insertions(+), 10637 deletions(-)
delete mode 100644 senjo/BackgroundCommand.cpp
delete mode 100644 senjo/BackgroundCommand.h
delete mode 100644 senjo/CMakeLists.txt
delete mode 100644 senjo/ChessEngine.cpp
delete mode 100644 senjo/ChessEngine.h
delete mode 100644 senjo/EngineOption.cpp
delete mode 100644 senjo/EngineOption.h
delete mode 100644 senjo/GoParams.h
delete mode 100644 senjo/Output.cpp
delete mode 100644 senjo/Output.h
delete mode 100644 senjo/Parameters.cpp
delete mode 100644 senjo/Parameters.h
delete mode 100644 senjo/Platform.h
delete mode 100644 senjo/README.md
delete mode 100644 senjo/SearchStats.h
delete mode 100644 senjo/Thread.cpp
delete mode 100644 senjo/Thread.h
delete mode 100644 senjo/UCIAdapter.cpp
delete mode 100644 senjo/UCIAdapter.h
delete mode 100644 src/bitboard.cpp
delete mode 100644 src/bitboard.h
delete mode 100644 src/bitwise.cpp
delete mode 100644 src/bitwise.h
delete mode 100644 src/constants.h
delete mode 100644 src/engine.cpp
delete mode 100644 src/engine.h
delete mode 100644 src/evaluate.cpp
delete mode 100644 src/evaluate.h
delete mode 100644 src/features.cpp
delete mode 100644 src/features.h
delete mode 100644 src/magics.cpp
delete mode 100644 src/magics.h
delete mode 100644 src/movegen.cpp
delete mode 100644 src/movelist_pool.cpp
delete mode 100644 src/movelist_pool.h
delete mode 100644 src/movepicker.cpp
delete mode 100644 src/movepicker.h
delete mode 100644 src/pst.cpp
delete mode 100644 src/pst.h
delete mode 100644 src/search.cpp
delete mode 100644 src/search.h
delete mode 100644 src/timemanager.cpp
delete mode 100644 src/timemanager.h
delete mode 100644 src/tt.cpp
delete mode 100644 src/tt.h
delete mode 100644 src/tuner.cpp
delete mode 100644 src/tuner.h
delete mode 100644 src/types.h
rename tests/tests_main.cpp => src/uci.cpp (68%)
rename src/{movegen.h => uci.h} (72%)
delete mode 100644 src/utils.cpp
delete mode 100644 src/utils.h
delete mode 100644 tests/ep_tests.cpp
delete mode 100644 tests/eval_tests.cpp
delete mode 100644 tests/perft_tests.cpp
delete mode 100644 tests/see_tests.cpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9c894b28..434aa478 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,9 +20,9 @@
# along with Zagreus. If not, see .
cmake_minimum_required(VERSION 3.25)
-set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD 23)
project(Zagreus)
-set(ZAGREUS_VERSION_MAJOR "5")
+set(ZAGREUS_VERSION_MAJOR "6")
set(ZAGREUS_VERSION_MINOR "0")
# Default values
@@ -200,27 +200,27 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${BUILD_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${BUILD_FLAGS}")
file(GLOB inc_zagreus "src/*.h" "src/*.cpp")
-file(GLOB inc_senjo "senjo/*.h" "senjo/*.cpp")
-add_executable(Zagreus src/main.cpp ${inc_senjo} ${inc_zagreus})
+add_executable(Zagreus src/main.cpp ${inc_zagreus})
target_compile_definitions(Zagreus PRIVATE ZAGREUS_VERSION_MAJOR="${ZAGREUS_VERSION_MAJOR}")
target_compile_definitions(Zagreus PRIVATE ZAGREUS_VERSION_MINOR="${ZAGREUS_VERSION_MINOR}")
-if (ENABLE_TESTS)
- file(GLOB tests_folder "tests/*.h" "tests/*.cpp")
-
- # Remove main from inc_zagreus
- list(REMOVE_ITEM inc_zagreus "${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp")
-
- add_executable(zagreus-tests ${tests_folder} ${inc_senjo} ${inc_zagreus})
- target_link_libraries(zagreus-tests PRIVATE Catch2::Catch2WithMain)
-
- target_compile_definitions(zagreus-tests PRIVATE ZAGREUS_VERSION_MAJOR="${ZAGREUS_VERSION_MAJOR}")
- target_compile_definitions(zagreus-tests PRIVATE ZAGREUS_VERSION_MINOR="${ZAGREUS_VERSION_MINOR}")
-
- list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras)
- include(CTest)
- include(Catch)
- catch_discover_tests(zagreus-tests)
-endif ()
\ No newline at end of file
+# TODO: re-enable
+#if (ENABLE_TESTS)
+# file(GLOB tests_folder "tests/*.h" "tests/*.cpp")
+#
+# # Remove main from inc_zagreus
+# list(REMOVE_ITEM inc_zagreus "${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp")
+#
+# add_executable(zagreus-tests ${tests_folder} ${inc_zagreus})
+# target_link_libraries(zagreus-tests PRIVATE Catch2::Catch2WithMain)
+#
+# target_compile_definitions(zagreus-tests PRIVATE ZAGREUS_VERSION_MAJOR="${ZAGREUS_VERSION_MAJOR}")
+# target_compile_definitions(zagreus-tests PRIVATE ZAGREUS_VERSION_MINOR="${ZAGREUS_VERSION_MINOR}")
+#
+# list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras)
+# include(CTest)
+# include(Catch)
+# catch_discover_tests(zagreus-tests)
+#endif ()
diff --git a/senjo/BackgroundCommand.cpp b/senjo/BackgroundCommand.cpp
deleted file mode 100644
index 1de45c9d..00000000
--- a/senjo/BackgroundCommand.cpp
+++ /dev/null
@@ -1,277 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2015-2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "BackgroundCommand.h"
-#include "Output.h"
-#include
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
- bool BackgroundCommand::parseAndExecute(Parameters ¶ms) {
- if (!parse(params)) {
- return false;
- }
-
- if (isRunning()) {
- Output() << "Another background command is still active, can't execute";
- return false;
- }
-
- if (!engine.isInitialized()) {
- engine.initialize();
- }
-
- return run();
- }
-
-//-----------------------------------------------------------------------------
- bool RegisterCommandHandle::parse(Parameters ¶ms) {
- later = false;
- code = "";
- name = "";
-
- params.popParam("later", later);
- params.popString("name", name, "code");
- params.popString("code", code);
-
- if (params.size()) {
- Output() << "Unexpected token: " << params.front();
- return false;
- }
-
- return true;
- }
-
-//-----------------------------------------------------------------------------
- void RegisterCommandHandle::doWork() {
- static const std::string registrationOK = "registration ok";
-
- Output(Output::NoPrefix) << "registration checking";
- if (engine.isRegistered()) {
- Output(Output::NoPrefix) << registrationOK;
- } else if (later) {
- engine.registerLater();
- Output(Output::NoPrefix) << registrationOK;
- } else if (engine.doRegistration(name, code)) {
- Output(Output::NoPrefix) << registrationOK;
- } else {
- Output(Output::NoPrefix) << "registration error";
- }
- }
-
-//-----------------------------------------------------------------------------
- bool GoCommandHandle::parse(Parameters ¶ms) {
- goParams = GoParams(); // reset all params to default values
-
- bool invalid = false;
- while (!invalid && params.size()) {
- if (params.firstParamIs("searchmoves")) {
- Output() << "searchmoves not implemented!"; // TODO
- break;
- }
- if (params.popParam("infinite", goParams.infinite) ||
- params.popParam("ponder", goParams.ponder) ||
- params.popNumber("depth", goParams.depth) ||
- params.popNumber("movestogo", goParams.movestogo) ||
- params.popNumber("binc", goParams.binc) ||
- params.popNumber("btime", goParams.btime) ||
- params.popNumber("movetime", goParams.movetime) ||
- params.popNumber("nodes", goParams.nodes) ||
- params.popNumber("winc", goParams.winc) ||
- params.popNumber("wtime", goParams.wtime)) {
- continue;
- }
- Output() << "Unexpected token: " << params.front();
- return false;
- }
-
- if (invalid) {
- Output() << "usage: " << usage();
- return false;
- }
-
- return true;
- }
-
-//-----------------------------------------------------------------------------
- void GoCommandHandle::doWork() {
- std::string ponderMove;
- std::string bestMove = engine.go(goParams, &ponderMove);
-
- if (bestMove.empty()) {
- bestMove = "none";
- ponderMove.clear();
- }
-
- if (ponderMove.size()) {
- Output(Output::NoPrefix) << "bestmove " << bestMove
- << " ponder " << ponderMove;
- } else {
- Output(Output::NoPrefix) << "bestmove " << bestMove;
- }
- }
-
-//-----------------------------------------------------------------------------
- const std::string PerftCommandHandle::_TEST_FILE = "epd/perftsuite.epd";
-
-//-----------------------------------------------------------------------------
- bool PerftCommandHandle::parse(Parameters ¶ms) {
- count = 0;
- skip = 0;
- maxDepth = 0;
- maxLeafs = 0;
- fileName = "";
-
- bool epd = false;
- bool invalid = false;
-
- while (params.size() && !invalid) {
- if (params.popParam("epd", epd) ||
- params.popNumber("count", count, invalid) ||
- params.popNumber("skip", skip, invalid) ||
- params.popNumber("depth", maxDepth, invalid) ||
- params.popNumber("leafs", maxLeafs, invalid) ||
- params.popString("file", fileName)) {
- continue;
- }
- Output() << "Unexpected token: " << params.front();
- return false;
- }
-
- if (invalid) {
- Output() << "usage: " << usage();
- return false;
- }
-
- if (epd && fileName.empty()) {
- fileName = _TEST_FILE;
- }
-
- return true;
- }
-
-//-----------------------------------------------------------------------------
- void PerftCommandHandle::doWork() {
- if (fileName.empty()) {
- engine.perft(maxDepth);
- return;
- }
-
- std::ifstream fs(fileName);
-
- const TimePoint start = now();
- uint64_t pcount = 0;
- bool done = false;
- int positions = 0;
- int line = 0;
-
- std::string fen;
- fen.reserve(16384);
-
- while (!done && std::getline(fs, fen)) {
- line++;
-
- size_t i = fen.find_first_not_of(" \t\r\n");
- if ((i == std::string::npos) || (fen[i] == '#')) {
- continue;
- }
-
- positions++;
- if ((skip > 0) && (positions <= skip)) {
- continue;
- }
-
- Output() << fileName << " line " << line << ' ' << fen;
- std::string remain;
- if (!engine.setPosition(fen, &remain)) {
- break;
- }
-
- // process "D " parameters (e.g. D5 4865609)
- Parameters params(remain);
- while (!done && params.size()) {
- std::string depthToken = trim(params.popString(), " ;");
- if (depthToken.empty() || (depthToken.at(0) != 'D')) {
- continue;
- }
-
- int16_t depth = toNumber(depthToken.substr(1));
- if (depth < 1) {
- Output() << "--- invalid depth: " << depthToken;
- break;
- }
-
- if (params.empty()) {
- Output() << "--- missing expected leaf count";
- break;
- }
-
- uint64_t leafs = params.popNumber();
- if (leafs < 1) {
- Output() << "--- invalid expected leaf count";
- break;
- }
-
- done |= !process(depth, leafs, pcount);
- }
-
- done |= ((count > 0) && (positions >= count));
- }
-
- double msecs = getMsecs(start, now());
- double kLeafs = (static_cast(pcount) / 1000);
-
- Output() << "Total Perft " << pcount << ' '
- << rate(kLeafs, msecs) << " KLeafs/sec";
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Perform [q]perft search, \p params format = 'D '
-//! \param[in] depth The depth to search to
-//! \param[in] expected_leaf_count The expected leaf count at \p depth
-//! \param[out] leaf_count The actual leaf count at \p depth
-//! \return false if leaf_count count does not match expected leaf count
-//-----------------------------------------------------------------------------
- bool PerftCommandHandle::process(const int16_t depth,
- const uint64_t expected_leaf_count,
- uint64_t &leaf_count) {
- if ((maxDepth > 0) && (depth > maxDepth)) {
- return true;
- }
-
- if ((maxLeafs > 0) && (expected_leaf_count > maxLeafs)) {
- return true;
- }
-
- Output() << "--- " << depth << " => " << expected_leaf_count;
- uint64_t perft_count = engine.perft(depth);
- leaf_count += perft_count;
-
- if (perft_count != expected_leaf_count) {
- Output() << "--- " << perft_count << " != " << expected_leaf_count;
- return false;
- }
-
- return true;
- }
-} // namespace senjo
diff --git a/senjo/BackgroundCommand.h b/senjo/BackgroundCommand.h
deleted file mode 100644
index 17616018..00000000
--- a/senjo/BackgroundCommand.h
+++ /dev/null
@@ -1,173 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2015-2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef SENJO_BACKGROUND_COMMAND_H
-#define SENJO_BACKGROUND_COMMAND_H
-
-#include "ChessEngine.h"
-#include "Parameters.h"
-#include "GoParams.h"
-#include "Thread.h"
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
-//! \brief Base class for a command that should run on a background thread
-//-----------------------------------------------------------------------------
- class BackgroundCommand : public Thread {
- public:
- //--------------------------------------------------------------------------
- //! \brief Constructor
- //! \param[in] engine The chess engine to use while executing
- //--------------------------------------------------------------------------
- BackgroundCommand(ChessEngine &chessEngine)
- : engine(chessEngine) {}
-
- //--------------------------------------------------------------------------
- //! \brief Parse command parameters and execute on the given thread
- //! \param[in] params The command parameters
- //! \return true if parameters are valid and execution started
- //--------------------------------------------------------------------------
- virtual bool parseAndExecute(Parameters ¶ms);
-
- //--------------------------------------------------------------------------
- //! \brief Provide usage syntax for this command
- //! For example: "command_name [boolean_option_name] [option_name ]"
- //! \return Usage syntax string for this command
- //--------------------------------------------------------------------------
- virtual std::string usage() const = 0;
-
- //--------------------------------------------------------------------------
- //! \brief Provide a brief description of this command
- //! \return A brief description of this command
- //--------------------------------------------------------------------------
- virtual std::string description() const = 0;
-
- //--------------------------------------------------------------------------
- //! \brief Parse command parameters
- //! \param[in] params The command parameters
- //! \return true if the given parameters are valid
- //--------------------------------------------------------------------------
- virtual bool parse(Parameters ¶ms) = 0;
-
- protected:
- ChessEngine &engine;
- };
-
-//-----------------------------------------------------------------------------
-//! \brief Wrapper for the UCI "register" command
-//-----------------------------------------------------------------------------
- class RegisterCommandHandle : public BackgroundCommand {
- public:
- RegisterCommandHandle(ChessEngine &eng) : BackgroundCommand(eng) {}
-
- std::string usage() const {
- return "register [later] [name ] [code ]";
- }
-
- std::string description() const {
- return "Register the chess engine to enable full functionality.";
- }
-
- void stop() {}
-
- protected:
- bool parse(Parameters ¶ms);
-
- void doWork();
-
- private:
- bool later;
- std::string code;
- std::string name;
- };
-
-//-----------------------------------------------------------------------------
-//! \brief Wrapper for the UCI "go" command
-//-----------------------------------------------------------------------------
- class GoCommandHandle : public BackgroundCommand {
- public:
- GoCommandHandle(ChessEngine &eng) : BackgroundCommand(eng) {}
-
- std::string usage() const {
- return "go [infinite] [ponder] [depth ] [nodes ] "
- "[wtime ] [btime ] [winc ] [binc ] "
- "[movetime ] [movestogo ] [searchmoves ]";
- }
-
- std::string description() const {
- return "Find the best move for the current position.";
- }
-
- void stop() {
- engine.stopSearching();
- }
-
- protected:
- bool parse(Parameters ¶ms);
-
- void doWork();
-
- private:
- GoParams goParams;
- };
-
-//-----------------------------------------------------------------------------
-//! \brief Wrapper for the "perft" command (not a UCI command)
-//-----------------------------------------------------------------------------
- class PerftCommandHandle : public BackgroundCommand {
- public:
- PerftCommandHandle(ChessEngine &eng) : BackgroundCommand(eng) {}
-
- std::string usage() const {
- return "perft [unsorted] [depth ] [count ] [skip ] [leafs ] "
- "[epd] [file (default=" + _TEST_FILE + ")]";
- }
-
- std::string description() const {
- return "Execute performance test.";
- }
-
- void stop() {
- engine.stopSearching();
- }
-
- protected:
- bool parse(Parameters ¶ms);
-
- void doWork();
-
- private:
- bool process(const int16_t depth, const uint64_t expected_leaf_count,
- uint64_t &leaf_count);
-
- static const std::string _TEST_FILE;
-
- int count;
- int skip;
- int maxDepth;
- uint64_t maxLeafs;
- std::string fileName;
- };
-} // namespace senjo
-
-#endif // SENJO_BACKGROUND_COMMAND_H
diff --git a/senjo/CMakeLists.txt b/senjo/CMakeLists.txt
deleted file mode 100644
index a8b55207..00000000
--- a/senjo/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-cmake_minimum_required(VERSION 3.1)
-project(senjo CXX)
-
-file(GLOB OBJ_HDR *.h)
-file(GLOB OBJ_SRC *.cpp)
-
-include_directories(.)
-add_library(${PROJECT_NAME} STATIC ${OBJ_HDR} ${OBJ_SRC})
-
diff --git a/senjo/ChessEngine.cpp b/senjo/ChessEngine.cpp
deleted file mode 100644
index ce8ca801..00000000
--- a/senjo/ChessEngine.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2015-2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "ChessEngine.h"
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
- const std::string ChessEngine::STARTPOS =
- "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
-
-//-----------------------------------------------------------------------------
- std::string ChessEngine::getEmailAddress() {
- return "";
- }
-
-//-----------------------------------------------------------------------------
- std::string ChessEngine::getCountryName() {
- return "";
- }
-
-//-----------------------------------------------------------------------------
- bool ChessEngine::isRegistered() {
- return true;
- }
-
-//-----------------------------------------------------------------------------
- void ChessEngine::registerLater() {
- }
-
-//-----------------------------------------------------------------------------
- bool ChessEngine::doRegistration(const std::string & /*name*/,
- const std::string & /*code*/) {
- return true;
- }
-
-//-----------------------------------------------------------------------------
- bool ChessEngine::isCopyProtected() {
- return false;
- }
-
-//-----------------------------------------------------------------------------
- bool ChessEngine::copyIsOK() {
- return true;
- }
-
-//-----------------------------------------------------------------------------
- void ChessEngine::resetEngineStats() {
- }
-
-//-----------------------------------------------------------------------------
- void ChessEngine::showEngineStats() {
- }
-
-} // namespace senjo
diff --git a/senjo/ChessEngine.h b/senjo/ChessEngine.h
deleted file mode 100644
index 92f29f73..00000000
--- a/senjo/ChessEngine.h
+++ /dev/null
@@ -1,279 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2015-2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef SENJO_CHESS_ENGINE_H
-#define SENJO_CHESS_ENGINE_H
-
-#include "EngineOption.h"
-#include "GoParams.h"
-#include "SearchStats.h"
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
-//! \brief Base class for Senjo compatible chess engines
-//! Derive from this class to create a chess engine that may be used with
-//! the Senjo UCIAdapter.
-//-----------------------------------------------------------------------------
- class ChessEngine {
- public:
- virtual ~ChessEngine() {}
-
- //---------------------------------------------------------------------------
- //! \brief FEN string of standard chess start position
- //! See http://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation
- //---------------------------------------------------------------------------
- static const std::string STARTPOS;
-
- //---------------------------------------------------------------------------
- //! \brief Get the engine name
- //! \return The engine name
- //---------------------------------------------------------------------------
- virtual std::string getEngineName() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Get the engine version (e.g. "major.minor.build" e.g. "1.0.0")
- //! \return The engine version
- //---------------------------------------------------------------------------
- virtual std::string getEngineVersion() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Get the engine author name(s)
- //! \return The engine author name(s)
- //---------------------------------------------------------------------------
- virtual std::string getAuthorName() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Get email address(es) for use with this engine
- //! Return an empty string if you don't wish to report an email address.
- //! \return An email address(es) for use with this engine
- //---------------------------------------------------------------------------
- virtual std::string getEmailAddress() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Get the name of the country this engine originates from
- //! Return an empty string if you don't wish to report a country
- //! \return The name of the country this engine originates from
- //---------------------------------------------------------------------------
- virtual std::string getCountryName() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Get options supported by the engine, and their current values
- //! \return A list of the engine's options and their current values
- //---------------------------------------------------------------------------
- virtual std::list getOptions() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Set a particular option to a given value
- //! Option value may be empty, particularly if the option type is Button
- //! \param[in] optionName The option name
- //! \param[in] optionValue The new option value
- //! \return false if the option name or value is invalid
- //---------------------------------------------------------------------------
- virtual bool setEngineOption(const std::string &optionName,
- const std::string &optionValue) = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Initialize the engine
- //---------------------------------------------------------------------------
- virtual void initialize() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Is the engine initialized?
- //! \return true if the engine is initialized
- //---------------------------------------------------------------------------
- virtual bool isInitialized() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Set the board position according to a given FEN string
- //! The engine should use Output() to report errors in the FEN string.
- //! Only use position info from the given FEN string, don't process any moves
- //! or other data present in the FEN string.
- //! \param[in] fen The FEN string on input
- //! \param[out] remain If not NULL populated with tail portion of \p fen
- //! string that was not used to set the position.
- //! \return false if the FEN string does not contain a valid position
- //---------------------------------------------------------------------------
- virtual bool setPosition(const std::string &fen,
- std::string* remain = nullptr) = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Execute a single move on the current position
- //! Determine whether the given string is a valid move
- //! and if it is apply the move to the current position.
- //! Moves should be in coordinate notation (e.g. "e2e4", "g8f6", "e7f8q").
- //! \param[in] move A string containing move coordinate notation
- //! \return false if the given string isn't a valid move
- //---------------------------------------------------------------------------
- virtual bool makeMove(const std::string &move) = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Get a FEN string representation of the current board position
- //! \return A FEN string representation of the current board postiion
- //---------------------------------------------------------------------------
- virtual std::string getFEN() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Output a text representation of the current board position
- //---------------------------------------------------------------------------
- virtual void printBoard() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Is it white to move in the current position?
- //! \return true if it is white to move in the current position
- //---------------------------------------------------------------------------
- virtual bool whiteToMove() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Clear any engine data that can persist between searches
- //! Examples of search data are the transposition transpositionTable and killer moves.
- //---------------------------------------------------------------------------
- virtual void clearSearchData() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief The last ponder move was played
- //! The Go() method may return a ponder move which is the expected response
- //! to the bestmove returned by Go(). If pondering is enabled the UCI
- //! adapter may tell the engine to ponder this move, e.g. start searching
- //! for a reply to the ponder move. If, while the engine is pondering, the
- //! ponder move is played this method will be called. In general the engine
- //! should make what it has learned from its pondering available for the next
- //! Go() call.
- //---------------------------------------------------------------------------
- virtual void ponderHit() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Is the engine registered?
- //! \return true if the engine is registered
- //---------------------------------------------------------------------------
- virtual bool isRegistered() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Register the engine later
- //! The engine should still function, but may cripple itself in some fashion.
- //---------------------------------------------------------------------------
- virtual void registerLater() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Register the engine now
- //! If this fails the engine should still function, but may cripple itself
- //! in some fashion.
- //! \param[in] name The name to register the engine to
- //! \param[in] code The code to use for registration
- //! \return true if successful
- //---------------------------------------------------------------------------
- virtual bool doRegistration(const std::string &name,
- const std::string &code) = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Does this engine use copy protection?
- //! \return true if the engine uses copy protection
- //---------------------------------------------------------------------------
- virtual bool isCopyProtected() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Determine whether this is a legitimate copy of the engine
- //! This method will be called if IsCopyProtected() returns true. This is
- //! where your engine should try to determine whether it is a legitimate
- //! copy or not.
- //! \return true if the engine is a legitimate copy
- //---------------------------------------------------------------------------
- virtual bool copyIsOK() = 0;
-
- //--------------------------------------------------------------------------
- //! \brief Set the engine's debug mode on or off
- //! \param[in] flag true to enable debug mode, false to disable debug mode
- //---------------------------------------------------------------------------
- virtual void setDebug(const bool flag) = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Is debug mode enabled?
- //! \return true if debug mode is enabled
- //---------------------------------------------------------------------------
- virtual bool isDebugOn() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Is the engine currently executing the Go() method?
- //! It is not recommended to set this to true while Perft() is executing.
- //! \return true if the engine is searching
- //---------------------------------------------------------------------------
- virtual bool isSearching() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Tell the engine to stop searching
- //! Exit Perft()/Go() methods as quickly as possible.
- //---------------------------------------------------------------------------
- virtual void stopSearching() = 0;
-
- //--------------------------------------------------------------------------
- //! \brief Was stopSearching() called after the last go() or perft() call?
- //! \return true if stopSearching() called after the last go() or perft() call
- //--------------------------------------------------------------------------
- virtual bool stopRequested() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Block execution on the calling thread until the engine is
- //! finished searching. Return immediateky if no search in progress.
- //---------------------------------------------------------------------------
- virtual void waitForSearchFinish() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Do performance test on the current position
- //! \param[in] depth How many half-moves (plies) to search
- //! \return The number of leaf nodes visited at \p depth
- //---------------------------------------------------------------------------
- virtual uint64_t perft(const int16_t depth) = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Execute search on current position to find best move
- //! \param[in] params UCI "go" command parameters
- //! \param[out] ponder If not null set to the move engine should ponder next
- //! \return Best move in coordinate notation (e.g. "e2e4", "g8f6", "e7f8q")
- //---------------------------------------------------------------------------
- virtual std::string go(GoParams ¶ms,
- std::string* ponder = nullptr) = 0;
-
- //--------------------------------------------------------------------------
- //! \brief Get statistics about the last (or current) search
- //! \param[in] count The maximum number of lines to get stats for
- //! \return a SearchStats struct updated with the latest search stats
- //--------------------------------------------------------------------------
- virtual SearchStats getSearchStats() = 0;
-
- //--------------------------------------------------------------------------
- //! \brief Reset custom engine statistical counter totals
- //! \remark Override if you desire custom engine stats to be output when
- //! the "test" command is run.
- //--------------------------------------------------------------------------
- virtual void resetEngineStats() = 0;
-
- //--------------------------------------------------------------------------
- //! \brief Output engine stats collected since last resetEngineStats call
- //! \remark Override if you desire custom engine stats to be output when
- //! the "test" command is run.
- //--------------------------------------------------------------------------
- virtual void showEngineStats() = 0;
- };
-
-} // namespace senjo
-
-#endif // SENJO_CHESS_ENGINE_H
diff --git a/senjo/EngineOption.cpp b/senjo/EngineOption.cpp
deleted file mode 100644
index 4b8ab3a2..00000000
--- a/senjo/EngineOption.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2015-2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "EngineOption.h"
-
-namespace senjo {
-
- static const char* OPT_BUTTON_NAME = "button";
- static const char* OPT_CHECK_NAME = "check";
- static const char* OPT_COMBO_NAME = "combo";
- static const char* OPT_SPIN_NAME = "spin";
- static const char* OPT_STRING_NAME = "string";
- static const char* OPT_UNKNOWN_NAME = "unknown";
-
-//-----------------------------------------------------------------------------
- EngineOption::OptionType EngineOption::toOptionType(const std::string &name) {
- if (!iEqual(name, OPT_BUTTON_NAME)) {
- return Button;
- }
- if (!iEqual(name, OPT_CHECK_NAME)) {
- return Checkbox;
- }
- if (!iEqual(name, OPT_COMBO_NAME)) {
- return ComboBox;
- }
- if (!iEqual(name, OPT_SPIN_NAME)) {
- return Spin;
- }
- if (!iEqual(name, OPT_STRING_NAME)) {
- return String;
- }
- return Unknown;
- }
-
-//-----------------------------------------------------------------------------
- std::string EngineOption::getTypeName(const OptionType type) {
- switch (type) {
- case Button:
- return OPT_BUTTON_NAME;
- case Checkbox:
- return OPT_CHECK_NAME;
- case ComboBox:
- return OPT_COMBO_NAME;
- case Spin:
- return OPT_SPIN_NAME;
- case String:
- return OPT_STRING_NAME;
- default:
- break;
- }
- return OPT_UNKNOWN_NAME;
- }
-
-//-----------------------------------------------------------------------------
- EngineOption::EngineOption(const std::string &optName,
- const std::string &defaultValue,
- const OptionType optType,
- const int64_t minValue,
- const int64_t maxValue,
- const std::set &comboValues)
- : optType(optType),
- optName(optName),
- optValue(defaultValue),
- defaultValue(defaultValue),
- minValue(minValue),
- maxValue(maxValue),
- comboValues(comboValues) {}
-
-//-----------------------------------------------------------------------------
- int64_t EngineOption::getIntValue() const {
- return toNumber(optValue);
- }
-
-//-----------------------------------------------------------------------------
- int64_t EngineOption::getDefaultIntValue() const {
- return toNumber(defaultValue);
- }
-
-//-----------------------------------------------------------------------------
- std::set EngineOption::getIntComboValues() const {
- std::set values;
- for (auto value : comboValues) {
- int64_t n = toNumber(value, -1);
- if (n >= 0) {
- values.insert(n);
- }
- }
- return values;
- }
-
-//-----------------------------------------------------------------------------
- bool EngineOption::setValue(const std::string &value) {
- switch (optType) {
- case Checkbox:
- if (!iEqual(value, "true") && !iEqual(value, "false")) {
- return false;
- }
- break;
- case ComboBox:
- if (!comboValues.count(value)) {
- return false;
- }
- break;
- case Spin: {
- int64_t intval = toNumber(value, minValue - 1);
- if (intval < minValue || intval > maxValue) {
- return false;
- }
- break;
- }
- case String:
- break;
- default:
- return false;
- }
- optValue = value;
- return true;
- }
-
-//-----------------------------------------------------------------------------
- bool EngineOption::setValue(const int64_t value) {
- return setValue(std::to_string(value));
- }
-
-//-----------------------------------------------------------------------------
- void EngineOption::setDefaultValue(const int64_t value) {
- setDefaultValue(std::to_string(value));
- }
-
-//-----------------------------------------------------------------------------
- void EngineOption::setComboValues(const std::set &values) {
- comboValues.clear();
- for (auto value : values) {
- comboValues.insert(std::to_string(value));
- }
- }
-
-} // namespace senjo
diff --git a/senjo/EngineOption.h b/senjo/EngineOption.h
deleted file mode 100644
index 5a9451ca..00000000
--- a/senjo/EngineOption.h
+++ /dev/null
@@ -1,223 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2015-2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef SENJO_ENGINE_OPTION_H
-#define SENJO_ENGINE_OPTION_H
-
-#include "Platform.h"
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
-//! \brief Simple representaion of a single chess engine option
-//! Provides details such as option type, name, default/min/max values.
-//-----------------------------------------------------------------------------
- class EngineOption {
- public:
- virtual ~EngineOption() {}
-
- enum OptionType {
- Unknown, ///< Unknown option type
- Button, ///< Option does not have a value
- Checkbox, ///< Option value must be "true" or "false"
- ComboBox, ///< Option value must be one of a predefined set
- Spin, ///< Option value must be an integer between min and max
- String ///< Option value must be a string
- };
-
- //--------------------------------------------------------------------------
- //! \brief Convert option type name to OptionType
- //! \param[in] name The option type name
- //! \return Unknown if \p name is not known
- //--------------------------------------------------------------------------
- static OptionType toOptionType(const std::string &name);
-
- //--------------------------------------------------------------------------
- //! \brief Get a string representation of a given option type
- //! \param[in] type The option type
- //! \return A string representation of \p type
- //--------------------------------------------------------------------------
- static std::string getTypeName(const OptionType type);
-
- //--------------------------------------------------------------------------
- //! \brief Constructor
- //! \param[in] name The option name (default = empty)
- //! \param[in] defaultValue The option default value (default = empty)
- //! \param[in] type The option type (default = String)
- //! \param[in] minValue The min value for Spin options (default = INT64_MIN)
- //! \param[in] maxValue The max value for Spin options (default = INT64_MAX)
- //! \param[in] combo Set of legal ComboBox values (default = empty)
- //--------------------------------------------------------------------------
- EngineOption(const std::string &name = std::string(),
- const std::string &defaultValue = std::string(),
- const OptionType type = String,
- const int64_t minValue = INT64_MIN,
- const int64_t maxValue = INT64_MAX,
- const std::set &combo = std::set());
-
- //--------------------------------------------------------------------------
- //! \brief Get the option type
- //! \return The option type
- //--------------------------------------------------------------------------
- OptionType getType() const { return optType; }
-
- //--------------------------------------------------------------------------
- //! \brief Get a string representation of the option type
- //! \return A string representation of the option type
- //--------------------------------------------------------------------------
- virtual std::string getTypeName() const { return getTypeName(optType); }
-
- //--------------------------------------------------------------------------
- //! \brief Get the option name
- //! \return The option name
- //--------------------------------------------------------------------------
- virtual std::string getName() const { return optName; }
-
- //--------------------------------------------------------------------------
- //! \brief Get the option's current value in string form
- //! \return The option's current value in string form
- //--------------------------------------------------------------------------
- virtual std::string getValue() const { return optValue; }
-
- //--------------------------------------------------------------------------
- //! \brief Get the option's current value in integer form
- //! \return The option's current value in integer form, 0 if not an integer
- //--------------------------------------------------------------------------
- virtual int64_t getIntValue() const;
-
- //--------------------------------------------------------------------------
- //! \brief Get the option's default value in string form
- //! \return The option's default value in string form
- //--------------------------------------------------------------------------
- virtual std::string getDefaultValue() const { return defaultValue; }
-
- //--------------------------------------------------------------------------
- //! \brief Get the option's default value in integer form
- //! \return The option's default value in integer form, 0 if not an integer
- //--------------------------------------------------------------------------
- virtual int64_t getDefaultIntValue() const;
-
- //--------------------------------------------------------------------------
- //! \brief Get the option's minimum value (applicable to Spin type only)
- //! \return The option's minimum value
- //--------------------------------------------------------------------------
- virtual int64_t getMinValue() const { return minValue; }
-
- //--------------------------------------------------------------------------
- //! \brief Get the option's maximum value (applicable to Spin type only)
- //! \return The option's maximum value
- //--------------------------------------------------------------------------
- virtual int64_t getMaxValue() const { return maxValue; }
-
- //--------------------------------------------------------------------------
- //! \brief Get set of legal values for ComboBox options in string form
- //! \return set of legal values for ComboBox options in string form
- //--------------------------------------------------------------------------
- virtual const std::set &getComboValues() const {
- return comboValues;
- }
-
- //--------------------------------------------------------------------------
- //! \brief Get set of legal values for ComboBox options in integer form
- //! \return set of legal values for ComboBox options in integer form
- //--------------------------------------------------------------------------
- virtual std::set getIntComboValues() const;
-
- //--------------------------------------------------------------------------
- //! \brief Set the option type
- //! \param[in] type The new option type
- //--------------------------------------------------------------------------
- virtual void setType(const OptionType type) { optType = type; }
-
- //--------------------------------------------------------------------------
- //! \brief Set the option name
- //! \param[in] name The new option name
- //--------------------------------------------------------------------------
- virtual void setName(const std::string &name) { optName = name; }
-
- //--------------------------------------------------------------------------
- //! \brief Set the option's current value
- //! \param[in] value The new option value
- //--------------------------------------------------------------------------
- virtual bool setValue(const std::string &value);
-
- //--------------------------------------------------------------------------
- //! \brief Set the option's current value
- //! \param[in] value The new option value
- //! \return true if \p value is valid, otherwise false
- //--------------------------------------------------------------------------
- virtual bool setValue(const int64_t value);
-
- //--------------------------------------------------------------------------
- //! \brief Set the option's default value
- //! \param[in] value The new default value
- //! \return true if \p value is valid, otherwise false
- //--------------------------------------------------------------------------
- virtual void setDefaultValue(const std::string &value) {
- defaultValue = value;
- }
-
- //--------------------------------------------------------------------------
- //! \brief Set the option's default value
- //! \param[in] value The new default value
- //--------------------------------------------------------------------------
- virtual void setDefaultValue(const int64_t value);
-
- //--------------------------------------------------------------------------
- //! \brief Set the option's minimum value (applicable to Spin type only)
- //! \param[in] min The new minimum value
- //--------------------------------------------------------------------------
- virtual void setMinValue(const int64_t min) { minValue = min; }
-
- //--------------------------------------------------------------------------
- //! \brief Set the option's maximum value (applicable to Spin type only)
- //! \param[in] max The new maximum value
- //--------------------------------------------------------------------------
- virtual void setMaxValue(const int64_t max) { maxValue = max; }
-
- //--------------------------------------------------------------------------
- //! \brief Set legal values for ComboBox options
- //! \param[in] values The set of legal values
- //--------------------------------------------------------------------------
- virtual void setComboValues(const std::set &values) {
- comboValues = values;
- }
-
- //--------------------------------------------------------------------------
- //! \brief Set legal values for ComboBox options
- //! \param[in] values The set of legal values
- //--------------------------------------------------------------------------
- virtual void setComboValues(const std::set &values);
-
- private:
- OptionType optType;
- std::string optName;
- std::string optValue;
- std::string defaultValue;
- int64_t minValue;
- int64_t maxValue;
- std::set comboValues;
- };
-
-} // namespace
-
-#endif // SENJO_ENGINE_OPTION_H
diff --git a/senjo/GoParams.h b/senjo/GoParams.h
deleted file mode 100644
index 2da7c56a..00000000
--- a/senjo/GoParams.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef SENJO_GO_PARAMS_H
-#define SENJO_GO_PARAMS_H
-
-#include "Platform.h"
-
-namespace senjo {
-
- struct GoParams {
- bool infinite = false; // SearchManager until the "stop" command
- bool ponder = false; // Start searching in pondering mode
- int16_t depth = 0; // Maximum number of half-moves (plies) to search
- int movestogo = 0; // Number of moves remaining until next time control
- uint64_t binc = 0; // BLACK increment per move in milliseconds
- uint64_t btime = 0; // Milliseconds remaining on black's clock
- uint64_t movetime = 0; // Maximum milliseconds to spend on this move
- uint64_t nodes = 0; // Maximum number of nodes to search
- uint64_t winc = 0; // WHITE increment per move in milliseconds
- uint64_t wtime = 0; // Milliseconds remaining on white's clock
- };
-
-} // namespace senjo
-
-#endif // SENJO_GO_PARAMS_H
diff --git a/senjo/Output.cpp b/senjo/Output.cpp
deleted file mode 100644
index cb8da25a..00000000
--- a/senjo/Output.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2015-2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "Output.h"
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
-// static variables
-//-----------------------------------------------------------------------------
- std::mutex Output::_mutex;
- TimePoint Output::_lastOutput = now();
-
-//-----------------------------------------------------------------------------
- TimePoint Output::lastOutput() {
- return _lastOutput;
- }
-
-//-----------------------------------------------------------------------------
- Output::Output(const OutputPrefix prefix) {
- _mutex.lock();
- switch (prefix) {
- case InfoPrefix:
- std::cout << "info string ";
- break;
- case NoPrefix:
- break;
- }
- }
-
-//-----------------------------------------------------------------------------
- Output::~Output() {
- std::cout << '\n';
- std::cout.flush();
- _lastOutput = now();
- _mutex.unlock();
- }
-
-} // namespace senjo
diff --git a/senjo/Output.h b/senjo/Output.h
deleted file mode 100644
index 41a80c6e..00000000
--- a/senjo/Output.h
+++ /dev/null
@@ -1,134 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2015-2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef SENJO_OUTPUT_H
-#define SENJO_OUTPUT_H
-
-#include "Platform.h"
-#include
-#include
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
-//! \brief Thread safe stdout stream
-//! Instantiating this class will obtain a lock on a mtuex guarding stdout.
-//! The stdout mutex is released when the instantiated object is destroyed.
-//!
-//! \e Important: '\n' is automatically appended when the object is destroyed.
-//! \e Important: The UCI protocol requires that lines end with a single
-//! new-line character: '\n'. So you should *not* use std::endl, as this will
-//! output '\r\n' on windows systems and '\r' on some other systems.
-//!
-//! Example:
-//!
-//! Output() << "Hello, world!";
-//!
-//! Notice it is not necessary to add '\n' on the end.
-//!
-//! Example of multiple line outout:
-//!
-//! Output() << "Line 1";
-//! Output() << "Line 2";
-//!
-//! Notice it is not necessary to add '\n' on the end of either line.
-//! Notice it is possible that other threads could output something between
-//! "Line 1" and "Line 2".
-//!
-//! Example of multiple line outout without allowing another thread to output
-//! between each line:
-//!
-//! Output() << "Line 1\n"
-//! << "info string Line 2";
-//! or
-//! Output() << "Line 1\ninfo string Line 2";
-//! or
-//! Output() << "Line " << 1 << '\n' << "info string " << "Line " << 2;
-//! etc..
-//!
-//! Notice each case uses a single Output() instance.
-//! Notice it is not necessary to add '\n' after the last line.
-//! Notice it is necessary to explicitly prefix all but the first line with
-//! "info string ". If you know what you're doing concerning the UCI protocol
-//! you can omit "info string " where appropriate.
-//!
-//! To maintain exclusive access to stdout so that processing can be done
-//! between lines of output without allowing another thread to output between
-//! lines:
-//!
-//! {
-//! Output out;
-//! out << "line 1\n";
-//! ... do some processing ...
-//! out << "info string line 2";
-//! }
-//!
-//! Notice the code is enclosed in { } to clearly define the scope of 'out'.
-//! Notice it is not necessary to add '\n' after the last line.
-//! Notice it is necessary to explicitly prefix all but the first line with
-//! "info string ". If you know what you're doing concerning the UCI protocol
-//! you can omit "info string " where appropriate.
-//-----------------------------------------------------------------------------
- class Output {
- public:
- enum OutputPrefix {
- NoPrefix, ///< Don't prefix output with "info string "
- InfoPrefix ///< Prefix output with "info string "
- };
-
- //--------------------------------------------------------------------------
- //! \brief Constructor
- //! If \p param is InfoPrefix then output is prefixed with "info string ".
- //! \param[in] prefix NoPrefix or InfoPrefix (InfoPrefix is the default)
- //--------------------------------------------------------------------------
- Output(const OutputPrefix prefix = InfoPrefix);
-
- //--------------------------------------------------------------------------
- //! \brief Destructor
- //--------------------------------------------------------------------------
- virtual ~Output();
-
- //--------------------------------------------------------------------------
- //! \brief Get timestamp of the last time an Output class was destroyed
- //! \return Timestamp of last Output class destruction, 0 if none
- //--------------------------------------------------------------------------
- static TimePoint lastOutput();
-
- //--------------------------------------------------------------------------
- //! \brief Insertion operator
- //! All data types supported by std::cout are supported here.
- //! \return Reference to self.
- //--------------------------------------------------------------------------
- template
- Output &operator<<(const T &x) {
- std::cout << x;
- return *this;
- }
-
- private:
- static std::mutex _mutex;
- static TimePoint _lastOutput;
- };
-
-} // namespace senjo
-
-#endif // SENJO_OUTPUT_H
diff --git a/senjo/Parameters.cpp b/senjo/Parameters.cpp
deleted file mode 100644
index 586b091c..00000000
--- a/senjo/Parameters.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "Parameters.h"
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
- Parameters::Parameters(const std::string &commandLine) {
- parse(commandLine);
- }
-
-//-----------------------------------------------------------------------------
- void Parameters::parse(const std::string &str) {
- std::stringstream ss(str);
- std::string param;
- clear();
- while (ss >> param) {
- push_back(param);
- }
- }
-
-//-----------------------------------------------------------------------------
- std::string Parameters::toString() const {
- std::stringstream ss;
- bool first = true;
- for (std::string param : *this) {
- if (first) {
- first = false;
- } else {
- ss << ' ';
- }
- ss << param;
- }
- return ss.str();
- }
-
-//-----------------------------------------------------------------------------
- bool Parameters::firstParamIs(const std::string ¶mName) const {
- return size() && iEqual(paramName, front());
- }
-
-//-----------------------------------------------------------------------------
- bool Parameters::popParam(const std::string ¶mName) {
- if (firstParamIs(paramName)) {
- pop_front();
- return true;
- }
-
- return false;
- }
-
-//-----------------------------------------------------------------------------
- bool Parameters::popParam(const std::string ¶mName, bool &exists) {
- if (popParam(paramName)) {
- exists = true;
- return true;
- }
- return false;
- }
-
-//-----------------------------------------------------------------------------
- std::string Parameters::popString() {
- if (empty()) {
- return "";
- }
-
- std::string str = front();
- pop_front();
- return str;
- }
-
-//-----------------------------------------------------------------------------
- bool Parameters::popString(const std::string ¶mName, std::string &value,
- const std::string &next) {
- if (size() < 2 || !iEqual(paramName, front())) {
- return false;
- }
-
- pop_front();
- while (size() && (next.empty() || !iEqual(next, front()))) {
- if (value.size()) {
- value += " ";
- }
- value += front();
- pop_front();
- }
-
- return value.size() > 0;
- }
-
-} // namespace senjo
-
diff --git a/senjo/Parameters.h b/senjo/Parameters.h
deleted file mode 100644
index 43bf1bf4..00000000
--- a/senjo/Parameters.h
+++ /dev/null
@@ -1,144 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef SENJO_PARAMETERS_H
-#define SENJO_PARAMETERS_H
-
-#include "Platform.h"
-
-namespace senjo {
-
- class Parameters : public std::list {
- public:
- Parameters() = default;
-
- Parameters(const std::string &commandLine);
-
- //---------------------------------------------------------------------------
- //! \brief Initialize this instance from the given string
- //---------------------------------------------------------------------------
- void parse(const std::string &str);
-
- //---------------------------------------------------------------------------
- //! \brief Join the parameters together into a single space delimited string
- //---------------------------------------------------------------------------
- std::string toString() const;
-
- //---------------------------------------------------------------------------
- //! \brief Test whether the specified paramName matches the first param
- //! \param[in] paramName The parameter name to check for
- //! \return true if the specified paramName matches the first param
- //---------------------------------------------------------------------------
- bool firstParamIs(const std::string ¶mName) const;
-
- //---------------------------------------------------------------------------
- //! \brief Pop the specified paramName
- //! \param[in] paramName The parameter name to pop
- //! \return true if the specified paramName was popped
- //---------------------------------------------------------------------------
- bool popParam(const std::string ¶mName);
-
- //---------------------------------------------------------------------------
- //! \brief Pop the specified paramName
- //! \param[in] paramName The parameter name to pop
- //! \param[out] exists Set to true if the specified paramName was popped
- //! \return true if the specified paramName was popped
- //---------------------------------------------------------------------------
- bool popParam(const std::string ¶mName, bool &exists);
-
- //-----------------------------------------------------------------------------
- //! \brief Pop the first string
- //! \return an empty string if the parameters list is empty
- //-----------------------------------------------------------------------------
- std::string popString();
-
- //-----------------------------------------------------------------------------
- //! \brief Pop the specified paramName and the following string value
- //! \param[in] paramName The name of the string parameter to pop
- //! \param[out] value Populated with the string value of \p paramName
- //! \param[in] next The next expected parameter name
- //! \return true If a non-empty value was assigned to \p value
- //-----------------------------------------------------------------------------
- bool popString(const std::string ¶mName, std::string &value,
- const std::string &next = "");
-
- //-----------------------------------------------------------------------------
- //! \brief Pop the first param as a number
- //! \return \defaultValue if the parameters list is empty
- //! or the first param could not be converted to the number type
- //-----------------------------------------------------------------------------
- template
- T popNumber(const T &defaultValue = 0) {
- if (empty()) {
- return defaultValue;
- }
-
- std::stringstream ss(front());
- T value;
- if (ss >> value) {
- pop_front();
- return value;
- }
-
- return defaultValue;
- }
-
- //-----------------------------------------------------------------------------
- //! \brief Pop the specified paramName and the following number value
- //! \param[in] paramName The name of the numeric parameter to pop
- //! \param[out] value Populated with the numeric value of \p paramName
- //! \param[out] invalid Set to true if paramName has a non-numeric value
- //! \return true if a number value was assigned to \p number
- //-----------------------------------------------------------------------------
- template
- bool popNumber(const std::string ¶mName, T &value, bool &invalid) {
- if (size() < 2 || !iEqual(paramName, front())) {
- return false;
- }
-
- pop_front();
- std::stringstream ss(front());
- if (ss >> value) {
- pop_front();
- return true;
- }
-
- invalid = true;
- return false;
- }
-
- //-----------------------------------------------------------------------------
- //! \brief Pop the specified paramName and the following number value
- //! \param[in] paramName The name of the numeric parameter to pop
- //! \param[out] value Populated with the numeric value of \p paramName
- //! \return true if a number value was assigned to \p number
- //-----------------------------------------------------------------------------
- template
- bool popNumber(const std::string ¶mName, T &value) {
- bool invalid;
- return popNumber(paramName, value, invalid);
- }
- };
-
-} // namespace senjo
-
-#endif // SENJO_PARAMETERS_H
diff --git a/senjo/Platform.h b/senjo/Platform.h
deleted file mode 100644
index 8376eec3..00000000
--- a/senjo/Platform.h
+++ /dev/null
@@ -1,140 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2015-2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef SENJO_PLATFORM_H
-#define SENJO_PLATFORM_H
-
-#ifdef WIN32
-
-#include
-
-#undef max
-#undef min
-#endif
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
- typedef std::chrono::system_clock::time_point TimePoint;
-
-//-----------------------------------------------------------------------------
- inline TimePoint now() {
- return std::chrono::system_clock::now();
- }
-
-//-----------------------------------------------------------------------------
- inline TimePoint maxTime() {
- return TimePoint::max();
- }
-
-//-----------------------------------------------------------------------------
- inline TimePoint addMsecs(const TimePoint &begin, const uint64_t msecs) {
- return (begin + std::chrono::milliseconds(msecs));
- }
-
-//-----------------------------------------------------------------------------
- inline uint64_t getMsecs(const TimePoint &begin, const TimePoint &end = now()) {
- auto duration = (end - begin);
- auto msecs = std::chrono::duration_cast(duration);
- return static_cast(msecs.count());
- }
-
-//-----------------------------------------------------------------------------
- template
- inline double average(const T total, const T count) {
- return (count != 0.0) ? (static_cast(total) / static_cast(count)) : 0;
- }
-
-//-----------------------------------------------------------------------------
- template
- inline double rate(const T count, const T msecs) {
- return (msecs != 0.0) ? ((static_cast(count) / static_cast(msecs)) * 1000) : 0;
- }
-
-//-----------------------------------------------------------------------------
- template
- inline double percent(const T top, const T bottom) {
- return bottom ? (100 * (static_cast(top) / static_cast(bottom))) : 0;
- }
-
-//-----------------------------------------------------------------------------
- template
- inline T toNumber(const std::string &str, const T defaultValue = 0) {
- T number;
- return (std::stringstream(str) >> number) ? number : defaultValue;
- }
-
-//-----------------------------------------------------------------------------
- inline std::string trimLeft(const std::string &str,
- const std::string &chars = " ") {
- size_t i = str.find_first_not_of(chars);
- return (i == std::string::npos) ? str : str.substr(i);
- }
-
-//-----------------------------------------------------------------------------
- inline std::string trimRight(const std::string &str,
- const std::string &chars = " ") {
- size_t i = str.size();
- while ((i > 0) && (chars.find_first_of(str[i - 1]) != std::string::npos)) {
- --i;
- }
- return str.substr(0, i);
- }
-
-//-----------------------------------------------------------------------------
- inline std::string trim(const std::string &str,
- const std::string &chars = " ") {
- return trimRight(trimLeft(str, chars), chars);
- }
-
-//-----------------------------------------------------------------------------
- inline bool iEqual(const std::string &a, const std::string &b) {
- return ((a.size() == b.size()) &&
- std::equal(a.begin(), a.end(), b.begin(), [](char c1, char c2) {
- return (c1 == c2) || (std::toupper(c1) == std::toupper(c2));
- }));
- }
-
-//-----------------------------------------------------------------------------
- inline bool isMove(const std::string &str) {
- return (str.size() >= 4) &&
- (str[0] >= 'a') && (str[0] <= 'h') &&
- (str[1] >= '1') && (str[1] <= '8') &&
- (str[2] >= 'a') && (str[2] <= 'h') &&
- (str[3] >= '1') && (str[3] <= '8') &&
- ((str.size() == 4) ||
- (str[4] == 'n') || (str[4] == 'b') ||
- (str[4] == 'r') || (str[4] == 'q'));
- }
-
-} // namespace senjo
-
-#endif // SENJO_PLATFORM_H
diff --git a/senjo/README.md b/senjo/README.md
deleted file mode 100644
index 55f860ea..00000000
--- a/senjo/README.md
+++ /dev/null
@@ -1,112 +0,0 @@
-Senjo
-=====
-
-Universal Chess Interface (UCI) adapter by Shawn Chidester .
-
-Just write your chess engine and let Senjo's UCIAdapter deal with the UCI protocol.
-See [Clubfoot](https://github.com/zd3nik/Clubfoot) for an example chess engine that uses Senjo.
-
-See the [senjo-light](https://github.com/zd3nik/SenjoUCIAdapter/tree/senjo-light) branch for a version that does not
-include a built-in `test` command.
-
-Description
------------
-
-Senjo is a UCI adapter for C++ chess engines. It handles the interaction between your chess engine and any UCI compliant
-user interface. All you have to do is implement a ChessEngine class that does the "thinking" parts, Senjo will deal with
-the rest.
-
-The Senjo UCI adapter comes with a few extra commands that are not part of the UCI specification. Here are some
-examples:
-
- * help
- * fen
- * print
- * perft
- * test
-
-In particular the *perft* and *test* commands are very handy for testing and tuning. A few EPD files are included in
-this repository for use with these commands. But of course you can use any EPD file(s) you prefer.
-
-How-To
-------
-
-To create a chess engine named "Trout" using the Senjo UCI adapter do the following:
-
- 1. Extend the "ChessEngine" class.
-
- // TroutEngine.h
- #include "senjo/ChessEngine.h"
-
- class TroutEngine : public senjo::ChessEngine {
- // implement required ChessEngine methods
- // see ChessEngine.h for documentation
- };
-
- 2. Wrap TroutEngine in a Senjo UCIAdapter and feed it one line of input from stdin at a time.
-
- // TroutMain.cpp
- #include "TroutEngine.h"
- #include "senjo/UCIAdapter.h"
- #include "senjo/Output.h"
-
- int main(int /*argc*/, char** /*argv*/) {
- try {
- TroutEngine engine;
- senjo::UCIAdapter adapter(engine);
-
- std::string line;
- line.reserve(16384);
-
- while (std::getline(std::coin, line)) {
- if (!adapter.doCommand(line)) {
- break;
- }
- }
-
- return 0;
- }
- catch (const std::exception& e) {
- senjo::Output() << "ERROR: " << e.what();
- return 1;
- }
- }
-
-
-Notes
------
-
-This example uses `std::getline` to obtain one line of input at a time from stdin. This is only an example. You may get
-input any way you prefer. All that is required is that you assign each line of input to a std::string, pass it to the
-senjo::UCIAdapter's doCommand() method, and exit the input loop if doCommand() returns false.
-
-The `senjo::Output` class (from Output.h) is very useful for debugging. Use it anywhere; it's thread safe and it
-prefixes your output with "string info " so it won't confuse UCI compliant user interfaces. See `Output.h` for more
-details.
-
-The senjo source directory contains a `CMakelists.txt` file, which is a cmake project file. If you're using cmake simply
-add the senjo directory to your project with `add_subirectory(senjo)`. If you're not using cmake simply remove he
-CMakeLists.txt file and include the senjo source files in your project in whatever way is most convenient for you.
-
-License
--------
-
-Copyright (c) 2015-2019 Shawn Chidester
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/senjo/SearchStats.h b/senjo/SearchStats.h
deleted file mode 100644
index 2ff3b874..00000000
--- a/senjo/SearchStats.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef SENJO_SEARCH_STATS_H
-#define SENJO_SEARCH_STATS_H
-
-#include "Platform.h"
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
- struct SearchStats {
- int16_t depth = 0; // The current search depth
- int seldepth = 0; // The maximum selective depth reached on "move"
- uint64_t nodes = 0; // The number of nodes searched so far
- uint64_t qnodes = 0; // The number of quiescence nodes searched so far
- uint64_t msecs = 0; // The number of milliseconds spent searching so far
- int score = 0;
- std::string pv = "";
- };
-
-//-----------------------------------------------------------------------------
- inline std::ostream &operator<<(std::ostream &os, const SearchStats &stats) {
- os << "info depth " << stats.depth
- << " seldepth " << stats.seldepth
- << " score cp " << stats.score
- << " nodes " << stats.nodes + stats.qnodes
- << " time " << stats.msecs
- << " nps " << static_cast((stats.nodes + stats.qnodes) / std::max(stats.msecs / 1000.0, 1.0))
- << " pv " << stats.pv;
-
- return os;
- }
-
-} // namespace senjo
-
-#endif // SENJO_SEARCH_STATS_H
diff --git a/senjo/Thread.cpp b/senjo/Thread.cpp
deleted file mode 100644
index a85a658e..00000000
--- a/senjo/Thread.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2015-2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "Thread.h"
-#include "Output.h"
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
- Thread::Thread(int id)
- : id(id) {}
-
-//-----------------------------------------------------------------------------
- Thread::~Thread() {
- waitForFinish();
- }
-
-//-----------------------------------------------------------------------------
- bool Thread::run() {
- std::lock_guard lock(mutex);
- if (thread && thread->joinable()) {
- return false;
- }
-
- thread.reset(new std::thread(staticRun, this));
- return true;
- }
-
-//-----------------------------------------------------------------------------
- bool Thread::isRunning() {
- std::lock_guard lock(mutex);
- return thread && thread->joinable();
- }
-
-//-----------------------------------------------------------------------------
- void Thread::waitForFinish() {
- std::lock_guard lock(mutex);
- if (thread && thread->joinable()) {
- thread->join();
- }
- }
-
-//-----------------------------------------------------------------------------
- void Thread::staticRun(Thread* thread) {
- if (thread) {
- try {
- thread->doWork();
- } catch (const std::exception &ex) {
- Output() << "ERROR: Thread(" << thread->getInfoPair() << ") " << ex.what();
- } catch (...) {
- Output() << "ERROR: Thread(" << thread->getInfoPair() << ") unhandled exception";
- }
- }
- }
-
-} // namespace senjo
diff --git a/senjo/Thread.h b/senjo/Thread.h
deleted file mode 100644
index 83ab99ad..00000000
--- a/senjo/Thread.h
+++ /dev/null
@@ -1,102 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2015-2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef SENJO_THREADING_H
-#define SENJO_THREADING_H
-
-#include "Platform.h"
-#include
-#include
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
-//! \brief Base class for a single background task.
-//-----------------------------------------------------------------------------
- class Thread {
- protected:
- std::shared_ptr thread;
- std::mutex mutex;
-
- //---------------------------------------------------------------------------
- //! \brief Constructor
- //---------------------------------------------------------------------------
- explicit Thread(int id = -1);
-
- //---------------------------------------------------------------------------
- //! This method is called once when the thread is run.
- //! When this method exits the thread is finished.
- //---------------------------------------------------------------------------
- virtual void doWork() = 0;
-
- public:
- //---------------------------------------------------------------------------
- // Delete copy operations
- //---------------------------------------------------------------------------
- Thread(const Thread &) = delete;
-
- Thread &operator=(const Thread &) = delete;
-
- //---------------------------------------------------------------------------
- //! \brief Destructor
- //---------------------------------------------------------------------------
- virtual ~Thread();
-
- //---------------------------------------------------------------------------
- //! \brief Get the id of this thread.
- //! \return the id of this thread
- //---------------------------------------------------------------------------
- int getInfoPair() const { return id; }
-
- //---------------------------------------------------------------------------
- //! \brief Run this thread.
- //! \return false if the thread is already running
- //---------------------------------------------------------------------------
- virtual bool run();
-
- //---------------------------------------------------------------------------
- //! \brief Tell this thread to exit the doWork() method as soon as possible.
- //! Should do nothing if the thread is already stopped.
- //---------------------------------------------------------------------------
- virtual void stop() = 0;
-
- //---------------------------------------------------------------------------
- //! \brief Is this thread running?
- //! \return true If this thread is running
- //---------------------------------------------------------------------------
- bool isRunning();
-
- //---------------------------------------------------------------------------
- //! \brief Wait for this thread to finish running.
- //! If this thread isn't running this method returns immediately.
- //---------------------------------------------------------------------------
- void waitForFinish();
-
- private:
- static void staticRun(Thread*);
-
- int id;
- };
-
-} // namespace senjo
-
-#endif // SENJO_THREADING_H
diff --git a/senjo/UCIAdapter.cpp b/senjo/UCIAdapter.cpp
deleted file mode 100644
index ef07f757..00000000
--- a/senjo/UCIAdapter.cpp
+++ /dev/null
@@ -1,667 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2015-2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "UCIAdapter.h"
-#include "Output.h"
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
- namespace token {
- static const std::string Debug("debug");
- static const std::string Exit("exit");
- static const std::string Fen("fen");
- static const std::string Go("go");
- static const std::string Help("help");
- static const std::string IsReady("isready");
- static const std::string Moves("moves");
- static const std::string Name("name");
- static const std::string New("new");
- static const std::string Opts("opts");
- static const std::string Perft("perft");
- static const std::string PonderHit("ponderhit");
- static const std::string Position("position");
- static const std::string Print("print");
- static const std::string Quit("quit");
- static const std::string Register("register");
- static const std::string SetOption("setoption");
- static const std::string StartPos("startpos");
- static const std::string Stop("stop");
- static const std::string Test("test");
- static const std::string Uci("uci");
- static const std::string UciNewGame("ucinewgame");
- static const std::string Value("value");
- }
-
-//-----------------------------------------------------------------------------
- UCIAdapter::UCIAdapter(ChessEngine &chessEngine)
- : engine(chessEngine) {}
-
-//-----------------------------------------------------------------------------
- UCIAdapter::~UCIAdapter() {
- if (lastCommand) {
- lastCommand->waitForFinish();
- }
- }
-
-//-----------------------------------------------------------------------------
- bool UCIAdapter::doCommand(const std::string &line) {
- Parameters params(line);
- if (params.empty()) {
- return true; // ignore empty lines
- }
-
- if (engine.isDebugOn()) {
- Output() << "received command: " << line;
- }
-
- std::string command = params.popString();
- if (iEqual(token::Go, command)) {
- doStopCommand();
- execute(std::shared_ptr(new GoCommandHandle(engine)), params);
- } else if (iEqual(token::Position, command)) {
- doStopCommand();
- doPositionCommand(line, params);
- } else if (iEqual(token::Stop, command)) {
- doStopCommand(params);
- } else if (iEqual(token::SetOption, command)) {
- doSetOptionCommand(params);
- } else if (iEqual(token::IsReady, command)) {
- doIsReadyCommand(params);
- } else if (iEqual(token::Uci, command)) {
- doUCICommand(params);
- } else if (iEqual(token::UciNewGame, command)) {
- doStopCommand();
- doUCINewGameCommand(params);
- } else if (iEqual(token::New, command)) {
- doStopCommand();
- doNewCommand(params);
- } else if (iEqual(token::Debug, command)) {
- doDebugCommand(params);
- } else if (iEqual(token::Register, command)) {
- doStopCommand(params);
- execute(std::shared_ptr(new RegisterCommandHandle(engine)), params);
- } else if (iEqual(token::PonderHit, command)) {
- doPonderHitCommand(params);
- } else if (iEqual(token::Fen, command)) {
- doFENCommand(params);
- } else if (iEqual(token::Print, command)) {
- doPrintCommand(params);
- } else if (iEqual(token::Perft, command)) {
- doStopCommand();
- execute(std::shared_ptr(new PerftCommandHandle(engine)), params);
- } else if (iEqual(token::Opts, command)) {
- doOptsCommand(params);
- } else if (iEqual(token::Help, command)) {
- doHelpCommand(params);
- } else if (iEqual(token::Exit, command) ||
- iEqual(token::Quit, command)) {
- if (doQuitCommand(params)) {
- return false;
- }
- } else if (isMove(command)) {
- doStopCommand();
- params.push_front(command);
- doMoveCommand(params);
- } else {
- Output() << "Unknown command: '" << command << "'";
- Output() << "Enter 'help' for a list of commands";
- }
- return true;
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Output list of available commands (not a UCI command)
-//-----------------------------------------------------------------------------
- void UCIAdapter::doHelpCommand(Parameters & /*params*/) {
- Output() << engine.getEngineName() << ' ' << engine.getEngineVersion()
- << " by " << engine.getAuthorName();
- Output() << "UCI commands:";
- Output() << " " << token::Debug;
- Output() << " " << token::Go;
- Output() << " " << token::IsReady;
- Output() << " " << token::Position;
- Output() << " " << token::Quit;
- Output() << " " << token::SetOption;
- Output() << " " << token::Stop;
- Output() << " " << token::Uci;
- Output() << " " << token::UciNewGame;
- Output() << "Additional commands:";
- Output() << " " << token::Exit;
- Output() << " " << token::Fen;
- Output() << " " << token::Help;
- Output() << " " << token::New;
- Output() << " " << token::Perft;
- Output() << " " << token::Print;
- Output() << "Also try ' help' for help on a specific command";
- Output() << "Or enter move(s) in coordinate notation, e.g. d2d4 g8f6";
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Execute the given background command thread
-//-----------------------------------------------------------------------------
- void UCIAdapter::execute(std::shared_ptr command,
- Parameters ¶ms) {
- if (!command) {
- return;
- }
-
- if (params.firstParamIs(token::Help)) {
- Output() << "usage: " << command->usage();
- Output() << command->description();
- return;
- }
-
- if (lastCommand) {
- lastCommand->stop();
- lastCommand->waitForFinish();
- }
-
- if (command->parseAndExecute(params)) {
- lastCommand.swap(command);
- }
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Do the "fen" command (not a UCI command)
-//! Print the FEN string for the current board position
-//-----------------------------------------------------------------------------
- void UCIAdapter::doFENCommand(Parameters ¶ms) {
- if (params.firstParamIs(token::Help)) {
- Output() << "usage: " << token::Fen;
- Output() << "Output FEN string of the current position.";
- return;
- }
-
- if (lastCommand) {
- lastCommand->stop();
- lastCommand->waitForFinish();
- }
-
- if (!engine.isInitialized()) {
- engine.initialize();
- }
-
- Output() << engine.getFEN();
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Do the "print" command (not a UCI command)
-//! Output an ascii representation of the current board position
-//-----------------------------------------------------------------------------
- void UCIAdapter::doPrintCommand(Parameters ¶ms) {
- if (params.firstParamIs(token::Help)) {
- Output() << "usage: " << token::Print;
- Output() << "Output text representation of the current position.";
- return;
- }
-
- if (!engine.isInitialized()) {
- engine.initialize();
- }
-
- engine.printBoard();
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Do the "new" command (not a UCI command)
-//! Clear search data, set position, and apply moves (if any given).
-//-----------------------------------------------------------------------------
- void UCIAdapter::doNewCommand(Parameters ¶ms) {
- if (params.firstParamIs(token::Help)) {
- Output() << "usage: " << token::New << " [" << token::StartPos << "|"
- << token::Fen << " ] [" << token::Moves
- << "] ";
- Output() << "Clear search data, set position, and apply .";
- Output() << "If no position is specified " << token::StartPos
- << " is assumed.";
- return;
- }
-
- doUCINewGameCommand();
-
- if (params.empty() ||
- params.popParam(token::StartPos) ||
- params.popParam(token::Moves)) {
- if (!engine.setPosition(ChessEngine::STARTPOS)) {
- return;
- }
- } else {
- // consume "fen" token if present
- params.popParam(token::Fen);
- std::string remain;
- if (!engine.setPosition(params.toString(), &remain)) {
- return;
- }
- params.parse(remain);
- }
-
- // consume "moves" token if present
- params.popParam(token::Moves);
-
- // apply moves (if any)
- while (params.size() && isMove(params.front())) {
- std::string move = params.popString();
- if (!engine.makeMove(move)) {
- Output() << "Invalid move: " << move;
- break;
- }
- }
-
- if (engine.isDebugOn()) {
- engine.printBoard();
- }
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Do the "opts" command (not a UCI command)
-//! Output current engine option values
-//-----------------------------------------------------------------------------
- void UCIAdapter::doOptsCommand(Parameters & /*params*/) {
- for (auto opt : engine.getOptions()) {
- switch (opt.getType()) {
- case EngineOption::Checkbox:
- case EngineOption::Spin:
- case EngineOption::String:
- Output() << opt.getTypeName() << ':' << opt.getName() << ' '
- << opt.getValue();
- break;
- case EngineOption::ComboBox: {
- const std::set &values = opt.getComboValues();
- Output out;
- out << opt.getTypeName() << ':' << opt.getName();
- for (auto value : values) {
- out << ' ' << value;
- }
- break;
- }
- default:
- break;
- }
- }
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Execute the given move(s) on the current position
-//-----------------------------------------------------------------------------
- void UCIAdapter::doMoveCommand(Parameters ¶ms) {
- if (!engine.isInitialized()) {
- engine.initialize();
- }
-
- if (lastCommand) {
- lastCommand->stop();
- lastCommand->waitForFinish();
- }
-
- lastPosition.clear();
- while (params.size()) {
- std::string move = params.popString();
- if (!isMove(move) || !engine.makeMove(move)) {
- Output() << "Invalid move: " << move;
- return;
- }
-
- if (engine.isDebugOn()) {
- engine.printBoard();
- }
- }
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Do the UCI "quit" command
-//! UCI specification:
-//! Quit the program as soon as possible.
-//! \return true if quit requested, otherwise false
-//-----------------------------------------------------------------------------
- bool UCIAdapter::doQuitCommand(Parameters ¶ms) {
- if (params.firstParamIs(token::Help)) {
- Output() << "usage: " << token::Quit;
- Output() << "Stop engine and terminate program.";
- return false;
- }
-
- engine.stopSearching();
-
- if (lastCommand) {
- lastCommand->stop();
- lastCommand->waitForFinish();
- }
-
- return true;
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Do the UCI "debug" command
-//! UCI specification:
-//! Switch the debug mode of the engine on and off. In debug mode the engine
-//! should send additional infos to the GUI, e.g. with the "info string"
-//! command, to help debugging, e.g. the commands that the engine has
-//! received etc. This mode should be switched off by default and this
-//! command can be sent any time, also when the engine is thinking.
-//-----------------------------------------------------------------------------
- void UCIAdapter::doDebugCommand(Parameters ¶ms) {
- if (params.firstParamIs(token::Help)) {
- Output() << "usage: " << token::Debug;
- Output() << "Toggle debug mode.";
- return;
- }
-
- engine.setDebug(!engine.isDebugOn());
- Output() << "debug " << (engine.isDebugOn() ? "on" : "off");
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Do the UCI "isready" command
-//! UCI specification:
-//! This is used to synchronize the engine with the GUI. When the GUI has
-//! sent a command or multiple commands that can take some time to complete,
-//! this command can be used to wait for the engine to be ready again or
-//! to ping the engine to find out if it is still alive. E.g. this should be
-//! sent after setting the path to the tablebases as this can take some time.
-//! This command is also required once before the engine is asked to do any
-//! search to wait for the engine to finish initializing. This command must
-//! always be answered with "readyok" and can be sent also when the engine
-//! is calculating in which case the engine should also immediately answer
-//! with "readyok" without stopping the search.
-//-----------------------------------------------------------------------------
- void UCIAdapter::doIsReadyCommand(Parameters ¶ms) {
- if (params.firstParamIs(token::Help)) {
- Output() << "usage: " << token::IsReady;
- Output() << "Output readyok when engine is ready to receive input.";
- return;
- }
-
- if (!engine.isInitialized()) {
- engine.initialize();
- }
-
- if (lastCommand) {
- // don't set stop flag
- lastCommand->waitForFinish();
- }
-
- Output(Output::NoPrefix) << "readyok";
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Do the UCI "stop" command
-//! UCI specification:
-//! Stop calculating as soon as possible, don't forget the "bestmove" and
-//! possibly the "ponder" token when finishing the search.
-//-----------------------------------------------------------------------------
- void UCIAdapter::doStopCommand(Parameters params) {
- if (params.firstParamIs(token::Help)) {
- Output() << "usage: " << token::Stop;
- Output() << "Stop engine if it is calculating.";
- return;
- }
-
- engine.stopSearching();
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Do the UCI "uci" command
-//! UCI specification:
-//! Tell engine to use the uci (universal chess interface), this will be sent
-//! once as a first command after program boot to tell the engine to switch
-//! to uci mode. After receiving the uci command the engine must identify
-//! itself with the "id" command and send the "option" commands to tell the
-//! GUI which engine settings the engine supports if any. After that the
-//! engine should send "uciok" to acknowledge the uci mode. If no uciok is
-//! sent within a certain time period, the engine task will be killed by the
-//! GUI.
-//-----------------------------------------------------------------------------
- void UCIAdapter::doUCICommand(Parameters ¶ms) {
- if (params.firstParamIs(token::Help)) {
- Output() << "usage: " << token::Uci;
- Output() << "Output engine info and options followed by uciok.";
- return;
- }
-
- Output(Output::NoPrefix) << "id name " << engine.getEngineName()
- << ' ' << engine.getEngineVersion();
-
- const std::string author = engine.getAuthorName();
- if (author.size()) {
- Output(Output::NoPrefix) << "id author " << author;
- }
-
- const std::string email = engine.getEmailAddress();
- if (email.size()) {
- Output(Output::NoPrefix) << "id email " << email;
- }
-
- const std::string country = engine.getCountryName();
- if (country.size()) {
- Output(Output::NoPrefix) << "id country " << country;
- }
-
- for (auto opt : engine.getOptions()) {
- Output out(Output::NoPrefix);
- out << "option name " << opt.getName() << " type " << opt.getTypeName();
- if (opt.getDefaultValue().size()) {
- out << " default " << opt.getDefaultValue();
- }
- if (opt.getMinValue() > INT64_MIN) {
- out << " min " << opt.getMinValue();
- }
- if (opt.getMaxValue() < INT64_MAX) {
- out << " max " << opt.getMaxValue();
- }
- for (auto val : opt.getComboValues()) {
- out << " var " << val;
- }
- }
-
- Output(Output::NoPrefix) << "uciok";
-
- if (engine.isCopyProtected()) {
- Output(Output::NoPrefix) << "copyprotection checking";
- if (engine.copyIsOK()) {
- Output(Output::NoPrefix) << "copyprotection ok";
- } else {
- Output(Output::NoPrefix) << "copyprotection error";
- }
- }
-
- if (!engine.isRegistered()) {
- Output(Output::NoPrefix) << "registration error";
- }
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Do the UCI "ucinewgame" command
-//! UCI specification:
-//! This is sent to the engine when the next search (started with "position"
-//! and "go") will be from a different game. This can be a new game the
-//! engine should play or a new game it should analyse but also the next
-//! position from a testsuite with positions only. If the GUI hasn't sent a
-//! "ucinewgame" before the first "position" command, the engine shouldn't
-//! expect any further ucinewgame commands as the GUI is probably not
-//! supporting the ucinewgame command. So the engine should not rely on this
-//! command even though all new GUIs should support it. As the engine's
-//! reaction to "ucinewgame" can take some time the GUI should always send
-//! "isready" after "ucinewgame" to wait for the engine to finish its
-//! operation.
-//-----------------------------------------------------------------------------
- void UCIAdapter::doUCINewGameCommand(Parameters params) {
- if (params.firstParamIs(token::Help)) {
- Output() << "usage: " << token::UciNewGame;
- Output() << "Clear all search data.";
- return;
- }
-
- if (!engine.isInitialized()) {
- engine.initialize();
- }
-
- if (lastCommand) {
- lastCommand->stop();
- lastCommand->waitForFinish();
- }
-
- lastPosition.clear();
- engine.clearSearchData();
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Do the UCI "position" command
-//! UCI specification:
-//! Set up the position described in fenstring on the internal board and
-//! play the moves on the internal chess board. If the game was played from
-//! the start position the string "startpos" will be sent.
-//! Note: no "new" command is needed. However, if this position is from a
-//! different game than the last position sent to the engine, the GUI should
-//! have sent a "ucinewgame" inbetween.
-//-----------------------------------------------------------------------------
- void UCIAdapter::doPositionCommand(const std::string &fenstring,
- Parameters ¶ms) {
- if (params.empty() || params.firstParamIs(token::Help)) {
- Output() << "usage: " << token::Position << " {" << token::StartPos << "|"
- << token::Fen << " } []";
- Output() << "Set a new position and apply (if given).";
- return;
- }
-
- if (!engine.isInitialized()) {
- engine.initialize();
- lastPosition.clear();
- }
-
- if (lastCommand) {
- lastCommand->stop();
- lastCommand->waitForFinish();
- }
-
- if (lastPosition.size() &&
- lastPosition == fenstring.substr(0, lastPosition.size())) {
- // continue from current position
- params.parse(fenstring.substr(lastPosition.size() + 1));
- } else {
- if (params.firstParamIs(token::StartPos)) {
- if (!engine.setPosition(ChessEngine::STARTPOS)) {
- return;
- }
- } else {
- // consume "fen" token if present
- params.popParam(token::Fen);
- std::string remain;
- if (!engine.setPosition(params.toString(), &remain)) {
- return;
- }
- params.parse(remain);
- }
- }
-
- // remember this position command for next time
- lastPosition = fenstring;
-
- // consume "moves" token if present
- params.popParam(token::StartPos);
- params.popParam(token::Moves);
-
- // apply moves (if any)
- while (params.size() && isMove(params.front())) {
- std::string move = params.popString();
- if (!engine.makeMove(move)) {
- Output() << "Invalid move: " << move;
- lastPosition.clear();
- break;
- }
- }
-
- if (engine.isDebugOn()) {
- engine.printBoard();
- }
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Do the UCI "setoption" command
-//! UCI specification:
-//! This is sent to the engine when the user wants to change the internal
-//! parameters of the engine. For the "button" type no value is needed.
-//! One string will be sent for each parameter and this will only be sent
-//! when the engine is waiting. The name and value of the option in
-//! should not be case sensitive and can inlude spaces. The substrings
-//! "value" and "name" should be avoided in and to allow unambiguous
-//! parsing, for example do not use = "draw value".
-//! Here are some strings for the example below:
-//! "setoption name Nullmove value true\n"
-//! "setoption name Selectivity value 3\n"
-//! "setoption name Style value Risky\n"
-//! "setoption name Clear Hash\n"
-//! "setoption name NalimovPath value c:\chess\tb\4;c:\chess\tb\5\n"
-//-----------------------------------------------------------------------------
- void UCIAdapter::doSetOptionCommand(Parameters ¶ms) {
- if (params.empty() || params.firstParamIs(token::Help)) {
- Output() << "usage: " << token::SetOption << ' ' << token::Name
- << " [" << token::Value << " ]";
- Output() << "Set the value of the specified option name.";
- Output() << "If no value specified the option's default value is used,";
- Output() << "or the option will be triggered if it's a button option.";
- return;
- }
-
- std::string name;
- std::string value;
-
- if (!params.firstParamIs(token::Name)) {
- Output() << "Missing name token";
- return;
- }
-
- if (!params.popString(token::Name, name, token::Value)) {
- Output() << "Missing name value";
- return;
- }
-
- if (params.firstParamIs(token::Value)) {
- if (!params.popString(token::Value, value)) {
- Output() << "Missing value";
- return;
- }
- }
-
- if (params.size()) {
- Output() << "Unexpected token: " << params.front();
- return;
- }
-
- if (!engine.setEngineOption(name, value)) {
- Output() << "Unknown option name '" << name
- << "' or invalid option value '" << value << "'";
- }
- }
-
-//-----------------------------------------------------------------------------
-//! \brief Do the UCI "ponderhit" command
-//! UCI specification:
-//! The user has played the expected move. This will be sent if the engine
-//! was told to ponder on the same move the user has played. The engine
-//! should continue searching but switch from pondering to normal search.
-//-----------------------------------------------------------------------------
- void UCIAdapter::doPonderHitCommand(Parameters & /*params*/) {
- engine.ponderHit();
- }
-
-} // namespace senjo
diff --git a/senjo/UCIAdapter.h b/senjo/UCIAdapter.h
deleted file mode 100644
index af021601..00000000
--- a/senjo/UCIAdapter.h
+++ /dev/null
@@ -1,88 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2015-2019 Shawn Chidester
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef SENJO_UCI_ADAPTER_H
-#define SENJO_UCI_ADAPTER_H
-
-#include "ChessEngine.h"
-#include "Parameters.h"
-#include "BackgroundCommand.h"
-
-namespace senjo {
-
-//-----------------------------------------------------------------------------
-//! \brief Convenience class to handle UCI communication for a ChessEngine
-//-----------------------------------------------------------------------------
- class UCIAdapter {
- public:
- UCIAdapter(ChessEngine &engine);
-
- ~UCIAdapter();
-
- //--------------------------------------------------------------------------
- //! \brief Execute the given one-line command
- //! \param[in] cmd The command to execute
- //! \return false when the program should exit, true to continue processing
- //--------------------------------------------------------------------------
- bool doCommand(const std::string &command);
-
- private:
- void doHelpCommand(Parameters ¶ms);
-
- void doFENCommand(Parameters ¶ms);
-
- void doMoveCommand(Parameters ¶ms);
-
- void doNewCommand(Parameters ¶ms);
-
- void doOptsCommand(Parameters ¶ms);
-
- void doPrintCommand(Parameters ¶ms);
-
- bool doQuitCommand(Parameters ¶ms);
-
- void doDebugCommand(Parameters ¶ms);
-
- void doIsReadyCommand(Parameters ¶ms);
-
- void doPonderHitCommand(Parameters ¶ms);
-
- void doSetOptionCommand(Parameters ¶ms);
-
- void doStopCommand(Parameters params = {});
-
- void doUCICommand(Parameters ¶ms);
-
- void doUCINewGameCommand(Parameters params = {});
-
- void doPositionCommand(const std::string &line, Parameters ¶ms);
-
- void execute(std::shared_ptr command, Parameters ¶ms);
-
- ChessEngine &engine;
- std::string lastPosition;
- std::shared_ptr lastCommand;
- };
-
-} // namespace senjo
-
-#endif // SENJO_UCI_ADAPTER_H
diff --git a/src/bitboard.cpp b/src/bitboard.cpp
deleted file mode 100644
index fd294f5f..00000000
--- a/src/bitboard.cpp
+++ /dev/null
@@ -1,891 +0,0 @@
-/*
- This file is part of Zagreus.
-
- Zagreus is a UCI chess engine
- Copyright (C) 2023 Danny Jelsma
-
- Zagreus is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Zagreus 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with Zagreus. If not, see .
- */
-
-#include "bitboard.h"
-
-#include
-
-#include "../senjo/Output.h"
-#include "bitwise.h"
-#include "magics.h"
-#include "movegen.h"
-#include "pst.h"
-#include "utils.h"
-
-namespace Zagreus {
-uint64_t Bitboard::getOccupiedBoard() const { return occupiedBB; }
-
-uint64_t Bitboard::getEmptyBoard() const { return ~occupiedBB; }
-
-PieceColor Bitboard::getMovingColor() const { return movingColor; }
-
-void Bitboard::setMovingColor(PieceColor movingColor) { this->movingColor = movingColor; }
-
-PieceType Bitboard::getPieceOnSquare(int8_t square) {
- return pieceSquareMapping[square];
-}
-
-uint64_t Bitboard::getQueenAttacks(int8_t square) {
- return getBishopAttacks(square) | getRookAttacks(square);
-}
-
-uint64_t Bitboard::getQueenAttacks(int8_t square, uint64_t occupancy) {
- return getBishopAttacks(square, occupancy) | getRookAttacks(square, occupancy);
-}
-
-uint64_t Bitboard::getBishopAttacks(int8_t square) {
- uint64_t occupancy = getOccupiedBoard();
- occupancy &= getBishopMask(square);
- occupancy *= getBishopMagic(square);
- occupancy >>= 64 - BBits[square];
-
- return getBishopMagicAttacks(square, occupancy);
-}
-
-uint64_t Bitboard::getBishopAttacks(int8_t square, uint64_t occupancy) {
- occupancy &= getBishopMask(square);
- occupancy *= getBishopMagic(square);
- occupancy >>= 64 - BBits[square];
-
- return getBishopMagicAttacks(square, occupancy);
-}
-
-uint64_t Bitboard::getRookAttacks(int8_t square) {
- uint64_t occupancy = getOccupiedBoard();
- occupancy &= getRookMask(square);
- occupancy *= getRookMagic(square);
- occupancy >>= 64 - RBits[square];
-
- return getRookMagicAttacks(square, occupancy);
-}
-
-uint64_t Bitboard::getRookAttacks(int8_t square, uint64_t occupancy) {
- occupancy &= getRookMask(square);
- occupancy *= getRookMagic(square);
- occupancy >>= 64 - RBits[square];
-
- return getRookMagicAttacks(square, occupancy);
-}
-
-void Bitboard::setPiece(int8_t square, PieceType piece) {
- pieceBB[piece] |= 1ULL << square;
- occupiedBB |= 1ULL << square;
- colorBB[piece % 2] |= 1ULL << square;
- pieceSquareMapping[square] = piece;
- zobristHash ^= getPieceZobristConstant(piece, square);
- materialCount[piece] += 1;
- pstValues[piece % 2] += getMidgamePstValue(piece, square);
- pstValues[piece % 2 + 2] += getEndgamePstValue(piece, square);
-}
-
-void Bitboard::removePiece(int8_t square, PieceType piece) {
- pieceBB[piece] &= ~(1ULL << square);
- occupiedBB &= ~(1ULL << square);
- colorBB[piece % 2] &= ~(1ULL << square);
- pieceSquareMapping[square] = EMPTY;
- zobristHash ^= getPieceZobristConstant(piece, square);
- materialCount[piece] -= 1;
- pstValues[piece % 2] -= getMidgamePstValue(piece, square);
- pstValues[piece % 2 + 2] -= getEndgamePstValue(piece, square);
-}
-
-void Bitboard::makeMove(Move& move) {
- PieceType capturedPiece = getPieceOnSquare(move.to);
-
- undoStack[ply].capturedPiece = capturedPiece;
- undoStack[ply].halfMoveClock = halfMoveClock;
- undoStack[ply].enPassantSquare = enPassantSquare;
- undoStack[ply].castlingRights = castlingRights;
- undoStack[ply].moveType = REGULAR;
- undoStack[ply].zobristHash = zobristHash;
- undoStack[ply].previousMove = previousMove;
-
- halfMoveClock += 1;
-
- if (capturedPiece != EMPTY) {
- halfMoveClock = 0;
- removePiece(move.to, capturedPiece);
- }
-
- if (move.piece == WHITE_PAWN || move.piece == BLACK_PAWN) {
- halfMoveClock = 0;
- }
-
- removePiece(move.from, move.piece);
-
- if (enPassantSquare != NO_SQUARE) {
- zobristHash ^= getEnPassantZobristConstant(enPassantSquare % 8);
- }
-
- if (move.piece == WHITE_PAWN || move.piece == BLACK_PAWN) {
- halfMoveClock = 0;
-
- if (move.to - move.from == 16) {
- enPassantSquare = move.to - 8;
- } else if (move.to - move.from == -16) {
- enPassantSquare = move.to + 8;
- } else if ((std::abs(move.to - move.from) == 7 || std::abs(move.to - move.from) == 9) &&
- move.to == enPassantSquare) {
- int8_t enPassantCaptureSquare = move.to - (movingColor == WHITE ? 8 : -8);
- removePiece(enPassantCaptureSquare, getPieceOnSquare(enPassantCaptureSquare));
- undoStack[ply].moveType = EN_PASSANT;
- enPassantSquare = NO_SQUARE;
- } else {
- enPassantSquare = NO_SQUARE;
- }
- } else {
- enPassantSquare = NO_SQUARE;
- }
-
- if (enPassantSquare != NO_SQUARE) {
- zobristHash ^= getEnPassantZobristConstant(enPassantSquare % 8);
- }
-
- if (move.piece == WHITE_KING || move.piece == BLACK_KING) {
- if (std::abs(move.to - move.from) == 2) {
- if (move.to == G1) {
- removePiece(H1, WHITE_ROOK);
- setPiece(F1, WHITE_ROOK);
- } else if (move.to == C1) {
- removePiece(A1, WHITE_ROOK);
- setPiece(D1, WHITE_ROOK);
- } else if (move.to == G8) {
- removePiece(H8, BLACK_ROOK);
- setPiece(F8, BLACK_ROOK);
- } else if (move.to == C8) {
- removePiece(A8, BLACK_ROOK);
- setPiece(D8, BLACK_ROOK);
- }
-
- undoStack[ply].moveType = CASTLING;
- }
-
- if (move.piece == WHITE_KING) {
- if (castlingRights & WHITE_KINGSIDE) {
- zobristHash ^= getCastleZobristConstant(ZOBRIST_WHITE_KINGSIDE_INDEX);
- castlingRights &= ~WHITE_KINGSIDE;
- }
-
- if (castlingRights & WHITE_QUEENSIDE) {
- zobristHash ^= getCastleZobristConstant(ZOBRIST_WHITE_QUEENSIDE_INDEX);
- castlingRights &= ~WHITE_QUEENSIDE;
- }
- } else {
- if (castlingRights & BLACK_KINGSIDE) {
- zobristHash ^= getCastleZobristConstant(ZOBRIST_BLACK_KINGSIDE_INDEX);
- castlingRights &= ~BLACK_KINGSIDE;
- }
-
- if (castlingRights & BLACK_QUEENSIDE) {
- zobristHash ^= getCastleZobristConstant(ZOBRIST_BLACK_QUEENSIDE_INDEX);
- castlingRights &= ~BLACK_QUEENSIDE;
- }
- }
- }
-
- if (move.piece == WHITE_ROOK) {
- if (move.from == A1 && (castlingRights & WHITE_QUEENSIDE)) {
- zobristHash ^= getCastleZobristConstant(ZOBRIST_WHITE_QUEENSIDE_INDEX);
- castlingRights &= ~WHITE_QUEENSIDE;
- } else if (move.from == H1 && (castlingRights & WHITE_KINGSIDE)) {
- zobristHash ^= getCastleZobristConstant(ZOBRIST_WHITE_KINGSIDE_INDEX);
- castlingRights &= ~WHITE_KINGSIDE;
- }
- } else if (move.piece == BLACK_ROOK) {
- if (move.from == A8 && (castlingRights & BLACK_QUEENSIDE)) {
- zobristHash ^= getCastleZobristConstant(ZOBRIST_BLACK_QUEENSIDE_INDEX);
- castlingRights &= ~BLACK_QUEENSIDE;
- } else if (move.from == H8 && (castlingRights & BLACK_KINGSIDE)) {
- zobristHash ^= getCastleZobristConstant(ZOBRIST_BLACK_KINGSIDE_INDEX);
- castlingRights &= ~BLACK_KINGSIDE;
- }
- }
-
- if (move.promotionPiece != EMPTY) {
- setPiece(move.to, move.promotionPiece);
- } else {
- setPiece(move.to, move.piece);
- }
-
- if (movingColor == BLACK) {
- fullmoveClock += 1;
- }
-
- movingColor = getOppositeColor(movingColor);
- zobristHash ^= getMovingColorZobristConstant();
- ply += 1;
- moveHistory[ply] = getZobristHash();
- previousMove = move;
-}
-
-int Bitboard::getHalfMoveClock() {
- return halfMoveClock;
-}
-
-void Bitboard::unmakeMove(Move& move) {
- moveHistory[ply] = 0;
- UndoData undoData = undoStack[ply - 1];
-
- if (move.promotionPiece != EMPTY) {
- removePiece(move.to, move.promotionPiece);
- } else {
- removePiece(move.to, move.piece);
- }
-
- if (undoData.capturedPiece != EMPTY) {
- setPiece(move.to, undoData.capturedPiece);
- }
-
- setPiece(move.from, move.piece);
-
- if (undoData.moveType == EN_PASSANT) {
- int8_t enPassantCaptureSquare = move.to - (getOppositeColor(movingColor) == WHITE ? 8 : -8);
- setPiece(enPassantCaptureSquare,
- getOppositeColor(movingColor) == WHITE ? BLACK_PAWN : WHITE_PAWN);
- }
-
- if (undoData.moveType == CASTLING) {
- if (move.to == G1) {
- removePiece(F1, WHITE_ROOK);
- setPiece(H1, WHITE_ROOK);
- } else if (move.to == C1) {
- removePiece(D1, WHITE_ROOK);
- setPiece(A1, WHITE_ROOK);
- } else if (move.to == G8) {
- removePiece(F8, BLACK_ROOK);
- setPiece(H8, BLACK_ROOK);
- } else if (move.to == C8) {
- removePiece(D8, BLACK_ROOK);
- setPiece(A8, BLACK_ROOK);
- }
- }
-
- ply -= 1;
- halfMoveClock = undoData.halfMoveClock;
- enPassantSquare = undoData.enPassantSquare;
- castlingRights = undoData.castlingRights;
- movingColor = getOppositeColor(movingColor);
- zobristHash = undoData.zobristHash;
- previousMove = undoData.previousMove;
-
- if (movingColor == BLACK) {
- fullmoveClock -= 1;
- }
-}
-
-void Bitboard::makeNullMove() {
- undoStack[ply].capturedPiece = EMPTY;
- undoStack[ply].halfMoveClock = halfMoveClock;
- undoStack[ply].enPassantSquare = enPassantSquare;
- undoStack[ply].castlingRights = castlingRights;
- undoStack[ply].moveType = REGULAR;
- undoStack[ply].zobristHash = zobristHash;
- undoStack[ply].previousMove = previousMove;
-
- if (enPassantSquare != NO_SQUARE) {
- zobristHash ^= getEnPassantZobristConstant(enPassantSquare % 8);
- enPassantSquare = NO_SQUARE;
- }
-
- movingColor = getOppositeColor(movingColor);
- zobristHash ^= getMovingColorZobristConstant();
- previousMove = {NO_SQUARE, NO_SQUARE, EMPTY, 0, EMPTY, 0};
- ply += 1;
-}
-
-void Bitboard::unmakeNullMove() {
- ply -= 1;
- UndoData undoData = undoStack[ply];
-
- enPassantSquare = undoData.enPassantSquare;
- castlingRights = undoData.castlingRights;
- movingColor = getOppositeColor(movingColor);
- zobristHash = undoData.zobristHash;
- previousMove = undoData.previousMove;
-}
-
-const Move& Bitboard::getPreviousMove() const { return previousMove; }
-
-bool Bitboard::hasMinorOrMajorPieces() {
- return hasMinorOrMajorPieces() || hasMinorOrMajorPieces();
-}
-
-int Bitboard::getAmountOfMinorOrMajorPieces() {
- return getAmountOfMinorOrMajorPieces() + getAmountOfMinorOrMajorPieces();
-}
-
-void Bitboard::print() {
- std::cout << " ---------------------------------";
-
- for (int index = 0; index < 64; index++) {
- if (index % 8 == 0) {
- std::cout << std::endl << index / 8 + 1 << " | ";
- }
-
- std::cout << getCharacterForPieceType(pieceSquareMapping[index]) << " | ";
- }
-
- std::cout << std::endl << " ---------------------------------" << std::endl;
- std::cout << " a b c d e f g h " << std::endl;
-}
-
-void Bitboard::printAvailableMoves(MoveList* moves) {
- std::cout << " ---------------------------------";
-
- for (int index = 0; index < 64; index++) {
- if (index % 8 == 0) {
- std::cout << std::endl << index / 8 + 1 << " | ";
- }
-
- bool didPrint = false;
-
- for (int i = 0; i < moves->size; i++) {
- Move move = moves->moves[i];
-
- if (move.to == index) {
- std::cout << 'X' << " | ";
- didPrint = true;
- break;
- }
- }
-
- if (!didPrint) {
- std::cout << getCharacterForPieceType(pieceSquareMapping[index]) << " | ";
- }
- }
-
- std::cout << std::endl << " ---------------------------------" << std::endl;
- std::cout << " a b c d e f g h " << std::endl;
-}
-
-bool Bitboard::setFromFen(const std::string& fen) {
- int index = A8;
- int spaces = 0;
-
- for (PieceType& type : pieceSquareMapping) {
- type = EMPTY;
- }
-
- for (uint64_t& bb : pieceBB) {
- bb = 0;
- }
-
- for (uint64_t& bb : colorBB) {
- bb = 0;
- }
-
- for (uint64_t& hash : moveHistory) {
- hash = 0;
- }
-
- for (UndoData& undo : undoStack) {
- undo = {};
- }
-
- for (int& count : materialCount) {
- count = 0;
- }
-
- occupiedBB = 0;
- movingColor = NONE;
- ply = 0;
- halfMoveClock = 0;
- fullmoveClock = 1;
- enPassantSquare = NO_SQUARE;
- castlingRights = 0;
- zobristHash = 0;
- pstValues[0] = 0;
- pstValues[1] = 0;
- pstValues[2] = 0;
- pstValues[3] = 0;
-
- for (char character : fen) {
- if (character == ' ') {
- spaces++;
- continue;
- }
-
- if (character == ',') {
- break;
- }
-
- if (spaces == 0) {
- if (character == '/') {
- index -= 16;
- continue;
- }
-
- if (character >= '1' && character <= '8') {
- index += character - '0';
- continue;
- }
-
- if (character >= 'A' && character <= 'z') {
- setPieceFromFENChar(character, index);
- index++;
- } else {
- senjo::Output(senjo::Output::InfoPrefix) << "Invalid piece character!";
- return false;
- }
- }
-
- if (spaces == 1) {
- if (tolower(character) == 'w') {
- movingColor = WHITE;
- } else if (tolower(character) == 'b') {
- movingColor = BLACK;
- zobristHash ^= getMovingColorZobristConstant();
- } else {
- senjo::Output(senjo::Output::InfoPrefix) << "Invalid color to move!";
- return false;
- }
- }
-
- if (spaces == 2) {
- if (character == '-') {
- continue;
- } else if (character == 'K') {
- castlingRights |= WHITE_KINGSIDE;
- zobristHash ^= getCastleZobristConstant(ZOBRIST_WHITE_KINGSIDE_INDEX);
- continue;
- } else if (character == 'Q') {
- castlingRights |= WHITE_QUEENSIDE;
- zobristHash ^= getCastleZobristConstant(ZOBRIST_WHITE_QUEENSIDE_INDEX);
- continue;
- } else if (character == 'k') {
- castlingRights |= BLACK_KINGSIDE;
- zobristHash ^= getCastleZobristConstant(ZOBRIST_BLACK_KINGSIDE_INDEX);
- continue;
- } else if (character == 'q') {
- castlingRights |= BLACK_QUEENSIDE;
- zobristHash ^= getCastleZobristConstant(ZOBRIST_BLACK_QUEENSIDE_INDEX);
- continue;
- }
-
- senjo::Output(senjo::Output::InfoPrefix) << "Invalid castling rights!";
- return false;
- }
-
- if (spaces == 3) {
- if (character == '-') {
- continue;
- }
-
- if (tolower(character) < 'a' || tolower(character) > 'h') {
- continue;
- }
-
- int8_t file = tolower(character) - 'a';
- // NOLINT(cppcoreguidelines-narrowing-conversions)
- int8_t rank = getOppositeColor(movingColor) == WHITE ? 2 : 5;
-
- if (file < 0 || file > 7) {
- senjo::Output(senjo::Output::InfoPrefix) << "Invalid en passant file!";
- return false;
- }
-
- enPassantSquare = rank * 8 + file;
- zobristHash ^= getEnPassantZobristConstant(enPassantSquare % 8);
-
- index += 2;
- }
-
- if (spaces == 4) {
- halfMoveClock = character - '0';
- }
-
- if (spaces == 5) {
- fullmoveClock = character - '0';
- }
- }
-
- moveHistory[ply] = getZobristHash();
- return true;
-}
-
-bool Bitboard::setFromFenTuner(const std::string& fen) {
- int index = A8;
- int spaces = 0;
-
- for (PieceType& type : pieceSquareMapping) {
- type = EMPTY;
- }
-
- for (uint64_t& bb : pieceBB) {
- bb = 0;
- }
-
- for (uint64_t& bb : colorBB) {
- bb = 0;
- }
-
- for (uint64_t& hash : moveHistory) {
- hash = 0;
- }
-
- for (UndoData& undo : undoStack) {
- undo = {};
- }
-
- for (int& count : materialCount) {
- count = 0;
- }
-
- occupiedBB = 0;
- movingColor = NONE;
- ply = 0;
- halfMoveClock = 0;
- fullmoveClock = 1;
- enPassantSquare = NO_SQUARE;
- castlingRights = 0;
- zobristHash = 0;
- pstValues[0] = 0;
- pstValues[1] = 0;
- pstValues[2] = 0;
- pstValues[3] = 0;
-
- for (char character : fen) {
- if (character == ' ') {
- spaces++;
- continue;
- }
-
- if (character == ',') {
- break;
- }
-
- if (spaces == 0) {
- if (character == '/') {
- index -= 16;
- continue;
- }
-
- if (character >= '1' && character <= '8') {
- index += character - '0';
- continue;
- }
-
- if (character >= 'A' && character <= 'z') {
- setPieceFromFENChar(character, index);
- index++;
- } else {
- senjo::Output(senjo::Output::InfoPrefix) << "Invalid piece character!";
- return false;
- }
- }
-
- if (spaces == 1) {
- if (tolower(character) == 'w') {
- movingColor = WHITE;
- } else if (tolower(character) == 'b') {
- movingColor = BLACK;
- } else {
- senjo::Output(senjo::Output::InfoPrefix) << "Invalid color to move!";
- return false;
- }
- }
-
- if (spaces == 2) {
- if (character == '-') {
- continue;
- } else if (character == 'K') {
- castlingRights |= WHITE_KINGSIDE;
- continue;
- } else if (character == 'Q') {
- castlingRights |= WHITE_QUEENSIDE;
- continue;
- } else if (character == 'k') {
- castlingRights |= BLACK_KINGSIDE;
- continue;
- } else if (character == 'q') {
- castlingRights |= BLACK_QUEENSIDE;
- continue;
- }
-
- senjo::Output(senjo::Output::InfoPrefix) << "Invalid castling rights!";
- return false;
- }
-
- if (spaces == 3) {
- if (character == '-') {
- continue;
- }
-
- if (tolower(character) < 'a' || tolower(character) > 'h') {
- continue;
- }
-
- int8_t file = tolower(character) - 'a';
- // NOLINT(cppcoreguidelines-narrowing-conversions)
- int8_t rank = getOppositeColor(movingColor) == WHITE ? 2 : 5;
-
- if (file < 0 || file > 7) {
- senjo::Output(senjo::Output::InfoPrefix) << "Invalid en passant file!";
- return false;
- }
-
- enPassantSquare = rank * 8 + file;
- index += 2;
- }
-
- if (spaces == 4) {
- halfMoveClock = character - '0';
- }
-
- if (spaces == 5) {
- fullmoveClock = character - '0';
- }
- }
-
- return true;
-}
-
-bool Bitboard::isDraw() {
- if (halfMoveClock >= 100) {
- return true;
- }
-
- if (isInsufficientMaterial()) {
- return true;
- }
-
- // Check if the same position has occurred 3 times using the movehistory array
- int samePositionCount = 0;
- uint64_t boardHash = getZobristHash();
-
- for (int i = ply; i >= 0; i--) {
- if (moveHistory[i] == boardHash) {
- samePositionCount++;
- }
-
- if (samePositionCount >= 3) {
- return true;
- }
- }
-
- return false;
-}
-
-uint64_t Bitboard::getZobristHash() const { return zobristHash; }
-
-void Bitboard::setZobristHash(uint64_t zobristHash) { Bitboard::zobristHash = zobristHash; }
-
-bool Bitboard::isInsufficientMaterial() {
- uint64_t kingBB = getPieceBoard(WHITE_KING) | getPieceBoard(BLACK_KING);
- uint64_t piecesBB = getOccupiedBoard();
- uint64_t piecesWithoutKings = piecesBB & ~kingBB;
- uint64_t sufficientPieces = getPieceBoard(WHITE_QUEEN) | getPieceBoard(BLACK_QUEEN) |
- getPieceBoard(WHITE_ROOK) | getPieceBoard(BLACK_ROOK) |
- getPieceBoard(WHITE_PAWN) | getPieceBoard(BLACK_PAWN);
-
- // If there are queens, rooks or pawns on the board, it can't be a draw
- if (sufficientPieces) {
- return false;
- }
-
- int pieceCountWithoutKings = popcnt(piecesWithoutKings);
-
- // If there is only one minor piece on the board, it's a draw. Covers KBvK, KNvK and KvK
- if (pieceCountWithoutKings == 1 || pieceCountWithoutKings == 0) {
- return true;
- }
-
- return false;
-}
-
-void Bitboard::setPieceFromFENChar(char character, int index) {
- // Uppercase = WHITE, lowercase = black
- switch (character) {
- case 'P':
- setPiece(index, WHITE_PAWN);
- break;
- case 'p':
- setPiece(index, BLACK_PAWN);
- break;
- case 'N':
- setPiece(index, WHITE_KNIGHT);
- break;
- case 'n':
- setPiece(index, BLACK_KNIGHT);
- break;
- case 'B':
- setPiece(index, WHITE_BISHOP);
- break;
- case 'b':
- setPiece(index, BLACK_BISHOP);
- break;
- case 'R':
- setPiece(index, WHITE_ROOK);
- break;
- case 'r':
- setPiece(index, BLACK_ROOK);
- break;
- case 'Q':
- setPiece(index, WHITE_QUEEN);
- break;
- case 'q':
- setPiece(index, BLACK_QUEEN);
- break;
- case 'K':
- setPiece(index, WHITE_KING);
- break;
- case 'k':
- setPiece(index, BLACK_KING);
- break;
- }
-}
-
-uint64_t Bitboard::getSquareAttacks(int8_t square) {
- uint64_t queenBB = getPieceBoard(WHITE_QUEEN) | getPieceBoard(BLACK_QUEEN);
- uint64_t straightSlidingPieces = getPieceBoard(WHITE_ROOK) | getPieceBoard(BLACK_ROOK) |
- queenBB;
- uint64_t diagonalSlidingPieces =
- getPieceBoard(WHITE_BISHOP) | getPieceBoard(BLACK_BISHOP) | queenBB;
-
- uint64_t pawnAttacks = getPawnAttacks(square) & getPieceBoard(WHITE_PAWN);
- pawnAttacks |= getPawnAttacks(square) & getPieceBoard(BLACK_PAWN);
- uint64_t rookAttacks = getRookAttacks(square) & straightSlidingPieces;
- uint64_t bishopAttacks = getBishopAttacks(square) & diagonalSlidingPieces;
- uint64_t knightAttacks =
- getKnightAttacks(square) & (getPieceBoard(WHITE_KNIGHT) | getPieceBoard(BLACK_KNIGHT));
- uint64_t kingAttacks =
- getKingAttacks(square) & (getPieceBoard(WHITE_KING) | getPieceBoard(BLACK_KING));
-
- return pawnAttacks | rookAttacks | bishopAttacks | knightAttacks | kingAttacks;
-}
-
-uint8_t Bitboard::getCastlingRights() const { return castlingRights; }
-
-void Bitboard::setCastlingRights(uint8_t castlingRights) {
- Bitboard::castlingRights = castlingRights;
-}
-
-int8_t Bitboard::getEnPassantSquare() const { return enPassantSquare; }
-
-void Bitboard::setEnPassantSquare(int8_t enPassantSquare) {
- Bitboard::enPassantSquare = enPassantSquare;
-}
-
-uint64_t Bitboard::getFile(int8_t square) {
- return getRayAttack(square, NORTH) | getRayAttack(square, SOUTH) | 1ULL << square;
-}
-
-bool Bitboard::makeStrMove(const std::string& strMove) {
- int8_t fromSquare = getSquareFromString(strMove.substr(0, 2));
- int8_t toSquare = getSquareFromString(strMove.substr(2, 2));
- PieceType promotionPiece = EMPTY;
-
- if (strMove.length() == 5) {
- if (strMove.ends_with("q")) {
- promotionPiece = getMovingColor() == WHITE ? WHITE_QUEEN : BLACK_QUEEN;
- } else if (strMove.ends_with("r")) {
- promotionPiece = getMovingColor() == WHITE ? WHITE_ROOK : BLACK_ROOK;
- } else if (strMove.ends_with("b")) {
- promotionPiece = getMovingColor() == WHITE ? WHITE_BISHOP : BLACK_BISHOP;
- } else if (strMove.ends_with("n")) {
- promotionPiece = getMovingColor() == WHITE ? WHITE_KNIGHT : BLACK_KNIGHT;
- }
- }
-
- PieceType movingPiece = getPieceOnSquare(fromSquare);
- PieceType capturedPiece = getPieceOnSquare(toSquare);
- int captureScore = -1;
-
- if (capturedPiece != EMPTY) {
- captureScore = mvvlva(movingPiece, capturedPiece);
- }
-
- Move move = {fromSquare, toSquare, movingPiece, captureScore, promotionPiece};
- makeMove(move);
- return true;
-}
-
-Line Bitboard::getPvLine() { return pvLine; }
-
-void Bitboard::setPvLine(Line& pvLine) {
- Bitboard::pvLine = pvLine;
-}
-
-uint16_t Bitboard::getPly() const { return ply; }
-
-void Bitboard::setPly(uint16_t ply) { this->ply = ply; }
-
-bool Bitboard::isOpenFile(int8_t square) {
- uint64_t fileMask = getFile(square);
- uint64_t occupied = getPieceBoard(WHITE_PAWN) | getPieceBoard(BLACK_PAWN);
-
- return fileMask == (fileMask & ~occupied);
-}
-
-int Bitboard::getWhiteMidgamePst() const { return pstValues[0]; }
-
-int Bitboard::getWhiteEndgamePst() const { return pstValues[2]; }
-
-int Bitboard::getBlackMidgamePst() const { return pstValues[1]; }
-
-int Bitboard::getBlackEndgamePst() const { return pstValues[3]; }
-
-uint64_t Bitboard::getPieceBoard(PieceType pieceType) { return pieceBB[pieceType]; }
-
-template
-bool Bitboard::isWinner() {
- if (color == WHITE) {
- if (!isKingInCheck()) {
- return false;
- }
- } else {
- if (!isKingInCheck()) {
- return false;
- }
- }
-
- MoveListPool* moveListPool = MoveListPool::getInstance();
- MoveList* moveList = moveListPool->getMoveList();
- generateMoves(*this, moveList);
-
- for (int i = 0; i < moveList->size; i++) {
- Move move = moveList->moves[i];
-
- makeMove(move);
-
- if (color == WHITE) {
- if (isKingInCheck()) {
- unmakeMove(move);
- continue;
- }
- } else {
- if (isKingInCheck()) {
- unmakeMove(move);
- continue;
- }
- }
-
- unmakeMove(move);
- moveListPool->releaseMoveList(moveList);
- return false;
- }
-
- moveListPool->releaseMoveList(moveList);
- return true;
-}
-
-template bool Bitboard::isWinner();
-template bool Bitboard::isWinner();
-} // namespace Zagreus
\ No newline at end of file
diff --git a/src/bitboard.h b/src/bitboard.h
deleted file mode 100644
index 43bcd2f8..00000000
--- a/src/bitboard.h
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- This file is part of Zagreus.
-
- Zagreus is a UCI chess engine
- Copyright (C) 2023 Danny Jelsma
-
- Zagreus is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Zagreus 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with Zagreus. If not, see .
- */
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"
-#pragma once
-
-#include
-
-#include
-#include
-#include
-
-#include "bitwise.h"
-#include "movelist_pool.h"
-#include "types.h"
-#include "utils.h"
-
-namespace Zagreus {
-class Bitboard {
-private:
- uint64_t pieceBB[12]{};
- PieceType pieceSquareMapping[64]{};
- uint64_t colorBB[2]{};
- uint64_t occupiedBB{0ULL};
-
- PieceColor movingColor = NONE;
- uint16_t ply = 0;
- uint8_t halfMoveClock = 0;
- uint8_t fullmoveClock = 1;
- int8_t enPassantSquare = NO_SQUARE;
- uint8_t castlingRights = 0b00001111;
-
- uint64_t zobristHash = 0ULL;
-
- UndoData undoStack[MAX_PLY]{};
- uint64_t moveHistory[MAX_PLY]{};
- Line pvLine{};
-
- int pstValues[4]{};
-
- Move previousMove{};
- int materialCount[12]{};
-
-public:
- uint64_t getPieceBoard(PieceType pieceType);
-
- template
- uint64_t getColorBoard() {
- return colorBB[color];
- }
-
- template
- uint64_t getPawnDoublePush(uint64_t pawns) {
- const uint64_t singlePush = getPawnSinglePush(pawns);
-
- if (color == WHITE) {
- return singlePush | (nortOne(singlePush) & getEmptyBoard() & RANK_4);
- }
-
- if (color == BLACK) {
- return singlePush | (soutOne(singlePush) & getEmptyBoard() & RANK_5);
- }
-
- return 0;
- }
-
- template
- uint64_t getPawnSinglePush(uint64_t pawns) {
- if (color == WHITE) {
- return nortOne(pawns) & getEmptyBoard();
- }
-
- if (color == BLACK) {
- return soutOne(pawns) & getEmptyBoard();
- }
-
- return 0;
- }
-
- uint64_t getOccupiedBoard() const;
-
- uint64_t getEmptyBoard() const;
-
- PieceType getPieceOnSquare(int8_t square);
-
- uint64_t getQueenAttacks(int8_t square);
-
- uint64_t getQueenAttacks(int8_t square, uint64_t occupancy);
-
- uint64_t getBishopAttacks(int8_t square);
-
- static uint64_t getBishopAttacks(int8_t square, uint64_t occupancy);
-
- uint64_t getRookAttacks(int8_t square);
-
- static uint64_t getRookAttacks(int8_t square, uint64_t occupancy);
-
- void setPiece(int8_t square, PieceType piece);
-
- void removePiece(int8_t square, PieceType piece);
-
- template
- int getMaterialCount() {
- return materialCount[piece];
- }
-
- void makeMove(Move& move);
- int getHalfMoveClock();
-
- void unmakeMove(Move& move);
-
- void print();
-
- void printAvailableMoves(MoveList* moves);
-
- bool setFromFen(const std::string& fen);
-
- bool setFromFenTuner(const std::string& fen);
-
- bool isDraw();
-
- template
- bool isWinner();
-
- void setPieceFromFENChar(char character, int index);
-
- PieceColor getMovingColor() const;
-
- void setMovingColor(PieceColor movingColor);
-
- uint64_t getSquareAttacks(int8_t square);
-
- template
- uint64_t getSquareAttackersByColor(int8_t square) {
- if (color == WHITE) {
- uint64_t queenBB = getPieceBoard(WHITE_QUEEN);
- uint64_t rookBB = getPieceBoard(WHITE_ROOK);
- uint64_t bishopBB = getPieceBoard(WHITE_BISHOP);
-
- uint64_t pawnAttacks = getPawnAttacks(square) & getPieceBoard(WHITE_PAWN);
- uint64_t bishopAttacks = getBishopAttacks(square) & bishopBB;
- uint64_t knightAttacks = getKnightAttacks(square) & getPieceBoard(WHITE_KNIGHT);
- uint64_t kingAttacks = getKingAttacks(square) & getPieceBoard(WHITE_KING);
- uint64_t rookAttacks = getRookAttacks(square) & rookBB;
- uint64_t queenAttacks = getQueenAttacks(square) & queenBB;
-
- return pawnAttacks | bishopAttacks | knightAttacks | rookAttacks | queenAttacks |
- kingAttacks;
- } else {
- uint64_t queenBB = getPieceBoard(BLACK_QUEEN);
- uint64_t rookBB = getPieceBoard(BLACK_ROOK);
- uint64_t bishopBB = getPieceBoard(BLACK_BISHOP);
-
- uint64_t pawnAttacks = getPawnAttacks(square) & getPieceBoard(BLACK_PAWN);
- uint64_t bishopAttacks = getBishopAttacks(square) & bishopBB;
- uint64_t knightAttacks = getKnightAttacks(square) & getPieceBoard(BLACK_KNIGHT);
- uint64_t rookAttacks = getRookAttacks(square) & rookBB;
- uint64_t queenAttacks = getQueenAttacks(square) & queenBB;
- uint64_t kingAttacks = getKingAttacks(square) & getPieceBoard(BLACK_KING);
-
- return pawnAttacks | bishopAttacks | knightAttacks | rookAttacks | queenAttacks |
- kingAttacks;
- }
- }
-
- template
- bool isSquareAttackedByColor(int8_t square) {
- return getSquareAttackersByColor(square) != 0;
- }
-
- template
- bool isKingInCheck() {
- constexpr PieceColor OPPOSITE_COLOR = color == WHITE ? BLACK : WHITE;
- uint64_t kingBB = getPieceBoard(color == WHITE ? WHITE_KING : BLACK_KING);
- int8_t kingLocation = bitscanForward(kingBB);
-
- return isSquareAttackedByColor(kingLocation);
- }
-
- int8_t getEnPassantSquare() const;
-
- void setEnPassantSquare(int8_t enPassantSquare);
-
- uint8_t getCastlingRights() const;
-
- void setCastlingRights(uint8_t castlingRights);
-
- bool isInsufficientMaterial();
-
- uint64_t getZobristHash() const;
-
- void setZobristHash(uint64_t zobristHash);
-
- bool makeStrMove(const std::string& strMove);
-
- Line getPvLine();
-
- void setPvLine(Line& pvLine);
-
- uint16_t getPly() const;
-
- void setPly(uint16_t ply);
-
- bool isOpenFile(int8_t square);
-
- template
- bool isSemiOpenFile(int8_t square) {
- uint64_t fileMask = getFile(square);
- if (color == WHITE) {
- uint64_t ownOccupied = getPieceBoard(WHITE_PAWN);
- uint64_t opponentOccupied = getPieceBoard(BLACK_PAWN);
-
- return fileMask == (fileMask & ~ownOccupied) && fileMask != (
- fileMask & ~opponentOccupied);
- } else {
- uint64_t ownOccupied = getPieceBoard(BLACK_PAWN);
- uint64_t opponentOccupied = getPieceBoard(WHITE_PAWN);
-
- return fileMask == (fileMask & ~ownOccupied) && fileMask != (
- fileMask & ~opponentOccupied);
- }
- }
-
- // Also returns true when it is an open file
- template
- bool isSemiOpenFileLenient(int8_t square) {
- uint64_t fileMask = getFile(square);
-
- if (color == WHITE) {
- uint64_t ownOccupied = getPieceBoard(WHITE_PAWN);
- return fileMask == (fileMask & ~ownOccupied);
- } else {
- uint64_t ownOccupied = getPieceBoard(BLACK_PAWN);
- return fileMask == (fileMask & ~ownOccupied);
- }
- }
-
- template
- int seeCapture(int8_t fromSquare, int8_t toSquare) {
- constexpr PieceColor OPPOSITE_COLOR = attackingColor == WHITE ? BLACK : WHITE;
- PieceType movingPiece = pieceSquareMapping[fromSquare];
- PieceType capturedPieceType = pieceSquareMapping[toSquare];
- int captureScore = mvvlva(movingPiece, capturedPieceType);
- Move move{fromSquare, toSquare, movingPiece, captureScore};
-
- makeMove(move);
- int score = getPieceWeight(capturedPieceType) - see(toSquare);
- unmakeMove(move);
-
- return score;
- }
-
- template
- int8_t getSmallestAttackerSquare(int8_t square) {
- uint64_t attacks = getSquareAttackersByColor(square);
- int8_t smallestAttackerSquare = NO_SQUARE;
- int smallestAttackerWeight = 999999999;
-
- while (attacks) {
- int attackerSquare = popLsb(attacks);
- PieceType pieceType = pieceSquareMapping[attackerSquare];
- int weight = getPieceWeight(pieceType);
-
- if (weight < smallestAttackerWeight) {
- smallestAttackerWeight = weight;
- smallestAttackerSquare = attackerSquare;
- }
- }
-
- return smallestAttackerSquare;
- }
-
- template
- int see(int8_t square) {
- constexpr PieceColor OPPOSITE_COLOR = attackingColor == WHITE ? BLACK : WHITE;
- int score = 0;
- int8_t smallestAttackerSquare = getSmallestAttackerSquare(square);
-
- if (smallestAttackerSquare != NO_SQUARE) {
- PieceType movingPiece = pieceSquareMapping[smallestAttackerSquare];
- PieceType capturedPieceType = pieceSquareMapping[square];
- int captureScore = mvvlva(movingPiece, capturedPieceType);
- Move move{smallestAttackerSquare, square, movingPiece, captureScore};
- makeMove(move);
- score = std::max(0, getPieceWeight(capturedPieceType) - see(square));
- unmakeMove(move);
- }
-
- return score;
- }
-
- // See, but after a move has already been made. We just check if the opponent can win material.
- // This method is basically seeCapture where the move has already been made. It is used to analyze a move already made to see if it appears to be safe.
- template
- int seeOpponent(int8_t square) {
- // moved color is the color that just moved
- constexpr PieceColor OPPOSITE_COLOR = movedColor == WHITE ? BLACK : WHITE;
- int score = NO_CAPTURE_SCORE;
- int8_t smallestAttackerSquare = getSmallestAttackerSquare(square);
-
- if (smallestAttackerSquare != NO_SQUARE) {
- PieceType movingPiece = pieceSquareMapping[smallestAttackerSquare];
- PieceType capturedPieceType = pieceSquareMapping[square];
- int captureScore = mvvlva(movingPiece, capturedPieceType);
- Move move{smallestAttackerSquare, square, movingPiece, captureScore};
- makeMove(move);
- score = getPieceWeight(capturedPieceType) - see(square);
- unmakeMove(move);
- }
-
- return score;
- }
-
- [[nodiscard]] const Move& getPreviousMove() const;
-
- uint64_t getFile(int8_t square);
-
- template
- uint64_t getPawnsOnSameFile(int8_t square) {
- return pieceBB[WHITE_PAWN + color] & getFile(square);
- }
-
- template
- bool isIsolatedPawn(int8_t square) {
- uint64_t neighborMask = 0;
-
- if (square % 8 != 0) {
- neighborMask |= getFile(square - 1);
- }
-
- if (square % 8 != 7) {
- neighborMask |= getFile(square + 1);
- }
-
- if (color == WHITE) {
- return !(neighborMask & getPieceBoard(WHITE_PAWN));
- } else {
- return !(neighborMask & getPieceBoard(BLACK_PAWN));
- }
- }
-
- template
- bool isPassedPawn(int8_t square) {
- Direction direction = color == WHITE ? NORTH : SOUTH;
- uint64_t neighborMask = getRayAttack(square, direction);
- uint64_t pawnBB = getPieceBoard(color == WHITE ? WHITE_PAWN : BLACK_PAWN);
-
- if (neighborMask & pawnBB) {
- return false;
- }
-
- if (square % 8 != 0) {
- // neighboring file
- neighborMask |= getRayAttack(square - 1, direction);
- }
-
- if (square % 8 != 7) {
- neighborMask |= getRayAttack(square + 1, direction);
- }
-
- if (color == WHITE) {
- return !(neighborMask & getPieceBoard(BLACK_PAWN));
- } else {
- return !(neighborMask & getPieceBoard(WHITE_PAWN));
- }
- }
-
- bool hasMinorOrMajorPieces();
-
- template
- bool hasMinorOrMajorPieces() {
- if (color == WHITE) {
- return getColorBoard() & ~(
- getPieceBoard(WHITE_PAWN) | getPieceBoard(WHITE_KING));
- } else {
- return getColorBoard() & ~(
- getPieceBoard(BLACK_PAWN) | getPieceBoard(BLACK_KING));
- }
- }
-
- template
- int getAmountOfMinorOrMajorPieces() {
- if (color == WHITE) {
- return popcnt(getColorBoard() &
- ~(getPieceBoard(WHITE_PAWN) | getPieceBoard(WHITE_KING)));
- } else {
- return popcnt(getColorBoard() &
- ~(getPieceBoard(BLACK_PAWN) | getPieceBoard(BLACK_KING)));
- }
- }
-
- template
- int getAmountOfPawns() {
- return popcnt(getColorBoard() & getPieceBoard(color == WHITE
- ? WHITE_PAWN
- : BLACK_PAWN));
- }
-
- template
- int getAmountOfPieces() {
- return popcnt(getColorBoard());
- }
-
- void makeNullMove();
-
- void unmakeNullMove();
-
- [[nodiscard]] int getWhiteMidgamePst() const;
-
- [[nodiscard]] int getWhiteEndgamePst() const;
-
- [[nodiscard]] int getBlackMidgamePst() const;
-
- [[nodiscard]] int getBlackEndgamePst() const;
-
- int getAmountOfMinorOrMajorPieces();
-};
-} // namespace Zagreus
-
-#pragma clang diagnostic pop
\ No newline at end of file
diff --git a/src/bitwise.cpp b/src/bitwise.cpp
deleted file mode 100644
index 2c948bd2..00000000
--- a/src/bitwise.cpp
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- This file is part of Zagreus.
-
- Zagreus is a UCI chess engine
- Copyright (C) 2023 Danny Jelsma
-
- Zagreus is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Zagreus 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with Zagreus. If not, see .
- */
-
-#include "bitwise.h"
-
-#include
-#include
-#include
-
-namespace Zagreus {
-static uint64_t kingAttacks[64]{};
-static uint64_t knightAttacks[64]{};
-static uint64_t pawnAttacks[2][64]{};
-static uint64_t rayAttacks[8][64]{};
-static uint64_t betweenTable[64][64]{};
-
-static uint64_t zobristPieceConstants[PIECE_TYPES][SQUARES]{};
-static uint64_t zobristMovingColorConstant{};
-static uint64_t zobristCastleConstants[4]{};
-static uint64_t zobristEnPassantConstants[8]{};
-
-uint64_t soutOne(uint64_t b) { return b >> 8ULL; }
-
-uint64_t nortOne(uint64_t b) { return b << 8ULL; }
-
-uint64_t eastOne(uint64_t b) { return b << 1ULL & NOT_A_FILE; }
-
-uint64_t noEaOne(uint64_t b) { return b << 9ULL & NOT_A_FILE; }
-
-uint64_t soEaOne(uint64_t b) { return b >> 7ULL & NOT_A_FILE; }
-
-uint64_t westOne(uint64_t b) { return b >> 1ULL & NOT_H_FILE; }
-
-uint64_t soWeOne(uint64_t b) { return b >> 9ULL & NOT_H_FILE; }
-
-uint64_t noWeOne(uint64_t b) { return b << 7ULL & NOT_H_FILE; }
-
-uint64_t noNoEa(uint64_t b) { return b << 17ULL & NOT_A_FILE; }
-
-uint64_t noEaEa(uint64_t b) { return b << 10ULL & NOT_AB_FILE; }
-
-uint64_t soEaEa(uint64_t b) { return b >> 6ULL & NOT_AB_FILE; }
-
-uint64_t soSoEa(uint64_t b) { return b >> 15ULL & NOT_A_FILE; }
-
-uint64_t noNoWe(uint64_t b) { return b << 15ULL & NOT_H_FILE; }
-
-uint64_t noWeWe(uint64_t b) { return b << 6ULL & NOT_GH_FILE; }
-
-uint64_t nortFill(uint64_t gen) {
- gen |= gen << 8;
- gen |= gen << 16;
- gen |= gen << 32;
-
- return gen;
-}
-
-uint64_t soutFill(uint64_t gen) {
- gen |= gen >> 8;
- gen |= gen >> 16;
- gen |= gen >> 32;
-
- return gen;
-}
-
-uint64_t whiteFrontSpans(uint64_t pawns) { return nortOne(nortFill(pawns)); }
-
-uint64_t whiteRearSpans(uint64_t pawns) { return soutOne(soutFill(pawns)); }
-
-uint64_t blackRearSpans(uint64_t pawns) { return nortOne(nortFill(pawns)); }
-
-uint64_t blackFrontSpans(uint64_t pawns) { return soutOne(soutFill(pawns)); }
-
-uint64_t soutOccl(uint64_t pieceBB, uint64_t empty) {
- pieceBB |= empty & pieceBB >> 8ULL;
- empty &= empty >> 8ULL;
- pieceBB |= empty & pieceBB >> 16ULL;
- empty &= empty >> 16ULL;
- pieceBB |= empty & pieceBB >> 32ULL;
- return soutOne(pieceBB);
-}
-
-uint64_t nortOccl(uint64_t pieceBB, uint64_t empty) {
- pieceBB |= empty & pieceBB << 8ULL;
- empty &= empty << 8ULL;
- pieceBB |= empty & pieceBB << 16ULL;
- empty &= empty << 16ULL;
- pieceBB |= empty & pieceBB << 32ULL;
- return nortOne(pieceBB);
-}
-
-uint64_t eastOccl(uint64_t pieceBB, uint64_t empty) {
- empty &= NOT_A_FILE;
- pieceBB |= empty & pieceBB << 1ULL;
- empty &= empty << 1ULL;
- pieceBB |= empty & pieceBB << 2ULL;
- empty &= empty << 2ULL;
- pieceBB |= empty & pieceBB << 4ULL;
- return eastOne(pieceBB);
-}
-
-uint64_t noEaOccl(uint64_t pieceBB, uint64_t empty) {
- empty &= NOT_A_FILE;
- pieceBB |= empty & pieceBB << 9ULL;
- empty &= empty << 9ULL;
- pieceBB |= empty & pieceBB << 18ULL;
- empty &= empty << 18ULL;
- pieceBB |= empty & pieceBB << 36ULL;
- return noEaOne(pieceBB);
-}
-
-uint64_t soEaOccl(uint64_t pieceBB, uint64_t empty) {
- empty &= NOT_A_FILE;
- pieceBB |= empty & pieceBB >> 7ULL;
- empty &= empty >> 7ULL;
- pieceBB |= empty & pieceBB >> 14ULL;
- empty &= empty >> 14ULL;
- pieceBB |= empty & pieceBB >> 28ULL;
- return soEaOne(pieceBB);
-}
-
-uint64_t westOccl(uint64_t pieceBB, uint64_t empty) {
- empty &= NOT_H_FILE;
- pieceBB |= empty & pieceBB >> 1ULL;
- empty &= empty >> 1ULL;
- pieceBB |= empty & pieceBB >> 2ULL;
- empty &= empty >> 2ULL;
- pieceBB |= empty & pieceBB >> 4ULL;
- return westOne(pieceBB);
-}
-
-uint64_t soWeOccl(uint64_t pieceBB, uint64_t empty) {
- empty &= NOT_H_FILE;
- pieceBB |= empty & pieceBB >> 9ULL;
- empty &= empty >> 9ULL;
- pieceBB |= empty & pieceBB >> 18ULL;
- empty &= empty >> 18ULL;
- pieceBB |= empty & pieceBB >> 36ULL;
- return soWeOne(pieceBB);
-}
-
-uint64_t noWeOccl(uint64_t pieceBB, uint64_t empty) {
- empty &= NOT_H_FILE;
- pieceBB |= empty & pieceBB << 7ULL;
- empty &= empty << 7ULL;
- pieceBB |= empty & pieceBB << 14ULL;
- empty &= empty << 14ULL;
- pieceBB |= empty & pieceBB << 28ULL;
- return noWeOne(pieceBB);
-}
-
-template
-uint64_t calculatePawnEastAttacks(uint64_t pawns) {
- if (color == WHITE) {
- return noEaOne(pawns);
- }
- return soEaOne(pawns);
-}
-
-template
-uint64_t calculatePawnWestAttacks(uint64_t pawns) {
- if (color == WHITE) {
- return noWeOne(pawns);
- }
- return soWeOne(pawns);
-}
-
-uint64_t calculateKnightAttacks(uint64_t knights) {
- uint64_t l1 = knights >> 1ULL & NOT_H_FILE;
- uint64_t l2 = knights >> 2ULL & NOT_GH_FILE;
- uint64_t r1 = knights << 1ULL & NOT_A_FILE;
- uint64_t r2 = knights << 2ULL & NOT_AB_FILE;
- uint64_t h1 = l1 | r1;
- uint64_t h2 = l2 | r2;
- return h1 << 16ULL | h1 >> 16ULL | h2 << 8ULL | h2 >> 8ULL;
-}
-
-uint64_t calculateKingAttacks(uint64_t kingSet) {
- uint64_t attacks = eastOne(kingSet) | westOne(kingSet);
- kingSet |= attacks;
- attacks |= nortOne(kingSet) | soutOne(kingSet);
-
- return attacks;
-}
-
-void initializeBitboardConstants() {
- std::mt19937_64 gen(0x6C7CCC580A348E7BULL);
- std::uniform_int_distribution dis(1ULL, UINT64_MAX);
- std::vector generatedZobristConstants(ZOBRIST_CONSTANT_SIZE);
-
- for (int pieceType = 0; pieceType < PIECE_TYPES; pieceType++) {
- for (int square = 0; square < SQUARES; square++) {
- uint64_t zobristConstant = dis(gen);
- zobristPieceConstants[pieceType][square] = zobristConstant;
-
- // if constant already generated, generate a new one
- if (std::ranges::find(generatedZobristConstants, zobristConstant) !=
- generatedZobristConstants.end()) {
- zobristConstant = dis(gen);
- }
-
- generatedZobristConstants.push_back(zobristConstant);
- }
- }
-
- zobristMovingColorConstant = dis(gen);
-
- for (int i = 0; i < 4; i++) {
- zobristCastleConstants[i] = dis(gen);
- }
-
- for (int i = 0; i < 8; i++) {
- zobristEnPassantConstants[i] = dis(gen);
- }
-
- uint64_t sqBB = 1ULL;
- for (int8_t sq = 0; sq < 64; sq++, sqBB <<= 1ULL) {
- kingAttacks[sq] = calculateKingAttacks(sqBB) & ~sqBB;
- }
-
- sqBB = 1ULL;
- for (int8_t sq = 0; sq < 64; sq++, sqBB <<= 1ULL) {
- knightAttacks[sq] = calculateKnightAttacks(sqBB) & ~sqBB;
- }
-
- sqBB = 1ULL;
- for (int8_t sq = 0; sq < 64; sq++, sqBB <<= 1ULL) {
- pawnAttacks[WHITE][sq] = calculatePawnAttacks(sqBB) & ~sqBB;
- pawnAttacks[BLACK][sq] = calculatePawnAttacks(sqBB) & ~sqBB;
- }
-
- initializeBetweenLookup();
- initializeRayAttacks();
-}
-
-void initializeBetweenLookup() {
- for (int from = 0; from < 64; from++) {
- for (int to = 0; to < 64; to++) {
- uint64_t m1 = -1ULL;
- uint64_t a2a7 = 0x0001010101010100ULL;
- uint64_t b2g7 = 0x0040201008040200ULL;
- uint64_t h1b7 = 0x0002040810204080ULL;
- uint64_t btwn, line, rank, file;
-
- btwn = m1 << from ^ m1 << to;
- file = (to & 7) - (from & 7);
- rank = ((to | 7) - from) >> 3;
- line = (file & 7) - 1 & a2a7; /* a2a7 if same file */
- line += 2 * (((rank & 7) - 1) >> 58); /* b1g1 if same rank */
- line += (rank - file & 15) - 1 & b2g7; /* b2g7 if same diagonal */
- line += (rank + file & 15) - 1 & h1b7; /* h1b7 if same antidiag */
- line *= btwn & -btwn; /* mul acts like shift by smaller square */
-
- betweenTable[from][to] = line & btwn; /* return the bits on that line in-between */
- }
- }
-}
-
-void initializeRayAttacks() {
- uint64_t sqBB = 1ULL;
-
- for (int sq = 0; sq < 64; sq++, sqBB <<= 1ULL) {
- rayAttacks[NORTH][sq] = nortOccl(sqBB, ~0ULL) & ~sqBB;
- rayAttacks[SOUTH][sq] = soutOccl(sqBB, ~0ULL) & ~sqBB;
- rayAttacks[EAST][sq] = eastOccl(sqBB, ~0ULL) & ~sqBB;
- rayAttacks[WEST][sq] = westOccl(sqBB, ~0ULL) & ~sqBB;
- rayAttacks[NORTH_EAST][sq] = noEaOccl(sqBB, ~0ULL) & ~sqBB;
- rayAttacks[NORTH_WEST][sq] = noWeOccl(sqBB, ~0ULL) & ~sqBB;
- rayAttacks[SOUTH_EAST][sq] = soEaOccl(sqBB, ~0ULL) & ~sqBB;
- rayAttacks[SOUTH_WEST][sq] = soWeOccl(sqBB, ~0ULL) & ~sqBB;
- }
-}
-
-uint64_t getRayAttack(int8_t square, Direction direction) {
- return rayAttacks[direction][square];
-}
-
-uint64_t getKingAttacks(int8_t square) {
- return kingAttacks[square];
-}
-
-uint64_t getKnightAttacks(int8_t square) {
- return knightAttacks[square];
-}
-
-uint64_t getBetweenSquares(int8_t from, int8_t to) {
- return betweenTable[from][to];
-}
-
-uint64_t getPieceZobristConstant(PieceType pieceType, int8_t square) {
- return zobristPieceConstants[pieceType][square];
-}
-
-uint64_t getMovingColorZobristConstant() {
- return zobristMovingColorConstant;
-}
-
-uint64_t getCastleZobristConstant(uint8_t index) {
- return zobristCastleConstants[index];
-}
-
-uint64_t getEnPassantZobristConstant(uint8_t file) {
- return zobristEnPassantConstants[file];
-}
-
-template
-uint64_t calculatePawnAttacks(uint64_t bb) {
- return calculatePawnEastAttacks(bb) | calculatePawnWestAttacks(bb);
-}
-
-template uint64_t calculatePawnAttacks(uint64_t);
-template uint64_t calculatePawnAttacks(uint64_t);
-
-template
-uint64_t getPawnAttacks(int8_t square) {
- return pawnAttacks[color][square];
-}
-
-template uint64_t getPawnAttacks(int8_t square);
-template uint64_t getPawnAttacks(int8_t square);
-} // namespace Zagreus
\ No newline at end of file
diff --git a/src/bitwise.h b/src/bitwise.h
deleted file mode 100644
index 5858379b..00000000
--- a/src/bitwise.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- This file is part of Zagreus.
-
- Zagreus is a UCI chess engine
- Copyright (C) 2023 Danny Jelsma
-
- Zagreus is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Zagreus 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with Zagreus. If not, see .
- */
-
-#pragma once
-
-#include
-
-#include "types.h"
-
-namespace Zagreus {
-uint64_t soutOne(uint64_t b);
-
-uint64_t nortOne(uint64_t b);
-
-uint64_t eastOne(uint64_t b);
-
-uint64_t noEaOne(uint64_t b);
-
-uint64_t soEaOne(uint64_t b);
-
-uint64_t westOne(uint64_t b);
-
-uint64_t soWeOne(uint64_t b);
-
-uint64_t noWeOne(uint64_t b);
-
-uint64_t noNoEa(uint64_t b);
-
-uint64_t noEaEa(uint64_t b);
-
-uint64_t soEaEa(uint64_t b);
-
-uint64_t soSoEa(uint64_t b);
-
-uint64_t noNoWe(uint64_t b);
-
-uint64_t noWeWe(uint64_t b);
-
-uint64_t soWeWe(uint64_t b);
-
-uint64_t soSoWe(uint64_t b);
-
-uint64_t soutOccl(uint64_t pieceBB, uint64_t empty);
-
-uint64_t nortOccl(uint64_t pieceBB, uint64_t empty);
-
-uint64_t eastOccl(uint64_t pieceBB, uint64_t empty);
-
-uint64_t noEaOccl(uint64_t pieceBB, uint64_t empty);
-
-uint64_t soEaOccl(uint64_t pieceBB, uint64_t empty);
-
-uint64_t westOccl(uint64_t rooks, uint64_t empty);
-
-uint64_t soWeOccl(uint64_t bishops, uint64_t empty);
-
-uint64_t noWeOccl(uint64_t bishops, uint64_t empty);
-
-uint64_t nortFill(uint64_t gen);
-
-uint64_t soutFill(uint64_t gen);
-
-uint64_t whiteFrontSpans(uint64_t pawns);
-
-uint64_t whiteRearSpans(uint64_t pawns);
-
-uint64_t blackRearSpans(uint64_t pawns);
-
-uint64_t blackFrontSpans(uint64_t pawns);
-
-template
-uint64_t calculatePawnEastAttacks(uint64_t pawns);
-
-template
-uint64_t calculatePawnWestAttacks(uint64_t pawns);
-
-uint64_t calculateKnightAttacks(uint64_t knights);
-
-uint64_t calculateKingAttacks(uint64_t kingSet);
-
-void initializeBetweenLookup();
-
-void initializeRayAttacks();
-
-void initializeBitboardConstants();
-
-uint64_t getKingAttacks(int8_t square);
-
-uint64_t getKnightAttacks(int8_t square);
-
-uint64_t getRayAttack(int8_t square, Direction direction);
-
-uint64_t getBetweenSquares(int8_t from, int8_t to);
-
-uint64_t getPieceZobristConstant(PieceType pieceType, int8_t square);
-
-uint64_t getMovingColorZobristConstant();
-
-uint64_t getCastleZobristConstant(uint8_t index);
-
-uint64_t getEnPassantZobristConstant(uint8_t file);
-
-template
-uint64_t getPawnAttacks(int8_t square);
-
-template
-uint64_t calculatePawnAttacks(uint64_t bb);
-} // namespace Zagreus
\ No newline at end of file
diff --git a/src/constants.h b/src/constants.h
deleted file mode 100644
index 1f60974b..00000000
--- a/src/constants.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- This file is part of Zagreus.
-
- Zagreus is a UCI chess engine
- Copyright (C) 2023 Danny Jelsma
-
- Zagreus is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Zagreus 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with Zagreus. If not, see .
- */
-
-#pragma once
-
-#include
-
-static constexpr uint16_t MAX_PLY = 750;
-static constexpr uint8_t MAX_MOVES = 255;
-static constexpr int ZOBRIST_CONSTANT_SIZE = 781;
-
-static constexpr int ZOBRIST_WHITE_KINGSIDE_INDEX = 0;
-static constexpr int ZOBRIST_WHITE_QUEENSIDE_INDEX = 1;
-static constexpr int ZOBRIST_BLACK_KINGSIDE_INDEX = 2;
-static constexpr int ZOBRIST_BLACK_QUEENSIDE_INDEX = 3;
-
-static constexpr int MATE_SCORE = 20000;
-static constexpr int MAX_POSITIVE = 1000000;
-static constexpr int MAX_NEGATIVE = -1000000;
-static constexpr int DRAW_SCORE = 0;
-
-static constexpr uint64_t A_FILE = 0x0101010101010101ULL;
-static constexpr uint64_t B_FILE = 0x0202020202020202ULL;
-static constexpr uint64_t C_FILE = 0x0404040404040404ULL;
-static constexpr uint64_t D_FILE = 0x0808080808080808ULL;
-static constexpr uint64_t E_FILE = 0x1010101010101010ULL;
-static constexpr uint64_t F_FILE = 0x2020202020202020ULL;
-static constexpr uint64_t G_FILE = 0x4040404040404040ULL;
-static constexpr uint64_t H_FILE = 0x8080808080808080ULL;
-static constexpr uint64_t DE_FILE = 0x01818181818181818ULL;
-static constexpr uint64_t NOT_A_FILE = 0XFEFEFEFEFEFEFEFEULL;
-static constexpr uint64_t NOT_AB_FILE = 0XFCFCFCFCFCFCFCFCULL;
-static constexpr uint64_t NOT_GH_FILE = 0X3F3F3F3F3F3F3F3FULL;
-static constexpr uint64_t NOT_H_FILE = 0X7F7F7F7F7F7F7F7FULL;
-static constexpr uint64_t RANK_1 = 0xFFULL;
-static constexpr uint64_t RANK_2 = 0xFF00ULL;
-static constexpr uint64_t RANK_3 = 0xFF0000ULL;
-static constexpr uint64_t RANK_4 = 0xFF000000ULL;
-static constexpr uint64_t RANK_5 = 0xFF00000000ULL;
-static constexpr uint64_t RANK_6 = 0xFF0000000000ULL;
-static constexpr uint64_t RANK_7 = 0xFF000000000000ULL;
-static constexpr uint64_t RANK_8 = 0xFF00000000000000ULL;
-static constexpr uint64_t A1_H8_DIAG = 0x8040201008040201ULL;
-static constexpr uint64_t H1_A8_DIAG = 0x0102040810204080ULL;
-static constexpr uint64_t LIGHT_SQUARES = 0x55AA55AA55AA55AAULL;
-static constexpr uint64_t DARK_SQUARES = 0xAA55AA55AA55AA55ULL;
-static constexpr uint64_t CENTER_SQUARES = 0x0000001818000000ULL;
-static constexpr uint64_t EXTENDED_CENTER_SQUARES = 0x00003C3C3C3C0000ULL;
-static constexpr uint64_t PROMOTION_SQUARES = 0xFF000000000000FFULL;
-
-static constexpr uint64_t WHITE_KING_SIDE_BETWEEN = 0x60ULL;
-static constexpr uint64_t WHITE_QUEEN_SIDE_BETWEEN = 0xEULL;
-static constexpr uint64_t BLACK_KING_SIDE_BETWEEN = 0x6000000000000000ULL;
-static constexpr uint64_t BLACK_QUEEN_SIDE_BETWEEN = 0xE00000000000000ULL;
-
-static constexpr int NO_CAPTURE_SCORE = -1;
-
-static constexpr int COLORS = 2;
-static constexpr int PIECE_TYPES = 12;
-static constexpr int SQUARES = 64;
-
-static constexpr int MVVLVA_TABLE[12][12] = {
- {105, 105, 205, 205, 305, 305, 405, 405, 505, 505, 605, 605},
- {104, 104, 204, 204, 304, 304, 404, 404, 504, 504, 604, 604},
- {103, 103, 203, 203, 303, 303, 403, 403, 503, 503, 603, 603},
- {102, 102, 202, 202, 302, 302, 402, 402, 502, 502, 602, 602},
- {101, 101, 201, 201, 301, 301, 401, 401, 501, 501, 601, 601},
- {100, 100, 200, 200, 300, 300, 400, 400, 500, 500, 600, 600},
- {105, 105, 205, 205, 305, 305, 405, 405, 505, 505, 605, 605},
- {104, 104, 204, 204, 304, 304, 404, 404, 504, 504, 604, 604},
- {103, 103, 203, 203, 303, 303, 403, 403, 503, 503, 603, 603},
- {102, 102, 202, 202, 302, 302, 402, 402, 502, 502, 602, 602},
- {101, 101, 201, 201, 301, 301, 401, 401, 501, 501, 601, 601},
- {100, 100, 200, 200, 300, 300, 400, 400, 500, 500, 600, 600},
-};
\ No newline at end of file
diff --git a/src/engine.cpp b/src/engine.cpp
deleted file mode 100644
index 27fa93e1..00000000
--- a/src/engine.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- This file is part of Zagreus.
-
- Zagreus is a UCI chess engine
- Copyright (C) 2023 Danny Jelsma
-
- Zagreus is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Zagreus 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with Zagreus. If not, see .
- */
-
-#include "engine.h"
-
-#include
-
-#include "../senjo/ChessEngine.h"
-#include "../senjo/Output.h"
-#include "../senjo/GoParams.h"
-#include "../senjo/SearchStats.h"
-#include "bitboard.h"
-#include "movegen.h"
-#include "search.h"
-#include "tt.h"
-#include "types.h"
-#include "utils.h"
-
-namespace Zagreus {
-uint64_t ZagreusEngine::doPerft(Bitboard& perftBoard, PieceColor color, int16_t depth,
- int startingDepth) {
- uint64_t nodes = 0ULL;
-
- if (depth == 0) {
- return 1ULL;
- }
-
- MoveListPool* moveListPool = MoveListPool::getInstance();
- MoveList* moves = moveListPool->getMoveList();
-
- if (color == WHITE) {
- generateMoves(perftBoard, moves);
- } else if (color == BLACK) {
- generateMoves(perftBoard, moves);
- } else {
- moveListPool->releaseMoveList(moves);
- return 0;
- }
-
- for (int i = 0; i < moves->size; i++) {
- Move move = moves->moves[i];
-
- perftBoard.makeMove(move);
-
- if (color == WHITE) {
- if (perftBoard.isKingInCheck()) {
- perftBoard.unmakeMove(move);
- continue;
- }
- } else {
- if (perftBoard.isKingInCheck()) {
- perftBoard.unmakeMove(move);
- continue;
- }
- }
-
- uint64_t nodeAmount = doPerft(perftBoard, getOppositeColor(color), depth - 1,
- startingDepth);
- nodes += nodeAmount;
- perftBoard.unmakeMove(move);
-
- if (depth == startingDepth && nodeAmount > 0ULL) {
- std::string notation = getNotation(move.from) + getNotation(move.to);
- senjo::Output(senjo::Output::NoPrefix) << notation << ": " << nodeAmount;
- }
- }
-
- moveListPool->releaseMoveList(moves);
- return nodes;
-}
-
-std::string ZagreusEngine::getEngineName() { return "Zagreus"; }
-
-std::string majorVersion = ZAGREUS_VERSION_MAJOR;
-std::string minorVersion = ZAGREUS_VERSION_MINOR;
-
-std::string ZagreusEngine::getEngineVersion() {
- if (majorVersion != "dev") {
- return "v" + majorVersion + "." + minorVersion;
- }
- return majorVersion + "-" + minorVersion;
-}
-
-std::string ZagreusEngine::getAuthorName() { return "Danny Jelsma"; }
-
-std::string ZagreusEngine::getEmailAddress() { return ""; }
-
-std::string ZagreusEngine::getCountryName() { return "The Netherlands"; }
-
-std::list ZagreusEngine::getOptions() { return options; }
-
-senjo::EngineOption ZagreusEngine::getOption(const std::string& optionName) {
- for (senjo::EngineOption& option : options) {
- if (option.getName() == optionName) {
- return option;
- }
- }
-
- return senjo::EngineOption("Invalid Option");
-}
-
-bool ZagreusEngine::setEngineOption(const std::string& optionName, const std::string& optionValue) {
- for (senjo::EngineOption& option : options) {
- if (option.getName() == optionName) {
- option.setValue(optionValue);
-
- if (option.getName() == "Hash") {
- TranspositionTable::getTT()->setTableSize(option.getIntValue());
- }
-
- return true;
- }
- }
-
- return false;
-}
-
-void ZagreusEngine::initialize() {
- stoppingSearch = false;
- board = Bitboard{};
- TranspositionTable::getTT()->setTableSize(getOption("Hash").getIntValue());
- isEngineInitialized = true;
-}
-
-bool ZagreusEngine::isInitialized() { return isEngineInitialized; }
-
-bool ZagreusEngine::setPosition(const std::string& fen, std::string* remain) {
- stoppingSearch = false;
- board = {};
- return board.setFromFen(fen);
-}
-
-bool ZagreusEngine::makeMove(const std::string& move) {
- stoppingSearch = false;
- return board.makeStrMove(move);
-}
-
-std::string ZagreusEngine::getFEN() {
- // TODO: implement
- return "";
-}
-
-void ZagreusEngine::printBoard() { board.print(); }
-
-bool ZagreusEngine::whiteToMove() { return board.getMovingColor() == WHITE; }
-
-void ZagreusEngine::clearSearchData() {
-}
-
-void ZagreusEngine::ponderHit() {
-}
-
-bool ZagreusEngine::isRegistered() { return true; }
-
-void ZagreusEngine::registerLater() {
-}
-
-bool ZagreusEngine::doRegistration(const std::string& name, const std::string& code) {
- return true;
-}
-
-bool ZagreusEngine::isCopyProtected() { return false; }
-
-bool ZagreusEngine::copyIsOK() { return true; }
-
-void ZagreusEngine::setDebug(const bool flag) {
-}
-
-bool ZagreusEngine::isDebugOn() { return false; }
-
-bool ZagreusEngine::isSearching() {
- return searching;
-}
-
-void ZagreusEngine::stopSearching() { stoppingSearch = true; }
-
-bool ZagreusEngine::stopRequested() { return stoppingSearch; }
-
-void ZagreusEngine::waitForSearchFinish() {
- while (isSearching()) {
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- }
-}
-
-uint64_t ZagreusEngine::perft(const int16_t depth) {
- stoppingSearch = false;
- auto start = std::chrono::steady_clock::now();
- uint64_t nodes = doPerft(board, board.getMovingColor(), depth, depth);
- auto end = std::chrono::steady_clock::now();
- std::chrono::duration elapsedSeconds = end - start;
-
- senjo::Output(senjo::Output::InfoPrefix)
- << "Depth " << depth << " Nodes: " << nodes
- << ", Took: " << elapsedSeconds.count() << "s";
- return nodes;
-}
-
-std::string ZagreusEngine::go(senjo::GoParams& params, std::string* ponder) {
- stoppingSearch = false;
- searching = true;
- searchStats = {};
- Move bestMove;
-
- if (board.getMovingColor() == WHITE) {
- bestMove = getBestMove(params, *this, board, searchStats);
- } else {
- bestMove = getBestMove(params, *this, board, searchStats);
- }
-
- if (bestMove.promotionPiece != EMPTY) {
- std::string result = getNotation(bestMove.from) + getNotation(bestMove.to) +
- getCharacterForPieceType(bestMove.promotionPiece);
-
- std::transform(result.begin(), result.end(), result.begin(),
- [](unsigned char c) { return std::tolower(c); });
-
- searching = false;
- return result;
- }
-
- std::string result = getNotation(bestMove.from) + getNotation(bestMove.to);
-
- searching = false;
- searching = true;
- return getNotation(bestMove.from) + getNotation(bestMove.to);
-}
-
-senjo::SearchStats ZagreusEngine::getSearchStats() { return searchStats; }
-
-void ZagreusEngine::resetEngineStats() {
-}
-
-void ZagreusEngine::showEngineStats() {
-}
-
-bool ZagreusEngine::isTuning() const { return tuning; }
-
-void ZagreusEngine::setTuning(bool tuning) { ZagreusEngine::tuning = tuning; }
-} // namespace Zagreus
\ No newline at end of file
diff --git a/src/engine.h b/src/engine.h
deleted file mode 100644
index 2f573171..00000000
--- a/src/engine.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- This file is part of Zagreus.
-
- Zagreus is a UCI chess engine
- Copyright (C) 2023 Danny Jelsma
-
- Zagreus is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Zagreus 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with Zagreus. If not, see .
- */
-
-#pragma once
-
-#include
-
-#include "../senjo/ChessEngine.h"
-#include "bitboard.h"
-#include "types.h"
-
-namespace Zagreus {
-class ZagreusEngine : public senjo::ChessEngine {
-private:
- Bitboard board{};
- bool isEngineInitialized = false;
- senjo::SearchStats searchStats{};
- bool stoppingSearch = false;
- bool searching = false;
- bool tuning = false;
-
- std::list options{
- senjo::EngineOption("MoveOverhead", "50", senjo::EngineOption::OptionType::Spin, 0, 5000),
- senjo::EngineOption("Hash", "512", senjo::EngineOption::OptionType::Spin, 1, 33554432),
- senjo::EngineOption("Threads", "1", senjo::EngineOption::OptionType::Spin, 1, 1),
- senjo::EngineOption("SyzygyPath", "", senjo::EngineOption::OptionType::String),
- senjo::EngineOption("SyzygyProbeLimit", "0", senjo::EngineOption::OptionType::Spin, 0, 100),
- };
-
-public:
- // uint64_t doPerft(Zagreus::Bitboard &board, Zagreus::PieceColor color, int16_t depth, int
- // startingDepth);
-
- std::string getEngineName() override;
-
- std::string getEngineVersion() override;
-
- std::string getAuthorName() override;
-
- std::string getEmailAddress() override;
-
- std::string getCountryName() override;
-
- std::list getOptions() override;
-
- bool setEngineOption(const std::string& optionName, const std::string& optionValue) override;
-
- void initialize() override;
-
- bool isInitialized() override;
-
- bool setPosition(const std::string& fen, std::string* remain) override;
-
- bool makeMove(const std::string& move) override;
-
- std::string getFEN() override;
-
- void printBoard() override;
-
- bool whiteToMove() override;
-
- void clearSearchData() override;
-
- void ponderHit() override;
-
- bool isRegistered() override;
-
- void registerLater() override;
-
- bool doRegistration(const std::string& name, const std::string& code) override;
-
- bool isCopyProtected() override;
-
- bool copyIsOK() override;
-
- void setDebug(const bool flag) override;
-
- bool isDebugOn() override;
-
- bool isSearching() override;
-
- void stopSearching() override;
-
- bool stopRequested() override;
-
- void waitForSearchFinish() override;
-
- uint64_t perft(const int16_t depth) override;
-
- std::string go(senjo::GoParams& params, std::string* ponder) override;
-
- senjo::SearchStats getSearchStats() override;
-
- void resetEngineStats() override;
-
- void showEngineStats() override;
-
- senjo::EngineOption getOption(const std::string& optionName);
-
- uint64_t doPerft(Bitboard& perftBoard, PieceColor color, int16_t depth, int startingDepth);
-
- bool isTuning() const;
-
- void setTuning(bool tuning);
-};
-} // namespace Zagreus
\ No newline at end of file
diff --git a/src/evaluate.cpp b/src/evaluate.cpp
deleted file mode 100644
index b481c5cb..00000000
--- a/src/evaluate.cpp
+++ /dev/null
@@ -1,773 +0,0 @@
-/*
- This file is part of Zagreus.
-
- Zagreus is a UCI chess engine
- Copyright (C) 2023 Danny Jelsma
-
- Zagreus is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Zagreus 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with Zagreus. If not, see .
- */
-
-#include "evaluate.h"
-
-#include
-
-#include "features.h"
-
-namespace Zagreus {
-void Evaluation::initEvalContext(Bitboard& bitboard) {
- uint64_t whitePawns = bitboard.getPieceBoard(WHITE_PAWN);
- while (whitePawns) {
- uint8_t square = popLsb(whitePawns);
- uint64_t attacks = getPawnAttacks(square);
-
- attacksByPiece[WHITE_PAWN] |= attacks;
- attackedBy2[WHITE] |= (attacks & attacksByColor[WHITE]);
- attacksByColor[WHITE] |= attacks;
- attacksFrom[square] |= attacks;
- }
-
- uint64_t whiteKnights = bitboard.getPieceBoard(WHITE_KNIGHT);
- while (whiteKnights) {
- uint8_t square = popLsb(whiteKnights);
- uint64_t attacks = getKnightAttacks(square);
-
- attacksByPiece[WHITE_KNIGHT] |= attacks;
- attackedBy2[WHITE] |= (attacks & attacksByColor[WHITE]);
- attacksByColor[WHITE] |= attacks;
- attacksFrom[square] |= attacks;
- }
-
- uint64_t whiteBishops = bitboard.getPieceBoard(WHITE_BISHOP);
- while (whiteBishops) {
- uint8_t square = popLsb(whiteBishops);
- uint64_t attacks = bitboard.getBishopAttacks(square);
-
- attacksByPiece[WHITE_BISHOP] |= attacks;
- attackedBy2[WHITE] |= (attacks & attacksByColor[WHITE]);
- attacksByColor[WHITE] |= attacks;
- attacksFrom[square] |= attacks;
- }
-
- uint64_t whiteRooks = bitboard.getPieceBoard(WHITE_ROOK);
- while (whiteRooks) {
- uint8_t square = popLsb(whiteRooks);
- uint64_t attacks = bitboard.getRookAttacks(square);
-
- attacksByPiece[WHITE_ROOK] |= attacks;
- attackedBy2[WHITE] |= (attacks & attacksByColor[WHITE]);
- attacksByColor[WHITE] |= attacks;
- attacksFrom[square] |= attacks;
- }
-
- uint64_t whiteQueens = bitboard.getPieceBoard(WHITE_QUEEN);
- while (whiteQueens) {
- uint8_t square = popLsb(whiteQueens);
- uint64_t attacks = bitboard.getQueenAttacks(square);
-
- attacksByPiece[WHITE_QUEEN] |= attacks;
- attackedBy2[WHITE] |= (attacks & attacksByColor[WHITE]);
- attacksByColor[WHITE] |= attacks;
- attacksFrom[square] |= attacks;
- }
-
- {
- uint64_t whiteKing = bitboard.getPieceBoard(WHITE_KING);
- uint8_t square = popLsb(whiteKing);
- uint64_t attacks = getKingAttacks(square);
-
- attacksByPiece[WHITE_KING] |= attacks;
- attacksByColor[WHITE] |= attacks;
- attacksFrom[square] |= attacks;
- }
-
- uint64_t blackPawns = bitboard.getPieceBoard(BLACK_PAWN);
- while (blackPawns) {
- uint8_t square = popLsb(blackPawns);
- uint64_t attacks = getPawnAttacks(square);
-
- attacksByPiece[BLACK_PAWN] |= attacks;
- attackedBy2[BLACK] |= (attacks & attacksByColor[BLACK]);
- attacksByColor[BLACK] |= attacks;
- attacksFrom[square] |= attacks;
- }
-
- uint64_t blackKnights = bitboard.getPieceBoard(BLACK_KNIGHT);
- while (blackKnights) {
- uint8_t square = popLsb(blackKnights);
- uint64_t attacks = getKnightAttacks(square);
-
- attacksByPiece[BLACK_KNIGHT] |= attacks;
- attackedBy2[BLACK] |= (attacks & attacksByColor[BLACK]);
- attacksByColor[BLACK] |= attacks;
- attacksFrom[square] |= attacks;
- }
-
- uint64_t blackBishops = bitboard.getPieceBoard(BLACK_BISHOP);
- while (blackBishops) {
- uint8_t square = popLsb(blackBishops);
- uint64_t attacks = bitboard.getBishopAttacks(square);
-
- attacksByPiece[BLACK_BISHOP] |= attacks;
- attackedBy2[BLACK] |= (attacks & attacksByColor[BLACK]);
- attacksByColor[BLACK] |= attacks;
- attacksFrom[square] |= attacks;
- }
-
- uint64_t blackRooks = bitboard.getPieceBoard(BLACK_ROOK);
- while (blackRooks) {
- uint8_t square = popLsb(blackRooks);
- uint64_t attacks = bitboard.getRookAttacks(square);
-
- attacksByPiece[BLACK_ROOK] |= attacks;
- attackedBy2[BLACK] |= (attacks & attacksByColor[BLACK]);
- attacksByColor[BLACK] |= attacks;
- attacksFrom[square] |= attacks;
- }
-
- uint64_t blackQueens = bitboard.getPieceBoard(BLACK_QUEEN);
- while (blackQueens) {
- uint8_t square = popLsb(blackQueens);
- uint64_t attacks = bitboard.getQueenAttacks(square);
-
- attacksByPiece[BLACK_QUEEN] |= attacks;
- attackedBy2[BLACK] |= (attacks & attacksByColor[BLACK]);
- attacksByColor[BLACK] |= attacks;
- attacksFrom[square] |= attacks;
- }
-
- {
- uint64_t blackKing = bitboard.getPieceBoard(BLACK_KING);
- uint8_t square = popLsb(blackKing);
- uint64_t attacks = getKingAttacks(square);
-
- attacksByPiece[BLACK_KING] |= attacks;
- attacksByColor[BLACK] |= attacks;
- attacksFrom[square] |= attacks;
- }
-}
-
-constexpr int knightPhase = 1;
-constexpr int bishopPhase = 1;
-constexpr int rookPhase = 2;
-constexpr int queenPhase = 4;
-constexpr int totalPhase = knightPhase * 4 + bishopPhase * 4 + rookPhase * 4 + queenPhase * 2;
-
-int Evaluation::getPhase() {
- int phase = totalPhase;
-
- phase -= (bitboard.getMaterialCount() + bitboard.getMaterialCount())
- * knightPhase;
- phase -= (bitboard.getMaterialCount() + bitboard.getMaterialCount())
- * bishopPhase;
- phase -= (bitboard.getMaterialCount() + bitboard.getMaterialCount()) *
- rookPhase;
- phase -= (bitboard.getMaterialCount() + bitboard.getMaterialCount()) *
- queenPhase;
-
- return (phase * 256 + (totalPhase / 2)) / totalPhase;
-}
-
-void Evaluation::addMobilityScoreForPiece(PieceType pieceType, int mobility) {
- switch (pieceType) {
- case WHITE_KNIGHT:
- whiteMidgameScore += mobility * getEvalValue(MIDGAME_KNIGHT_MOBILITY);
- whiteEndgameScore += mobility * getEvalValue(ENDGAME_KNIGHT_MOBILITY);
- break;
- case BLACK_KNIGHT:
- blackMidgameScore += mobility * getEvalValue(MIDGAME_KNIGHT_MOBILITY);
- blackEndgameScore += mobility * getEvalValue(ENDGAME_KNIGHT_MOBILITY);
- break;
- case WHITE_BISHOP:
- whiteMidgameScore += mobility * getEvalValue(MIDGAME_BISHOP_MOBILITY);
- whiteEndgameScore += mobility * getEvalValue(ENDGAME_BISHOP_MOBILITY);
- break;
- case BLACK_BISHOP:
- blackMidgameScore += mobility * getEvalValue(MIDGAME_BISHOP_MOBILITY);
- blackEndgameScore += mobility * getEvalValue(ENDGAME_BISHOP_MOBILITY);
- break;
- case WHITE_ROOK:
- whiteMidgameScore += mobility * getEvalValue(MIDGAME_ROOK_MOBILITY);
- whiteEndgameScore += mobility * getEvalValue(ENDGAME_ROOK_MOBILITY);
- break;
- case BLACK_ROOK:
- blackMidgameScore += mobility * getEvalValue(MIDGAME_ROOK_MOBILITY);
- blackEndgameScore += mobility * getEvalValue(ENDGAME_ROOK_MOBILITY);
- break;
- case WHITE_QUEEN:
- whiteMidgameScore += mobility * getEvalValue(MIDGAME_QUEEN_MOBILITY);
- whiteEndgameScore += mobility * getEvalValue(ENDGAME_QUEEN_MOBILITY);
- break;
- case BLACK_QUEEN:
- blackMidgameScore += mobility * getEvalValue(MIDGAME_QUEEN_MOBILITY);
- blackEndgameScore += mobility * getEvalValue(ENDGAME_QUEEN_MOBILITY);
- break;
- }
-}
-
-void Evaluation::addKingAttackScore(PieceType pieceType, int attackCount) {
- switch (pieceType) {
- case WHITE_PAWN:
- blackMidgameScore += attackCount * getEvalValue(MIDGAME_KING_ATTACK_PAWN_PENALTY);
- blackEndgameScore += attackCount * getEvalValue(ENDGAME_KING_ATTACK_PAWN_PENALTY);
- break;
- case BLACK_PAWN:
- whiteMidgameScore += attackCount * getEvalValue(MIDGAME_KING_ATTACK_PAWN_PENALTY);
- whiteEndgameScore += attackCount * getEvalValue(ENDGAME_KING_ATTACK_PAWN_PENALTY);
- break;
- case WHITE_KNIGHT:
- blackMidgameScore += attackCount * getEvalValue(MIDGAME_KING_ATTACK_KNIGHT_PENALTY);
- blackEndgameScore += attackCount * getEvalValue(ENDGAME_KING_ATTACK_KNIGHT_PENALTY);
- break;
- case BLACK_KNIGHT:
- whiteMidgameScore += attackCount * getEvalValue(MIDGAME_KING_ATTACK_KNIGHT_PENALTY);
- whiteEndgameScore += attackCount * getEvalValue(ENDGAME_KING_ATTACK_KNIGHT_PENALTY);
- break;
- case WHITE_BISHOP:
- blackMidgameScore += attackCount * getEvalValue(MIDGAME_KING_ATTACK_BISHOP_PENALTY);
- blackEndgameScore += attackCount * getEvalValue(ENDGAME_KING_ATTACK_BISHOP_PENALTY);
- break;
- case BLACK_BISHOP:
- whiteMidgameScore += attackCount * getEvalValue(MIDGAME_KING_ATTACK_BISHOP_PENALTY);
- whiteEndgameScore += attackCount * getEvalValue(ENDGAME_KING_ATTACK_BISHOP_PENALTY);
- break;
- case WHITE_ROOK:
- blackMidgameScore += attackCount * getEvalValue(MIDGAME_KING_ATTACK_ROOK_PENALTY);
- blackEndgameScore += attackCount * getEvalValue(ENDGAME_KING_ATTACK_ROOK_PENALTY);
- break;
- case BLACK_ROOK:
- whiteMidgameScore += attackCount * getEvalValue(MIDGAME_KING_ATTACK_ROOK_PENALTY);
- whiteEndgameScore += attackCount * getEvalValue(ENDGAME_KING_ATTACK_ROOK_PENALTY);
- break;
- case WHITE_QUEEN:
- blackMidgameScore += attackCount * getEvalValue(MIDGAME_KING_ATTACK_QUEEN_PENALTY);
- blackEndgameScore += attackCount * getEvalValue(ENDGAME_KING_ATTACK_QUEEN_PENALTY);
- break;
- case BLACK_QUEEN:
- whiteMidgameScore += attackCount * getEvalValue(MIDGAME_KING_ATTACK_QUEEN_PENALTY);
- whiteEndgameScore += attackCount * getEvalValue(ENDGAME_KING_ATTACK_QUEEN_PENALTY);
- break;
- }
-}
-
-template
-void Evaluation::evaluatePieces() {
- uint64_t colorBoard = bitboard.getColorBoard();
- int8_t blackKingSquare = bitscanForward(bitboard.getPieceBoard(BLACK_KING));
- int8_t whiteKingSquare = bitscanForward(bitboard.getPieceBoard(WHITE_KING));
- uint64_t blackKingAttacks = attacksFrom[blackKingSquare];
- uint64_t whiteKingAttacks = attacksFrom[whiteKingSquare];
-
- while (colorBoard) {
- uint8_t index = popLsb(colorBoard);
- PieceType pieceType = bitboard.getPieceOnSquare(index);
-
- // Mobility
- if (isNotPawnOrKing(pieceType)) {
- uint64_t mobilitySquares = attacksFrom[index];
-
- if (color == WHITE) {
- uint64_t weakSquares = attackedBy2[BLACK] & ~attackedBy2[WHITE];
-
- // Exclude own pieces and attacks by opponent pawns
- mobilitySquares &= ~(bitboard.getColorBoard() | attacksByPiece[BLACK_PAWN]);
-
- // If pieceType == queen, exclude tiles attacked by opponent bishop, knight and rook
- if (pieceType == WHITE_QUEEN) {
- mobilitySquares &= ~(
- attacksByPiece[BLACK_BISHOP] | attacksByPiece[BLACK_KNIGHT] |
- attacksByPiece[BLACK_ROOK]);
- }
-
- // If pieceType == rook, exclude tiles attacked by opponent bishop and knight
- if (pieceType == WHITE_ROOK) {
- mobilitySquares &= ~(
- attacksByPiece[BLACK_BISHOP] | attacksByPiece[BLACK_KNIGHT]);
- }
-
- mobilitySquares &= ~weakSquares;
- } else {
- uint64_t weakSquares = attackedBy2[WHITE] & ~attackedBy2[BLACK];
-
- // Exclude own pieces and attacks by opponent pawns
- mobilitySquares &= ~(bitboard.getColorBoard() | attacksByPiece[WHITE_PAWN]);
-
- // If pieceType == queen, exclude tiles attacked by opponent bishop, knight and rook
- if (pieceType == BLACK_QUEEN) {
- mobilitySquares &= ~(
- attacksByPiece[WHITE_BISHOP] | attacksByPiece[WHITE_KNIGHT] |
- attacksByPiece[WHITE_ROOK]);
- }
-
- // If pieceType == rook, exclude tiles attacked by opponent bishop and knight
- if (pieceType == BLACK_ROOK) {
- mobilitySquares &= ~(
- attacksByPiece[WHITE_BISHOP] | attacksByPiece[WHITE_KNIGHT]);
- }
-
- mobilitySquares &= ~weakSquares;
- }
-
- uint8_t mobility = popcnt(mobilitySquares);
- addMobilityScoreForPiece(pieceType, mobility);
- }
-
- // King safety - Attacks around king
- if (!isKing(pieceType)) {
- uint64_t attackSquares = attacksFrom[index];
- uint64_t opponentKingAttacks = color == WHITE ? blackKingAttacks : whiteKingAttacks;
- uint64_t attacksAroundKing = attackSquares & opponentKingAttacks;
- uint8_t attackCount = popcnt(attacksAroundKing);
-
- addKingAttackScore(pieceType, attackCount);
- }
-
- // Other King safety
- if (isKing(pieceType)) {
- if (color == WHITE) {
- // Pawn Shield
- uint64_t kingBB = bitboard.getPieceBoard(WHITE_KING);
- uint64_t pawnBB = bitboard.getPieceBoard(WHITE_PAWN);
- uint64_t pawnShieldMask = nortOne(kingBB) | noEaOne(kingBB) | noWeOne(kingBB);
- pawnShieldMask |= nortOne(pawnShieldMask);
- uint64_t pawnShield = pawnBB & pawnShieldMask;
- uint8_t pawnShieldCount = std::min(popcnt(pawnShield), 3ULL);
-
- whiteMidgameScore += getEvalValue(MIDGAME_PAWN_SHIELD) * pawnShieldCount;
- whiteEndgameScore += getEvalValue(ENDGAME_PAWN_SHIELD) * pawnShieldCount;
-
- // Virtual mobility - Get queen attacks from king position, with only occupied squares by
- // own pieces. We also ignore the squares around the king.
- uint64_t virtualMobilitySquares =
- bitboard.getQueenAttacks(index, bitboard.getColorBoard()) &
- ~(attacksFrom[index] | bitboard.getColorBoard());
- whiteMidgameScore +=
- popcnt(virtualMobilitySquares) * getEvalValue(
- MIDGAME_KING_VIRTUAL_MOBILITY_PENALTY);
- whiteEndgameScore +=
- popcnt(virtualMobilitySquares) * getEvalValue(
- ENDGAME_KING_VIRTUAL_MOBILITY_PENALTY);
- } else {
- // Pawn Shield
- uint64_t kingBB = bitboard.getPieceBoard(BLACK_KING);
- uint64_t pawnBB = bitboard.getPieceBoard(BLACK_PAWN);
- uint64_t pawnShieldMask = soutOne(kingBB) | soEaOne(kingBB) | soWeOne(kingBB);
- pawnShieldMask |= soutOne(pawnShieldMask);
- uint64_t pawnShield = pawnBB & pawnShieldMask;
- uint8_t pawnShieldCount = std::min(popcnt(pawnShield), 3ULL);
-
- blackMidgameScore += getEvalValue(MIDGAME_PAWN_SHIELD) * pawnShieldCount;
- blackEndgameScore += getEvalValue(ENDGAME_PAWN_SHIELD) * pawnShieldCount;
-
- // Virtual mobility - Get queen attacks from king position, with only occupied squares by
- // own pieces. We also ignore the squares around the king.
- uint64_t virtualMobilitySquares =
- bitboard.getQueenAttacks(index, bitboard.getColorBoard()) &
- ~(attacksFrom[index] | bitboard.getColorBoard());
- blackMidgameScore +=
- popcnt(virtualMobilitySquares) * getEvalValue(
- MIDGAME_KING_VIRTUAL_MOBILITY_PENALTY);
- blackEndgameScore +=
- popcnt(virtualMobilitySquares) * getEvalValue(
- ENDGAME_KING_VIRTUAL_MOBILITY_PENALTY);
- }
- }
-
- // Per piece evaluation
- if (isPawn(pieceType)) {
- // Doubled pawn
- uint64_t pawnBB = bitboard.getPieceBoard(pieceType);
- Direction direction = color == WHITE ? NORTH : SOUTH;
- Direction oppositeDirection = color == WHITE ? SOUTH : NORTH;
- uint64_t frontMask = getRayAttack(index, direction);
- uint64_t behindMask = getRayAttack(index, oppositeDirection);
- uint64_t doubledPawns = pawnBB & frontMask;
-
- if (doubledPawns) {
- if (color == WHITE) {
- whiteMidgameScore += getEvalValue(MIDGAME_DOUBLED_PAWN_PENALTY);
- whiteEndgameScore += getEvalValue(ENDGAME_DOUBLED_PAWN_PENALTY);
- } else {
- blackMidgameScore += getEvalValue(MIDGAME_DOUBLED_PAWN_PENALTY);
- blackEndgameScore += getEvalValue(ENDGAME_DOUBLED_PAWN_PENALTY);
- }
- }
-
- // Passed pawn
- if (bitboard.isPassedPawn(index)) {
- if (color == WHITE) {
- whiteMidgameScore += getEvalValue(MIDGAME_PASSED_PAWN);
- whiteEndgameScore += getEvalValue(ENDGAME_PASSED_PAWN);
- } else {
- blackMidgameScore += getEvalValue(MIDGAME_PASSED_PAWN);
- blackEndgameScore += getEvalValue(ENDGAME_PASSED_PAWN);
- }
-
- // Tarrasch rule
- if (color == WHITE) {
- // Rook in front of own passed pawn penalty
- if (frontMask & bitboard.getPieceBoard(WHITE_ROOK)) {
- whiteMidgameScore += getEvalValue(MIDGAME_TARRASCH_OWN_ROOK_PENALTY);
- whiteEndgameScore += getEvalValue(ENDGAME_TARRASCH_OWN_ROOK_PENALTY);
- }
-
- // Rook behind own passed pawn bonus
- if (behindMask & bitboard.getPieceBoard(WHITE_ROOK)) {
- whiteMidgameScore += getEvalValue(MIDGAME_TARRASCH_OWN_ROOK_DEFEND);
- whiteEndgameScore += getEvalValue(ENDGAME_TARRASCH_OWN_ROOK_DEFEND);
- }
-
- // Opponent rook behind own passed pawn penalty
- if (behindMask & bitboard.getPieceBoard(BLACK_ROOK)) {
- whiteMidgameScore += getEvalValue(MIDGAME_TARRASCH_OPPONENT_ROOK_PENALTY);
- whiteEndgameScore += getEvalValue(ENDGAME_TARRASCH_OPPONENT_ROOK_PENALTY);
- }
- } else {
- // Rook in front of own passed pawn penalty
- if (frontMask & bitboard.getPieceBoard(BLACK_ROOK)) {
- blackMidgameScore += getEvalValue(MIDGAME_TARRASCH_OWN_ROOK_PENALTY);
- blackEndgameScore += getEvalValue(ENDGAME_TARRASCH_OWN_ROOK_PENALTY);
- }
-
- // Rook behind own passed pawn bonus
- if (behindMask & bitboard.getPieceBoard(BLACK_ROOK)) {
- blackMidgameScore += getEvalValue(MIDGAME_TARRASCH_OWN_ROOK_DEFEND);
- blackEndgameScore += getEvalValue(ENDGAME_TARRASCH_OWN_ROOK_DEFEND);
- }
-
- // Opponent rook behind own passed pawn penalty
- if (behindMask & bitboard.getPieceBoard(WHITE_ROOK)) {
- blackMidgameScore += getEvalValue(MIDGAME_TARRASCH_OPPONENT_ROOK_PENALTY);
- blackEndgameScore += getEvalValue(ENDGAME_TARRASCH_OPPONENT_ROOK_PENALTY);
- }
- }
- }
-
- // Isolated pawn
- if (bitboard.isIsolatedPawn(index)) {
- if (color == WHITE) {
- whiteMidgameScore += getEvalValue(MIDGAME_ISOLATED_PAWN_PENALTY);
- whiteEndgameScore += getEvalValue(ENDGAME_ISOLATED_PAWN_PENALTY);
- } else {
- blackMidgameScore += getEvalValue(MIDGAME_ISOLATED_PAWN_PENALTY);
- blackEndgameScore += getEvalValue(ENDGAME_ISOLATED_PAWN_PENALTY);
- }
-
- if (bitboard.isSemiOpenFile(index)) {
- if (color == WHITE) {
- whiteMidgameScore += getEvalValue(MIDGAME_ISOLATED_SEMI_OPEN_PAWN_PENALTY);
- whiteEndgameScore += getEvalValue(ENDGAME_ISOLATED_SEMI_OPEN_PAWN_PENALTY);
- } else {
- blackMidgameScore += getEvalValue(MIDGAME_ISOLATED_SEMI_OPEN_PAWN_PENALTY);
- blackEndgameScore += getEvalValue(ENDGAME_ISOLATED_SEMI_OPEN_PAWN_PENALTY);
- }
- }
-
- if ((1ULL << index) & DE_FILE) {
- if (color == WHITE) {
- whiteMidgameScore += getEvalValue(MIDGAME_ISOLATED_CENTRAL_PAWN_PENALTY);
- whiteEndgameScore += getEvalValue(ENDGAME_ISOLATED_CENTRAL_PAWN_PENALTY);
- } else {
- blackMidgameScore += getEvalValue(MIDGAME_ISOLATED_CENTRAL_PAWN_PENALTY);
- blackEndgameScore += getEvalValue(ENDGAME_ISOLATED_CENTRAL_PAWN_PENALTY);
- }
- }
- }
- }
-
- // Knight eval
- if (isKnight(pieceType)) {
- // Penalize the knight's value for each missing pawn
- uint64_t pawnBB = bitboard.getPieceBoard(color == WHITE ? WHITE_PAWN : BLACK_PAWN);
- uint8_t pawnCount = popcnt(pawnBB);
-
- if (color == WHITE) {
- whiteMidgameScore += getEvalValue(MIDGAME_KNIGHT_MISSING_PAWN_PENALTY) * (
- 8 - pawnCount);
- whiteEndgameScore += getEvalValue(ENDGAME_KNIGHT_MISSING_PAWN_PENALTY) * (
- 8 - pawnCount);
- } else {
- blackMidgameScore += getEvalValue(MIDGAME_KNIGHT_MISSING_PAWN_PENALTY) * (
- 8 - pawnCount);
- blackEndgameScore += getEvalValue(ENDGAME_KNIGHT_MISSING_PAWN_PENALTY) * (
- 8 - pawnCount);
- }
-
- // Slight bonus for knights defended by a pawn
- uint64_t pawnAttacks = attacksByPiece[color == WHITE ? WHITE_PAWN : BLACK_PAWN];
-
- if ((1ULL << index) & pawnAttacks) {
- if (color == WHITE) {
- whiteMidgameScore += getEvalValue(MIDGAME_KNIGHT_DEFENDED_BY_PAWN);
- whiteEndgameScore += getEvalValue(ENDGAME_KNIGHT_DEFENDED_BY_PAWN);
- } else {
- blackMidgameScore += getEvalValue(MIDGAME_KNIGHT_DEFENDED_BY_PAWN);
- blackEndgameScore += getEvalValue(ENDGAME_KNIGHT_DEFENDED_BY_PAWN);
- }
- }
- }
-
- // Bishop eval
- if (isBishop(pieceType)) {
- // Bad bishop
- uint64_t bishopAttacks = attacksFrom[index];
- uint64_t pawnBB = bitboard.getPieceBoard(color == WHITE ? WHITE_PAWN : BLACK_PAWN);
- uint64_t forwardMobility;
-
- if (color == WHITE) {
- forwardMobility = getRayAttack(index, NORTH_WEST) | getRayAttack(index, NORTH_EAST);
- } else {
- forwardMobility = getRayAttack(index, SOUTH_WEST) | getRayAttack(index, SOUTH_EAST);
- }
-
- bishopAttacks &= forwardMobility;
-
- // If one of our own pawns is on the same diagonal as the bishop and the bishop has <= 3
- // squares of mobility, it's a bad bishop
- if (bishopAttacks & pawnBB) {
- uint64_t bishopAttacksWithoutPawns = bishopAttacks & ~pawnBB;
- uint64_t attackCount = popcnt(bishopAttacksWithoutPawns);
-
- if (attackCount <= 3) {
- if (color == WHITE) {
- whiteMidgameScore += getEvalValue(MIDGAME_BAD_BISHOP_PENALTY);
- whiteEndgameScore += getEvalValue(ENDGAME_BAD_BISHOP_PENALTY);
- } else {
- blackMidgameScore += getEvalValue(MIDGAME_BAD_BISHOP_PENALTY);
- blackEndgameScore += getEvalValue(ENDGAME_BAD_BISHOP_PENALTY);
- }
- }
- }
-
- // Only one bishop (no bishop pair)
- if (color == WHITE) {
- if (bitboard.getMaterialCount() == 1) {
- whiteMidgameScore += getEvalValue(MIDGAME_MISSING_BISHOP_PAIR_PENALTY);
- whiteEndgameScore += getEvalValue(ENDGAME_MISSING_BISHOP_PAIR_PENALTY);
- }
- } else {
- if (bitboard.getMaterialCount() == 1) {
- blackMidgameScore += getEvalValue(MIDGAME_MISSING_BISHOP_PAIR_PENALTY);
- blackEndgameScore += getEvalValue(ENDGAME_MISSING_BISHOP_PAIR_PENALTY);
- }
- }
-
- // Fianchetto
- if (color == WHITE) {
- if (index == G2 || index == B2) {
- uint64_t fianchettoPattern =
- nortOne(1ULL << index) | westOne(1ULL << index) | eastOne(1ULL << index);
- uint64_t antiPattern = noWeOne(1ULL << index) | noEaOne(1ULL << index);
-
- if (popcnt(pawnBB & fianchettoPattern) == 3 && !(pawnBB & antiPattern)) {
- whiteMidgameScore += getEvalValue(MIDGAME_BISHOP_FIANCHETTO);
- whiteEndgameScore += getEvalValue(ENDGAME_BISHOP_FIANCHETTO);
- }
- }
- } else {
- if (index == G7 || index == B7) {
- uint64_t fianchettoPattern =
- soutOne(1ULL << index) | westOne(1ULL << index) | eastOne(1ULL << index);
- uint64_t antiPattern = soWeOne(1ULL << index) | soEaOne(1ULL << index);
-
- if (popcnt(pawnBB & fianchettoPattern) == 3 && !(pawnBB & antiPattern)) {
- blackMidgameScore += getEvalValue(MIDGAME_BISHOP_FIANCHETTO);
- blackEndgameScore += getEvalValue(ENDGAME_BISHOP_FIANCHETTO);
- }
- }
- }
- }
-
- // Rook eval
- if (isRook(pieceType)) {
- // Increase in value as pawns disappear
- uint64_t pawnBB = bitboard.getPieceBoard(color == WHITE ? WHITE_PAWN : BLACK_PAWN);
- uint8_t pawnCount = popcnt(pawnBB);
-
- if (color == WHITE) {
- whiteMidgameScore += getEvalValue(MIDGAME_ROOK_PAWN_COUNT) * (8 - pawnCount);
- whiteEndgameScore += getEvalValue(ENDGAME_ROOK_PAWN_COUNT) * (8 - pawnCount);
- } else {
- blackMidgameScore += getEvalValue(MIDGAME_ROOK_PAWN_COUNT) * (8 - pawnCount);
- blackEndgameScore += getEvalValue(ENDGAME_ROOK_PAWN_COUNT) * (8 - pawnCount);
- }
-
- // Rook on open file
- if (bitboard.isOpenFile(index)) {
- if (color == WHITE) {
- whiteMidgameScore += getEvalValue(MIDGAME_ROOK_ON_OPEN_FILE);
- whiteEndgameScore += getEvalValue(ENDGAME_ROOK_ON_OPEN_FILE);
- } else {
- blackMidgameScore += getEvalValue(MIDGAME_ROOK_ON_OPEN_FILE);
- blackEndgameScore += getEvalValue(ENDGAME_ROOK_ON_OPEN_FILE);
- }
- } else if (bitboard.isSemiOpenFile(index)) {
- if (color == WHITE) {
- whiteMidgameScore += getEvalValue(MIDGAME_ROOK_ON_SEMI_OPEN_FILE);
- whiteEndgameScore += getEvalValue(ENDGAME_ROOK_ON_SEMI_OPEN_FILE);
- } else {
- blackMidgameScore += getEvalValue(MIDGAME_ROOK_ON_SEMI_OPEN_FILE);
- blackEndgameScore += getEvalValue(ENDGAME_ROOK_ON_SEMI_OPEN_FILE);
- }
- }
-
- // Rook on 7th or 8th rank (or 2nd or 1st rank for black)
- if (color == WHITE) {
- if ((1ULL << index) & (RANK_8 | RANK_7)) {
- whiteMidgameScore += getEvalValue(MIDGAME_ROOK_ON_7TH_RANK);
- whiteEndgameScore += getEvalValue(ENDGAME_ROOK_ON_7TH_RANK);
- }
- } else {
- if ((1ULL << index) & (RANK_1 | RANK_2)) {
- blackMidgameScore += getEvalValue(MIDGAME_ROOK_ON_7TH_RANK);
- blackEndgameScore += getEvalValue(ENDGAME_ROOK_ON_7TH_RANK);
- }
- }
-
- uint64_t file = bitboard.getFile(index);
- uint64_t opponentQueens = bitboard.getPieceBoard(
- color == WHITE ? BLACK_QUEEN : WHITE_QUEEN);
-
- // Bonus for rook with enemy queen on same file
- if (file & opponentQueens) {
- if (color == WHITE) {
- whiteMidgameScore += getEvalValue(MIDGAME_ROOK_ON_QUEEN_FILE);
- whiteEndgameScore += getEvalValue(ENDGAME_ROOK_ON_QUEEN_FILE);
- } else {
- blackMidgameScore += getEvalValue(MIDGAME_ROOK_ON_QUEEN_FILE);
- blackEndgameScore += getEvalValue(ENDGAME_ROOK_ON_QUEEN_FILE);
- }
- }
- }
-
- // Undefended minor pieces
- if (isKnight(pieceType) || isBishop(pieceType)) {
- if (!((1ULL << index) & attacksByColor[color])) {
- // Penalize a minor piece for not being defended
- if (color == WHITE) {
- whiteMidgameScore += getEvalValue(MIDGAME_MINOR_PIECE_NOT_DEFENDED_PENALTY);
- whiteEndgameScore += getEvalValue(ENDGAME_MINOR_PIECE_NOT_DEFENDED_PENALTY);
- } else {
- blackMidgameScore += getEvalValue(MIDGAME_MINOR_PIECE_NOT_DEFENDED_PENALTY);
- blackEndgameScore += getEvalValue(ENDGAME_MINOR_PIECE_NOT_DEFENDED_PENALTY);
- }
- }
-
- uint64_t weakSquares;
-
- if (color == WHITE) {
- weakSquares = attackedBy2[BLACK] & ~attackedBy2[WHITE];
-
- if ((1ULL << index) & weakSquares) {
- whiteMidgameScore += getEvalValue(MIDGAME_MINOR_PIECE_ON_WEAK_SQUARE_PENALTY);
- whiteEndgameScore += getEvalValue(ENDGAME_MINOR_PIECE_ON_WEAK_SQUARE_PENALTY);
- }
- } else {
- weakSquares = attackedBy2[WHITE] & ~attackedBy2[BLACK];
-
- if ((1ULL << index) & weakSquares) {
- blackMidgameScore += getEvalValue(MIDGAME_MINOR_PIECE_ON_WEAK_SQUARE_PENALTY);
- blackEndgameScore += getEvalValue(ENDGAME_MINOR_PIECE_ON_WEAK_SQUARE_PENALTY);
- }
- }
- }
- }
-}
-
-int Evaluation::evaluate() {
- int phase = getPhase();
- int modifier = bitboard.getMovingColor() == WHITE ? 1 : -1;
-
- initEvalContext(bitboard);
-
- evaluateMaterial();
- evaluateMaterial();
-
- evaluatePst();
- evaluatePst();
-
- evaluatePieces();
- evaluatePieces();
-
- int whiteScore = ((whiteMidgameScore * (256 - phase)) + (whiteEndgameScore * phase)) / 256;
- int blackScore = ((blackMidgameScore * (256 - phase)) + (blackEndgameScore * phase)) / 256;
-
- return (whiteScore - blackScore) * modifier;
-}
-
-template
-void Evaluation::evaluateMaterial() {
- if (color == WHITE) {
- whiteMidgameScore +=
- bitboard.getMaterialCount() * getEvalValue(MIDGAME_PAWN_MATERIAL);
- whiteEndgameScore +=
- bitboard.getMaterialCount() * getEvalValue(ENDGAME_PAWN_MATERIAL);
-
- whiteMidgameScore +=
- bitboard.getMaterialCount() * getEvalValue(MIDGAME_KNIGHT_MATERIAL);
- whiteEndgameScore +=
- bitboard.getMaterialCount() * getEvalValue(ENDGAME_KNIGHT_MATERIAL);
-
- whiteMidgameScore +=
- bitboard.getMaterialCount() * getEvalValue(MIDGAME_BISHOP_MATERIAL);
- whiteEndgameScore +=
- bitboard.getMaterialCount() * getEvalValue(ENDGAME_BISHOP_MATERIAL);
-
- whiteMidgameScore +=
- bitboard.getMaterialCount() * getEvalValue(MIDGAME_ROOK_MATERIAL);
- whiteEndgameScore +=
- bitboard.getMaterialCount() * getEvalValue(ENDGAME_ROOK_MATERIAL);
-
- whiteMidgameScore +=
- bitboard.getMaterialCount() * getEvalValue(MIDGAME_QUEEN_MATERIAL);
- whiteEndgameScore +=
- bitboard.getMaterialCount() * getEvalValue(ENDGAME_QUEEN_MATERIAL);
- } else {
- blackMidgameScore +=
- bitboard.getMaterialCount() * getEvalValue(MIDGAME_PAWN_MATERIAL);
- blackEndgameScore +=
- bitboard.getMaterialCount() * getEvalValue(ENDGAME_PAWN_MATERIAL);
-
- blackMidgameScore +=
- bitboard.getMaterialCount() * getEvalValue(MIDGAME_KNIGHT_MATERIAL);
- blackEndgameScore +=
- bitboard.getMaterialCount