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:
Calcitem 2020-12-31 12:22:48 +08:00
parent b3577d6b78
commit 096af01919
9 changed files with 58 additions and 68 deletions

View File

@ -97,7 +97,6 @@
//#define ENDGAME_LEARNING
//#define ENDGAME_LEARNING_FORCE
//#define ENDGAME_LEARNING_DEBUG
#define THREEFOLD_REPETITION

View File

@ -31,21 +31,20 @@
using namespace std;
using namespace CTSL;
// TODO: uint8_t
enum endgame_t : uint32_t
static const int SAVE_ENDGAME_EVERY_N_GAMES = 256;
enum class EndGameType : uint32_t
{
ENDGAME_NONE,
ENDGAME_PLAYER_BLACK_WIN,
ENDGAME_PLAYER_WHITE_WIN,
ENDGAME_DRAW,
none,
blackWin,
whiteWin,
draw,
};
//#pragma pack (push, 1)
struct Endgame
{
endgame_t type;
EndGameType type;
};
//#pragma pack(pop)
extern HashMap<Key, Endgame> endgameHashMap;

View File

@ -79,7 +79,7 @@ public:
#endif
}
bool getLearnEndgameEnabled()
bool isEndgameLearningEnabled()
{
#ifdef ENDGAME_LEARNING_FORCE
return true;

View File

@ -169,7 +169,7 @@ Position::Position()
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];
}
int Position::get_piece_in_hand_count()
int Position::piece_in_hand_count()
{
pieceInHandCount[BLACK] = rule.piecesCount - pieceOnBoardCount[BLACK];
pieceInHandCount[WHITE] = rule.piecesCount - pieceOnBoardCount[WHITE];
@ -736,8 +736,9 @@ bool Position::reset()
currentSquare = SQ_0;
#ifdef ENDGAME_LEARNING
if (gameOptions.getLearnEndgameEnabled() && nPlayed != 0 && nPlayed % 256 == 0) {
Thread::recordEndgameHashMapToFile();
if (gameOptions.isEndgameLearningEnabled() &&
gamesPlayedCount > 0 && gamesPlayedCount % SAVE_ENDGAME_EVERY_N_GAMES == 0) {
Thread::saveEndgameHashMapToFile();
}
#endif /* ENDGAME_LEARNING */

View File

@ -145,7 +145,7 @@ public:
static void print_board();
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_in_hand_count(Color c);
@ -203,7 +203,7 @@ public:
static Bitboard millTableBB[SQUARE_NB][LD_NB];
Square currentSquare;
int nPlayed { 0 };
int gamesPlayedCount { 0 };
char cmdline[64] { '\0' };

View File

@ -233,14 +233,14 @@ Value search(Position *pos, Sanmill::Stack<Position> &ss, Depth depth, Depth ori
#ifdef ENDGAME_LEARNING
Endgame endgame;
if (gameOptions.getLearnEndgameEnabled() &&
Thread::findEndgameHash(posKey, endgame)) {
if (gameOptions.isEndgameLearningEnabled() &&
Thread::probeEndgameHash(posKey, endgame)) {
switch (endgame.type) {
case ENDGAME_PLAYER_BLACK_WIN:
case EndGameType::blackWin:
bestValue = VALUE_MATE;
bestValue += depth;
break;
case ENDGAME_PLAYER_WHITE_WIN:
case EndGameType::whiteWin:
bestValue = -VALUE_MATE;
bestValue -= depth;
break;

View File

@ -424,15 +424,15 @@ Depth Thread::adjustDepth()
#ifdef ENDGAME_LEARNING
const Depth movingDiffDepthTable[] = {
0, 0, 0, /* 0 ~ 2 */
0, 0, 0, 0, 0, /* 3 ~ 7 */
0, 0, 0, 0, 0 /* 8 ~ 12 */
0, 0, 0, /* 0 ~ 2 */
0, 0, 0, 0, 0, /* 3 ~ 7 */
0, 0, 0, 0, 0 /* 8 ~ 12 */
};
#else
const Depth movingDiffDepthTable[] = {
0, 0, 0, /* 0 ~ 2 */
0, 0, 0, /* 0 ~ 2 */
11, 11, 10, 9, 8, /* 3 ~ 7 */
7, 6, 5, 4, 3 /* 8 ~ 12 */
7, 6, 5, 4, 3 /* 8 ~ 12 */
};
#endif /* ENDGAME_LEARNING */
@ -506,12 +506,6 @@ void Thread::clearTT()
#ifdef TRANSPOSITION_TABLE_ENABLE
TranspositionTable::clear();
#endif // TRANSPOSITION_TABLE_ENABLE
#ifdef ENDGAME_LEARNING
// TODO: ??????????
//clearEndgameHashMap();
//endgameList.clear();
#endif // ENDGAME_LEARNING
}
}
@ -548,13 +542,13 @@ string Thread::nextMove()
#ifdef ENDGAME_LEARNING
// Check if very weak
if (gameOptions.getLearnEndgameEnabled()) {
if (gameOptions.isEndgameLearningEnabled()) {
if (bestValue <= -VALUE_KNOWN_WIN) {
Endgame endgame;
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
recordEndgameHash(endgameHash, endgame);
saveEndgameHash(endgameHash, endgame);
}
}
#endif /* ENDGAME_LEARNING */
@ -591,31 +585,28 @@ string Thread::nextMove()
}
#ifdef ENDGAME_LEARNING
bool Thread::findEndgameHash(Key posKey, Endgame &endgame)
bool Thread::probeEndgameHash(Key posKey, Endgame &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);
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;
}
void Thread::clearEndgameHashMap()
{
//hashMapMutex.lock();
endgameHashMap.clear();
//hashMapMutex.unlock();
}
void Thread::recordEndgameHashMapToFile()
void Thread::saveEndgameHashMapToFile()
{
const string filename = "endgame.txt";
endgameHashMap.dump(filename);

View File

@ -94,10 +94,10 @@ public:
#endif
#ifdef ENDGAME_LEARNING
static bool findEndgameHash(Key key, Endgame &endgame);
static int recordEndgameHash(Key key, const Endgame &endgame);
static bool probeEndgameHash(Key key, Endgame &endgame);
static int saveEndgameHash(Key key, const Endgame &endgame);
void clearEndgameHashMap();
static void recordEndgameHashMapToFile();
static void saveEndgameHashMapToFile();
static void loadEndgameFileToHashMap();
#endif // ENDGAME_LEARNING

View File

@ -106,8 +106,8 @@ Game::Game(
#endif // NET_FIGHT_SUPPORT
#ifdef ENDGAME_LEARNING_FORCE
if (gameOptions.getLearnEndgameEnabled()) {
AIAlgorithm::loadEndgameFileToHashMap();
if (gameOptions.isEndgameLearningEnabled()) {
Thread::loadEndgameFileToHashMap();
}
#endif
@ -129,8 +129,8 @@ Game::~Game()
deleteAiThreads();
#ifdef ENDGAME_LEARNING
if (gameOptions.getLearnEndgameEnabled()) {
Thread::recordEndgameHashMapToFile();
if (gameOptions.isEndgameLearningEnabled()) {
Thread::saveEndgameHashMapToFile();
}
#endif /* ENDGAME_LEARNING */
@ -286,18 +286,18 @@ void Game::gameReset()
emit statusBarChanged(message);
// 更新比分 LCD 显示
emit nGamesPlayedChanged(QString::number(position.nPlayed, 10));
emit nGamesPlayedChanged(QString::number(position.gamesPlayedCount, 10));
emit score1Changed(QString::number(position.score[BLACK], 10));
emit score2Changed(QString::number(position.score[WHITE], 10));
emit scoreDrawChanged(QString::number(position.score_draw, 10));
// 更新胜率 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;
if (position.nPlayed != 0) {
winningRate_1 = position.score[BLACK] * 10000 / position.nPlayed;
winningRate_2 = position.score[WHITE] * 10000 / position.nPlayed;
winningRate_draw = position.score_draw * 10000 / position.nPlayed;
if (position.gamesPlayedCount != 0) {
winningRate_1 = position.score[BLACK] * 10000 / position.gamesPlayedCount;
winningRate_2 = position.score[WHITE] * 10000 / position.gamesPlayedCount;
winningRate_draw = position.score_draw * 10000 / position.gamesPlayedCount;
}
emit winningRate1Changed(QString::number(winningRate_1, 10));
@ -559,7 +559,7 @@ void Game::setLearnEndgame(bool enabled)
gameOptions.setLearnEndgameEnabled(enabled);
#ifdef ENDGAME_LEARNING
if (gameOptions.getLearnEndgameEnabled()) {
if (gameOptions.isEndgameLearningEnabled()) {
Thread::loadEndgameFileToHashMap();
}
#endif
@ -1364,12 +1364,12 @@ bool Game::updateScence(Position &p)
emit scoreDrawChanged(QString::number(p.score_draw, 10));
// 更新胜率 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;
if (position.nPlayed != 0) {
winningRate_1 = position.score[BLACK] * 10000 / position.nPlayed;
winningRate_2 = position.score[WHITE] * 10000 / position.nPlayed;
winningRate_draw = position.score_draw * 10000 / position.nPlayed;
if (position.gamesPlayedCount != 0) {
winningRate_1 = position.score[BLACK] * 10000 / position.gamesPlayedCount;
winningRate_2 = position.score[WHITE] * 10000 / position.gamesPlayedCount;
winningRate_draw = position.score_draw * 10000 / position.gamesPlayedCount;
}
emit winningRate1Changed(QString::number(winningRate_1, 10));
@ -1450,16 +1450,16 @@ void Game::saveScore()
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;
}
textStream << "Sum\t" + QString::number(position.nPlayed) << endl;
textStream << "Black\t" + QString::number(position.score[BLACK]) + "\t" + QString::number(position.score[BLACK] * 10000 / position.nPlayed) << endl;
textStream << "White\t" + QString::number(position.score[WHITE]) + "\t" + QString::number(position.score[WHITE] * 10000 / position.nPlayed) << endl;
textStream << "Draw\t" + QString::number(position.score_draw) + "\t" + QString::number(position.score_draw * 10000 / 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.gamesPlayedCount) << 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.gamesPlayedCount) << endl;
out:
file.flush();