From 8eecaf0bfb721d409e338c0e837d2e634aa12203 Mon Sep 17 00:00:00 2001 From: Fabian Fichter Date: Sun, 15 Sep 2024 12:20:08 +0200 Subject: [PATCH] Support trainer_config command To write variant.h and variant.py specify variant and directory, e.g., `trainer_config antichess .` --- src/uci.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++++ src/ucioption.cpp | 39 ----------------------- 2 files changed, 79 insertions(+), 39 deletions(-) diff --git a/src/uci.cpp b/src/uci.cpp index a594bc6f..668191d9 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -365,6 +366,83 @@ void search_mcts_cmd(Position& pos, istringstream& is) } } + // write_trainer_config() writes the variant.h and variant.py for the trainer + void write_trainer_config(istringstream& is) { + string variant = Options["UCI_Variant"]; + string path = ""; + + is >> variant; + ostream* varianth = &std::cerr; + ostream* variantpy = &std::cerr; + ofstream out1; + ofstream out2; + if (std::getline(is >> std::ws, path) && !path.empty()) + { + path.erase(path.find_last_not_of(" \t\n\r\f\v") + 1); + out1.open(path + "/variant.h"); + out2.open(path + "/variant.py"); + if (out1.is_open()) + varianth = &out1; + if (out2.is_open()) + variantpy = &out2; + } + + const Variant* v = variants.find(variant)->second; + std::cerr << "Writing config for variant " + variant << std::endl; + + const int dataSize = (v->maxFile + 1) * (v->maxRank + 1) + v->nnueMaxPieces * 5 + + popcount(v->pieceTypes) * 2 * 5 + 50 > 512 ? 1024 : 512; + + if (dataSize > DATA_SIZE) + std::cerr << std::endl << "Warning: Recommended training data size " << dataSize + << " not compatible with current version. " + << "Please recompile with largedata=yes" << std::endl << std::endl; + + if (out1.is_open()) + std::cerr << "Writing variant.h to " << path << std::endl; + else + std::cerr << "---------------- variant.h ---------------------" << std::endl; + *varianth + << "#define FILES " << v->maxFile + 1 << std::endl + << "#define RANKS " << v->maxRank + 1 << std::endl + << "#define PIECE_TYPES " << popcount(v->pieceTypes) << std::endl + << "#define PIECE_COUNT " << v->nnueMaxPieces << std::endl + << "#define POCKETS " << (v->nnueUsePockets ? "true" : "false") << std::endl + << "#define KING_SQUARES " << v->nnueKingSquare << std::endl + << "#define DATA_SIZE " << DATA_SIZE << std::endl; + + if (out1.is_open()) { + out1.close(); + } + + if (out2.is_open()) + std::cerr << "Writing variant.py to " << path << std::endl; + else + std::cerr << "---------------- variant.py --------------------" << std::endl; + *variantpy + << "RANKS = " << v->maxRank + 1 << std::endl + << "FILES = " << v->maxFile + 1 << std::endl + << "SQUARES = RANKS * FILES" << std::endl + << "KING_SQUARES = " << v->nnueKingSquare << std::endl + << "PIECE_TYPES = " << popcount(v->pieceTypes) << std::endl + << "PIECES = 2 * PIECE_TYPES" << std::endl + << "USE_POCKETS = " << (v->nnueUsePockets ? "True" : "False") << std::endl + << "POCKETS = 2 * FILES if USE_POCKETS else 0" << std::endl + << std::endl + << "PIECE_VALUES = {" << std::endl; + for (PieceSet ps = v->pieceTypes; ps;) + { + PieceType pt = pop_lsb(ps); + if (pt != v->nnueKing) + *variantpy << " " << v->pieceIndex[pt] + 1 << ": " << PieceValue[MG][pt] << "," << std::endl; + } + *variantpy << "}" << std::endl; + + if (out2.is_open()) { + out2.close(); + } + } + /// UCI::loop() waits for a command from stdin, parses it and calls the appropriate /// function. Also intercepts EOF from stdin to ensure gracefully exiting if the @@ -479,6 +557,7 @@ void UCI::loop(int argc, char* argv[]) { } else if (token == "load") { load(is); argc = 1; } // continue reading stdin else if (token == "check") load(is, true); + else if (token == "trainer_config") write_trainer_config(is); // UCI-Cyclone omits the "position" keyword else if (token == "fen" || token == "startpos") { diff --git a/src/ucioption.cpp b/src/ucioption.cpp index 8da39455..b7e1617d 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -97,45 +97,6 @@ void on_variant_change(const Option &o) { const Variant* v = variants.find(o)->second; - const int dataSize = (v->maxFile + 1) * (v->maxRank + 1) + v->nnueMaxPieces * 5 - + popcount(v->pieceTypes) * 2 * 5 + 50 > 512 ? 1024 : 512; - - if (dataSize > DATA_SIZE) - std::cerr << std::endl << "Warning: Recommended training data size " << dataSize - << " not compatible with current version. " - << "Please recompile with largedata=yes" << std::endl << std::endl; - - std::cerr<< std::endl - << "---------------- variant.h ---------------------" << std::endl - << "#define FILES " << v->maxFile + 1 << std::endl - << "#define RANKS " << v->maxRank + 1 << std::endl - << "#define PIECE_TYPES " << popcount(v->pieceTypes) << std::endl - << "#define PIECE_COUNT " << v->nnueMaxPieces << std::endl - << "#define POCKETS " << (v->nnueUsePockets ? "true" : "false") << std::endl - << "#define KING_SQUARES " << v->nnueKingSquare << std::endl - << "#define DATA_SIZE " << DATA_SIZE << std::endl - << "------------------------------------------------" << std::endl; - - std::cerr << std::endl - << "---------------- variant.py --------------------" << std::endl - << "RANKS = " << v->maxRank + 1 << std::endl - << "FILES = " << v->maxFile + 1 << std::endl - << "SQUARES = RANKS * FILES" << std::endl - << "KING_SQUARES = " << v->nnueKingSquare << std::endl - << "PIECE_TYPES = " << popcount(v->pieceTypes) << std::endl - << "PIECES = 2 * PIECE_TYPES" << std::endl - << "USE_POCKETS = " << (v->nnueUsePockets ? "True" : "False") << std::endl - << "POCKETS = 2 * FILES if USE_POCKETS else 0" << std::endl - << std::endl - << "PIECE_VALUES = {" << std::endl; - for (PieceSet ps = v->pieceTypes; ps;) - { - PieceType pt = pop_lsb(ps); - if (pt != v->nnueKing) - std::cerr << " " << v->pieceIndex[pt] + 1 << ": " << PieceValue[MG][pt] << "," << std::endl; - } - std::cerr << "}" << std::endl - << "------------------------------------------------" << std::endl; // Do not send setup command for known variants if (standard_variants.find(o) != standard_variants.end()) return;