2019-11-03 13:00:45 +08:00
|
|
|
|
/*
|
2020-12-14 00:59:45 +08:00
|
|
|
|
This file is part of Sanmill.
|
|
|
|
|
Copyright (C) 2019-2021 The Sanmill developers (see AUTHORS file)
|
2019-11-03 13:00:45 +08:00
|
|
|
|
|
|
|
|
|
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/>.
|
|
|
|
|
*/
|
2019-10-26 21:40:26 +08:00
|
|
|
|
|
|
|
|
|
#include "tt.h"
|
2019-09-09 00:19:02 +08:00
|
|
|
|
|
2019-09-09 00:56:46 +08:00
|
|
|
|
#ifdef TRANSPOSITION_TABLE_ENABLE
|
2021-04-26 22:55:08 +08:00
|
|
|
|
|
2021-05-01 20:40:39 +08:00
|
|
|
|
static constexpr int TRANSPOSITION_TABLE_SIZE = 0x1000000;
|
2020-05-17 11:04:08 +08:00
|
|
|
|
HashMap<Key, TTEntry> TT(TRANSPOSITION_TABLE_SIZE);
|
2019-09-09 01:22:38 +08:00
|
|
|
|
|
2019-10-02 12:18:31 +08:00
|
|
|
|
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
|
|
|
|
|
uint8_t transpositionTableAge;
|
|
|
|
|
#endif // TRANSPOSITION_TABLE_FAKE_CLEAN
|
|
|
|
|
|
2020-05-17 11:04:08 +08:00
|
|
|
|
Value TranspositionTable::probe(const Key &key,
|
|
|
|
|
const Depth &depth,
|
|
|
|
|
const Value &alpha,
|
|
|
|
|
const Value &beta,
|
|
|
|
|
Bound &type
|
2020-05-03 13:16:30 +08:00
|
|
|
|
#ifdef TT_MOVE_ENABLE
|
2020-05-17 11:04:08 +08:00
|
|
|
|
, Move &ttMove
|
2020-05-03 13:16:30 +08:00
|
|
|
|
#endif // TT_MOVE_ENABLE
|
2020-01-25 09:23:50 +08:00
|
|
|
|
)
|
2019-09-09 01:22:38 +08:00
|
|
|
|
{
|
2020-05-13 01:27:44 +08:00
|
|
|
|
TTEntry tte {};
|
2019-09-09 01:22:38 +08:00
|
|
|
|
|
2020-05-13 01:27:44 +08:00
|
|
|
|
if (!TT.find(key, tte)) {
|
2019-09-13 02:30:23 +08:00
|
|
|
|
return VALUE_UNKNOWN;
|
2019-09-09 01:22:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-02 12:18:31 +08:00
|
|
|
|
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
|
2020-05-13 00:46:36 +08:00
|
|
|
|
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN_NOT_EXACT_ONLY
|
2020-05-13 01:27:44 +08:00
|
|
|
|
if (tte.type != BOUND_EXACT) {
|
2020-05-13 00:46:36 +08:00
|
|
|
|
#endif
|
2020-09-01 23:49:12 +08:00
|
|
|
|
if (tte.age8 != transpositionTableAge) {
|
2020-05-13 00:46:36 +08:00
|
|
|
|
return VALUE_UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN_NOT_EXACT_ONLY
|
2019-10-02 12:18:31 +08:00
|
|
|
|
}
|
2020-05-13 00:46:36 +08:00
|
|
|
|
#endif
|
2019-10-02 12:18:31 +08:00
|
|
|
|
#endif // TRANSPOSITION_TABLE_FAKE_CLEAN
|
|
|
|
|
|
2020-09-01 23:49:12 +08:00
|
|
|
|
if (depth > tte.depth()) {
|
2019-09-09 01:22:38 +08:00
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-01 23:49:12 +08:00
|
|
|
|
type = tte.bound();
|
2019-09-09 01:22:38 +08:00
|
|
|
|
|
2020-09-01 23:49:12 +08:00
|
|
|
|
switch (tte.bound()) {
|
2020-05-10 00:33:34 +08:00
|
|
|
|
case BOUND_EXACT:
|
2020-09-01 23:49:12 +08:00
|
|
|
|
return tte.value();
|
2019-12-05 00:17:08 +08:00
|
|
|
|
break;
|
2020-06-27 01:18:02 +08:00
|
|
|
|
case BOUND_UPPER:
|
2020-09-01 23:49:12 +08:00
|
|
|
|
if (tte.value8 <= alpha) {
|
2021-04-26 22:55:08 +08:00
|
|
|
|
return alpha;
|
2019-12-05 00:17:08 +08:00
|
|
|
|
}
|
|
|
|
|
break;
|
2020-06-27 01:18:02 +08:00
|
|
|
|
case BOUND_LOWER:
|
2020-09-01 23:49:12 +08:00
|
|
|
|
if (tte.value() >= beta) {
|
2019-12-05 00:17:08 +08:00
|
|
|
|
return beta;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2020-03-22 23:59:26 +08:00
|
|
|
|
default:
|
|
|
|
|
break;
|
2019-09-09 01:22:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out:
|
2020-01-25 09:23:50 +08:00
|
|
|
|
|
2020-05-03 13:16:30 +08:00
|
|
|
|
#ifdef TT_MOVE_ENABLE
|
2020-05-13 01:27:44 +08:00
|
|
|
|
ttMove = tte.ttMove;
|
2020-05-03 13:16:30 +08:00
|
|
|
|
#endif // TT_MOVE_ENABLE
|
2020-01-25 09:23:50 +08:00
|
|
|
|
|
2019-09-13 02:30:23 +08:00
|
|
|
|
return VALUE_UNKNOWN;
|
2019-09-09 01:22:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-17 11:04:08 +08:00
|
|
|
|
bool TranspositionTable::search(const Key &key, TTEntry &tte)
|
2019-09-09 01:22:38 +08:00
|
|
|
|
{
|
2020-05-13 01:27:44 +08:00
|
|
|
|
return TT.find(key, tte);
|
2019-09-09 01:22:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-17 11:04:08 +08:00
|
|
|
|
void TranspositionTable::prefetch(const Key &key)
|
2020-04-19 02:53:04 +08:00
|
|
|
|
{
|
2020-05-13 01:27:44 +08:00
|
|
|
|
TT.prefetchValue(key);
|
2020-04-19 02:53:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-17 11:04:08 +08:00
|
|
|
|
int TranspositionTable::save(const Value &value,
|
|
|
|
|
const Depth &depth,
|
|
|
|
|
const Bound &type,
|
|
|
|
|
const Key &key
|
2020-05-03 13:16:30 +08:00
|
|
|
|
#ifdef TT_MOVE_ENABLE
|
2020-05-17 11:04:08 +08:00
|
|
|
|
, const Move &ttMove
|
2020-05-03 13:16:30 +08:00
|
|
|
|
#endif // TT_MOVE_ENABLE
|
2020-01-25 09:23:50 +08:00
|
|
|
|
)
|
2019-09-09 01:22:38 +08:00
|
|
|
|
{
|
2020-05-13 01:27:44 +08:00
|
|
|
|
TTEntry tte {};
|
2019-10-02 12:18:31 +08:00
|
|
|
|
|
2020-05-13 01:27:44 +08:00
|
|
|
|
if (search(key, tte)) {
|
2019-10-02 12:18:31 +08:00
|
|
|
|
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
|
2020-09-01 23:49:12 +08:00
|
|
|
|
if (tte.age8 == transpositionTableAge) {
|
2019-10-02 12:18:31 +08:00
|
|
|
|
#endif // TRANSPOSITION_TABLE_FAKE_CLEAN
|
2020-09-01 23:49:12 +08:00
|
|
|
|
if (tte.genBound8 != BOUND_NONE &&
|
|
|
|
|
tte.depth() > depth) {
|
2019-10-02 12:18:31 +08:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
|
|
|
|
|
}
|
|
|
|
|
#endif // TRANSPOSITION_TABLE_FAKE_CLEAN
|
2019-09-09 01:22:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-01 23:49:12 +08:00
|
|
|
|
tte.value8 = value;
|
|
|
|
|
tte.depth8 = depth;
|
|
|
|
|
tte.genBound8 = type;
|
2020-01-25 09:23:50 +08:00
|
|
|
|
|
2020-05-03 13:16:30 +08:00
|
|
|
|
#ifdef TT_MOVE_ENABLE
|
2020-05-13 01:27:44 +08:00
|
|
|
|
tte.ttMove = ttMove;
|
2020-05-03 13:16:30 +08:00
|
|
|
|
#endif // TT_MOVE_ENABLE
|
2019-09-09 01:22:38 +08:00
|
|
|
|
|
2019-10-02 12:18:31 +08:00
|
|
|
|
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
|
2020-09-01 23:49:12 +08:00
|
|
|
|
tte.age8 = transpositionTableAge;
|
2019-10-02 12:18:31 +08:00
|
|
|
|
#endif // TRANSPOSITION_TABLE_FAKE_CLEAN
|
|
|
|
|
|
2020-05-13 01:27:44 +08:00
|
|
|
|
TT.insert(key, tte);
|
2019-09-09 01:22:38 +08:00
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-19 23:36:47 +08:00
|
|
|
|
Bound TranspositionTable::boundType(Value value, Value alpha, Value beta)
|
|
|
|
|
{
|
|
|
|
|
if (value <= alpha)
|
|
|
|
|
return BOUND_UPPER;
|
|
|
|
|
if (value >= beta)
|
|
|
|
|
return BOUND_LOWER;
|
|
|
|
|
|
|
|
|
|
return BOUND_EXACT;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-13 01:27:44 +08:00
|
|
|
|
void TranspositionTable::clear()
|
2019-09-09 01:22:38 +08:00
|
|
|
|
{
|
2019-10-02 12:18:31 +08:00
|
|
|
|
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
|
2019-11-03 19:21:11 +08:00
|
|
|
|
if (transpositionTableAge == std::numeric_limits<uint8_t>::max())
|
2019-10-02 12:18:31 +08:00
|
|
|
|
{
|
|
|
|
|
loggerDebug("Clean TT\n");
|
2020-05-13 01:27:44 +08:00
|
|
|
|
TT.clear();
|
2019-10-02 12:18:31 +08:00
|
|
|
|
transpositionTableAge = 0;
|
|
|
|
|
} else {
|
|
|
|
|
transpositionTableAge++;
|
|
|
|
|
}
|
|
|
|
|
#else
|
2020-05-13 01:27:44 +08:00
|
|
|
|
TT.clear();
|
2019-10-02 12:18:31 +08:00
|
|
|
|
#endif // TRANSPOSITION_TABLE_FAKE_CLEAN
|
2019-09-09 01:22:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* TRANSPOSITION_TABLE_ENABLE */
|