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.
// 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.
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.
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
+3 -3
View File
@@ -179,17 +179,17 @@ public:
// --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.
// 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.
// 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.
// 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)); }
+3 -3
View File
@@ -103,7 +103,7 @@ namespace Stockfish::Tools
filtered_size_fen++;
}
else {
tpos.sfen_pack(p.sfen);
tpos.sfen_pack(p.sfen, false);
}
}
else if (token == "move") {
@@ -337,7 +337,7 @@ namespace Stockfish::Tools
StateInfo si;
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)
@@ -478,7 +478,7 @@ namespace Stockfish::Tools
{
if (fs.read((char*)&p, sizeof(PackedSfenValue))) {
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
ofs << "fen " << tpos.fen() << std::endl;
+17 -12
View File
@@ -94,7 +94,7 @@ namespace Stockfish::Tools {
//
struct SfenPacker
{
void pack(const Position& pos);
void pack(const Position& pos, bool resetCastlingRights);
// sfen packed by pack() (256bit = 32bytes)
// Or sfen to decode with unpack()
@@ -149,7 +149,7 @@ namespace Stockfish::Tools {
};
// 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 */);
stream.set_data(data);
@@ -175,11 +175,17 @@ namespace Stockfish::Tools {
}
}
// TODO(someone): Support chess960.
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 (resetCastlingRights)
{
stream.write_n_bit(0, 4);
}
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) {
stream.write_one_bit(0);
@@ -249,7 +255,7 @@ namespace Stockfish::Tools {
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;
auto& stream = packer.stream;
@@ -304,7 +310,6 @@ namespace Stockfish::Tools {
}
// Castling availability.
// TODO(someone): Support chess960.
pos.st->castlingRights = 0;
if (stream.read_one_bit()) {
Square rsq;
@@ -362,7 +367,7 @@ namespace Stockfish::Tools {
assert(stream.get_cursor() <= 256);
pos.chess960 = false;
pos.chess960 = frc;
pos.thisThread = th;
pos.set_state(pos.st);
@@ -371,13 +376,13 @@ namespace Stockfish::Tools {
return 0;
}
PackedSfen sfen_pack(Position& pos)
PackedSfen sfen_pack(Position& pos, bool resetCastlingRights)
{
PackedSfen sfen;
SfenPacker sp;
sp.data = (uint8_t*)&sfen;
sp.pack(pos);
sp.pack(pos, resetCastlingRights);
return sfen;
}
+2 -2
View File
@@ -15,8 +15,8 @@ namespace Stockfish {
namespace Stockfish::Tools {
int set_from_packed_sfen(Position& pos, const PackedSfen& sfen, StateInfo* si, Thread* th);
PackedSfen sfen_pack(Position& pos);
int set_from_packed_sfen(Position& pos, const PackedSfen& sfen, StateInfo* si, Thread* th, bool frc);
PackedSfen sfen_pack(Position& pos, bool resetCastlingRights);
}
#endif
+2 -1
View File
@@ -1192,6 +1192,7 @@ namespace Stockfish::Tools::Stats
Thread* th = Threads.main();
Position& pos = th->rootPos;
StateInfo si;
const bool frc = Options["UCI_Chess960"];
auto in = Tools::open_sfen_input_file(filename);
@@ -1214,7 +1215,7 @@ namespace Stockfish::Tools::Stats
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);
+12 -4
View File
@@ -271,6 +271,7 @@ namespace Stockfish::Tools
const auto start_time = now();
const bool frc = Options["UCI_Chess960"];
// repeat until the specified number of times
while (!quit)
{
@@ -286,11 +287,11 @@ namespace Stockfish::Tools
if (opening_book != nullptr)
{
auto& fen = opening_book->next_fen();
pos.set(fen, false, &si, &th);
pos.set(fen, frc, &si, &th);
}
else
{
pos.set(StartFEN, false, &si, &th);
pos.set(StartFEN, frc, &si, &th);
}
int resign_counter = 0;
@@ -367,7 +368,7 @@ namespace Stockfish::Tools
// Here we only write the position data.
// 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.move = search_pv[0];
@@ -695,9 +696,17 @@ namespace Stockfish::Tools
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
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.
const auto iter = counter.fetch_add(1);
if (iter >= limit)
@@ -858,7 +867,6 @@ namespace Stockfish::Tools
else if (token == "set_recommended_uci_options")
{
UCI::setoption("Skill Level", "20");
UCI::setoption("UCI_Chess960", "false");
UCI::setoption("UCI_LimitStrength", "false");
UCI::setoption("PruneAtShallowDepth", "false");
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)
{
psv.emplace_back();
pos.sfen_pack(psv.back().sfen);
pos.sfen_pack(psv.back().sfen, pos.is_chess960());
}
});
auto& pos = th.rootPos;
StateInfo si;
const bool frc = Options["UCI_Chess960"];
for (int i = 0; i < count; ++i)
{
if (opening_book != nullptr)
{
auto& fen = opening_book->next_fen();
pos.set(fen, false, &si, &th);
pos.set(fen, frc, &si, &th);
}
else
{
pos.set(StartFEN, false, &si, &th);
pos.set(StartFEN, frc, &si, &th);
}
for(int ply = 0; ply < params.exploration_max_ply; ++ply)
@@ -267,6 +268,7 @@ namespace Stockfish::Tools
// end flag
bool quit = false;
const bool frc = Options["UCI_Chess960"];
// repeat until the specified number of times
while (!quit)
{
@@ -280,7 +282,7 @@ namespace Stockfish::Tools
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;
if (params.smart_fen_skipping && pos.checkers())
@@ -306,7 +308,7 @@ namespace Stockfish::Tools
}
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.move = search_pv[0];
new_ps.gamePly = 1;
@@ -329,9 +331,17 @@ namespace Stockfish::Tools
std::atomic<uint64_t>& counter,
uint64_t limit)
{
const bool frc = th.rootPos.is_chess960();
// Write sfens in move order to make potential compression easier
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.
const auto iter = counter.fetch_add(1);
if (iter >= limit)
@@ -435,7 +445,6 @@ namespace Stockfish::Tools
else if (token == "set_recommended_uci_options")
{
UCI::setoption("Skill Level", "20");
UCI::setoption("UCI_Chess960", "false");
UCI::setoption("UCI_LimitStrength", "false");
UCI::setoption("PruneAtShallowDepth", "false");
UCI::setoption("EnableTranspositionTable", "true");
+8 -5
View File
@@ -140,6 +140,7 @@ namespace Stockfish::Tools
buffer.reserve(batch_size);
const bool frc = Options["UCI_Chess960"];
uint64_t num_processed = 0;
for (;;)
{
@@ -149,7 +150,7 @@ namespace Stockfish::Tools
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 deep_eval = ps.score;
ps.score = nudge(params, static_eval, deep_eval);
@@ -290,6 +291,7 @@ namespace Stockfish::Tools
Threads.execute_with_workers([&](auto& th){
Position& pos = th.rootPos;
StateInfo si;
const bool frc = Options["UCI_Chess960"];
for(;;)
{
@@ -297,7 +299,7 @@ namespace Stockfish::Tools
if (!fen.has_value())
return;
pos.set(*fen, false, &si, &th);
pos.set(*fen, frc, &si, &th);
pos.state()->rule50 = 0;
@@ -310,7 +312,7 @@ namespace Stockfish::Tools
continue;
PackedSfenValue ps;
pos.sfen_pack(ps.sfen);
pos.sfen_pack(ps.sfen, pos.is_chess960());
ps.score = search_value;
ps.move = search_pv[0];
ps.gamePly = 1;
@@ -401,6 +403,7 @@ namespace Stockfish::Tools
Threads.execute_with_workers([&](auto& th){
Position& pos = th.rootPos;
StateInfo si;
const bool frc = Options["UCI_Chess960"];
for (;;)
{
@@ -410,7 +413,7 @@ namespace Stockfish::Tools
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)
Search::search(pos, params.depth, 1);
@@ -420,7 +423,7 @@ namespace Stockfish::Tools
if (search_pv.empty())
continue;
pos.sfen_pack(ps.sfen);
pos.sfen_pack(ps.sfen, false);
ps.score = search_value;
if (!params.keep_moves)
ps.move = search_pv[0];