ai: tt: 完全去除 bestMove 相关参数
内存占用由 409M 缩小到 285M。 自对弈时长几乎无变化。
This commit is contained in:
parent
9e206cf972
commit
f2e4f00a5a
|
@ -88,6 +88,7 @@
|
|||
#define CLEAR_TRANSPOSITION_TABLE
|
||||
#define TRANSPOSITION_TABLE_FAKE_CLEAN
|
||||
#define TRANSPOSITION_TABLE_CUTDOWN
|
||||
//#define BEST_MOVE_ENABLE
|
||||
//#define TRANSPOSITION_TABLE_DEBUG
|
||||
#endif
|
||||
|
||||
|
|
|
@ -24,8 +24,14 @@
|
|||
#include "misc.h"
|
||||
#include "option.h"
|
||||
|
||||
void MoveList::generate(AIAlgorithm &ai, Game &tempGame,
|
||||
Node *parent, Node *root, move_t bestMove)
|
||||
void MoveList::generate(AIAlgorithm &ai,
|
||||
Game &tempGame,
|
||||
Node *parent,
|
||||
Node *root
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, move_t bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
)
|
||||
{
|
||||
square_t square = SQ_0;
|
||||
player_t opponent = PLAYER_NOBODY;
|
||||
|
@ -47,11 +53,19 @@ void MoveList::generate(AIAlgorithm &ai, Game &tempGame,
|
|||
|
||||
// 否则如果是空位
|
||||
if (tempGame.position.phase != PHASE_READY || parent != root) {
|
||||
ai.addNode(parent, VALUE_ZERO, RATING_ZERO, (move_t)square, bestMove);
|
||||
ai.addNode(parent, VALUE_ZERO, RATING_ZERO, (move_t)square
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
} else {
|
||||
// 若为先手,则抢占星位
|
||||
if (Board::isStar(square)) {
|
||||
ai.addNode(parent, VALUE_INFINITE, RATING_STAR_SQUARE, (move_t)square, bestMove);
|
||||
ai.addNode(parent, VALUE_INFINITE, RATING_STAR_SQUARE, (move_t)square
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +92,11 @@ void MoveList::generate(AIAlgorithm &ai, Game &tempGame,
|
|||
newSquare = static_cast<square_t>(moveTable[oldSquare][direction]);
|
||||
if (newSquare && !tempGame.boardLocations[newSquare]) {
|
||||
move_t move = move_t((oldSquare << 8) + newSquare);
|
||||
ai.addNode(parent, VALUE_ZERO, RATING_ZERO, move, bestMove); // (12%)
|
||||
ai.addNode(parent, VALUE_ZERO, RATING_ZERO, move
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -86,7 +104,11 @@ void MoveList::generate(AIAlgorithm &ai, Game &tempGame,
|
|||
for (newSquare = SQ_BEGIN; newSquare < SQ_END; newSquare = static_cast<square_t>(newSquare + 1)) {
|
||||
if (!tempGame.boardLocations[newSquare]) {
|
||||
move_t move = move_t((oldSquare << 8) + newSquare);
|
||||
ai.addNode(parent, VALUE_ZERO, RATING_ZERO, move, bestMove);
|
||||
ai.addNode(parent, VALUE_ZERO, RATING_ZERO, move
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +125,11 @@ void MoveList::generate(AIAlgorithm &ai, Game &tempGame,
|
|||
for (int i = Board::MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
|
||||
square = static_cast<square_t>(movePriorityTable[i]);
|
||||
if (tempGame.boardLocations[square] & opponent) {
|
||||
ai.addNode(parent, VALUE_ZERO, RATING_ZERO, (move_t)-square, bestMove);
|
||||
ai.addNode(parent, VALUE_ZERO, RATING_ZERO, (move_t)-square
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -114,7 +140,11 @@ void MoveList::generate(AIAlgorithm &ai, Game &tempGame,
|
|||
square = static_cast<square_t>(movePriorityTable[i]);
|
||||
if (tempGame.boardLocations[square] & opponent) {
|
||||
if (rule.allowRemoveMill || !tempGame.position.board.inHowManyMills(square)) {
|
||||
ai.addNode(parent, VALUE_ZERO, RATING_ZERO, (move_t)-square, bestMove);
|
||||
ai.addNode(parent, VALUE_ZERO, RATING_ZERO, (move_t)-square
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,9 +32,14 @@ public:
|
|||
MoveList &operator=(const MoveList &) = delete;
|
||||
|
||||
// 生成所有合法的着法并建立子节点
|
||||
static void generate(AIAlgorithm &ai, Game &tempGame,
|
||||
Node *parent, Node *root,
|
||||
move_t bestMove);
|
||||
static void generate(AIAlgorithm &ai,
|
||||
Game &tempGame,
|
||||
Node *parent,
|
||||
Node *root
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, move_t bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
|
||||
// 生成着法表
|
||||
static void create();
|
||||
|
|
|
@ -167,7 +167,11 @@ depth_t AIAlgorithm::changeDepth(depth_t origDepth)
|
|||
|
||||
void AIAlgorithm::buildRoot()
|
||||
{
|
||||
root = addNode(nullptr, VALUE_ZERO, RATING_ZERO, MOVE_NONE, MOVE_NONE);
|
||||
root = addNode(nullptr, VALUE_ZERO, RATING_ZERO, MOVE_NONE
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, MOVE_NONE
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
root->sideToMove = PLAYER_NOBODY;
|
||||
|
||||
assert(root != nullptr);
|
||||
|
@ -177,8 +181,10 @@ Node *AIAlgorithm::addNode(
|
|||
Node *parent,
|
||||
const value_t &value,
|
||||
const rating_t &rating,
|
||||
const move_t &move,
|
||||
const move_t &bestMove
|
||||
const move_t &move
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, const move_t &bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
)
|
||||
{
|
||||
Node *newNode = (Node *)memmgr.memmgr_alloc(sizeof(Node));
|
||||
|
@ -253,13 +259,13 @@ Node *AIAlgorithm::addNode(
|
|||
parent->children[parent->childrenSize] = newNode;
|
||||
parent->childrenSize++;
|
||||
|
||||
#if 0
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
// 如果启用了置换表并且不是叶子结点
|
||||
if (move == bestMove && move != 0) {
|
||||
newNode->rating += RATING_TT;
|
||||
return newNode;
|
||||
}
|
||||
#endif
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
|
||||
// 若没有启用置换表,或启用了但为叶子节点,则 bestMove 为0
|
||||
square_t sq = SQ_0;
|
||||
|
@ -660,8 +666,10 @@ value_t AIAlgorithm::search(depth_t depth, value_t alpha, value_t beta, Node *no
|
|||
// 临时增加的深度,克服水平线效应用
|
||||
depth_t epsilon = 0;
|
||||
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
// 子节点的最优着法
|
||||
move_t bestMove = MOVE_NONE;
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
|
||||
#if defined (TRANSPOSITION_TABLE_ENABLE) || defined(ENDGAME_LEARNING)
|
||||
// 获取哈希值
|
||||
|
@ -701,7 +709,11 @@ value_t AIAlgorithm::search(depth_t depth, value_t alpha, value_t beta, Node *no
|
|||
|
||||
TT::HashType type = TT::hashfEMPTY;
|
||||
|
||||
value_t probeVal = TT::probeHash(hash, depth, alpha, beta, bestMove, type);
|
||||
value_t probeVal = TT::probeHash(hash, depth, alpha, beta, type
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
|
||||
if (probeVal != VALUE_UNKNOWN) {
|
||||
#ifdef DEBUG_MODE
|
||||
|
@ -779,14 +791,25 @@ value_t AIAlgorithm::search(depth_t depth, value_t alpha, value_t beta, Node *no
|
|||
|
||||
#ifdef TRANSPOSITION_TABLE_ENABLE
|
||||
// 记录确切的哈希值
|
||||
TT::recordHash(node->value, depth, TT::hashfEXACT, hash, MOVE_NONE);
|
||||
TT::recordHash(node->value,
|
||||
depth,
|
||||
TT::hashfEXACT,
|
||||
hash
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, MOVE_NONE
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
#endif
|
||||
|
||||
return node->value;
|
||||
}
|
||||
|
||||
// 生成子节点树,即生成每个合理的着法
|
||||
MoveList::generate(*this, tempGame, node, root, bestMove);
|
||||
MoveList::generate(*this, tempGame, node, root
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
|
||||
// 排序子节点树
|
||||
sortMoves(node);
|
||||
|
@ -926,7 +949,14 @@ value_t AIAlgorithm::search(depth_t depth, value_t alpha, value_t beta, Node *no
|
|||
|
||||
#ifdef TRANSPOSITION_TABLE_ENABLE
|
||||
// 记录不一定确切的哈希值
|
||||
TT::recordHash(node->value, depth, hashf, hash, node->children[0]->move);
|
||||
TT::recordHash(node->value,
|
||||
depth,
|
||||
hashf,
|
||||
hash
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, node->children[0]->move
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
#endif /* TRANSPOSITION_TABLE_ENABLE */
|
||||
|
||||
// 返回
|
||||
|
|
|
@ -162,8 +162,14 @@ public:
|
|||
|
||||
public: /* TODO: Move to private or protected */
|
||||
// 增加新节点
|
||||
Node *addNode(Node *parent, const value_t &value, const rating_t &rating,
|
||||
const move_t &move, const move_t &bestMove);
|
||||
Node *addNode(Node *parent,
|
||||
const value_t &value,
|
||||
const rating_t &rating,
|
||||
const move_t &move
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, const move_t &bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
|
||||
protected:
|
||||
// 对合法的着法降序排序
|
||||
|
|
|
@ -31,7 +31,11 @@ value_t TT::probeHash(const hash_t &hash,
|
|||
const depth_t &depth,
|
||||
const value_t &alpha,
|
||||
const value_t &beta,
|
||||
move_t &bestMove, HashType &type)
|
||||
HashType &type
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, move_t &bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
)
|
||||
{
|
||||
HashValue hashValue{};
|
||||
|
||||
|
@ -69,7 +73,11 @@ value_t TT::probeHash(const hash_t &hash,
|
|||
}
|
||||
|
||||
out:
|
||||
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
bestMove = hashValue.bestMove;
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
|
||||
return VALUE_UNKNOWN;
|
||||
}
|
||||
|
||||
|
@ -105,8 +113,11 @@ bool TT::findHash(const hash_t &hash, TT::HashValue &hashValue)
|
|||
int TT::recordHash(const value_t &value,
|
||||
const depth_t &depth,
|
||||
const TT::HashType &type,
|
||||
const hash_t &hash,
|
||||
const move_t &bestMove)
|
||||
const hash_t &hash
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, const move_t &bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
)
|
||||
{
|
||||
// 同样深度或更深时替换
|
||||
// 注意: 每走一步以前都必须把散列表中所有的标志项置为 hashfEMPTY
|
||||
|
@ -130,7 +141,10 @@ int TT::recordHash(const value_t &value,
|
|||
hashValue.value = value;
|
||||
hashValue.depth = depth;
|
||||
hashValue.type = type;
|
||||
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
hashValue.bestMove = bestMove;
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
|
||||
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
|
||||
hashValue.age = transpositionTableAge;
|
||||
|
|
21
src/ai/tt.h
21
src/ai/tt.h
|
@ -53,15 +53,32 @@ public:
|
|||
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
|
||||
uint8_t age;
|
||||
#endif // TRANSPOSITION_TABLE_FAKE_CLEAN
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
move_t bestMove;
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
};
|
||||
|
||||
// 查找哈希表
|
||||
static bool findHash(const hash_t &hash, HashValue &hashValue);
|
||||
static value_t probeHash(const hash_t &hash, const depth_t &depth, const value_t &alpha, const value_t &beta, move_t &bestMove, HashType &type);
|
||||
static value_t probeHash(const hash_t &hash,
|
||||
const depth_t &depth,
|
||||
const value_t &alpha,
|
||||
const value_t &beta,
|
||||
HashType &type
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, move_t &bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
|
||||
// 插入哈希表
|
||||
static int recordHash(const value_t &value, const depth_t &depth, const HashType &type, const hash_t &hash, const move_t &bestMove);
|
||||
static int recordHash(const value_t &value,
|
||||
const depth_t &depth,
|
||||
const HashType &type,
|
||||
const hash_t &hash
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, const move_t &bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
);
|
||||
|
||||
// 清空置换表
|
||||
static void clear();
|
||||
|
|
Loading…
Reference in New Issue