Sanmill/src/tt.cpp

169 lines
3.9 KiB
C++

/*
This file is part of Sanmill.
Copyright (C) 2019-2021 The Sanmill developers (see AUTHORS file)
Sanmill is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Sanmill is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tt.h"
#ifdef TRANSPOSITION_TABLE_ENABLE
static constexpr int TRANSPOSITION_TABLE_SIZE = 0x1000000;
HashMap<Key, TTEntry> TT(TRANSPOSITION_TABLE_SIZE);
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
uint8_t transpositionTableAge;
#endif // TRANSPOSITION_TABLE_FAKE_CLEAN
Value TranspositionTable::probe(const Key &key,
const Depth &depth,
const Value &alpha,
const Value &beta,
Bound &type
#ifdef TT_MOVE_ENABLE
, Move &ttMove
#endif // TT_MOVE_ENABLE
)
{
TTEntry tte {};
if (!TT.find(key, tte)) {
return VALUE_UNKNOWN;
}
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN_NOT_EXACT_ONLY
if (tte.type != BOUND_EXACT) {
#endif
if (tte.age8 != transpositionTableAge) {
return VALUE_UNKNOWN;
}
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN_NOT_EXACT_ONLY
}
#endif
#endif // TRANSPOSITION_TABLE_FAKE_CLEAN
if (depth > tte.depth()) {
goto out;
}
type = tte.bound();
switch (tte.bound()) {
case BOUND_EXACT:
return tte.value();
break;
case BOUND_UPPER:
if (tte.value8 <= alpha) {
return alpha;
}
break;
case BOUND_LOWER:
if (tte.value() >= beta) {
return beta;
}
break;
default:
break;
}
out:
#ifdef TT_MOVE_ENABLE
ttMove = tte.ttMove;
#endif // TT_MOVE_ENABLE
return VALUE_UNKNOWN;
}
bool TranspositionTable::search(const Key &key, TTEntry &tte)
{
return TT.find(key, tte);
}
void TranspositionTable::prefetch(const Key &key)
{
TT.prefetchValue(key);
}
int TranspositionTable::save(const Value &value,
const Depth &depth,
const Bound &type,
const Key &key
#ifdef TT_MOVE_ENABLE
, const Move &ttMove
#endif // TT_MOVE_ENABLE
)
{
TTEntry tte {};
if (search(key, tte)) {
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
if (tte.age8 == transpositionTableAge) {
#endif // TRANSPOSITION_TABLE_FAKE_CLEAN
if (tte.genBound8 != BOUND_NONE &&
tte.depth() > depth) {
return -1;
}
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
}
#endif // TRANSPOSITION_TABLE_FAKE_CLEAN
}
tte.value8 = value;
tte.depth8 = depth;
tte.genBound8 = type;
#ifdef TT_MOVE_ENABLE
tte.ttMove = ttMove;
#endif // TT_MOVE_ENABLE
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
tte.age8 = transpositionTableAge;
#endif // TRANSPOSITION_TABLE_FAKE_CLEAN
TT.insert(key, tte);
return 0;
}
Bound TranspositionTable::boundType(Value value, Value alpha, Value beta)
{
if (value <= alpha)
return BOUND_UPPER;
if (value >= beta)
return BOUND_LOWER;
return BOUND_EXACT;
}
void TranspositionTable::clear()
{
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
if (transpositionTableAge == std::numeric_limits<uint8_t>::max())
{
loggerDebug("Clean TT\n");
TT.clear();
transpositionTableAge = 0;
} else {
transpositionTableAge++;
}
#else
TT.clear();
#endif // TRANSPOSITION_TABLE_FAKE_CLEAN
}
#endif /* TRANSPOSITION_TABLE_ENABLE */