parent
c4ba910072
commit
c9ec23603a
|
@ -74,7 +74,7 @@
|
||||||
|
|
||||||
//#define RAPID_GAME
|
//#define RAPID_GAME
|
||||||
|
|
||||||
//#define BOOK_LEARNING
|
#define ENDGAME_LEARNING
|
||||||
|
|
||||||
#define THREEFOLD_REPETITION
|
#define THREEFOLD_REPETITION
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ INCLUDEPATH += src/game
|
||||||
INCLUDEPATH += src/ui/qt
|
INCLUDEPATH += src/ui/qt
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
src/ai/endgame.cpp \
|
||||||
src/ai/evaluate.cpp \
|
src/ai/evaluate.cpp \
|
||||||
src/ai/movegen.cpp \
|
src/ai/movegen.cpp \
|
||||||
src/ai/tt.cpp \
|
src/ai/tt.cpp \
|
||||||
|
@ -47,6 +48,7 @@ HEADERS += \
|
||||||
include/config.h \
|
include/config.h \
|
||||||
include/version.h \
|
include/version.h \
|
||||||
include/version.h.template \
|
include/version.h.template \
|
||||||
|
src/ai/endgame.h \
|
||||||
src/ai/evaluate.h \
|
src/ai/evaluate.h \
|
||||||
src/ai/movegen.h \
|
src/ai/movegen.h \
|
||||||
src/ai/tt.h \
|
src/ai/tt.h \
|
||||||
|
@ -59,7 +61,6 @@ HEADERS += \
|
||||||
src/base/stackalloc.h \
|
src/base/stackalloc.h \
|
||||||
src/base/thread.h \
|
src/base/thread.h \
|
||||||
src/ai/search.h \
|
src/ai/search.h \
|
||||||
src/ai/zobrist.h \
|
|
||||||
src/base/zobrist.h \
|
src/base/zobrist.h \
|
||||||
src/game/board.h \
|
src/game/board.h \
|
||||||
src/game/player.h \
|
src/game/player.h \
|
||||||
|
|
|
@ -441,6 +441,7 @@
|
||||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
</AdditionalInputs>
|
</AdditionalInputs>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<ClInclude Include="src\ai\endgame.h" />
|
||||||
<ClInclude Include="src\ai\evaluate.h" />
|
<ClInclude Include="src\ai\evaluate.h" />
|
||||||
<ClInclude Include="src\ai\movegen.h" />
|
<ClInclude Include="src\ai\movegen.h" />
|
||||||
<ClInclude Include="src\ai\search.h" />
|
<ClInclude Include="src\ai\search.h" />
|
||||||
|
@ -692,6 +693,7 @@
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\ai\endgame.cpp" />
|
||||||
<ClCompile Include="src\ai\evaluate.cpp" />
|
<ClCompile Include="src\ai\evaluate.cpp" />
|
||||||
<ClCompile Include="src\ai\movegen.cpp" />
|
<ClCompile Include="src\ai\movegen.cpp" />
|
||||||
<ClCompile Include="src\ai\search.cpp" />
|
<ClCompile Include="src\ai\search.cpp" />
|
||||||
|
|
|
@ -117,6 +117,9 @@
|
||||||
<ClInclude Include="src\base\zobrist.h">
|
<ClInclude Include="src\base\zobrist.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ai\endgame.h">
|
||||||
|
<Filter>ai</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="debug\moc_predefs.h.cbt">
|
<CustomBuild Include="debug\moc_predefs.h.cbt">
|
||||||
|
@ -335,6 +338,9 @@
|
||||||
<ClCompile Include="src\base\zobrist.cpp">
|
<ClCompile Include="src\base\zobrist.cpp">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\ai\endgame.cpp">
|
||||||
|
<Filter>ai</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="millgame.rc">
|
<ResourceCompile Include="millgame.rc">
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* Copyright (C) 2018-2019 MillGame authors
|
||||||
|
*
|
||||||
|
* Authors: liuweilhy <liuweilhy@163.com>
|
||||||
|
* Calcitem <calcitem@outlook.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "endgame.h"
|
||||||
|
|
||||||
|
#ifdef ENDGAME_LEARNING
|
||||||
|
static constexpr int endgameHashsize = 0x1000000; // 16M
|
||||||
|
HashMap<hash_t, Endgame> endgameHashMap(endgameHashsize);
|
||||||
|
#endif // ENDGAME_LEARNING
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* Copyright (C) 2018-2019 MillGame authors
|
||||||
|
*
|
||||||
|
* Authors: liuweilhy <liuweilhy@163.com>
|
||||||
|
* Calcitem <calcitem@outlook.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef ENDGAME_H
|
||||||
|
#define ENDGAME_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef ENDGAME_LEARNING
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "hashmap.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace CTSL;
|
||||||
|
|
||||||
|
enum endgame_t : uint8_t
|
||||||
|
{
|
||||||
|
ENDGAME_NONE,
|
||||||
|
ENDGAME_PLAYER_1_WIN,
|
||||||
|
ENDGAME_PLAYER_2_WIN,
|
||||||
|
ENDGAME_DRAW,
|
||||||
|
};
|
||||||
|
|
||||||
|
//#pragma pack (push, 1)
|
||||||
|
struct Endgame
|
||||||
|
{
|
||||||
|
endgame_t type;
|
||||||
|
};
|
||||||
|
//#pragma pack(pop)
|
||||||
|
|
||||||
|
extern HashMap<hash_t, Endgame> endgameHashMap;
|
||||||
|
|
||||||
|
#endif // ENDGAME_LEARNING
|
||||||
|
|
||||||
|
#endif // ENDGAME_H
|
|
@ -40,49 +40,49 @@ public:
|
||||||
#ifdef EVALUATE_ENABLE
|
#ifdef EVALUATE_ENABLE
|
||||||
|
|
||||||
#ifdef EVALUATE_MATERIAL
|
#ifdef EVALUATE_MATERIAL
|
||||||
static value_t evaluateMaterial(MillGameAi_ab::Node *node)
|
static value_t evaluateMaterial(AIAlgorithm::Node *node)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EVALUATE_SPACE
|
#ifdef EVALUATE_SPACE
|
||||||
static value_t evaluateSpace(MillGameAi_ab::Node *node)
|
static value_t evaluateSpace(AIAlgorithm::Node *node)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EVALUATE_MOBILITY
|
#ifdef EVALUATE_MOBILITY
|
||||||
static value_t evaluateMobility(MillGameAi_ab::Node *node)
|
static value_t evaluateMobility(AIAlgorithm::Node *node)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EVALUATE_TEMPO
|
#ifdef EVALUATE_TEMPO
|
||||||
static value_t evaluateTempo(MillGameAi_ab::Node *node)
|
static value_t evaluateTempo(AIAlgorithm::Node *node)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EVALUATE_THREAT
|
#ifdef EVALUATE_THREAT
|
||||||
static value_t evaluateThreat(MillGameAi_ab::Node *node)
|
static value_t evaluateThreat(AIAlgorithm::Node *node)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EVALUATE_SHAPE
|
#ifdef EVALUATE_SHAPE
|
||||||
static value_t evaluateShape(MillGameAi_ab::Node *node)
|
static value_t evaluateShape(AIAlgorithm::Node *node)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EVALUATE_MOTIF
|
#ifdef EVALUATE_MOTIF
|
||||||
static value_t MillGameAi_ab::evaluateMotif(MillGameAi_ab::Node *node)
|
static value_t AIAlgorithm::evaluateMotif(AIAlgorithm::Node *node)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,16 +29,11 @@
|
||||||
#include "movegen.h"
|
#include "movegen.h"
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "tt.h"
|
#include "tt.h"
|
||||||
|
#include "endgame.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
using namespace CTSL;
|
using namespace CTSL;
|
||||||
|
|
||||||
#ifdef BOOK_LEARNING
|
|
||||||
static constexpr int bookHashsize = 0x1000000; // 16M
|
|
||||||
HashMap<hash_t, MillGameAi_ab::HashValue> bookHashMap(bookHashsize);
|
|
||||||
vector<hash_t> openingBook;
|
|
||||||
#endif // BOOK_LEARNING
|
|
||||||
|
|
||||||
// 用于检测重复局面 (Position)
|
// 用于检测重复局面 (Position)
|
||||||
vector<hash_t> history;
|
vector<hash_t> history;
|
||||||
|
|
||||||
|
@ -79,11 +74,19 @@ depth_t AIAlgorithm::changeDepth(depth_t origDepth)
|
||||||
12, 12, 13, 14, /* 20 ~ 23 */
|
12, 12, 13, 14, /* 20 ~ 23 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef ENDGAME_LEARNING
|
||||||
|
const depth_t movingDiffDepthTable[] = {
|
||||||
|
0, 0, 0, /* 0 ~ 2 */
|
||||||
|
0, 0, 0, 0, 0, /* 3 ~ 7 */
|
||||||
|
0, 0, 0, 0, 0 /* 8 ~ 12 */
|
||||||
|
};
|
||||||
|
#else
|
||||||
const depth_t movingDiffDepthTable[] = {
|
const depth_t movingDiffDepthTable[] = {
|
||||||
0, 0, 0, /* 0 ~ 2 */
|
0, 0, 0, /* 0 ~ 2 */
|
||||||
11, 10, 9, 8, 7, /* 3 ~ 7 */
|
11, 10, 9, 8, 7, /* 3 ~ 7 */
|
||||||
6, 5, 4, 3, 2 /* 8 ~ 12 */
|
6, 5, 4, 3, 2 /* 8 ~ 12 */
|
||||||
};
|
};
|
||||||
|
#endif /* ENDGAME_LEARNING */
|
||||||
|
|
||||||
if ((tempGame.position.phase) & (PHASE_PLACING)) {
|
if ((tempGame.position.phase) & (PHASE_PLACING)) {
|
||||||
d = placingDepthTable[tempGame.getPiecesInHandCount(1)];
|
d = placingDepthTable[tempGame.getPiecesInHandCount(1)];
|
||||||
|
@ -288,11 +291,11 @@ void AIAlgorithm::setGame(const Game &game)
|
||||||
TranspositionTable::clear();
|
TranspositionTable::clear();
|
||||||
#endif // TRANSPOSITION_TABLE_ENABLE
|
#endif // TRANSPOSITION_TABLE_ENABLE
|
||||||
|
|
||||||
#ifdef BOOK_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
// TODO: 规则改变时清空学习表
|
// TODO: 规则改变时清空残局库
|
||||||
//clearBookHashMap();
|
//clearEndgameHashMap();
|
||||||
//openingBook.clear();
|
//endgameList.clear();
|
||||||
#endif // BOOK_LEARNING
|
#endif // ENDGAME_LEARNING
|
||||||
|
|
||||||
history.clear();
|
history.clear();
|
||||||
}
|
}
|
||||||
|
@ -332,19 +335,6 @@ int AIAlgorithm::search(depth_t depth)
|
||||||
auto timeStart = chrono::steady_clock::now();
|
auto timeStart = chrono::steady_clock::now();
|
||||||
chrono::steady_clock::time_point timeEnd;
|
chrono::steady_clock::time_point timeEnd;
|
||||||
|
|
||||||
#ifdef BOOK_LEARNING
|
|
||||||
if (position_.getPhase() == GAME_PLACING)
|
|
||||||
{
|
|
||||||
if (position_.position.nPiecesInHand[1] <= 10) {
|
|
||||||
// 开局库只记录摆棋阶段最后的局面
|
|
||||||
openingBook.push_back(position_.getHash());
|
|
||||||
} else {
|
|
||||||
// 暂时在此处清空开局库
|
|
||||||
openingBook.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef THREEFOLD_REPETITION
|
#ifdef THREEFOLD_REPETITION
|
||||||
static int nRepetition = 0;
|
static int nRepetition = 0;
|
||||||
|
|
||||||
|
@ -415,18 +405,37 @@ value_t AIAlgorithm::search(depth_t depth, value_t alpha, value_t beta, Node *no
|
||||||
// 子节点的最优着法
|
// 子节点的最优着法
|
||||||
move_t bestMove = MOVE_NONE;
|
move_t bestMove = MOVE_NONE;
|
||||||
|
|
||||||
#if ((defined TRANSPOSITION_TABLE_ENABLE) || (defined BOOK_LEARNING))
|
#if defined (TRANSPOSITION_TABLE_ENABLE) || defined(ENDGAME_LEARNING)
|
||||||
// 哈希类型
|
|
||||||
enum TranspositionTable::HashType hashf = TranspositionTable::hashfALPHA;
|
|
||||||
|
|
||||||
// 获取哈希值
|
// 获取哈希值
|
||||||
hash_t hash = tempGame.getHash();
|
hash_t hash = tempGame.getHash();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENDGAME_LEARNING
|
||||||
|
// 检索残局库
|
||||||
|
Endgame endgame;
|
||||||
|
|
||||||
|
if (findEndgameHash(hash, endgame)) {
|
||||||
|
switch (endgame.type) {
|
||||||
|
case ENDGAME_PLAYER_1_WIN:
|
||||||
|
node->value = VALUE_WIN;
|
||||||
|
case ENDGAME_PLAYER_2_WIN:
|
||||||
|
node->value = -VALUE_WIN;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node->value;
|
||||||
|
}
|
||||||
|
#endif /* ENDGAME_LEARNING */
|
||||||
|
|
||||||
|
#ifdef TRANSPOSITION_TABLE_ENABLE
|
||||||
|
// 哈希类型
|
||||||
|
enum TranspositionTable::HashType hashf = TranspositionTable::hashfALPHA;
|
||||||
|
|
||||||
#ifdef DEBUG_AB_TREE
|
#ifdef DEBUG_AB_TREE
|
||||||
node->hash = hash;
|
node->hash = hash;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TRANSPOSITION_TABLE_ENABLE
|
|
||||||
TranspositionTable::HashType type = TranspositionTable::hashfEMPTY;
|
TranspositionTable::HashType type = TranspositionTable::hashfEMPTY;
|
||||||
|
|
||||||
value_t probeVal = TranspositionTable::probeHash(hash, depth, alpha, beta, bestMove, type);
|
value_t probeVal = TranspositionTable::probeHash(hash, depth, alpha, beta, bestMove, type);
|
||||||
|
@ -455,7 +464,7 @@ value_t AIAlgorithm::search(depth_t depth, value_t alpha, value_t beta, Node *no
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return node->value;
|
return node->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
//hashMapMutex.unlock();
|
//hashMapMutex.unlock();
|
||||||
#endif /* TRANSPOSITION_TABLE_ENABLE */
|
#endif /* TRANSPOSITION_TABLE_ENABLE */
|
||||||
|
@ -515,16 +524,6 @@ value_t AIAlgorithm::search(depth_t depth, value_t alpha, value_t beta, Node *no
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BOOK_LEARNING
|
|
||||||
// 检索开局库
|
|
||||||
if (position->phase == GAME_PLACING && findBookHash(hash, hashValue)) {
|
|
||||||
if (position->turn == ???) {
|
|
||||||
// TODO:
|
|
||||||
node->value += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TRANSPOSITION_TABLE_ENABLE
|
#ifdef TRANSPOSITION_TABLE_ENABLE
|
||||||
// 记录确切的哈希值
|
// 记录确切的哈希值
|
||||||
TranspositionTable::recordHash(node->value, depth, TranspositionTable::hashfEXACT, hash, MOVE_NONE);
|
TranspositionTable::recordHash(node->value, depth, TranspositionTable::hashfEXACT, hash, MOVE_NONE);
|
||||||
|
@ -702,6 +701,13 @@ const char* AIAlgorithm::bestMove()
|
||||||
|
|
||||||
// 自动认输
|
// 自动认输
|
||||||
if (isMostLose) {
|
if (isMostLose) {
|
||||||
|
#ifdef ENDGAME_LEARNING
|
||||||
|
Endgame endgame;
|
||||||
|
endgame.type = game_.position.sideToMove == PLAYER_1 ?
|
||||||
|
ENDGAME_PLAYER_2_WIN : ENDGAME_PLAYER_1_WIN;
|
||||||
|
recordEndgameHash(this->game_.getHash(), endgame);
|
||||||
|
#endif /* ENDGAME_LEARNING */
|
||||||
|
|
||||||
sprintf(cmdline, "Player%d give up!", game_.position.sideId);
|
sprintf(cmdline, "Player%d give up!", game_.position.sideId);
|
||||||
return cmdline;
|
return cmdline;
|
||||||
}
|
}
|
||||||
|
@ -760,58 +766,37 @@ const char *AIAlgorithm::moveToCommand(move_t move)
|
||||||
return cmdline;
|
return cmdline;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BOOK_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
|
bool AIAlgorithm::findEndgameHash(hash_t hash, Endgame &endgame)
|
||||||
bool AIAlgorithm::findBookHash(hash_t hash, HashValue &hashValue)
|
|
||||||
{
|
{
|
||||||
return bookHashMap.find(hash, hashValue);
|
return endgameHashMap.find(hash, endgame);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AIAlgorithm::recordBookHash(hash_t hash, const HashValue &hashValue)
|
int AIAlgorithm::recordEndgameHash(hash_t hash, const Endgame &endgame)
|
||||||
{
|
{
|
||||||
//hashMapMutex.lock();
|
//hashMapMutex.lock();
|
||||||
bookHashMap.insert(hash, hashValue);
|
endgameHashMap.insert(hash, endgame);
|
||||||
//hashMapMutex.unlock();
|
//hashMapMutex.unlock();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AIAlgorithm::clearBookHashMap()
|
void AIAlgorithm::clearEndgameHashMap()
|
||||||
{
|
{
|
||||||
//hashMapMutex.lock();
|
//hashMapMutex.lock();
|
||||||
bookHashMap.clear();
|
endgameHashMap.clear();
|
||||||
//hashMapMutex.unlock();
|
//hashMapMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AIAlgorithm::recordOpeningBookToHashMap()
|
void AIAlgorithm::recordEndgameHashMapToFile()
|
||||||
{
|
{
|
||||||
HashValue hashValue;
|
const QString filename = "endgame.txt";
|
||||||
hash_t hash = 0;
|
endgameHashMap.dump(filename);
|
||||||
|
|
||||||
for (auto iter = openingBook.begin(); iter != openingBook.end(); ++iter)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
if (findBookHash(*iter, hashValue))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
memset(&hashValue, 0, sizeof(HashValue));
|
|
||||||
hash = *iter;
|
|
||||||
recordBookHash(hash, hashValue); // 暂时使用直接覆盖策略
|
|
||||||
}
|
|
||||||
|
|
||||||
openingBook.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AIAlgorithm::recordOpeningBookHashMapToFile()
|
void AIAlgorithm::loadEndgameFileToHashMap()
|
||||||
{
|
{
|
||||||
const QString bookFileName = "opening-book.txt";
|
const QString filename = "endgame.txt";
|
||||||
bookHashMap.dump(bookFileName);
|
endgameHashMap.load(filename);
|
||||||
}
|
}
|
||||||
|
#endif // ENDGAME_LEARNING
|
||||||
void AIAlgorithm::loadOpeningBookFileToHashMap()
|
|
||||||
{
|
|
||||||
const QString bookFileName = "opening-book.txt";
|
|
||||||
bookHashMap.load(bookFileName);
|
|
||||||
}
|
|
||||||
#endif // BOOK_LEARNING
|
|
||||||
|
|
|
@ -36,7 +36,10 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
|
#include "tt.h"
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
|
#include "endgame.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
#ifdef MEMORY_POOL
|
#ifdef MEMORY_POOL
|
||||||
#include "MemoryPool.h"
|
#include "MemoryPool.h"
|
||||||
|
@ -111,7 +114,7 @@ public:
|
||||||
// 返回最佳走法的命令行
|
// 返回最佳走法的命令行
|
||||||
const char *bestMove();
|
const char *bestMove();
|
||||||
|
|
||||||
#if ((defined TRANSPOSITION_TABLE_ENABLE) || (defined BOOK_LEARNING))
|
#ifdef TRANSPOSITION_TABLE_ENABLE
|
||||||
// 清空哈希表
|
// 清空哈希表
|
||||||
void clearTranspositionTable();
|
void clearTranspositionTable();
|
||||||
#endif
|
#endif
|
||||||
|
@ -120,14 +123,14 @@ public:
|
||||||
static bool nodeLess(const Node *first, const Node *second);
|
static bool nodeLess(const Node *first, const Node *second);
|
||||||
static bool nodeGreater(const Node *first, const Node *second);
|
static bool nodeGreater(const Node *first, const Node *second);
|
||||||
|
|
||||||
#ifdef BOOK_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
bool findBookHash(hash_t hash, HashValue &hashValue);
|
bool findEndgameHash(hash_t hash, Endgame &endgame);
|
||||||
static int recordBookHash(hash_t hash, const HashValue &hashValue);
|
static int recordEndgameHash(hash_t hash, const Endgame &endgame);
|
||||||
void clearBookHashMap();
|
void clearEndgameHashMap();
|
||||||
static void recordOpeningBookToHashMap();
|
static void recordEndgameHashMapToFile();
|
||||||
static void recordOpeningBookHashMapToFile();
|
static void loadEndgameFileToHashMap();
|
||||||
static void loadOpeningBookFileToHashMap();
|
#endif // ENDGAME_LEARNING
|
||||||
#endif // BOOK_LEARNING
|
|
||||||
|
|
||||||
public: /* TODO: Move to private or protected */
|
public: /* TODO: Move to private or protected */
|
||||||
// 增加新节点
|
// 增加新节点
|
||||||
|
|
|
@ -34,9 +34,9 @@ Game::Game()
|
||||||
// 创建哈希数据
|
// 创建哈希数据
|
||||||
constructHash();
|
constructHash();
|
||||||
|
|
||||||
#ifdef BOOK_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
// TODO: 开局库文件被加载了多次
|
// TODO: 残局文件被加载了多次
|
||||||
MillGameAi_ab::loadOpeningBookFileToHashMap();
|
AIAlgorithm::loadEndgameFileToHashMap();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 默认选择第1号规则,即“打三棋”
|
// 默认选择第1号规则,即“打三棋”
|
||||||
|
@ -886,9 +886,6 @@ bool Game::win(bool forceDraw)
|
||||||
position.phase = PHASE_GAMEOVER;
|
position.phase = PHASE_GAMEOVER;
|
||||||
sprintf(cmdline, "Player%d win!", o);
|
sprintf(cmdline, "Player%d win!", o);
|
||||||
cmdlist.emplace_back(string(cmdline));
|
cmdlist.emplace_back(string(cmdline));
|
||||||
#ifdef BOOK_LEARNING
|
|
||||||
MillGameAi_ab::recordOpeningBookToHashMap(); // TODO: 目前是对"双方"失败都记录到开局库
|
|
||||||
#endif /* BOOK_LEARNING */
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -922,9 +919,6 @@ bool Game::win(bool forceDraw)
|
||||||
int winnerId = Player::toId(winner);
|
int winnerId = Player::toId(winner);
|
||||||
sprintf(cmdline, "Player%d no way to go. Player%d win!", position.sideId, winnerId);
|
sprintf(cmdline, "Player%d no way to go. Player%d win!", position.sideId, winnerId);
|
||||||
cmdlist.emplace_back(string(cmdline));
|
cmdlist.emplace_back(string(cmdline));
|
||||||
#ifdef BOOK_LEARNING
|
|
||||||
MillGameAi_ab::recordOpeningBookToHashMap(); // TODO: 目前是对所有的失败记录到开局库
|
|
||||||
#endif /* BOOK_LEARNING */
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,9 +98,9 @@ GameController::~GameController()
|
||||||
delete ai[1];
|
delete ai[1];
|
||||||
delete ai[2];
|
delete ai[2];
|
||||||
|
|
||||||
#ifdef BOOK_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
MillGameAi_ab::recordOpeningBookHashMapToFile();
|
AIAlgorithm::recordEndgameHashMapToFile();
|
||||||
#endif /* BOOK_LEARNING */
|
#endif /* ENDGAME_LEARNING */
|
||||||
}
|
}
|
||||||
|
|
||||||
const QMap<int, QStringList> GameController::getActions()
|
const QMap<int, QStringList> GameController::getActions()
|
||||||
|
|
Loading…
Reference in New Issue