diff --git a/.gitmodules b/.gitmodules index 333a85e..47e98be 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "Sources/ChessKitEngineCore/Engines/lc0"] path = Sources/ChessKitEngineCore/Engines/lc0 url = https://github.com/chesskit-app/lc0.git +[submodule "Sources/ChessKitEngineCore/Engines/arasan-chess"] + path = Sources/ChessKitEngineCore/Engines/arasan-chess + url = git@github.com:ameter/arasan-chess.git diff --git a/Package.swift b/Package.swift index a6aadf2..6b8ff67 100644 --- a/Package.swift +++ b/Package.swift @@ -21,7 +21,8 @@ let package = Package( dependencies: ["ChessKitEngineCore"], resources: [ .copy("Resources/192x15_network"), - .copy("Resources/nn-1337b1adec5b.nnue") + .copy("Resources/nn-1337b1adec5b.nnue"), + .copy("Resources/book.bin") ] ), .target( @@ -31,7 +32,17 @@ let package = Package( .headerSearchPath("Engines/lc0/src"), .headerSearchPath("Engines/lc0/subprojects/eigen-3.4.0"), .define("NNUE_EMBEDDING_OFF"), - .define("NO_PEXT") + .define("NO_PEXT"), + // Arasan + .headerSearchPath("Engines/arasan-chess/src"), + .headerSearchPath("Engines/arasan-chess/src/nnue"), + .define("ARASAN_VERSION=v24.0.0"), + .define("_64BIT"), + .define("USE_INTRINSICS"), + .define("USE_ASM"), + .define("SYZYGY_TBS"), + .define("SMP"), + .define("SMP_STATS"), ], linkerSettings: [ .linkedLibrary("z") @@ -48,6 +59,18 @@ let package = Package( // MARK: - ChessKitEngineCore excludes package.targets.first { $0.name == "ChessKitEngineCore" }?.exclude = [ + // Arasan + "Engines/arasan-chess/src/arasanx.cpp", + "Engines/arasan-chess/src/unit.cpp", + "Engines/arasan-chess/src/tuner.cpp", + "Engines/arasan-chess/src/tune.cpp", + "Engines/arasan-chess/src/topo.cpp", + "Engines/arasan-chess/src/bitbase.cpp", + "Engines/arasan-chess/src/util", + "Engines/arasan-chess/src/nnue/test", + "Engines/arasan-chess/src/syzygy/src/apps", + "Engines/arasan-chess/src/syzygy/src/tbchess.c", + "Engines/arasan-chess/src/nnueintf.cpp", // lc0 "Engines/lc0/build", "Engines/lc0/cross-files", diff --git a/README.md b/README.md index 68a0183..3f08705 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,7 @@ The following engines are currently supported: | :---: | --- | :---: | :---: | :---: | | | [Stockfish](https://stockfishchess.org) | [15.1](https://github.com/official-stockfish/Stockfish/tree/sf_15.1) | [GPL v3](https://github.com/official-stockfish/Stockfish/blob/sf_15.1/Copying.txt) | [🔗](https://github.com/official-stockfish/Stockfish/tree/sf_15.1#the-uci-protocol-and-available-options) | | [lc0](https://lczero.org) | [0.29](https://github.com/LeelaChessZero/lc0/tree/v0.29.0) | [GPL v3](https://github.com/LeelaChessZero/lc0/blob/v0.29.0/COPYING) | [🔗](https://github.com/LeelaChessZero/lc0/wiki/Lc0-options) +| | [Arasan](https://www.arasanchess.org) | [24.0.0](https://github.com/jdart1/arasan-chess/tree/v24.0.0) | [MIT License](https://github.com/jdart1/arasan-chess/blob/v24.0.0/LICENSE) | [🔗](https://github.com/jdart1/arasan-chess/tree/v24.0.0#uci-options) ## Author diff --git a/Sources/ChessKitEngine/EngineType.swift b/Sources/ChessKitEngine/EngineType.swift index 73b2767..7016f2a 100644 --- a/Sources/ChessKitEngine/EngineType.swift +++ b/Sources/ChessKitEngine/EngineType.swift @@ -10,12 +10,14 @@ public enum EngineType: Int { case stockfish case lc0 + case arasan /// Internal mapping from Swift to Obj-C type. var objc: EngineType_objc { switch self { case .stockfish: return .stockfish case .lc0: return .lc0 + case .arasan: return .arasan } } @@ -24,6 +26,7 @@ public enum EngineType: Int { switch self { case .stockfish: return "Stockfish" case .lc0: return "LeelaChessZero (Lc0)" + case .arasan: return "Arasan" } } @@ -32,6 +35,7 @@ public enum EngineType: Int { switch self { case .stockfish: return "15.1" case .lc0: return "0.29" + case .arasan: return "24.0.0" } } @@ -59,6 +63,15 @@ public enum EngineType: Int { weights != nil ? .setoption(id: "WeightsFile", value: weights!) : nil ].compactMap { $0 } + case .arasan: + let openingBook = Bundle.module.url(forResource: "book", withExtension: "bin")? + .absoluteString + .replacingOccurrences(of: "file://", with: "") + + return [ + openingBook != nil ? + .setoption(id: "BookPath", value: openingBook!) : nil + ].compactMap { $0 } } } diff --git a/Sources/ChessKitEngine/Resources/book.bin b/Sources/ChessKitEngine/Resources/book.bin new file mode 100644 index 0000000..f4955e4 Binary files /dev/null and b/Sources/ChessKitEngine/Resources/book.bin differ diff --git a/Sources/ChessKitEngineCore/EngineMessenger/EngineMessenger.mm b/Sources/ChessKitEngineCore/EngineMessenger/EngineMessenger.mm index 906de71..fae0a8f 100644 --- a/Sources/ChessKitEngineCore/EngineMessenger/EngineMessenger.mm +++ b/Sources/ChessKitEngineCore/EngineMessenger/EngineMessenger.mm @@ -28,6 +28,9 @@ - (id)initWithEngineType: (EngineType_objc) type { case EngineTypeLc0: _engine = new Lc0Engine(); break; + case EngineTypeArasan: + _engine = new ArasanEngine(); + break; } _engine->initialize(); diff --git a/Sources/ChessKitEngineCore/Engines/AvailableEngines.h b/Sources/ChessKitEngineCore/Engines/AvailableEngines.h index 07bd7b8..a47f5dd 100644 --- a/Sources/ChessKitEngineCore/Engines/AvailableEngines.h +++ b/Sources/ChessKitEngineCore/Engines/AvailableEngines.h @@ -8,5 +8,6 @@ #import "../Engines/Extensions/stockfish+engine.h" #import "../Engines/Extensions/lc0+engine.h" +#import "../Engines/Extensions/arasan+engine.h" #endif /* AvailableEngines_h */ diff --git a/Sources/ChessKitEngineCore/Engines/EngineType_objc.h b/Sources/ChessKitEngineCore/Engines/EngineType_objc.h index e63b42e..290f41e 100644 --- a/Sources/ChessKitEngineCore/Engines/EngineType_objc.h +++ b/Sources/ChessKitEngineCore/Engines/EngineType_objc.h @@ -8,7 +8,8 @@ typedef NS_ENUM(NSInteger, EngineType_objc) { EngineTypeStockfish, - EngineTypeLc0 + EngineTypeLc0, + EngineTypeArasan }; #endif /* EngineType_objc_h */ diff --git a/Sources/ChessKitEngineCore/Engines/Extensions/arasan+engine.cpp b/Sources/ChessKitEngineCore/Engines/Extensions/arasan+engine.cpp new file mode 100644 index 0000000..c6182cd --- /dev/null +++ b/Sources/ChessKitEngineCore/Engines/Extensions/arasan+engine.cpp @@ -0,0 +1,73 @@ +// +// arasan+engine.cpp +// +// Created by Chris Ameter on 10/10/23. +// + +#import "arasan+engine.h" + +#include "../arasan-chess/src/types.h" +#include "../arasan-chess/src/globals.h" +#include "../arasan-chess/src/options.h" +#include "../arasan-chess/src/protocol.h" + +#include +#include + +Protocol *protocol; +Board board; + +void ArasanEngine::initialize() { + signal(SIGINT,SIG_IGN); + + // Show a message on the console + std::cout << "Arasan " Arasan_Version << ' ' << Arasan_Copyright << std::endl; + // Must use unbuffered console + setbuf(stdin,NULL); + setbuf(stdout, NULL); + std::cout.rdbuf()->pubsetbuf(NULL, 0); + std::cin.rdbuf()->pubsetbuf(NULL, 0); + + Bitboard::init(); + Board::init(); + globals::initOptions(); + Attacks::init(); + Scoring::init(); + Search::init(); + if (!globals::initGlobals(true)) { + globals::cleanupGlobals(); + exit(-1); + } + + struct rlimit rl; + const rlim_t STACK_MAX = static_cast(globals::LINUX_STACK_SIZE); + auto result = getrlimit(RLIMIT_STACK, &rl); + if (result == 0) + { + if (rl.rlim_cur < STACK_MAX) + { + rl.rlim_cur = STACK_MAX; + result = setrlimit(RLIMIT_STACK, &rl); + if (result) + { + std::cerr << "failed to increase stack size" << std::endl; + exit(-1); + } + } + } + + bool ics = true, trace = false, cpusSet = false, memorySet = false; + + protocol = new Protocol(board, trace, ics, cpusSet, memorySet); + // Begins protocol (UCI) run loop, listening on standard input + // protocol->poll(globals::polling_terminated); +} + +void ArasanEngine::deinitialize() { + globals::cleanupGlobals(); + delete protocol; +} + +void ArasanEngine::send_command(const std::string &cmd) { + protocol->do_command(cmd, board); +} diff --git a/Sources/ChessKitEngineCore/Engines/Extensions/arasan+engine.h b/Sources/ChessKitEngineCore/Engines/Extensions/arasan+engine.h new file mode 100644 index 0000000..c12cfbd --- /dev/null +++ b/Sources/ChessKitEngineCore/Engines/Extensions/arasan+engine.h @@ -0,0 +1,21 @@ +// +// arasan+engine.h +// +// Created by Chris Ameter on 10/10/23. +// + +#ifndef arasan_engine_h +#define arasan_engine_h + +#import "engine.h" +#import + +/// Arasan implementation of `Engine`. +class ArasanEngine: public Engine { +public: + void initialize(); + void deinitialize(); + void send_command(const std::string &cmd); +}; + +#endif /* arasan_engine_h */ diff --git a/Sources/ChessKitEngineCore/Engines/arasan-chess b/Sources/ChessKitEngineCore/Engines/arasan-chess new file mode 160000 index 0000000..c4786a9 --- /dev/null +++ b/Sources/ChessKitEngineCore/Engines/arasan-chess @@ -0,0 +1 @@ +Subproject commit c4786a9e109215759132d94ae39feab0a632fa83 diff --git a/Tests/ChessKitEngineTests/EngineTests/ArasanTests.swift b/Tests/ChessKitEngineTests/EngineTests/ArasanTests.swift new file mode 100644 index 0000000..4e9d3d6 --- /dev/null +++ b/Tests/ChessKitEngineTests/EngineTests/ArasanTests.swift @@ -0,0 +1,17 @@ +// +// ArasanTests.swift +// +// Created by Chris Ameter on 10/20/23. +// + +import XCTest +@testable import ChessKitEngine + +final class ArasanTests: BaseEngineTests { + + override func setUp() { + engineType = .arasan + super.setUp() + } + +}