添加未完成的Hash代码但暂时关闭宏

This commit is contained in:
CalciteM Team 2019-07-13 18:43:21 +08:00
parent 702a562bbd
commit 527fec2856
9 changed files with 105 additions and 40 deletions

View File

View File

@ -34,7 +34,9 @@ void AiThread::setAi(const NineChess &chess)
this->chess_ = &chess;
ai_ab.setChess(*(this->chess_));
#ifdef HASH_MAP_ENABLE
ai_ab.clearHashMap();
#endif
mutex.unlock();
}

View File

@ -1,15 +1,15 @@
#ifndef CONFIG_H
#define CONFIG_H
#define DEBUG
//#define DEBUG
//#define RANDOM_MOVE
#define RANDOM_MOVE
//#define DEAL_WITH_HORIZON_EFFECT
#define DEAL_WITH_HORIZON_EFFECT
//#define RANDOM_BEST_MOVE
#define HASH_MAP_ENABLE
//#define HASH_MAP_ENABLE
//#define DONOT_DELETE_TREE
@ -27,7 +27,7 @@
//#define DONOT_PLAY_SOUND
#ifdef DEBUG
#define GAME_PLACING_FIXED_DEPTH 3
#define GAME_PLACING_FIXED_DEPTH 4
#endif
#ifdef DEBUG
@ -48,7 +48,7 @@
#define DRAW_SEAT_NUMBER
#endif
//#define IDS_SUPPORT
#define IDS_SUPPORT
#define SAVE_CHESSBOOK_WHEN_ACTION_NEW_TRIGGERED

View File

@ -39,7 +39,7 @@ template <typename T>
T& HashMap<T>::at(uint64_t i)
{
if (i >= capacity) {
qDebug() << "索引超过最大值";
qDebug() << "Error";
return pool[0];
}
return pool[i];

View File

@ -1,4 +1,5 @@
#ifndef HASHMAP_H
#define HASHMAP_H
#include <limits>
#include <qDebug>
@ -8,7 +9,7 @@ class HashMap
{
public:
HashMap();
HashMap(size_t capacity);
HashMap(size_t capacity);
~HashMap();
enum FindResult
@ -25,6 +26,8 @@ public:
return pool[addr];
}
uint64_t hashToAddr(uint64_t hash);
T &find(uint64_t hash)
{
uint64_t addr = hashToAddr(hash);
@ -39,17 +42,15 @@ public:
void insert(uint64_t hash, const T &hashValue);
protected:
bool construct();
private:
size_t capacity;
size_t size;
T *pool;
T *pool;
bool construct();
uint64_t hashToAddr(uint64_t hash);
};
#endif // HASHMAP_H
#endif // HASHMAP_H

View File

@ -121,11 +121,14 @@ NineChess::NineChess()
{
// 单独提出 board 等数据,免得每次都写 context.board;
board_ = context.board;
#ifdef HASH_MAP_ENABLE
//hash_ = &context.hash;
//zobrist_ = &context.zobrist;
// 创建哈希数据
constructHash();
#endif
// 默认选择第1号规则即“打三棋”
setContext(&RULES[1]);
@ -176,6 +179,7 @@ NineChess::~NineChess()
{
}
#ifdef HASH_MAP_ENABLE
void NineChess::constructHash()
{
context.hash = 0ull;
@ -193,6 +197,7 @@ void NineChess::constructHash()
}
}
}
#endif /* HASH_MAP_ENABLE */
NineChess::Player NineChess::getOpponent(NineChess::Player player)
{
@ -324,8 +329,7 @@ void NineChess::createMillTable()
// 设置棋局状态和棋盘数据,用于初始化
bool NineChess::setContext(const struct Rule *rule, int maxStepsLedToDraw, int maxTimeLedToLose,
int initialStep, int flags, const char *board,
int nPiecesInHand_1, int nPiecesInHand_2, int nPiecesNeedRemove,
uint64_t hash, uint64_t hashCheckCode)
int nPiecesInHand_1, int nPiecesInHand_2, int nPiecesNeedRemove)
{
// 有效性判断
if (maxStepsLedToDraw < 0 || maxTimeLedToLose < 0 || initialStep < 0 ||
@ -391,12 +395,16 @@ bool NineChess::setContext(const struct Rule *rule, int maxStepsLedToDraw, int m
// 当前棋局3×8
if (board == nullptr) {
memset(context.board, 0, sizeof(context.board));
#ifdef HASH_MAP_ENABLE
context.hash = 0ull;
context.hashCheckCode = 0ull;
#endif
} else {
memcpy(context.board, board, sizeof(context.board));
#ifdef HASH_MAP_ENABLE
context.hash = hash;
context.hashCheckCode = hashCheckCode;
#endif
}
// 计算盘面子数
@ -493,8 +501,7 @@ bool NineChess::setContext(const struct Rule *rule, int maxStepsLedToDraw, int m
}
void NineChess::getContext(struct Rule &rule, int &step, int &flags,
int *&board, int &nPiecesInHand_1, int &nPiecesInHand_2, int &num_NeedRemove,
uint64_t &hash, uint64_t &hashCheckCode)
int *&board, int &nPiecesInHand_1, int &nPiecesInHand_2, int &num_NeedRemove)
{
rule = this->currentRule;
step = this->currentStep;
@ -503,7 +510,9 @@ void NineChess::getContext(struct Rule &rule, int &step, int &flags,
nPiecesInHand_1 = context.nPiecesInHand_1;
nPiecesInHand_2 = context.nPiecesInHand_2;
num_NeedRemove = context.nPiecesNeedRemove;
hashCheckCode = context.hashCheckCode;
#ifdef HASH_MAP_ENABLE
hash = context.hash;
#endif
}
bool NineChess::reset()
@ -547,9 +556,11 @@ bool NineChess::reset()
// 用时置零
elapsedMS_1 = elapsedMS_2 = 0;
#ifdef HASH_MAP_ENABLE
// 哈希以及哈希校验码归零
context.hash = 0;
context.hashCheckCode = 0;
#endif
// 提示
setTips();
@ -703,7 +714,9 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/)
}
board_[pos] = piece;
#ifdef HASH_MAP_ENABLE
updateHash(pos);
#endif
move_ = pos;
player_ms = update(time_p);
sprintf(cmdline, "(%1u,%1u) %02u:%02u.%03u",
@ -792,9 +805,13 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/)
c, p, player_ms / 60000, (player_ms % 60000) / 1000, player_ms % 1000);
cmdlist.push_back(string(cmdline));
board_[pos] = board_[currentPos];
#ifdef HASH_MAP_ENABLE
updateHash(pos);
#endif
board_[currentPos] = '\x00';
#ifdef HASH_MAP_ENABLE
updateHash(currentPos);
#endif
currentPos = pos;
currentStep++;
n = addMills(currentPos);
@ -880,7 +897,9 @@ bool NineChess::capture(int c, int p, long time_p /* = -1*/)
currentPos = 0;
context.nPiecesNeedRemove--;
currentStep++;
#ifdef HASH_MAP_ENABLE
updateHash(pos);
#endif
// 去子完成
// 如果决出胜负
@ -1030,7 +1049,9 @@ bool NineChess::place(int pos)
}
board_[pos] = piece;
#ifdef HASH_MAP_ENABLE
updateHash(pos);
#endif
move_ = pos;
currentPos = pos;
//step++;
@ -1106,9 +1127,13 @@ bool NineChess::place(int pos)
// 移子
move_ = (currentPos << 8) + pos;
board_[pos] = board_[currentPos];
#ifdef HASH_MAP_ENABLE
updateHash(pos);
#endif
board_[currentPos] = '\x00';
#ifdef HASH_MAP_ENABLE
updateHash(currentPos);
#endif
currentPos = pos;
//step++;
n = addMills(currentPos);
@ -1185,7 +1210,9 @@ bool NineChess::capture(int pos)
move_ = -pos;
currentPos = 0;
context.nPiecesNeedRemove--;
#ifdef HASH_MAP_ENABLE
updateHash(pos);
#endif
//step++;
// 去子完成
@ -1290,6 +1317,8 @@ bool NineChess::choose(int pos)
return false;
}
#ifdef HASH_MAP_ENABLE
uint64_t NineChess::getHash()
{
return context.hash;
@ -1341,6 +1370,7 @@ uint64_t NineChess::updateHash(int pos)
return context.hashCheckCode; // TODO: 返回什么
}
#endif /* HASH_MAP_ENABLE */
bool NineChess::giveup(Player loser)
{
@ -1775,7 +1805,9 @@ void NineChess::cleanForbiddenPoints()
pos = i * N_SEATS + j;
if (board_[pos] == '\x0f') {
board_[pos] = '\x00';
#ifdef HASH_MAP_ENABLE
updateHash(pos);
#endif
}
}
}

View File

@ -179,7 +179,8 @@ public:
*/
int board[N_POINTS];
// 局面哈希的校验码,校验码相同 才能认为是同一局面
#ifdef HASH_MAP_ENABLE
// 局面哈希的校验码(过时)
uint64_t hashCheckCode;
// 局面的哈希值
@ -189,16 +190,17 @@ public:
uint16_t hashAddr;
// 标记处于走子阶段的哈希
uint16_t gameMovingHash;
uint64_t gameMovingHash;
// 吃子动作的哈希
uint16_t actionCaptureHash;
uint64_t actionCaptureHash;
// 标记轮到玩家2行棋的哈希
uint16_t player2sTurnHash;
uint64_t player2sTurnHash;
// Zobrist 数组
uint64_t zobrist[N_POINTS][POINT_TYPE_COUNT];
#endif /* HASH_MAP_ENABLE */
// 局面阶段标识
enum NineChess::GameStage stage;
@ -283,15 +285,12 @@ public:
const char *board = nullptr, // 默认空棋盘
int nPiecesInHand_1 = 12, // 玩家1剩余未放置子数
int nPiecesInHand_2 = 12, // 玩家2剩余未放置子数
int nPiecesNeedRemove = 0, // 尚待去除的子数
uint64_t hash = 0ull, // 哈希值
uint64_t hashCheckCode = 0ull // 哈希校验码
int nPiecesNeedRemove = 0 // 尚待去除的子数
);
// 获取棋局状态和棋盘上下文
void getContext(struct Rule &rule, int &step, int &flags, int *&board,
int &nPiecesInHand_1, int &p2_nPiecesInHand_2InHand, int &nPiecesNeedRemove,
uint64_t &hash, uint64_t &hashCheckCode);
int &nPiecesInHand_1, int &p2_nPiecesInHand_2InHand, int &nPiecesNeedRemove);
// 获取当前规则
const struct Rule *getRule() const
@ -495,10 +494,12 @@ protected:
bool place(int pos);
bool capture(int pos);
#ifdef HASH_MAP_ENABLE
// hash相关
uint64_t getHash();
uint64_t getHashCheckCode();
uint64_t updateHash(int pos);
#endif /* HASH_MAP_ENABLE */
private:
// 当前使用的规则

View File

@ -22,6 +22,10 @@ NineChessAi_ab::NineChessAi_ab() :
hashHitCount(0)
{
buildRoot();
#ifdef HASH_MAP_ENABLE
hashMap.construct(); // TODO
#endif
}
NineChessAi_ab::~NineChessAi_ab()
@ -61,7 +65,9 @@ struct NineChessAi_ab::Node *NineChessAi_ab::addNode(Node *parent, int value, in
newNode->alpha = -INF_VALUE;
newNode->beta = INF_VALUE;
newNode->result = 0;
#ifdef HASH_MAP_ENABLE
newNode->isHash = false;
#endif
newNode->visited = false;
int c, p;
@ -94,8 +100,7 @@ struct NineChessAi_ab::Node *NineChessAi_ab::addNode(Node *parent, int value, in
//mutex NineChessAi_ab::hashMapMutex;
//HashMap<NineChessAi_ab::HashValue> NineChessAi_ab::hashmap;
mutex hashMapMutex;
HashMap<NineChessAi_ab::HashValue> hashmap;
#ifdef MOVE_PRIORITY_TABLE_SUPPORT
#ifdef RANDOM_MOVE
@ -359,10 +364,12 @@ void NineChessAi_ab::deleteTree(Node *node)
void NineChessAi_ab::setChess(const NineChess &chess)
{
#ifdef HASH_MAP_ENABLE
// 如果规则改变重建hashmap
if (strcmp(this->chess_.currentRule.name, chess.currentRule.name)) {
clearHashMap();
}
#endif
this->chess_ = chess;
chessTemp = chess;
@ -602,8 +609,10 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
// 临时增加的深度,克服水平线效应用
int epsilon = 0;
#ifdef HASH_MAP_ENABLE
// 哈希类型
enum HashType hashf = hashfALPHA;
#endif
#ifdef DEBUG_AB_TREE
node->depth = depth;
@ -612,10 +621,12 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
// 初始化
node->isLeaf = false;
node->isTimeout = false;
node->isHash = false;
node->visited = true;
#ifdef HASH_MAP_ENABLE
node->isHash = false;
node->hash = 0;
#endif
#endif // HASH_MAP_ENABLE
#endif // DEBUG_AB_TREE
#ifdef HASH_MAP_ENABLE
// 检索 hashmap
@ -758,8 +769,9 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
// α 为走棋一方搜索到的最好值,任何比它小的值对当前结点的走棋方都没有意义
// 如果某个着法的结果小于或等于 α,那么它就是很差的着法,因此可以抛弃
alpha = std::max(value, alpha);
#ifdef HASH_MAP_ENABLE
hashf = hashfALPHA; // ????
#endif
} else {
@ -776,8 +788,9 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
// 如果某个着法的结果大于或等于 β,那么整个结点就作废了,因为对手不希望走到这个局面,而它有别的着法可以避免到达这个局面。
// 因此如果我们找到的评价大于或等于β,就证明了这个结点是不会发生的,因此剩下的合理着法没有必要再搜索。
beta = std::min(value, beta);
#ifdef HASH_MAP_ENABLE
hashf = hashfBETA; // ????
#endif
}
// 如果某个着法的结果大于 α 但小于β,那么这个着法就是走棋一方可以考虑走的
@ -834,16 +847,18 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
return node->value;
}
#ifdef HASH_MAP_ENABLE
int NineChessAi_ab::recordHash(const HashValue &hashValue)
{
#ifdef HASH_MAP_ENABLE
hashMapMutex.lock();
hashmap.insert(hashValue.hash, hashValue);
hashMap.insert(hashValue.hash, hashValue);
hashMapMutex.unlock();
#endif // HASH_MAP_ENABLE
return 0;
}
#endif
const char* NineChessAi_ab::bestMove()
{
@ -940,9 +955,10 @@ const char *NineChessAi_ab::move2string(int move)
return cmdline;
}
#ifdef HASH_MAP_ENABLE
NineChessAi_ab::HashValue NineChessAi_ab::findHash(uint64_t hash)
{
NineChessAi_ab::HashValue hashValue = hashmap.find(hash);
NineChessAi_ab::HashValue hashValue = hashMap.find(hash);
// TODO: 变换局面
#if 0
@ -974,6 +990,7 @@ NineChessAi_ab::HashValue NineChessAi_ab::findHash(uint64_t hash)
void NineChessAi_ab::clearHashMap()
{
hashMapMutex.lock();
hashmap.clear();
hashMap.clear();
hashMapMutex.unlock();
}
#endif /* HASH_MAP_ENABLE */

View File

@ -27,6 +27,7 @@ using namespace std;
class NineChessAi_ab
{
public:
#ifdef HASH_MAP_ENABLE
// 定义哈希值的类型
enum HashType : int16_t
{
@ -46,6 +47,7 @@ public:
uint64_t hash;
enum HashType type;
};
#endif /* HASH_MAP_ENABLE */
// 定义一个节点结构体
struct Node
@ -57,9 +59,11 @@ public:
struct Node* parent; // 父节点
size_t id; // 结点编号
int rand; // 随机数,对于 value 一致的结点随机排序用
#ifdef HASH_MAP_ENABLE
uint64_t hash;
uint64_t hashCheckCode;
bool isHash; // 是否从 Hash 读取
#endif /* HASH_MAP_ENABLE */
bool pruned; // 是否在此处剪枝
#ifdef DEBUG_AB_TREE
string cmd;
@ -116,13 +120,20 @@ public:
// 返回最佳走法的命令行
const char *bestMove();
#ifdef HASH_MAP_ENABLE
// 清空哈希表
void clearHashMap();
#endif
// 比较函数
static bool nodeLess(const Node *first, const Node *second);
static bool nodeGreater(const Node *first, const Node *second);
#ifdef HASH_MAP_ENABLE
static std::mutex hashMapMutex;
static HashMap<HashValue> hashMap;
#endif
protected:
// 生成所有合法的着法并建立子节点
void generateLegalMoves(Node *node);
@ -139,8 +150,10 @@ protected:
// 增加新节点
struct Node *addNode(Node *parent, int value, NineChess::move_t move, enum NineChess::Player player);
#ifdef HASH_MAP_ENABLE
// 插入哈希表
int recordHash(const HashValue &hashValue);
#endif
// 评价函数
int evaluate(Node *node);
@ -161,8 +174,10 @@ protected:
#endif
#endif
#ifdef HASH_MAP_ENABLE
// 查找哈希表
HashValue findHash(uint64_t hash);
#endif
private:
// 原始模型
@ -212,7 +227,4 @@ private:
char cmdline[32];
};
extern mutex hashMapMutex;
extern HashMap<NineChessAi_ab::HashValue> hashmap;
#endif