BEST_MOVE_ENABLE 改为 TT_MOVE_ENABLE 并完善部分代码 (未完成)
目前在开启后,700盘自对弈显示速度为关闭时的 96.5%, 和关闭时对战600盘,胜率相差 0.8% 左右,可以认为相当。 暂未开启此宏。
This commit is contained in:
parent
2e10e9d380
commit
8d844cd919
|
@ -90,7 +90,7 @@
|
|||
#define CLEAR_TRANSPOSITION_TABLE
|
||||
#define TRANSPOSITION_TABLE_FAKE_CLEAN
|
||||
//#define TRANSPOSITION_TABLE_CUTDOWN
|
||||
//#define BEST_MOVE_ENABLE
|
||||
//#define TT_MOVE_ENABLE
|
||||
//#define TRANSPOSITION_TABLE_DEBUG
|
||||
#endif
|
||||
|
||||
|
|
|
@ -402,7 +402,7 @@ move_t AIAlgorithm::computeMove(StateInfo state,
|
|||
|
||||
// Find the node with the highest score.
|
||||
double bestScore = -1;
|
||||
move_t bestMove = move_t();
|
||||
move_t ttMove = move_t();
|
||||
|
||||
for (auto iter : visits) {
|
||||
auto move = iter.first;
|
||||
|
@ -412,7 +412,7 @@ move_t AIAlgorithm::computeMove(StateInfo state,
|
|||
// https://en.wikipedia.org/wiki/Beta_distribution
|
||||
double expectedSuccessRate = (w + 1) / (v + 2);
|
||||
if (expectedSuccessRate > bestScore) {
|
||||
bestMove = move;
|
||||
ttMove = move;
|
||||
bestScore = expectedSuccessRate;
|
||||
}
|
||||
|
||||
|
@ -424,10 +424,10 @@ move_t AIAlgorithm::computeMove(StateInfo state,
|
|||
}
|
||||
|
||||
if (options.verbose) {
|
||||
auto best_wins = wins[bestMove];
|
||||
auto best_visits = visits[bestMove];
|
||||
auto best_wins = wins[ttMove];
|
||||
auto best_visits = visits[ttMove];
|
||||
cerr << "----" << endl;
|
||||
cerr << "Best: " << bestMove
|
||||
cerr << "Best: " << ttMove
|
||||
<< " (" << 100.0 * best_visits / double(gamesPlayed) << "% visits)"
|
||||
<< " (" << 100.0 * best_wins / best_visits << "% wins)" << endl;
|
||||
}
|
||||
|
@ -441,7 +441,7 @@ move_t AIAlgorithm::computeMove(StateInfo state,
|
|||
}
|
||||
#endif
|
||||
|
||||
return bestMove;
|
||||
return ttMove;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -30,9 +30,9 @@
|
|||
void StateInfo::generateChildren(const Stack<move_t, MOVE_COUNT> &moves,
|
||||
AIAlgorithm *ai,
|
||||
Node *node
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, move_t bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
, move_t ttMove
|
||||
#endif // TT_MOVE_ENABLE
|
||||
)
|
||||
{
|
||||
int size = moves.size();
|
||||
|
@ -48,9 +48,9 @@ void StateInfo::generateChildren(const Stack<move_t, MOVE_COUNT> &moves,
|
|||
|
||||
for (int i = 0; i < size; i++) {
|
||||
node->addChild(moves[i], ai, this
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
, ttMove
|
||||
#endif // TT_MOVE_ENABLE
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
Sanmill, a mill game playing engine derived from NineChess 1.5
|
||||
Copyright (C) 2015-2018 liuweilhy (NineChess author)
|
||||
Copyright (C) 2019-2020 Calcitem <calcitem@outlook.com>
|
||||
|
||||
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 "movepick.h"
|
||||
#include "option.h"
|
||||
#include "types.h"
|
||||
#include "config.h"
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
Sanmill, a mill game playing engine derived from NineChess 1.5
|
||||
Copyright (C) 2015-2018 liuweilhy (NineChess author)
|
||||
Copyright (C) 2019-2020 Calcitem <calcitem@outlook.com>
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#ifndef MOVEPICK_H
|
||||
#define MOVEPICK_H
|
||||
|
||||
#include "stack.h"
|
||||
#include "types.h"
|
||||
|
||||
// TODO: Fix size
|
||||
typedef Stack<score_t, 64> PlaceHistory;
|
||||
typedef Stack<score_t, 64> CaptureHistory;
|
||||
typedef Stack<score_t, 10240> MoveHistory;
|
||||
|
||||
class MovePicker
|
||||
{
|
||||
public:
|
||||
static PlaceHistory placeHistory;
|
||||
static CaptureHistory captureHistory;
|
||||
static MoveHistory moveHistory;
|
||||
|
||||
static score_t getHistoryScore(move_t move)
|
||||
{
|
||||
score_t ret;
|
||||
|
||||
if (move < 0) {
|
||||
ret = placeHistory[-move];
|
||||
} else if (move & 0x7f00) {
|
||||
ret = moveHistory[move];
|
||||
} else {
|
||||
ret = placeHistory[move & 0x007f];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void setHistoryScore(move_t move, depth_t depth)
|
||||
{
|
||||
if (move == MOVE_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
score_t score = 1 << depth;
|
||||
|
||||
if (move < 0) {
|
||||
placeHistory[-move] += score;
|
||||
} else if (move & 0x7f00) {
|
||||
moveHistory[move] += score;
|
||||
} else {
|
||||
moveHistory[move & 0x007f] += score;
|
||||
}
|
||||
}
|
||||
|
||||
static void clearHistoryScore()
|
||||
{
|
||||
placeHistory.clear();
|
||||
captureHistory.clear();
|
||||
moveHistory.clear();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // MOVEPICK_H
|
|
@ -178,19 +178,15 @@ void AIAlgorithm::buildRoot()
|
|||
#endif // ALPHABETA_AI
|
||||
|
||||
root->sideToMove = PLAYER_NOBODY;
|
||||
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
root->bestMove = MOVE_NONE;
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
}
|
||||
|
||||
Node *Node::addChild(
|
||||
const move_t &m,
|
||||
AIAlgorithm *ai,
|
||||
StateInfo *st
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, const move_t &bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
, const move_t &ttMove
|
||||
#endif // TT_MOVE_ENABLE
|
||||
)
|
||||
{
|
||||
Node *newNode = (Node *)ai->memmgr.memmgr_alloc(sizeof(Node));
|
||||
|
@ -261,15 +257,15 @@ Node *Node::addChild(
|
|||
children[childrenSize] = newNode;
|
||||
childrenSize++;
|
||||
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
// 如果启用了置换表并且不是叶子结点
|
||||
if (move == bestMove && move != 0) {
|
||||
if (move == ttMove && move != 0) {
|
||||
newNode->rating += RATING_TT;
|
||||
return newNode;
|
||||
}
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#endif // TT_MOVE_ENABLE
|
||||
|
||||
// 若没有启用置换表,或启用了但为叶子节点,则 bestMove 为0
|
||||
// 若没有启用置换表,或启用了但为叶子节点,则 ttMove 为0
|
||||
square_t sq = SQ_0;
|
||||
|
||||
if (m > 0) {
|
||||
|
@ -677,10 +673,10 @@ value_t AIAlgorithm::search(depth_t depth, value_t alpha, value_t beta, Node *no
|
|||
// 临时增加的深度,克服水平线效应用
|
||||
depth_t epsilon;
|
||||
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
// 子节点的最优着法
|
||||
move_t bestMove = MOVE_NONE;
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
// 置换表中读取到的最优着法
|
||||
move_t ttMove = MOVE_NONE;
|
||||
#endif // TT_MOVE_ENABLE
|
||||
|
||||
#if defined (TRANSPOSITION_TABLE_ENABLE) || defined(ENDGAME_LEARNING)
|
||||
// 获取哈希值
|
||||
|
@ -721,9 +717,9 @@ 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, type
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
, ttMove
|
||||
#endif // TT_MOVE_ENABLE
|
||||
);
|
||||
|
||||
if (probeVal != VALUE_UNKNOWN) {
|
||||
|
@ -746,6 +742,12 @@ value_t AIAlgorithm::search(depth_t depth, value_t alpha, value_t beta, Node *no
|
|||
node->value -= hashValue.depth - depth;
|
||||
#endif
|
||||
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
// if (ttMove != MOVE_NONE) {
|
||||
// best = ttMove;
|
||||
// }
|
||||
#endif // TT_MOVE_ENABLE
|
||||
|
||||
return node->value;
|
||||
}
|
||||
#ifdef TRANSPOSITION_TABLE_DEBUG
|
||||
|
@ -819,9 +821,9 @@ value_t AIAlgorithm::search(depth_t depth, value_t alpha, value_t beta, Node *no
|
|||
depth,
|
||||
TT::hashfEXACT,
|
||||
hash
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
, MOVE_NONE
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#endif // TT_MOVE_ENABLE
|
||||
);
|
||||
#endif
|
||||
|
||||
|
@ -833,9 +835,9 @@ value_t AIAlgorithm::search(depth_t depth, value_t alpha, value_t beta, Node *no
|
|||
int moveSize = st->generateMoves(moves);
|
||||
|
||||
st->generateChildren(moves, this, node
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
, ttMove
|
||||
#endif // TT_MOVE_ENABLE
|
||||
);
|
||||
|
||||
if (node == root && moveSize == 1) {
|
||||
|
@ -963,9 +965,9 @@ out:
|
|||
depth,
|
||||
hashf,
|
||||
hash
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
, best
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#endif // TT_MOVE_ENABLE
|
||||
);
|
||||
#endif /* TRANSPOSITION_TABLE_ENABLE */
|
||||
|
||||
|
@ -1007,7 +1009,7 @@ void AIAlgorithm::undoNullMove()
|
|||
}
|
||||
|
||||
#ifdef ALPHABETA_AI
|
||||
const char* AIAlgorithm::bestMove()
|
||||
const char* AIAlgorithm::ttMove()
|
||||
{
|
||||
char charChoose = '*';
|
||||
|
||||
|
|
|
@ -78,9 +78,9 @@ public:
|
|||
const move_t &move,
|
||||
AIAlgorithm *ai,
|
||||
StateInfo *st
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, const move_t &bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
, const move_t &ttMove
|
||||
#endif // TT_MOVE_ENABLE
|
||||
);
|
||||
|
||||
#ifdef MCTS_AI
|
||||
|
@ -115,10 +115,6 @@ public:
|
|||
move_t move { MOVE_NONE };
|
||||
int childrenSize { 0 };
|
||||
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
move_t bestMove;
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
|
||||
#ifdef ALPHABETA_AI
|
||||
value_t value { VALUE_UNKNOWN };
|
||||
rating_t rating { RATING_ZERO };
|
||||
|
@ -182,7 +178,7 @@ public:
|
|||
int search(depth_t depth);
|
||||
|
||||
// 返回最佳走法的命令行
|
||||
const char *bestMove();
|
||||
const char *ttMove();
|
||||
#endif // ALPHABETA_AI
|
||||
|
||||
// 暂存局面
|
||||
|
|
|
@ -32,9 +32,9 @@ value_t TT::probeHash(const hash_t &hash,
|
|||
const value_t &alpha,
|
||||
const value_t &beta,
|
||||
HashType &type
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, move_t &bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
, move_t &ttMove
|
||||
#endif // TT_MOVE_ENABLE
|
||||
)
|
||||
{
|
||||
HashValue hashValue{};
|
||||
|
@ -76,9 +76,9 @@ value_t TT::probeHash(const hash_t &hash,
|
|||
|
||||
out:
|
||||
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
bestMove = hashValue.bestMove;
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
ttMove = hashValue.ttMove;
|
||||
#endif // TT_MOVE_ENABLE
|
||||
|
||||
return VALUE_UNKNOWN;
|
||||
}
|
||||
|
@ -121,9 +121,9 @@ int TT::recordHash(const value_t &value,
|
|||
const depth_t &depth,
|
||||
const TT::HashType &type,
|
||||
const hash_t &hash
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, const move_t &bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
, const move_t &ttMove
|
||||
#endif // TT_MOVE_ENABLE
|
||||
)
|
||||
{
|
||||
// 同样深度或更深时替换
|
||||
|
@ -149,9 +149,9 @@ int TT::recordHash(const value_t &value,
|
|||
hashValue.depth = depth;
|
||||
hashValue.type = type;
|
||||
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
hashValue.bestMove = bestMove;
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
hashValue.ttMove = ttMove;
|
||||
#endif // TT_MOVE_ENABLE
|
||||
|
||||
#ifdef TRANSPOSITION_TABLE_FAKE_CLEAN
|
||||
hashValue.age = transpositionTableAge;
|
||||
|
|
18
src/ai/tt.h
18
src/ai/tt.h
|
@ -53,9 +53,9 @@ 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
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
move_t ttMove;
|
||||
#endif // TT_MOVE_ENABLE
|
||||
};
|
||||
|
||||
// 查找哈希表
|
||||
|
@ -65,9 +65,9 @@ public:
|
|||
const value_t &alpha,
|
||||
const value_t &beta,
|
||||
HashType &type
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, move_t &bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
, move_t &ttMove
|
||||
#endif // TT_MOVE_ENABLE
|
||||
);
|
||||
|
||||
// 插入哈希表
|
||||
|
@ -75,9 +75,9 @@ public:
|
|||
const depth_t &depth,
|
||||
const HashType &type,
|
||||
const hash_t &hash
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, const move_t &bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
, const move_t &ttMove
|
||||
#endif // TT_MOVE_ENABLE
|
||||
);
|
||||
|
||||
// 清空置换表
|
||||
|
|
|
@ -139,7 +139,7 @@ void AiThread::run()
|
|||
strCommand = "draw";
|
||||
emitCommand();
|
||||
} else {
|
||||
strCommand = ai.bestMove();
|
||||
strCommand = ai.ttMove();
|
||||
if (strCommand && strcmp(strCommand, "error!") != 0) {
|
||||
loggerDebug("Computer: %s\n\n", strCommand);
|
||||
emitCommand();
|
||||
|
|
|
@ -242,9 +242,9 @@ public:
|
|||
void generateChildren(const Stack<move_t, MOVE_COUNT> &moves,
|
||||
AIAlgorithm *ai,
|
||||
Node *node
|
||||
#ifdef BEST_MOVE_ENABLE
|
||||
, move_t bestMove
|
||||
#endif // BEST_MOVE_ENABLE
|
||||
#ifdef TT_MOVE_ENABLE
|
||||
, move_t ttMove
|
||||
#endif // TT_MOVE_ENABLE
|
||||
);
|
||||
|
||||
// 着法生成
|
||||
|
|
Loading…
Reference in New Issue