endgame: refactor
Known Issue: After the previous series of code refactoring, it still cannot work normally, but it can work normally in the early stage.
This commit is contained in:
parent
b3577d6b78
commit
096af01919
|
@ -97,7 +97,6 @@
|
||||||
|
|
||||||
//#define ENDGAME_LEARNING
|
//#define ENDGAME_LEARNING
|
||||||
//#define ENDGAME_LEARNING_FORCE
|
//#define ENDGAME_LEARNING_FORCE
|
||||||
//#define ENDGAME_LEARNING_DEBUG
|
|
||||||
|
|
||||||
#define THREEFOLD_REPETITION
|
#define THREEFOLD_REPETITION
|
||||||
|
|
||||||
|
|
|
@ -31,21 +31,20 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace CTSL;
|
using namespace CTSL;
|
||||||
|
|
||||||
// TODO: uint8_t
|
static const int SAVE_ENDGAME_EVERY_N_GAMES = 256;
|
||||||
enum endgame_t : uint32_t
|
|
||||||
|
enum class EndGameType : uint32_t
|
||||||
{
|
{
|
||||||
ENDGAME_NONE,
|
none,
|
||||||
ENDGAME_PLAYER_BLACK_WIN,
|
blackWin,
|
||||||
ENDGAME_PLAYER_WHITE_WIN,
|
whiteWin,
|
||||||
ENDGAME_DRAW,
|
draw,
|
||||||
};
|
};
|
||||||
|
|
||||||
//#pragma pack (push, 1)
|
|
||||||
struct Endgame
|
struct Endgame
|
||||||
{
|
{
|
||||||
endgame_t type;
|
EndGameType type;
|
||||||
};
|
};
|
||||||
//#pragma pack(pop)
|
|
||||||
|
|
||||||
extern HashMap<Key, Endgame> endgameHashMap;
|
extern HashMap<Key, Endgame> endgameHashMap;
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ public:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getLearnEndgameEnabled()
|
bool isEndgameLearningEnabled()
|
||||||
{
|
{
|
||||||
#ifdef ENDGAME_LEARNING_FORCE
|
#ifdef ENDGAME_LEARNING_FORCE
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -169,7 +169,7 @@ Position::Position()
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
score[BLACK] = score[WHITE] = score_draw = nPlayed = 0;
|
score[BLACK] = score[WHITE] = score_draw = gamesPlayedCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -693,7 +693,7 @@ int Position::piece_on_board_count()
|
||||||
return pieceOnBoardCount[BLACK] + pieceOnBoardCount[WHITE];
|
return pieceOnBoardCount[BLACK] + pieceOnBoardCount[WHITE];
|
||||||
}
|
}
|
||||||
|
|
||||||
int Position::get_piece_in_hand_count()
|
int Position::piece_in_hand_count()
|
||||||
{
|
{
|
||||||
pieceInHandCount[BLACK] = rule.piecesCount - pieceOnBoardCount[BLACK];
|
pieceInHandCount[BLACK] = rule.piecesCount - pieceOnBoardCount[BLACK];
|
||||||
pieceInHandCount[WHITE] = rule.piecesCount - pieceOnBoardCount[WHITE];
|
pieceInHandCount[WHITE] = rule.piecesCount - pieceOnBoardCount[WHITE];
|
||||||
|
@ -736,8 +736,9 @@ bool Position::reset()
|
||||||
currentSquare = SQ_0;
|
currentSquare = SQ_0;
|
||||||
|
|
||||||
#ifdef ENDGAME_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
if (gameOptions.getLearnEndgameEnabled() && nPlayed != 0 && nPlayed % 256 == 0) {
|
if (gameOptions.isEndgameLearningEnabled() &&
|
||||||
Thread::recordEndgameHashMapToFile();
|
gamesPlayedCount > 0 && gamesPlayedCount % SAVE_ENDGAME_EVERY_N_GAMES == 0) {
|
||||||
|
Thread::saveEndgameHashMapToFile();
|
||||||
}
|
}
|
||||||
#endif /* ENDGAME_LEARNING */
|
#endif /* ENDGAME_LEARNING */
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,7 @@ public:
|
||||||
static void print_board();
|
static void print_board();
|
||||||
|
|
||||||
int piece_on_board_count();
|
int piece_on_board_count();
|
||||||
int get_piece_in_hand_count();
|
int piece_in_hand_count();
|
||||||
|
|
||||||
int piece_on_board_count(Color c);
|
int piece_on_board_count(Color c);
|
||||||
int piece_in_hand_count(Color c);
|
int piece_in_hand_count(Color c);
|
||||||
|
@ -203,7 +203,7 @@ public:
|
||||||
static Bitboard millTableBB[SQUARE_NB][LD_NB];
|
static Bitboard millTableBB[SQUARE_NB][LD_NB];
|
||||||
|
|
||||||
Square currentSquare;
|
Square currentSquare;
|
||||||
int nPlayed { 0 };
|
int gamesPlayedCount { 0 };
|
||||||
|
|
||||||
char cmdline[64] { '\0' };
|
char cmdline[64] { '\0' };
|
||||||
|
|
||||||
|
|
|
@ -233,14 +233,14 @@ Value search(Position *pos, Sanmill::Stack<Position> &ss, Depth depth, Depth ori
|
||||||
#ifdef ENDGAME_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
Endgame endgame;
|
Endgame endgame;
|
||||||
|
|
||||||
if (gameOptions.getLearnEndgameEnabled() &&
|
if (gameOptions.isEndgameLearningEnabled() &&
|
||||||
Thread::findEndgameHash(posKey, endgame)) {
|
Thread::probeEndgameHash(posKey, endgame)) {
|
||||||
switch (endgame.type) {
|
switch (endgame.type) {
|
||||||
case ENDGAME_PLAYER_BLACK_WIN:
|
case EndGameType::blackWin:
|
||||||
bestValue = VALUE_MATE;
|
bestValue = VALUE_MATE;
|
||||||
bestValue += depth;
|
bestValue += depth;
|
||||||
break;
|
break;
|
||||||
case ENDGAME_PLAYER_WHITE_WIN:
|
case EndGameType::whiteWin:
|
||||||
bestValue = -VALUE_MATE;
|
bestValue = -VALUE_MATE;
|
||||||
bestValue -= depth;
|
bestValue -= depth;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -424,15 +424,15 @@ Depth Thread::adjustDepth()
|
||||||
|
|
||||||
#ifdef ENDGAME_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
const Depth movingDiffDepthTable[] = {
|
const Depth movingDiffDepthTable[] = {
|
||||||
0, 0, 0, /* 0 ~ 2 */
|
0, 0, 0, /* 0 ~ 2 */
|
||||||
0, 0, 0, 0, 0, /* 3 ~ 7 */
|
0, 0, 0, 0, 0, /* 3 ~ 7 */
|
||||||
0, 0, 0, 0, 0 /* 8 ~ 12 */
|
0, 0, 0, 0, 0 /* 8 ~ 12 */
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
const Depth movingDiffDepthTable[] = {
|
const Depth movingDiffDepthTable[] = {
|
||||||
0, 0, 0, /* 0 ~ 2 */
|
0, 0, 0, /* 0 ~ 2 */
|
||||||
11, 11, 10, 9, 8, /* 3 ~ 7 */
|
11, 11, 10, 9, 8, /* 3 ~ 7 */
|
||||||
7, 6, 5, 4, 3 /* 8 ~ 12 */
|
7, 6, 5, 4, 3 /* 8 ~ 12 */
|
||||||
};
|
};
|
||||||
#endif /* ENDGAME_LEARNING */
|
#endif /* ENDGAME_LEARNING */
|
||||||
|
|
||||||
|
@ -506,12 +506,6 @@ void Thread::clearTT()
|
||||||
#ifdef TRANSPOSITION_TABLE_ENABLE
|
#ifdef TRANSPOSITION_TABLE_ENABLE
|
||||||
TranspositionTable::clear();
|
TranspositionTable::clear();
|
||||||
#endif // TRANSPOSITION_TABLE_ENABLE
|
#endif // TRANSPOSITION_TABLE_ENABLE
|
||||||
|
|
||||||
#ifdef ENDGAME_LEARNING
|
|
||||||
// TODO: ??????????
|
|
||||||
//clearEndgameHashMap();
|
|
||||||
//endgameList.clear();
|
|
||||||
#endif // ENDGAME_LEARNING
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,13 +542,13 @@ string Thread::nextMove()
|
||||||
|
|
||||||
#ifdef ENDGAME_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
// Check if very weak
|
// Check if very weak
|
||||||
if (gameOptions.getLearnEndgameEnabled()) {
|
if (gameOptions.isEndgameLearningEnabled()) {
|
||||||
if (bestValue <= -VALUE_KNOWN_WIN) {
|
if (bestValue <= -VALUE_KNOWN_WIN) {
|
||||||
Endgame endgame;
|
Endgame endgame;
|
||||||
endgame.type = state->position->playerSideToMove == PLAYER_BLACK ?
|
endgame.type = state->position->playerSideToMove == PLAYER_BLACK ?
|
||||||
ENDGAME_PLAYER_WHITE_WIN : ENDGAME_PLAYER_BLACK_WIN;
|
whiteWin : blackWin;
|
||||||
Key endgameHash = position->key(); // TODO: Do not generate hash repeately
|
Key endgameHash = position->key(); // TODO: Do not generate hash repeately
|
||||||
recordEndgameHash(endgameHash, endgame);
|
saveEndgameHash(endgameHash, endgame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* ENDGAME_LEARNING */
|
#endif /* ENDGAME_LEARNING */
|
||||||
|
@ -591,31 +585,28 @@ string Thread::nextMove()
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENDGAME_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
bool Thread::findEndgameHash(Key posKey, Endgame &endgame)
|
bool Thread::probeEndgameHash(Key posKey, Endgame &endgame)
|
||||||
{
|
{
|
||||||
return endgameHashMap.find(posKey, endgame);
|
return endgameHashMap.find(posKey, endgame);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Thread::recordEndgameHash(Key posKey, const Endgame &endgame)
|
int Thread::saveEndgameHash(Key posKey, const Endgame &endgame)
|
||||||
{
|
{
|
||||||
//hashMapMutex.lock();
|
|
||||||
Key hashValue = endgameHashMap.insert(posKey, endgame);
|
Key hashValue = endgameHashMap.insert(posKey, endgame);
|
||||||
unsigned addr = hashValue * (sizeof(posKey) + sizeof(endgame));
|
unsigned addr = hashValue * (sizeof(posKey) + sizeof(endgame));
|
||||||
//hashMapMutex.unlock();
|
|
||||||
|
|
||||||
loggerDebug("[endgame] Record 0x%08I32x (%d) to Endgame Hash map, TTEntry: 0x%08I32x, Address: 0x%08I32x\n", posKey, endgame.type, hashValue, addr);
|
loggerDebug("[endgame] Record 0x%08I32x (%d) to Endgame hash map, TTEntry: 0x%08I32x, Address: 0x%08I32x\n",
|
||||||
|
posKey, endgame.type, hashValue, addr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::clearEndgameHashMap()
|
void Thread::clearEndgameHashMap()
|
||||||
{
|
{
|
||||||
//hashMapMutex.lock();
|
|
||||||
endgameHashMap.clear();
|
endgameHashMap.clear();
|
||||||
//hashMapMutex.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::recordEndgameHashMapToFile()
|
void Thread::saveEndgameHashMapToFile()
|
||||||
{
|
{
|
||||||
const string filename = "endgame.txt";
|
const string filename = "endgame.txt";
|
||||||
endgameHashMap.dump(filename);
|
endgameHashMap.dump(filename);
|
||||||
|
|
|
@ -94,10 +94,10 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENDGAME_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
static bool findEndgameHash(Key key, Endgame &endgame);
|
static bool probeEndgameHash(Key key, Endgame &endgame);
|
||||||
static int recordEndgameHash(Key key, const Endgame &endgame);
|
static int saveEndgameHash(Key key, const Endgame &endgame);
|
||||||
void clearEndgameHashMap();
|
void clearEndgameHashMap();
|
||||||
static void recordEndgameHashMapToFile();
|
static void saveEndgameHashMapToFile();
|
||||||
static void loadEndgameFileToHashMap();
|
static void loadEndgameFileToHashMap();
|
||||||
#endif // ENDGAME_LEARNING
|
#endif // ENDGAME_LEARNING
|
||||||
|
|
||||||
|
|
|
@ -106,8 +106,8 @@ Game::Game(
|
||||||
#endif // NET_FIGHT_SUPPORT
|
#endif // NET_FIGHT_SUPPORT
|
||||||
|
|
||||||
#ifdef ENDGAME_LEARNING_FORCE
|
#ifdef ENDGAME_LEARNING_FORCE
|
||||||
if (gameOptions.getLearnEndgameEnabled()) {
|
if (gameOptions.isEndgameLearningEnabled()) {
|
||||||
AIAlgorithm::loadEndgameFileToHashMap();
|
Thread::loadEndgameFileToHashMap();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -129,8 +129,8 @@ Game::~Game()
|
||||||
deleteAiThreads();
|
deleteAiThreads();
|
||||||
|
|
||||||
#ifdef ENDGAME_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
if (gameOptions.getLearnEndgameEnabled()) {
|
if (gameOptions.isEndgameLearningEnabled()) {
|
||||||
Thread::recordEndgameHashMapToFile();
|
Thread::saveEndgameHashMapToFile();
|
||||||
}
|
}
|
||||||
#endif /* ENDGAME_LEARNING */
|
#endif /* ENDGAME_LEARNING */
|
||||||
|
|
||||||
|
@ -286,18 +286,18 @@ void Game::gameReset()
|
||||||
emit statusBarChanged(message);
|
emit statusBarChanged(message);
|
||||||
|
|
||||||
// 更新比分 LCD 显示
|
// 更新比分 LCD 显示
|
||||||
emit nGamesPlayedChanged(QString::number(position.nPlayed, 10));
|
emit nGamesPlayedChanged(QString::number(position.gamesPlayedCount, 10));
|
||||||
emit score1Changed(QString::number(position.score[BLACK], 10));
|
emit score1Changed(QString::number(position.score[BLACK], 10));
|
||||||
emit score2Changed(QString::number(position.score[WHITE], 10));
|
emit score2Changed(QString::number(position.score[WHITE], 10));
|
||||||
emit scoreDrawChanged(QString::number(position.score_draw, 10));
|
emit scoreDrawChanged(QString::number(position.score_draw, 10));
|
||||||
|
|
||||||
// 更新胜率 LCD 显示
|
// 更新胜率 LCD 显示
|
||||||
position.nPlayed = position.score[BLACK] + position.score[WHITE] + position.score_draw;
|
position.gamesPlayedCount = position.score[BLACK] + position.score[WHITE] + position.score_draw;
|
||||||
int winningRate_1 = 0, winningRate_2 = 0, winningRate_draw = 0;
|
int winningRate_1 = 0, winningRate_2 = 0, winningRate_draw = 0;
|
||||||
if (position.nPlayed != 0) {
|
if (position.gamesPlayedCount != 0) {
|
||||||
winningRate_1 = position.score[BLACK] * 10000 / position.nPlayed;
|
winningRate_1 = position.score[BLACK] * 10000 / position.gamesPlayedCount;
|
||||||
winningRate_2 = position.score[WHITE] * 10000 / position.nPlayed;
|
winningRate_2 = position.score[WHITE] * 10000 / position.gamesPlayedCount;
|
||||||
winningRate_draw = position.score_draw * 10000 / position.nPlayed;
|
winningRate_draw = position.score_draw * 10000 / position.gamesPlayedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit winningRate1Changed(QString::number(winningRate_1, 10));
|
emit winningRate1Changed(QString::number(winningRate_1, 10));
|
||||||
|
@ -559,7 +559,7 @@ void Game::setLearnEndgame(bool enabled)
|
||||||
gameOptions.setLearnEndgameEnabled(enabled);
|
gameOptions.setLearnEndgameEnabled(enabled);
|
||||||
|
|
||||||
#ifdef ENDGAME_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
if (gameOptions.getLearnEndgameEnabled()) {
|
if (gameOptions.isEndgameLearningEnabled()) {
|
||||||
Thread::loadEndgameFileToHashMap();
|
Thread::loadEndgameFileToHashMap();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1364,12 +1364,12 @@ bool Game::updateScence(Position &p)
|
||||||
emit scoreDrawChanged(QString::number(p.score_draw, 10));
|
emit scoreDrawChanged(QString::number(p.score_draw, 10));
|
||||||
|
|
||||||
// 更新胜率 LCD 显示
|
// 更新胜率 LCD 显示
|
||||||
position.nPlayed = position.score[BLACK] + position.score[WHITE] + position.score_draw;
|
position.gamesPlayedCount = position.score[BLACK] + position.score[WHITE] + position.score_draw;
|
||||||
int winningRate_1 = 0, winningRate_2 = 0, winningRate_draw = 0;
|
int winningRate_1 = 0, winningRate_2 = 0, winningRate_draw = 0;
|
||||||
if (position.nPlayed != 0) {
|
if (position.gamesPlayedCount != 0) {
|
||||||
winningRate_1 = position.score[BLACK] * 10000 / position.nPlayed;
|
winningRate_1 = position.score[BLACK] * 10000 / position.gamesPlayedCount;
|
||||||
winningRate_2 = position.score[WHITE] * 10000 / position.nPlayed;
|
winningRate_2 = position.score[WHITE] * 10000 / position.gamesPlayedCount;
|
||||||
winningRate_draw = position.score_draw * 10000 / position.nPlayed;
|
winningRate_draw = position.score_draw * 10000 / position.gamesPlayedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit winningRate1Changed(QString::number(winningRate_1, 10));
|
emit winningRate1Changed(QString::number(winningRate_1, 10));
|
||||||
|
@ -1450,16 +1450,16 @@ void Game::saveScore()
|
||||||
|
|
||||||
textStream << "" << endl;
|
textStream << "" << endl;
|
||||||
|
|
||||||
position.nPlayed = position.score[BLACK] + position.score[WHITE] + position.score_draw;
|
position.gamesPlayedCount = position.score[BLACK] + position.score[WHITE] + position.score_draw;
|
||||||
|
|
||||||
if (position.nPlayed == 0) {
|
if (position.gamesPlayedCount == 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
textStream << "Sum\t" + QString::number(position.nPlayed) << endl;
|
textStream << "Sum\t" + QString::number(position.gamesPlayedCount) << endl;
|
||||||
textStream << "Black\t" + QString::number(position.score[BLACK]) + "\t" + QString::number(position.score[BLACK] * 10000 / position.nPlayed) << endl;
|
textStream << "Black\t" + QString::number(position.score[BLACK]) + "\t" + QString::number(position.score[BLACK] * 10000 / position.gamesPlayedCount) << endl;
|
||||||
textStream << "White\t" + QString::number(position.score[WHITE]) + "\t" + QString::number(position.score[WHITE] * 10000 / position.nPlayed) << endl;
|
textStream << "White\t" + QString::number(position.score[WHITE]) + "\t" + QString::number(position.score[WHITE] * 10000 / position.gamesPlayedCount) << endl;
|
||||||
textStream << "Draw\t" + QString::number(position.score_draw) + "\t" + QString::number(position.score_draw * 10000 / position.nPlayed) << endl;
|
textStream << "Draw\t" + QString::number(position.score_draw) + "\t" + QString::number(position.score_draw * 10000 / position.gamesPlayedCount) << endl;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
file.flush();
|
file.flush();
|
||||||
|
|
Loading…
Reference in New Issue