添加哈希表部分代码

编译通过,链接不通过
This commit is contained in:
CalciteM Team 2019-07-13 16:51:12 +08:00
parent 03294e1557
commit 702a562bbd
10 changed files with 326 additions and 133 deletions

0
NineChess/Source.cpp Normal file
View File

View File

@ -18,6 +18,7 @@ CONFIG += C++11 \
INCLUDEPATH += src
SOURCES += \
src/hashmap.cpp \
src/main.cpp \
src/boarditem.cpp \
src/gamecontroller.cpp \
@ -36,6 +37,7 @@ HEADERS += \
src/gamescene.h \
src/gameview.h \
src/graphicsconst.h \
src/hashmap.h \
src/ninechess.h \
src/ninechessai_ab.h \
src/ninechesswindow.h \

View File

@ -378,6 +378,7 @@
<ClCompile Include="src\gamecontroller.cpp" />
<ClCompile Include="src\gamescene.cpp" />
<ClCompile Include="src\gameview.cpp" />
<ClCompile Include="src\hashmap.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\ninechess.cpp" />
<ClCompile Include="src\ninechessai_ab.cpp" />
@ -426,6 +427,7 @@
</QtMoc>
<ClInclude Include="src\config.h" />
<ClInclude Include="src\graphicsconst.h" />
<ClInclude Include="src\hashmap.h" />
<ClInclude Include="src\ninechess.h" />
<QtMoc Include="src\ninechesswindow.h">
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include;debug;\include;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\mkspecs\win32-msvc;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtWidgets;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtCore;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtGui;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtANGLE;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtMultimedia;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtNetwork;%(AdditionalIncludeDirectories)</IncludePath>

View File

@ -84,6 +84,9 @@
<ClCompile Include="src\ninechessai_ab.cpp">
<Filter>Model</Filter>
</ClCompile>
<ClCompile Include="src\hashmap.cpp">
<Filter>Model</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h">
@ -110,6 +113,9 @@
<ClInclude Include="src\config.h">
<Filter>Control</Filter>
</ClInclude>
<ClInclude Include="src\hashmap.h">
<Filter>Model</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="debug\moc_predefs.h.cbt">

80
NineChess/src/hashmap.cpp Normal file
View File

@ -0,0 +1,80 @@
#include "hashmap.h"
template <typename T>
HashMap<T>::HashMap():
capacity(0),
size(0),
pool(nullptr)
{
this->capacity = 0x20000000; // TODO
}
template <typename T>
HashMap<T>::HashMap(size_t capacity)
{
this->capacity = capacity;
this->size = 0;
construct();
}
template <typename T>
HashMap<T>::~HashMap()
{
clear();
}
template <typename T>
bool HashMap<T>::construct()
{
pool = new T[capacity];
if (pool == nullptr) {
return false;
}
return true;
}
template <typename T>
T& HashMap<T>::at(uint64_t i)
{
if (i >= capacity) {
qDebug() << "Ë÷Òý³¬¹ý×î´óÖµ";
return pool[0];
}
return pool[i];
}
template <typename T>
size_t HashMap<T>::getSize()
{
return size;
}
template <typename T>
size_t HashMap<T>::getCapacity()
{
return capacity;
}
template <typename T>
uint64_t HashMap<T>::hashToAddr(uint64_t hash)
{
return hash << 32 >> 32;
}
template <typename T>
void HashMap<T>::insert(uint64_t hash, const T &hashValue)
{
uint64_t addr = hashToAddr(hash);
pool[addr] = hashValue;
}
template <typename T>
void HashMap<T>::clear()
{
delete[] pool;
pool = nullptr;
}

55
NineChess/src/hashmap.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef HASHMAP_H
#include <limits>
#include <qDebug>
template <typename T>
class HashMap
{
public:
HashMap();
HashMap(size_t capacity);
~HashMap();
enum FindResult
{
HASHMAP_NOTFOUND = INT32_MAX,
};
T& at(uint64_t i);
T& operator[](uint64_t hash)
{
uint64_t addr = hashToAddr(hash);
return pool[addr];
}
T &find(uint64_t hash)
{
uint64_t addr = hashToAddr(hash);
return pool[addr];
}
size_t getSize();
size_t getCapacity();
void clear();
void insert(uint64_t hash, const T &hashValue);
protected:
private:
size_t capacity;
size_t size;
T *pool;
bool construct();
uint64_t hashToAddr(uint64_t hash);
};
#endif // HASHMAP_H

View File

@ -178,11 +178,12 @@ NineChess::~NineChess()
void NineChess::constructHash()
{
context.hashCheckCode = 0;
context.hash = 0ull;
context.hashCheckCode = 0ull;
#if 0
gameMovingHash = rand64();
player2sTurnHash = rand64();
context.gameMovingHash = rand64();
context.actionCaptureHash = rand64();
context.player2sTurnHash = rand64();
uint64_t zobrist[N_POINTS][POINT_TYPE_COUNT];
@ -191,7 +192,6 @@ void NineChess::constructHash()
zobrist[p][t] = rand64();
}
}
#endif
}
NineChess::Player NineChess::getOpponent(NineChess::Player player)
@ -324,7 +324,8 @@ 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 hashCheckCode)
int nPiecesInHand_1, int nPiecesInHand_2, int nPiecesNeedRemove,
uint64_t hash, uint64_t hashCheckCode)
{
// 有效性判断
if (maxStepsLedToDraw < 0 || maxTimeLedToLose < 0 || initialStep < 0 ||
@ -390,9 +391,11 @@ bool NineChess::setContext(const struct Rule *rule, int maxStepsLedToDraw, int m
// 当前棋局3×8
if (board == nullptr) {
memset(context.board, 0, sizeof(context.board));
context.hashCheckCode = 0;
context.hash = 0ull;
context.hashCheckCode = 0ull;
} else {
memcpy(context.board, board, sizeof(context.board));
context.hash = hash;
context.hashCheckCode = hashCheckCode;
}
@ -491,7 +494,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 &hashCheckCode)
uint64_t &hash, uint64_t &hashCheckCode)
{
rule = this->currentRule;
step = this->currentStep;
@ -544,7 +547,8 @@ bool NineChess::reset()
// 用时置零
elapsedMS_1 = elapsedMS_2 = 0;
// 哈希校验码归零
// 哈希以及哈希校验码归零
context.hash = 0;
context.hashCheckCode = 0;
// 提示
@ -699,7 +703,7 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/)
}
board_[pos] = piece;
updateHashCheckCode(pos);
updateHash(pos);
move_ = pos;
player_ms = update(time_p);
sprintf(cmdline, "(%1u,%1u) %02u:%02u.%03u",
@ -788,9 +792,9 @@ 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];
updateHashCheckCode(pos);
updateHash(pos);
board_[currentPos] = '\x00';
updateHashCheckCode(currentPos);
updateHash(currentPos);
currentPos = pos;
currentStep++;
n = addMills(currentPos);
@ -876,7 +880,7 @@ bool NineChess::capture(int c, int p, long time_p /* = -1*/)
currentPos = 0;
context.nPiecesNeedRemove--;
currentStep++;
updateHashCheckCode(pos);
updateHash(pos);
// 去子完成
// 如果决出胜负
@ -1026,7 +1030,7 @@ bool NineChess::place(int pos)
}
board_[pos] = piece;
updateHashCheckCode(pos);
updateHash(pos);
move_ = pos;
currentPos = pos;
//step++;
@ -1102,9 +1106,9 @@ bool NineChess::place(int pos)
// 移子
move_ = (currentPos << 8) + pos;
board_[pos] = board_[currentPos];
updateHashCheckCode(pos);
updateHash(pos);
board_[currentPos] = '\x00';
updateHashCheckCode(currentPos);
updateHash(currentPos);
currentPos = pos;
//step++;
n = addMills(currentPos);
@ -1181,7 +1185,7 @@ bool NineChess::capture(int pos)
move_ = -pos;
currentPos = 0;
context.nPiecesNeedRemove--;
updateHashCheckCode(pos);
updateHash(pos);
//step++;
// 去子完成
@ -1286,16 +1290,21 @@ bool NineChess::choose(int pos)
return false;
}
uint64_t NineChess::getHash()
{
return context.hash;
}
uint64_t NineChess::getHashCheckCode()
{
return context.hashCheckCode;
}
// hash函数对应可重复去子的规则
uint64_t NineChess::updateHashCheckCode(int pos)
uint64_t NineChess::updateHash(int pos)
{
/*
* hash校验码各数据位详
* hashCheckCode
* 56-630
* 5501
* 5401
@ -1305,28 +1314,32 @@ uint64_t NineChess::updateHashCheckCode(int pos)
* 0-3player1的手棋数player2的
*/
#if 0
uint64_t hash = 0ull;
// TODO: 本函数效率低下,啥时调用?
for (int i = POS_BEGIN; i < POS_END; i++) {
hash |= board_[i] & 0x30;
hash <<= 2;
// hash ^= context.zobrist[i][pointType]; // TODO: 待完善
}
#endif
uint64_t temp = board_[pos] & 0x30 >> 4;
context.hashCheckCode |= (temp) << ((pos - 8) * 2 + 6);
// TODO: context.hash =
if (context.turn == PLAYER2)
if (context.turn == PLAYER2) {
context.hashCheckCode |= 1ull << 55;
context.hash ^= context.player2sTurnHash;
}
if (context.action == ACTION_CAPTURE)
if (context.action == ACTION_CAPTURE) {
context.hashCheckCode |= 1ull << 54;
context.hash ^= context.actionCaptureHash;
}
context.hashCheckCode |= (uint64_t)context.nPiecesNeedRemove << 4;
context.hashCheckCode |= context.nPiecesInHand_1;
// TODO: hash 应该 不需要
return context.hashCheckCode;
return context.hashCheckCode; // TODO: 返回什么
}
bool NineChess::giveup(Player loser)
@ -1762,7 +1775,7 @@ void NineChess::cleanForbiddenPoints()
pos = i * N_SEATS + j;
if (board_[pos] == '\x0f') {
board_[pos] = '\x00';
updateHashCheckCode(pos);
updateHash(pos);
}
}
}

View File

@ -182,8 +182,23 @@ public:
// 局面哈希的校验码,校验码相同 才能认为是同一局面
uint64_t hashCheckCode;
// 局面的哈希值
uint64_t hash;
// 哈希表中的地址, 为 hash 的后 16 位
uint16_t hashAddr;
// 标记处于走子阶段的哈希
uint16_t gameMovingHash;
// 吃子动作的哈希
uint16_t actionCaptureHash;
// 标记轮到玩家2行棋的哈希
uint16_t player2sTurnHash;
// Zobrist 数组
//uint64_t zobrist[N_POINTS][POINT_TYPE_COUNT];
uint64_t zobrist[N_POINTS][POINT_TYPE_COUNT];
// 局面阶段标识
enum NineChess::GameStage stage;
@ -269,13 +284,14 @@ public:
int nPiecesInHand_1 = 12, // 玩家1剩余未放置子数
int nPiecesInHand_2 = 12, // 玩家2剩余未放置子数
int nPiecesNeedRemove = 0, // 尚待去除的子数
uint64_t hashCheckCode = 0ull // Hash 为0
uint64_t hash = 0ull, // 哈希值
uint64_t hashCheckCode = 0ull // 哈希校验码
);
// 获取棋局状态和棋盘上下文
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 &hash, uint64_t &hashCheckCode);
// 获取当前规则
const struct Rule *getRule() const
@ -479,9 +495,10 @@ protected:
bool place(int pos);
bool capture(int pos);
// hash校验值相关
// hash相关
uint64_t getHash();
uint64_t getHashCheckCode();
uint64_t updateHashCheckCode(int pos);
uint64_t updateHash(int pos);
private:
// 当前使用的规则

View File

@ -3,17 +3,16 @@
** Mail: liuweilhy@163.com
** This file is part of the NineChess game.
****************************************************************************/
#include "ninechessai_ab.h"
#include <cmath>
#include <time.h>
#include <Qdebug>
#include <QTime>
#include <array>
#include <random>
#include <chrono>
#include <algorithm>
#include <array>
#include <random>
#include <chrono>
#include <algorithm>
#include "ninechessai_ab.h"
NineChessAi_ab::NineChessAi_ab() :
rootNode(nullptr),
@ -31,14 +30,6 @@ NineChessAi_ab::~NineChessAi_ab()
rootNode = nullptr;
}
void NineChessAi_ab::clearHashMap()
{
hashMapMutex.lock();
hashmap.clear();
hashmap.reserve(maxHashCount);
hashMapMutex.unlock();
}
void NineChessAi_ab::buildRoot()
{
rootNode = addNode(nullptr, 0, 0, NineChess::NOBODY);
@ -100,45 +91,48 @@ struct NineChessAi_ab::Node *NineChessAi_ab::addNode(Node *parent, int value, in
}
// 静态hashmap初始化
mutex NineChessAi_ab::hashMapMutex;
unordered_map<uint64_t, NineChessAi_ab::HashValue> NineChessAi_ab::hashmap;
//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
void NineChessAi_ab::shuffleMovePriorityTable()
{
array<int, 4> movePriorityTable0 = { 17, 19, 21, 23 }; // 中圈四个顶点 (星位)
array<int, 4> movePriorityTable0 = { 17, 19, 21, 23 }; // 中圈四个顶点 (星位)
array<int, 8> movePriorityTable1 = { 25, 27, 29, 31, 9, 11, 13, 15 }; // 外圈和内圈四个顶点
array<int, 4> movePriorityTable2 = { 16, 18, 20, 22 }; // 中圈十字架
array<int, 4> movePriorityTable3 = { 8, 10, 12, 14 }; // 内圈十字架
array<int, 4> movePriorityTable4 = { 24, 26, 28, 30 }; // 外圈十字架
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::shuffle(movePriorityTable0.begin(), movePriorityTable0.end(), std::default_random_engine(seed));
std::shuffle(movePriorityTable1.begin(), movePriorityTable1.end(), std::default_random_engine(seed));
std::shuffle(movePriorityTable2.begin(), movePriorityTable2.end(), std::default_random_engine(seed));
std::shuffle(movePriorityTable3.begin(), movePriorityTable3.end(), std::default_random_engine(seed));
std::shuffle(movePriorityTable4.begin(), movePriorityTable4.end(), std::default_random_engine(seed));
for (int i = 0; i < 4; i++) {
movePriorityTable[i + 0] = movePriorityTable0[i];
}
for (int i = 0; i < 8; i++) {
movePriorityTable[i + 4] = movePriorityTable1[i];
}
for (int i = 0; i < 4; i++) {
movePriorityTable[i + 12] = movePriorityTable2[i];
}
for (int i = 0; i < 4; i++) {
movePriorityTable[i + 16] = movePriorityTable3[i];
array<int, 4> movePriorityTable2 = { 16, 18, 20, 22 }; // 中圈十字架
array<int, 4> movePriorityTable3 = { 8, 10, 12, 14 }; // 内圈十字架
array<int, 4> movePriorityTable4 = { 24, 26, 28, 30 }; // 外圈十字架
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::shuffle(movePriorityTable0.begin(), movePriorityTable0.end(), std::default_random_engine(seed));
std::shuffle(movePriorityTable1.begin(), movePriorityTable1.end(), std::default_random_engine(seed));
std::shuffle(movePriorityTable2.begin(), movePriorityTable2.end(), std::default_random_engine(seed));
std::shuffle(movePriorityTable3.begin(), movePriorityTable3.end(), std::default_random_engine(seed));
std::shuffle(movePriorityTable4.begin(), movePriorityTable4.end(), std::default_random_engine(seed));
for (int i = 0; i < 4; i++) {
movePriorityTable[i + 0] = movePriorityTable0[i];
}
for (int i = 0; i < 4; i++) {
movePriorityTable[i + 20] = movePriorityTable4[i];
for (int i = 0; i < 8; i++) {
movePriorityTable[i + 4] = movePriorityTable1[i];
}
for (int i = 0; i < 4; i++) {
movePriorityTable[i + 12] = movePriorityTable2[i];
}
for (int i = 0; i < 4; i++) {
movePriorityTable[i + 16] = movePriorityTable3[i];
}
for (int i = 0; i < 4; i++) {
movePriorityTable[i + 20] = movePriorityTable4[i];
}
}
#endif // #ifdef RANDOM_MOVE
@ -187,7 +181,7 @@ void NineChessAi_ab::generateLegalMoves(Node *node)
case NineChess::ACTION_PLACE:
// 对于摆子阶段
if (chessTemp.context.stage & (NineChess::GAME_PLACING | NineChess::GAME_NOTSTARTED)) {
for (int i = 0; i < MOVE_PRIORITY_TABLE_SIZE; i++) {
for (int i = 0; i < MOVE_PRIORITY_TABLE_SIZE; i++) {
pos = movePriorityTable[i];
if (!chessTemp.board_[pos]) {
if (node == rootNode && chessTemp.context.stage == NineChess::GAME_NOTSTARTED) {
@ -211,7 +205,7 @@ void NineChessAi_ab::generateLegalMoves(Node *node)
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
#else
for (int i = 0; i < MOVE_PRIORITY_TABLE_SIZE; i++) {
#endif // MOVE_PRIORITY_TABLE_SUPPORT
#endif // MOVE_PRIORITY_TABLE_SUPPORT
oldPos = movePriorityTable[i];
if (!chessTemp.choose(oldPos))
continue;
@ -246,7 +240,7 @@ void NineChessAi_ab::generateLegalMoves(Node *node)
case NineChess::ACTION_CAPTURE:
if (chessTemp.isAllInMills(opponent)) {
// 全成三的情况
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
pos = movePriorityTable[i];
if (chessTemp.board_[pos] & opponent) {
addNode(node, 0, -pos, chessTemp.context.turn);
@ -254,7 +248,7 @@ void NineChessAi_ab::generateLegalMoves(Node *node)
}
} else {
// 不是全成三的情况
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
pos = movePriorityTable[i];
if (chessTemp.board_[pos] & opponent) {
if (chessTemp.getRule()->allowRemoveMill || !chessTemp.isInMills(pos)) {
@ -626,26 +620,29 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
#ifdef HASH_MAP_ENABLE
// 检索 hashmap
uint64_t hashCheckCode = chessTemp.getHashCheckCode();
node->hash = hashCheckCode;
node->hashCheckCode = hashCheckCode;
uint64_t hash = chessTemp.getHash();
node->hash = hash;
hashMapMutex.lock();
auto iter = findHash(hashCheckCode);
HashValue hashValue = findHash(hash);
if (node != rootNode &&
iter != hashmap.end() &&
iter->second.depth >= depth) {
hashValue.hash == hash &&
hashValue.depth >= depth) {
#ifdef DEBUG_AB_TREE
node->isHash = true;
#endif
// TODO: 处理 Alpha/Beta 确切值
node->value = iter->second.value;
node->value = hashValue.value;
if (chessContext->turn == NineChess::PLAYER1)
node->value += iter->second.depth - depth;
node->value += hashValue.depth - depth;
else
node->value -= iter->second.depth - depth;
node->value -= hashValue.depth - depth;
hashMapMutex.unlock();
hashHitCount++;
@ -673,7 +670,14 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
#ifdef HASH_MAP_ENABLE
// 记录确切的哈希值
recordHash(hashCheckCode, depth, node->value, hashfEXACT);
HashValue newHashValue;
newHashValue.alpha = alpha;
newHashValue.beta = beta;
newHashValue.depth = depth;
newHashValue.type = hashfEXACT;
newHashValue.hash = hash;
newHashValue.value = node->value;
recordHash(newHashValue);
#endif
return node->value;
@ -698,7 +702,14 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
#ifdef HASH_MAP_ENABLE
// 记录确切的哈希值
recordHash(hashCheckCode, depth, node->value, hashfEXACT);
HashValue newHashValue;
newHashValue.alpha = alpha;
newHashValue.beta = beta;
newHashValue.depth = depth;
newHashValue.type = hashfEXACT;
newHashValue.hash = hash;
newHashValue.value = node->value;
recordHash(newHashValue);
#endif
return node->value;
@ -794,18 +805,25 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
#endif // DONOT_DELETE_TREE
#ifdef HASH_MAP_ENABLE
if (iter == hashmap.end()) {
if (hashValue.hash != hash) {
// 添加到hashmap
recordHash(hashCheckCode, depth, node->value, hashf);
HashValue newHashValue;
newHashValue.alpha = alpha;
newHashValue.beta = beta;
newHashValue.depth = depth;
newHashValue.type = hashf;
newHashValue.hash = hash;
newHashValue.value = node->value;
recordHash(newHashValue);
}
// 更新更深层数据
else {
//hashMapMutex.lock();
//if (iter->second.depth < depth) {
//iter->second.value = node->value;
//iter->second.depth = depth;
//}
//hashMapMutex.unlock();
hashMapMutex.lock();
if (hashValue.depth < depth) {
hashValue.value = node->value;
hashValue.depth = depth;
}
hashMapMutex.unlock();
}
#endif
@ -816,20 +834,11 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
return node->value;
}
int NineChessAi_ab::recordHash(uint64_t hash, int16_t depth, int value, enum HashType type)
int NineChessAi_ab::recordHash(const HashValue &hashValue)
{
#ifdef HASH_MAP_ENABLE
hashMapMutex.lock();
HashValue hashValue;
hashValue.value = value;
hashValue.depth = depth;
hashValue.type = type;
if (hashmap.size() <= maxHashCount)
hashmap.insert({ hash, hashValue });
hashmap.insert(hashValue.hash, hashValue);
hashMapMutex.unlock();
#endif // HASH_MAP_ENABLE
@ -931,10 +940,11 @@ const char *NineChessAi_ab::move2string(int move)
return cmdline;
}
unordered_map<uint64_t, NineChessAi_ab::HashValue>::iterator NineChessAi_ab::findHash(uint64_t hash)
NineChessAi_ab::HashValue NineChessAi_ab::findHash(uint64_t hash)
{
auto iter = hashmap.find(hash);
NineChessAi_ab::HashValue hashValue = hashmap.find(hash);
// TODO: 变换局面
#if 0
if (iter != hashmap.end())
return iter;
@ -958,5 +968,12 @@ unordered_map<uint64_t, NineChessAi_ab::HashValue>::iterator NineChessAi_ab::fin
}
#endif
return iter;
return hashValue;
}
void NineChessAi_ab::clearHashMap()
{
hashMapMutex.lock();
hashmap.clear();
hashMapMutex.unlock();
}

View File

@ -9,13 +9,13 @@
#include <list>
#include <stack>
#include <unordered_map>
#include <mutex>
#include <string>
#include <Qdebug>
#include <array>
#include "ninechess.h"
#include "hashmap.h"
using namespace std;
@ -39,8 +39,11 @@ public:
// 定义哈希表的值
struct HashValue
{
int16_t value;
int16_t depth;
int value;
int depth;
int alpha;
int beta;
uint64_t hash;
enum HashType type;
};
@ -55,6 +58,7 @@ public:
size_t id; // 结点编号
int rand; // 随机数,对于 value 一致的结点随机排序用
uint64_t hash;
uint64_t hashCheckCode;
bool isHash; // 是否从 Hash 读取
bool pruned; // 是否在此处剪枝
#ifdef DEBUG_AB_TREE
@ -77,19 +81,19 @@ public:
#endif /* DEBUG_AB_TREE */
#if 0
bool operator < (const Node &another) const
{
return this->value < another.value;
bool operator < (const Node &another) const
{
return this->value < another.value;
}
bool operator > (const Node &another) const
{
return this->value > another.value;
bool operator > (const Node &another) const
{
return this->value > another.value;
}
bool operator == (const Node &another) const
{
return this->value == another.value;
bool operator == (const Node &another) const
{
return this->value == another.value;
}
#endif
};
@ -136,7 +140,7 @@ protected:
struct Node *addNode(Node *parent, int value, NineChess::move_t move, enum NineChess::Player player);
// 插入哈希表
int recordHash(uint64_t hash, int16_t depth, int value, enum HashType type);
int recordHash(const HashValue &hashValue);
// 评价函数
int evaluate(Node *node);
@ -157,8 +161,8 @@ protected:
#endif
#endif
// 判断是否在哈希表中
unordered_map<uint64_t, NineChessAi_ab::HashValue>::iterator findHash(uint64_t hash);
// 查找哈希表
HashValue findHash(uint64_t hash);
private:
// 原始模型
@ -190,12 +194,6 @@ private:
// 标识,用于跳出剪枝算法,立即返回
bool requiredQuit;
// 互斥锁
static mutex hashMapMutex;
// 局面数据哈希表
static unordered_map<uint64_t, HashValue> hashmap;
#ifdef MOVE_PRIORITY_TABLE_SUPPORT
array<int, NineChess::N_RINGS *NineChess::N_SEATS> movePriorityTable;
#endif // MOVE_PRIORITY_TABLE_SUPPORT
@ -214,4 +212,7 @@ private:
char cmdline[32];
};
extern mutex hashMapMutex;
extern HashMap<NineChessAi_ab::HashValue> hashmap;
#endif