Actually, I was thinking of simply storing two ExtMove pointers inside the StateInfo class, and to let the move generator check these pointers against NULL before generating moves. If the moves have been generated before, return a pair of pointers to the begin/end of that storage. If they haven't, generate them, and return two pointers to the beginning and end of that range.mcostalba wrote:In SF move list is allocated on the stack so you can't really do this without copying the moves to a permanent storage.Rein Halbersma wrote:Are there any engines that cache the generated move list? What I mean with that is that during internal iterative deepening, multi-probe cut, PVS and LMR re-searches, the position from which is being re-searched is the same one at the current ply level inside a recursive search() function.
Maybe you could use a global storage as backup to generate the moves, but this seems quite complex to me, considering also SMP case and the fact that you have to allocate in advance MAX_MOVES * MAX_PLY size storage.
Something like this (untested)
Code: Select all
struct StateInfo {
ExtMove* first;
ExtMove* last;
// as before
};
void Position::do_cache_movelist(ExtMove* first, ExtMove* last) {
st->first = first;
st->last = last;
}
void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveIsCheck) {
// as before
// this is also already there, but after this statement...
st = &newSt;
// ... you can reset the status to "uncached" by putting in null pointers
do_cache_movelist(nullptr, nullptr); // undo_move will restore to previous StateInfo with the cached movelist
// as before
}
template<>
std::pair<ExtMove*, ExtMove*> cached_generate<LEGAL>(const Position& pos, ExtMove* first) {
if (p.st->last == nullptr) // haven't generated moves for this position before
p.cache_movelist(first, generate<LEGAL>(p, first));
return std::make_pair(p.st->first, p.st->last);
}