summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
ec6aab0)
In this position we should have draw for repetition:
position fen rnbqkbnr/2pppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 moves g1f3 g8f6 f3g1
go infinite
But latest patch broke it.
Actually we had two(!) very subtle bugs, the first is that Position::set()
clears the passed state and in particular 'previous' member, so
that on passing setupStates, 'previous' pointer was reset.
Second bug is even more subtle: SetupStates was based on std::vector
as container, but when vector grows, std::vector copies all its contents
to a new location invalidating all references to its entries. Because
all StateInfo records are linked by 'previous' pointer, this made pointers
go stale upon adding more element to setupStates. So revert to use a
std::deque that ensures references are preserved when pushing back new
elements.
No functional change.
for (size_t i = 0; i < fens.size(); ++i)
{
for (size_t i = 0; i < fens.size(); ++i)
{
- StateListPtr states(new std::vector<StateInfo>(1));
+ StateListPtr states(new std::deque<StateInfo>(1));
pos.set(fens[i], Options["UCI_Chess960"], &states->back(), Threads.main());
cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
pos.set(fens[i], Options["UCI_Chess960"], &states->back(), Threads.main());
cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
#include <cassert>
#include <cstddef> // For offsetof()
#include <cassert>
#include <cstddef> // For offsetof()
#include <memory> // For std::unique_ptr
#include <string>
#include <vector>
#include <memory> // For std::unique_ptr
#include <string>
#include <vector>
-typedef std::unique_ptr<std::vector<StateInfo>> StateListPtr;
+// In a std::deque references to elements are unaffected upon resizing
+typedef std::unique_ptr<std::deque<StateInfo>> StateListPtr;
/// Position class stores information regarding the board representation as
/// Position class stores information regarding the board representation as
if (states.get())
setupStates = std::move(states); // Ownership transfer, states is now empty
if (states.get())
setupStates = std::move(states); // Ownership transfer, states is now empty
+ StateInfo tmp = setupStates->back();
+
for (Thread* th : Threads)
{
th->maxPly = 0;
for (Thread* th : Threads)
{
th->maxPly = 0;
th->rootPos.set(pos.fen(), pos.is_chess960(), &setupStates->back(), th);
}
th->rootPos.set(pos.fen(), pos.is_chess960(), &setupStates->back(), th);
}
+ setupStates->back() = tmp; // Restore st->previous, cleared by Position::set()
+
main()->start_searching();
}
main()->start_searching();
}
// A list to keep track of the position states along the setup moves (from the
// start position to the position just before the search starts). Needed by
// 'draw by repetition' detection.
// A list to keep track of the position states along the setup moves (from the
// start position to the position just before the search starts). Needed by
// 'draw by repetition' detection.
- StateListPtr States(new std::vector<StateInfo>(1));
+ StateListPtr States(new std::deque<StateInfo>(1));
// position() is called when engine receives the "position" UCI command.
// position() is called when engine receives the "position" UCI command.
- States = StateListPtr(new std::vector<StateInfo>(1));
+ States = StateListPtr(new std::deque<StateInfo>(1));
pos.set(fen, Options["UCI_Chess960"], &States->back(), Threads.main());
// Parse move list (if any)
pos.set(fen, Options["UCI_Chess960"], &States->back(), Threads.main());
// Parse move list (if any)