Minimal support for FRC in the data generator. (#4049)

Allows UCI_Chess960 to be true during data generation.
If UCI_Chess960 is true then strips castling rights from all saved
positions and skips saving positions with castling move.
UCI_Chess960 is respected in transforms.
This commit is contained in:
Tomasz Sobczyk
2022-06-03 06:36:46 +02:00
committed by GitHub
parent 6e907f52c5
commit 399d556c27
9 changed files with 66 additions and 40 deletions
+4 -4
View File
@@ -1370,15 +1370,15 @@ bool Position::pos_is_ok() const {
// Add a function that directly unpacks for speed. It's pretty tough. // Add a function that directly unpacks for speed. It's pretty tough.
// Write it by combining packer::unpack() and Position::set(). // Write it by combining packer::unpack() and Position::set().
// If there is a problem with the passed phase and there is an error, non-zero is returned. // If there is a problem with the passed phase and there is an error, non-zero is returned.
int Position::set_from_packed_sfen(const Tools::PackedSfen& sfen , StateInfo* si, Thread* th) int Position::set_from_packed_sfen(const Tools::PackedSfen& sfen , StateInfo* si, Thread* th, bool frc)
{ {
return Tools::set_from_packed_sfen(*this, sfen, si, th); return Tools::set_from_packed_sfen(*this, sfen, si, th, frc);
} }
// Get the packed sfen. Returns to the buffer specified in the argument. // Get the packed sfen. Returns to the buffer specified in the argument.
void Position::sfen_pack(Tools::PackedSfen& sfen) void Position::sfen_pack(Tools::PackedSfen& sfen, bool resetCastlingRights)
{ {
sfen = Tools::sfen_pack(*this); sfen = Tools::sfen_pack(*this, resetCastlingRights);
} }
} // namespace Stockfish } // namespace Stockfish
+3 -3
View File
@@ -179,17 +179,17 @@ public:
// --sfenization helper // --sfenization helper
friend int Tools::set_from_packed_sfen(Position& pos, const Tools::PackedSfen& sfen, StateInfo* si, Thread* th); friend int Tools::set_from_packed_sfen(Position& pos, const Tools::PackedSfen& sfen, StateInfo* si, Thread* th, bool frc);
// Get the packed sfen. Returns to the buffer specified in the argument. // Get the packed sfen. Returns to the buffer specified in the argument.
// Do not include gamePly in pack. // Do not include gamePly in pack.
void sfen_pack(Tools::PackedSfen& sfen); void sfen_pack(Tools::PackedSfen& sfen, bool resetCastlingRights);
// It is slow to go through sfen, so I made a function to set packed sfen directly. // It is slow to go through sfen, so I made a function to set packed sfen directly.
// Equivalent to pos.set(sfen_unpack(data),si,th);. // Equivalent to pos.set(sfen_unpack(data),si,th);.
// If there is a problem with the passed phase and there is an error, non-zero is returned. // If there is a problem with the passed phase and there is an error, non-zero is returned.
// PackedSfen does not include gamePly so it cannot be restored. If you want to set it, specify it with an argument. // PackedSfen does not include gamePly so it cannot be restored. If you want to set it, specify it with an argument.
int set_from_packed_sfen(const Tools::PackedSfen& sfen, StateInfo* si, Thread* th); int set_from_packed_sfen(const Tools::PackedSfen& sfen, StateInfo* si, Thread* th, bool frc);
void clear() { std::memset(this, 0, sizeof(Position)); } void clear() { std::memset(this, 0, sizeof(Position)); }
+3 -3
View File
@@ -103,7 +103,7 @@ namespace Stockfish::Tools
filtered_size_fen++; filtered_size_fen++;
} }
else { else {
tpos.sfen_pack(p.sfen); tpos.sfen_pack(p.sfen, false);
} }
} }
else if (token == "move") { else if (token == "move") {
@@ -337,7 +337,7 @@ namespace Stockfish::Tools
StateInfo si; StateInfo si;
pos.set(str_fen, false, &si, th); pos.set(str_fen, false, &si, th);
pos.sfen_pack(psv.sfen); pos.sfen_pack(psv.sfen, false);
} }
#if defined(DEBUG_CONVERT_BIN_FROM_PGN_EXTRACT) #if defined(DEBUG_CONVERT_BIN_FROM_PGN_EXTRACT)
@@ -478,7 +478,7 @@ namespace Stockfish::Tools
{ {
if (fs.read((char*)&p, sizeof(PackedSfenValue))) { if (fs.read((char*)&p, sizeof(PackedSfenValue))) {
StateInfo si; StateInfo si;
tpos.set_from_packed_sfen(p.sfen, &si, th); tpos.set_from_packed_sfen(p.sfen, &si, th, false);
// write as plain text // write as plain text
ofs << "fen " << tpos.fen() << std::endl; ofs << "fen " << tpos.fen() << std::endl;
+17 -12
View File
@@ -94,7 +94,7 @@ namespace Stockfish::Tools {
// //
struct SfenPacker struct SfenPacker
{ {
void pack(const Position& pos); void pack(const Position& pos, bool resetCastlingRights);
// sfen packed by pack() (256bit = 32bytes) // sfen packed by pack() (256bit = 32bytes)
// Or sfen to decode with unpack() // Or sfen to decode with unpack()
@@ -149,7 +149,7 @@ namespace Stockfish::Tools {
}; };
// Pack sfen and store in data[32]. // Pack sfen and store in data[32].
void SfenPacker::pack(const Position& pos) void SfenPacker::pack(const Position& pos, bool resetCastlingRights)
{ {
memset(data, 0, 32 /* 256bit */); memset(data, 0, 32 /* 256bit */);
stream.set_data(data); stream.set_data(data);
@@ -175,11 +175,17 @@ namespace Stockfish::Tools {
} }
} }
// TODO(someone): Support chess960. if (resetCastlingRights)
stream.write_one_bit(pos.can_castle(WHITE_OO)); {
stream.write_one_bit(pos.can_castle(WHITE_OOO)); stream.write_n_bit(0, 4);
stream.write_one_bit(pos.can_castle(BLACK_OO)); }
stream.write_one_bit(pos.can_castle(BLACK_OOO)); else
{
stream.write_one_bit(pos.can_castle(WHITE_OO));
stream.write_one_bit(pos.can_castle(WHITE_OOO));
stream.write_one_bit(pos.can_castle(BLACK_OO));
stream.write_one_bit(pos.can_castle(BLACK_OOO));
}
if (pos.ep_square() == SQ_NONE) { if (pos.ep_square() == SQ_NONE) {
stream.write_one_bit(0); stream.write_one_bit(0);
@@ -249,7 +255,7 @@ namespace Stockfish::Tools {
return make_piece(c, pr); return make_piece(c, pr);
} }
int set_from_packed_sfen(Position& pos, const PackedSfen& sfen, StateInfo* si, Thread* th) int set_from_packed_sfen(Position& pos, const PackedSfen& sfen, StateInfo* si, Thread* th, bool frc)
{ {
SfenPacker packer; SfenPacker packer;
auto& stream = packer.stream; auto& stream = packer.stream;
@@ -304,7 +310,6 @@ namespace Stockfish::Tools {
} }
// Castling availability. // Castling availability.
// TODO(someone): Support chess960.
pos.st->castlingRights = 0; pos.st->castlingRights = 0;
if (stream.read_one_bit()) { if (stream.read_one_bit()) {
Square rsq; Square rsq;
@@ -362,7 +367,7 @@ namespace Stockfish::Tools {
assert(stream.get_cursor() <= 256); assert(stream.get_cursor() <= 256);
pos.chess960 = false; pos.chess960 = frc;
pos.thisThread = th; pos.thisThread = th;
pos.set_state(pos.st); pos.set_state(pos.st);
@@ -371,13 +376,13 @@ namespace Stockfish::Tools {
return 0; return 0;
} }
PackedSfen sfen_pack(Position& pos) PackedSfen sfen_pack(Position& pos, bool resetCastlingRights)
{ {
PackedSfen sfen; PackedSfen sfen;
SfenPacker sp; SfenPacker sp;
sp.data = (uint8_t*)&sfen; sp.data = (uint8_t*)&sfen;
sp.pack(pos); sp.pack(pos, resetCastlingRights);
return sfen; return sfen;
} }
+2 -2
View File
@@ -15,8 +15,8 @@ namespace Stockfish {
namespace Stockfish::Tools { namespace Stockfish::Tools {
int set_from_packed_sfen(Position& pos, const PackedSfen& sfen, StateInfo* si, Thread* th); int set_from_packed_sfen(Position& pos, const PackedSfen& sfen, StateInfo* si, Thread* th, bool frc);
PackedSfen sfen_pack(Position& pos); PackedSfen sfen_pack(Position& pos, bool resetCastlingRights);
} }
#endif #endif
+2 -1
View File
@@ -1192,6 +1192,7 @@ namespace Stockfish::Tools::Stats
Thread* th = Threads.main(); Thread* th = Threads.main();
Position& pos = th->rootPos; Position& pos = th->rootPos;
StateInfo si; StateInfo si;
const bool frc = Options["UCI_Chess960"];
auto in = Tools::open_sfen_input_file(filename); auto in = Tools::open_sfen_input_file(filename);
@@ -1214,7 +1215,7 @@ namespace Stockfish::Tools::Stats
auto& psv = v.value(); auto& psv = v.value();
pos.set_from_packed_sfen(psv.sfen, &si, th); pos.set_from_packed_sfen(psv.sfen, &si, th, frc);
on_entry(pos, (Move)psv.move, psv); on_entry(pos, (Move)psv.move, psv);
+12 -4
View File
@@ -271,6 +271,7 @@ namespace Stockfish::Tools
const auto start_time = now(); const auto start_time = now();
const bool frc = Options["UCI_Chess960"];
// repeat until the specified number of times // repeat until the specified number of times
while (!quit) while (!quit)
{ {
@@ -286,11 +287,11 @@ namespace Stockfish::Tools
if (opening_book != nullptr) if (opening_book != nullptr)
{ {
auto& fen = opening_book->next_fen(); auto& fen = opening_book->next_fen();
pos.set(fen, false, &si, &th); pos.set(fen, frc, &si, &th);
} }
else else
{ {
pos.set(StartFEN, false, &si, &th); pos.set(StartFEN, frc, &si, &th);
} }
int resign_counter = 0; int resign_counter = 0;
@@ -367,7 +368,7 @@ namespace Stockfish::Tools
// Here we only write the position data. // Here we only write the position data.
// Result is added after the whole game is done. // Result is added after the whole game is done.
pos.sfen_pack(psv.sfen); pos.sfen_pack(psv.sfen, pos.is_chess960());
psv.score = search_value; psv.score = search_value;
psv.move = search_pv[0]; psv.move = search_pv[0];
@@ -695,9 +696,17 @@ namespace Stockfish::Tools
it->game_result = side_to_move == result_color ? result : -result; it->game_result = side_to_move == result_color ? result : -result;
} }
const bool frc = th.rootPos.is_chess960();
// Write sfens in move order to make potential compression easier // Write sfens in move order to make potential compression easier
for (auto& sfen : sfens) for (auto& sfen : sfens)
{ {
// Skip positions with castling bestmove in FRC so that we don't
// need to support it in the trainer.
if (frc && type_of((Move)sfen.move) == CASTLING)
{
continue;
}
// Return true if there is already enough data generated. // Return true if there is already enough data generated.
const auto iter = counter.fetch_add(1); const auto iter = counter.fetch_add(1);
if (iter >= limit) if (iter >= limit)
@@ -858,7 +867,6 @@ namespace Stockfish::Tools
else if (token == "set_recommended_uci_options") else if (token == "set_recommended_uci_options")
{ {
UCI::setoption("Skill Level", "20"); UCI::setoption("Skill Level", "20");
UCI::setoption("UCI_Chess960", "false");
UCI::setoption("UCI_LimitStrength", "false"); UCI::setoption("UCI_LimitStrength", "false");
UCI::setoption("PruneAtShallowDepth", "false"); UCI::setoption("PruneAtShallowDepth", "false");
UCI::setoption("EnableTranspositionTable", "true"); UCI::setoption("EnableTranspositionTable", "true");
+15 -6
View File
@@ -204,23 +204,24 @@ namespace Stockfish::Tools
if ((double)prng.rand<uint64_t>() / std::numeric_limits<uint64_t>::max() < params.exploration_save_rate) if ((double)prng.rand<uint64_t>() / std::numeric_limits<uint64_t>::max() < params.exploration_save_rate)
{ {
psv.emplace_back(); psv.emplace_back();
pos.sfen_pack(psv.back().sfen); pos.sfen_pack(psv.back().sfen, pos.is_chess960());
} }
}); });
auto& pos = th.rootPos; auto& pos = th.rootPos;
StateInfo si; StateInfo si;
const bool frc = Options["UCI_Chess960"];
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
{ {
if (opening_book != nullptr) if (opening_book != nullptr)
{ {
auto& fen = opening_book->next_fen(); auto& fen = opening_book->next_fen();
pos.set(fen, false, &si, &th); pos.set(fen, frc, &si, &th);
} }
else else
{ {
pos.set(StartFEN, false, &si, &th); pos.set(StartFEN, frc, &si, &th);
} }
for(int ply = 0; ply < params.exploration_max_ply; ++ply) for(int ply = 0; ply < params.exploration_max_ply; ++ply)
@@ -267,6 +268,7 @@ namespace Stockfish::Tools
// end flag // end flag
bool quit = false; bool quit = false;
const bool frc = Options["UCI_Chess960"];
// repeat until the specified number of times // repeat until the specified number of times
while (!quit) while (!quit)
{ {
@@ -280,7 +282,7 @@ namespace Stockfish::Tools
for (auto& ps : packed_sfens) for (auto& ps : packed_sfens)
{ {
pos.set_from_packed_sfen(ps.sfen, &si, &th); pos.set_from_packed_sfen(ps.sfen, &si, &th, frc);
pos.state()->rule50 = 0; pos.state()->rule50 = 0;
if (params.smart_fen_skipping && pos.checkers()) if (params.smart_fen_skipping && pos.checkers())
@@ -306,7 +308,7 @@ namespace Stockfish::Tools
} }
auto& new_ps = psv.emplace_back(); auto& new_ps = psv.emplace_back();
pos.sfen_pack(new_ps.sfen); pos.sfen_pack(new_ps.sfen, pos.is_chess960());
new_ps.score = search_value; new_ps.score = search_value;
new_ps.move = search_pv[0]; new_ps.move = search_pv[0];
new_ps.gamePly = 1; new_ps.gamePly = 1;
@@ -329,9 +331,17 @@ namespace Stockfish::Tools
std::atomic<uint64_t>& counter, std::atomic<uint64_t>& counter,
uint64_t limit) uint64_t limit)
{ {
const bool frc = th.rootPos.is_chess960();
// Write sfens in move order to make potential compression easier // Write sfens in move order to make potential compression easier
for (auto& sfen : sfens) for (auto& sfen : sfens)
{ {
// Skip positions with castling bestmove in FRC so that we don't
// need to support it in the trainer.
if (frc && type_of((Move)sfen.move) == CASTLING)
{
continue;
}
// Return true if there is already enough data generated. // Return true if there is already enough data generated.
const auto iter = counter.fetch_add(1); const auto iter = counter.fetch_add(1);
if (iter >= limit) if (iter >= limit)
@@ -435,7 +445,6 @@ namespace Stockfish::Tools
else if (token == "set_recommended_uci_options") else if (token == "set_recommended_uci_options")
{ {
UCI::setoption("Skill Level", "20"); UCI::setoption("Skill Level", "20");
UCI::setoption("UCI_Chess960", "false");
UCI::setoption("UCI_LimitStrength", "false"); UCI::setoption("UCI_LimitStrength", "false");
UCI::setoption("PruneAtShallowDepth", "false"); UCI::setoption("PruneAtShallowDepth", "false");
UCI::setoption("EnableTranspositionTable", "true"); UCI::setoption("EnableTranspositionTable", "true");
+8 -5
View File
@@ -140,6 +140,7 @@ namespace Stockfish::Tools
buffer.reserve(batch_size); buffer.reserve(batch_size);
const bool frc = Options["UCI_Chess960"];
uint64_t num_processed = 0; uint64_t num_processed = 0;
for (;;) for (;;)
{ {
@@ -149,7 +150,7 @@ namespace Stockfish::Tools
auto& ps = v.value(); auto& ps = v.value();
pos.set_from_packed_sfen(ps.sfen, &si, th); pos.set_from_packed_sfen(ps.sfen, &si, th, frc);
auto static_eval = Eval::evaluate(pos); auto static_eval = Eval::evaluate(pos);
auto deep_eval = ps.score; auto deep_eval = ps.score;
ps.score = nudge(params, static_eval, deep_eval); ps.score = nudge(params, static_eval, deep_eval);
@@ -290,6 +291,7 @@ namespace Stockfish::Tools
Threads.execute_with_workers([&](auto& th){ Threads.execute_with_workers([&](auto& th){
Position& pos = th.rootPos; Position& pos = th.rootPos;
StateInfo si; StateInfo si;
const bool frc = Options["UCI_Chess960"];
for(;;) for(;;)
{ {
@@ -297,7 +299,7 @@ namespace Stockfish::Tools
if (!fen.has_value()) if (!fen.has_value())
return; return;
pos.set(*fen, false, &si, &th); pos.set(*fen, frc, &si, &th);
pos.state()->rule50 = 0; pos.state()->rule50 = 0;
@@ -310,7 +312,7 @@ namespace Stockfish::Tools
continue; continue;
PackedSfenValue ps; PackedSfenValue ps;
pos.sfen_pack(ps.sfen); pos.sfen_pack(ps.sfen, pos.is_chess960());
ps.score = search_value; ps.score = search_value;
ps.move = search_pv[0]; ps.move = search_pv[0];
ps.gamePly = 1; ps.gamePly = 1;
@@ -401,6 +403,7 @@ namespace Stockfish::Tools
Threads.execute_with_workers([&](auto& th){ Threads.execute_with_workers([&](auto& th){
Position& pos = th.rootPos; Position& pos = th.rootPos;
StateInfo si; StateInfo si;
const bool frc = Options["UCI_Chess960"];
for (;;) for (;;)
{ {
@@ -410,7 +413,7 @@ namespace Stockfish::Tools
for(auto& ps : psv) for(auto& ps : psv)
{ {
pos.set_from_packed_sfen(ps.sfen, &si, &th); pos.set_from_packed_sfen(ps.sfen, &si, &th, frc);
for (int cnt = 0; cnt < params.research_count; ++cnt) for (int cnt = 0; cnt < params.research_count; ++cnt)
Search::search(pos, params.depth, 1); Search::search(pos, params.depth, 1);
@@ -420,7 +423,7 @@ namespace Stockfish::Tools
if (search_pv.empty()) if (search_pv.empty())
continue; continue;
pos.sfen_pack(ps.sfen); pos.sfen_pack(ps.sfen, false);
ps.score = search_value; ps.score = search_value;
if (!params.keep_moves) if (!params.keep_moves)
ps.move = search_pv[0]; ps.move = search_pv[0];