移除 player_t 类型并全部用 Color 类型取代
This commit is contained in:
parent
58acff7ce2
commit
1d7ecd6680
|
@ -45,7 +45,7 @@ Value Eval::evaluate(Position *pos)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACTION_REMOVE:
|
case ACTION_REMOVE:
|
||||||
nPiecesNeedRemove = (pos->sideToMove == PLAYER_BLACK) ?
|
nPiecesNeedRemove = (pos->sideToMove == BLACK) ?
|
||||||
pos->nPiecesNeedRemove : -(pos->nPiecesNeedRemove);
|
pos->nPiecesNeedRemove : -(pos->nPiecesNeedRemove);
|
||||||
value += nPiecesNeedRemove * VALUE_EACH_PIECE_PLACING_NEEDREMOVE;
|
value += nPiecesNeedRemove * VALUE_EACH_PIECE_PLACING_NEEDREMOVE;
|
||||||
break;
|
break;
|
||||||
|
@ -69,7 +69,7 @@ Value Eval::evaluate(Position *pos)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACTION_REMOVE:
|
case ACTION_REMOVE:
|
||||||
nPiecesNeedRemove = (pos->sideToMove == PLAYER_BLACK) ?
|
nPiecesNeedRemove = (pos->sideToMove == BLACK) ?
|
||||||
pos->nPiecesNeedRemove : -(pos->nPiecesNeedRemove);
|
pos->nPiecesNeedRemove : -(pos->nPiecesNeedRemove);
|
||||||
value += nPiecesNeedRemove * VALUE_EACH_PIECE_MOVING_NEEDREMOVE;
|
value += nPiecesNeedRemove * VALUE_EACH_PIECE_MOVING_NEEDREMOVE;
|
||||||
break;
|
break;
|
||||||
|
@ -88,9 +88,9 @@ Value Eval::evaluate(Position *pos)
|
||||||
value = VALUE_DRAW;
|
value = VALUE_DRAW;
|
||||||
}
|
}
|
||||||
} else if (pos->action == ACTION_SELECT &&
|
} else if (pos->action == ACTION_SELECT &&
|
||||||
pos->board.isAllSurrounded(pos->sideId, pos->nPiecesOnBoard, pos->sideToMove) &&
|
pos->board.isAllSurrounded(pos->sideToMove, pos->nPiecesOnBoard) &&
|
||||||
rule.isLoseButNotChangeTurnWhenNoWay) {
|
rule.isLoseButNotChangeTurnWhenNoWay) {
|
||||||
Value delta = pos->sideToMove == PLAYER_BLACK ? -VALUE_MATE : VALUE_MATE;
|
Value delta = pos->sideToMove == BLACK ? -VALUE_MATE : VALUE_MATE;
|
||||||
value += delta;
|
value += delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ Value Eval::evaluate(Position *pos)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos->sideToMove == PLAYER_WHITE) {
|
if (pos->sideToMove == WHITE) {
|
||||||
value = -value;
|
value = -value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -293,7 +293,7 @@ void MoveList::shuffle()
|
||||||
ExtMove *generateMoves(/* TODO: const */ Position *position, ExtMove *moveList)
|
ExtMove *generateMoves(/* TODO: const */ Position *position, ExtMove *moveList)
|
||||||
{
|
{
|
||||||
Square square;
|
Square square;
|
||||||
player_t opponent;
|
Color opponent;
|
||||||
|
|
||||||
//moves.clear();
|
//moves.clear();
|
||||||
ExtMove *cur = moveList;
|
ExtMove *cur = moveList;
|
||||||
|
@ -340,7 +340,7 @@ ExtMove *generateMoves(/* TODO: const */ Position *position, ExtMove *moveList)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (position->nPiecesOnBoard[position->sideId] > rule.nPiecesAtLeast ||
|
if (position->nPiecesOnBoard[position->sideToMove] > rule.nPiecesAtLeast ||
|
||||||
!rule.allowFlyWhenRemainThreePieces) {
|
!rule.allowFlyWhenRemainThreePieces) {
|
||||||
for (int direction = MD_BEGIN; direction < MD_NB; direction++) {
|
for (int direction = MD_BEGIN; direction < MD_NB; direction++) {
|
||||||
newSquare = static_cast<Square>(MoveList::moveTable[oldSquare][direction]);
|
newSquare = static_cast<Square>(MoveList::moveTable[oldSquare][direction]);
|
||||||
|
@ -368,7 +368,7 @@ ExtMove *generateMoves(/* TODO: const */ Position *position, ExtMove *moveList)
|
||||||
if (position->board.isAllInMills(opponent)) {
|
if (position->board.isAllInMills(opponent)) {
|
||||||
for (int i = Board::MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
|
for (int i = Board::MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
|
||||||
square = static_cast<Square>(MoveList::movePriorityTable[i]);
|
square = static_cast<Square>(MoveList::movePriorityTable[i]);
|
||||||
if (position->board.locations[square] & opponent) {
|
if (position->board.locations[square] & (opponent << PLAYER_SHIFT)) {
|
||||||
*cur++ = ((Move)-square);
|
*cur++ = ((Move)-square);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,8 +378,8 @@ ExtMove *generateMoves(/* TODO: const */ Position *position, ExtMove *moveList)
|
||||||
// not is all in mills
|
// not is all in mills
|
||||||
for (int i = Board::MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
|
for (int i = Board::MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
|
||||||
square = static_cast<Square>(MoveList::movePriorityTable[i]);
|
square = static_cast<Square>(MoveList::movePriorityTable[i]);
|
||||||
if (position->board.locations[square] & opponent) {
|
if (position->board.locations[square] & (opponent << PLAYER_SHIFT)) {
|
||||||
if (rule.allowRemovePieceInMill || !position->board.inHowManyMills(square, PLAYER_NOBODY)) {
|
if (rule.allowRemovePieceInMill || !position->board.inHowManyMills(square, NOBODY)) {
|
||||||
*cur++ = ((Move)-square);
|
*cur++ = ((Move)-square);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ void MovePicker::score()
|
||||||
int nBanned = 0;
|
int nBanned = 0;
|
||||||
int nEmpty = 0;
|
int nEmpty = 0;
|
||||||
|
|
||||||
position->board.getSurroundedPieceCount(sq, position->sideId,
|
position->board.getSurroundedPieceCount(sq, position->sideToMove,
|
||||||
nPlayerPiece, nOpponentPiece, nBanned, nEmpty);
|
nPlayerPiece, nOpponentPiece, nBanned, nEmpty);
|
||||||
|
|
||||||
#ifdef ALPHABETA_AI
|
#ifdef ALPHABETA_AI
|
||||||
|
@ -114,7 +114,7 @@ void MovePicker::score()
|
||||||
int nBanned = 0;
|
int nBanned = 0;
|
||||||
int nEmpty = 0;
|
int nEmpty = 0;
|
||||||
|
|
||||||
position->board.getSurroundedPieceCount(sq, position->sideId,
|
position->board.getSurroundedPieceCount(sq, position->sideToMove,
|
||||||
nPlayerPiece, nOpponentPiece, nBanned, nEmpty);
|
nPlayerPiece, nOpponentPiece, nBanned, nEmpty);
|
||||||
|
|
||||||
#ifdef ALPHABETA_AI
|
#ifdef ALPHABETA_AI
|
||||||
|
|
|
@ -33,8 +33,6 @@
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "movepick.h"
|
#include "movepick.h"
|
||||||
|
|
||||||
player_t gSideToMove;
|
|
||||||
|
|
||||||
using namespace CTSL;
|
using namespace CTSL;
|
||||||
|
|
||||||
vector<Key> moveHistory;
|
vector<Key> moveHistory;
|
||||||
|
@ -471,10 +469,10 @@ Value AIAlgorithm::search(Depth depth, Value alpha, Value beta)
|
||||||
|
|
||||||
for (int i = 0; i < nchild; i++) {
|
for (int i = 0; i < nchild; i++) {
|
||||||
stashPosition();
|
stashPosition();
|
||||||
player_t before = pos->sideToMove;
|
Color before = pos->sideToMove;
|
||||||
Move move = extMoves[i].move;
|
Move move = extMoves[i].move;
|
||||||
doMove(move);
|
doMove(move);
|
||||||
player_t after = pos->sideToMove;
|
Color after = pos->sideToMove;
|
||||||
|
|
||||||
if (gameOptions.getDepthExtension() == true && nchild == 1) {
|
if (gameOptions.getDepthExtension() == true && nchild == 1) {
|
||||||
epsilon = 1;
|
epsilon = 1;
|
||||||
|
@ -617,14 +615,14 @@ const char* AIAlgorithm::nextMove()
|
||||||
moveIndex++;
|
moveIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//player_t side = position->sideToMove;
|
Color side = position->sideToMove;
|
||||||
|
|
||||||
#ifdef ENDGAME_LEARNING
|
#ifdef ENDGAME_LEARNING
|
||||||
// Check if very weak
|
// Check if very weak
|
||||||
if (gameOptions.getLearnEndgameEnabled()) {
|
if (gameOptions.getLearnEndgameEnabled()) {
|
||||||
if (bestValue <= -VALUE_KNOWN_WIN) {
|
if (bestValue <= -VALUE_KNOWN_WIN) {
|
||||||
Endgame endgame;
|
Endgame endgame;
|
||||||
endgame.type = state->position->sideToMove == PLAYER_BLACK ?
|
endgame.type = state->position->playerSideToMove == PLAYER_BLACK ?
|
||||||
ENDGAME_PLAYER_WHITE_WIN : ENDGAME_PLAYER_BLACK_WIN;
|
ENDGAME_PLAYER_WHITE_WIN : ENDGAME_PLAYER_BLACK_WIN;
|
||||||
key_t endgameHash = position->getPosKey(); // TODO: Do not generate hash repeately
|
key_t endgameHash = position->getPosKey(); // TODO: Do not generate hash repeately
|
||||||
recordEndgameHash(endgameHash, endgame);
|
recordEndgameHash(endgameHash, endgame);
|
||||||
|
@ -634,7 +632,7 @@ const char* AIAlgorithm::nextMove()
|
||||||
|
|
||||||
if (gameOptions.getGiveUpIfMostLose() == true) {
|
if (gameOptions.getGiveUpIfMostLose() == true) {
|
||||||
if (root->value <= -VALUE_MATE) {
|
if (root->value <= -VALUE_MATE) {
|
||||||
sprintf(cmdline, "Player%d give up!", position->sideId);
|
sprintf(cmdline, "Player%d give up!", position->sideToMove);
|
||||||
return cmdline;
|
return cmdline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,20 +31,20 @@ using namespace std;
|
||||||
#pragma execution_character_set("GB2312")
|
#pragma execution_character_set("GB2312")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AiThread::AiThread(int id, QObject *parent) :
|
AiThread::AiThread(int color, QObject *parent) :
|
||||||
QThread(parent),
|
QThread(parent),
|
||||||
position(nullptr),
|
position(nullptr),
|
||||||
depth(2),
|
depth(2),
|
||||||
timeLimit(3600)
|
timeLimit(3600)
|
||||||
{
|
{
|
||||||
this->playerId = id;
|
this->playerId = color;
|
||||||
|
|
||||||
connect(this, &AiThread::searchStarted, this, [=]() {timer.start(timeLimit * 1000 - 118 /* 118ms is return time */); }, Qt::QueuedConnection);
|
connect(this, &AiThread::searchStarted, this, [=]() {timer.start(timeLimit * 1000 - 118 /* 118ms is return time */); }, Qt::QueuedConnection);
|
||||||
connect(this, &AiThread::searchFinished, this, [=]() {timer.stop(); }, Qt::QueuedConnection);
|
connect(this, &AiThread::searchFinished, this, [=]() {timer.stop(); }, Qt::QueuedConnection);
|
||||||
connect(&timer, &QTimer::timeout, this, &AiThread::act, Qt::QueuedConnection);
|
connect(&timer, &QTimer::timeout, this, &AiThread::act, Qt::QueuedConnection);
|
||||||
|
|
||||||
#ifndef TRAINING_MODE
|
#ifndef TRAINING_MODE
|
||||||
if (id == 1) {
|
if (color == 1) {
|
||||||
server = new Server(nullptr, 30001); // TODO: WARNING: ThreadSanitizer: data race
|
server = new Server(nullptr, 30001); // TODO: WARNING: ThreadSanitizer: data race
|
||||||
uint16_t clientPort = server->getPort() == 30001 ? 30002 : 30001;
|
uint16_t clientPort = server->getPort() == 30001 ? 30002 : 30001;
|
||||||
client = new Client(nullptr, clientPort);
|
client = new Client(nullptr, clientPort);
|
||||||
|
@ -208,7 +208,7 @@ void AiThread::run()
|
||||||
int iTemp = 0;
|
int iTemp = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int sideId = 0;
|
Color sideToMove = NOCOLOR;
|
||||||
|
|
||||||
loggerDebug("Thread %d start\n", playerId);
|
loggerDebug("Thread %d start\n", playerId);
|
||||||
|
|
||||||
|
@ -217,9 +217,9 @@ void AiThread::run()
|
||||||
while (!isInterruptionRequested()) {
|
while (!isInterruptionRequested()) {
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
|
|
||||||
sideId = Player::toId(position->sideToMove);
|
sideToMove = position->sideToMove;
|
||||||
|
|
||||||
if (sideId != playerId) {
|
if (sideToMove != playerId) {
|
||||||
pauseCondition.wait(&mutex);
|
pauseCondition.wait(&mutex);
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -36,7 +36,7 @@ class AiThread : public QThread
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AiThread(QObject *parent = nullptr);
|
explicit AiThread(QObject *parent = nullptr);
|
||||||
explicit AiThread(int id, QObject *parent = nullptr);
|
explicit AiThread(int color, QObject *parent = nullptr);
|
||||||
~AiThread() override;
|
~AiThread() override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
|
@ -198,18 +198,18 @@ Square Board::polarToSquare(File file, Rank rank)
|
||||||
return static_cast<Square>(file * N_RANKS + rank - 1);
|
return static_cast<Square>(file * N_RANKS + rank - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
player_t Board::locationToPlayer(Square square)
|
Color Board::locationToColor(Square square)
|
||||||
{
|
{
|
||||||
return player_t(locations[square] & 0x30);
|
return Color((locations[square] & 0x30) >> PLAYER_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Board::inHowManyMills(Square square, player_t player, Square squareSelected)
|
int Board::inHowManyMills(Square square, Color c, Square squareSelected)
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
Location locbak = SQ_0;
|
Location locbak = SQ_0;
|
||||||
|
|
||||||
if (player == PLAYER_NOBODY) {
|
if (c == NOBODY) {
|
||||||
player = locationToPlayer(square);
|
c = Color(locationToColor(square) >> PLAYER_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (squareSelected != SQ_0) {
|
if (squareSelected != SQ_0) {
|
||||||
|
@ -218,7 +218,7 @@ int Board::inHowManyMills(Square square, player_t player, Square squareSelected)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int l = 0; l < LD_NB; l++) {
|
for (int l = 0; l < LD_NB; l++) {
|
||||||
if (player &
|
if ((c << PLAYER_SHIFT) &
|
||||||
locations[millTable[square][l][0]] &
|
locations[millTable[square][l][0]] &
|
||||||
locations[millTable[square][l][1]]) {
|
locations[millTable[square][l][1]]) {
|
||||||
n++;
|
n++;
|
||||||
|
@ -237,7 +237,7 @@ int Board::addMills(Square square)
|
||||||
uint64_t mill = 0;
|
uint64_t mill = 0;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
int idx[3], min, temp;
|
int idx[3], min, temp;
|
||||||
player_t m = locationToPlayer(square);
|
Color m = locationToColor(square);
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
idx[0] = square;
|
idx[0] = square;
|
||||||
|
@ -245,7 +245,7 @@ int Board::addMills(Square square)
|
||||||
idx[2] = millTable[square][i][1];
|
idx[2] = millTable[square][i][1];
|
||||||
|
|
||||||
// no mill
|
// no mill
|
||||||
if (!(m & locations[idx[1]] & locations[idx[2]])) {
|
if (!((m << PLAYER_SHIFT) & locations[idx[1]] & locations[idx[2]])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,11 +298,11 @@ int Board::addMills(Square square)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::isAllInMills(player_t player)
|
bool Board::isAllInMills(Color c)
|
||||||
{
|
{
|
||||||
for (Square i = SQ_BEGIN; i < SQ_END; i = static_cast<Square>(i + 1)) {
|
for (Square i = SQ_BEGIN; i < SQ_END; i = static_cast<Square>(i + 1)) {
|
||||||
if (locations[i] & (uint8_t)player) {
|
if (locations[i] & ((uint8_t)(c << PLAYER_SHIFT))) {
|
||||||
if (!inHowManyMills(i, PLAYER_NOBODY)) {
|
if (!inHowManyMills(i, NOBODY)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,14 +312,14 @@ bool Board::isAllInMills(player_t player)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat include ban
|
// Stat include ban
|
||||||
int Board::getSurroundedEmptyLocationCount(int sideId, int nPiecesOnBoard[],
|
int Board::getSurroundedEmptyLocationCount(Color sideToMove, int nPiecesOnBoard[],
|
||||||
Square square, bool includeFobidden)
|
Square square, bool includeFobidden)
|
||||||
{
|
{
|
||||||
//assert(rule.hasBannedLocations == includeFobidden);
|
//assert(rule.hasBannedLocations == includeFobidden);
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
if (nPiecesOnBoard[sideId] > rule.nPiecesAtLeast ||
|
if (nPiecesOnBoard[sideToMove] > rule.nPiecesAtLeast ||
|
||||||
!rule.allowFlyWhenRemainThreePieces) {
|
!rule.allowFlyWhenRemainThreePieces) {
|
||||||
Square moveSquare;
|
Square moveSquare;
|
||||||
for (MoveDirection d = MD_BEGIN; d < MD_NB; d = (MoveDirection)(d + 1)) {
|
for (MoveDirection d = MD_BEGIN; d < MD_NB; d = (MoveDirection)(d + 1)) {
|
||||||
|
@ -336,7 +336,7 @@ int Board::getSurroundedEmptyLocationCount(int sideId, int nPiecesOnBoard[],
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::getSurroundedPieceCount(Square square, int sideId, int &nPlayerPiece, int &nOpponentPiece, int &nBanned, int &nEmpty)
|
void Board::getSurroundedPieceCount(Square square, Color sideToMove, int &nPlayerPiece, int &nOpponentPiece, int &nBanned, int &nEmpty)
|
||||||
{
|
{
|
||||||
Square moveSquare;
|
Square moveSquare;
|
||||||
|
|
||||||
|
@ -357,7 +357,7 @@ void Board::getSurroundedPieceCount(Square square, int sideId, int &nPlayerPiece
|
||||||
nBanned++;
|
nBanned++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (sideId == pieceType >> PLAYER_SHIFT) {
|
if (sideToMove == pieceType >> PLAYER_SHIFT) {
|
||||||
nPlayerPiece++;
|
nPlayerPiece++;
|
||||||
} else {
|
} else {
|
||||||
nOpponentPiece++;
|
nOpponentPiece++;
|
||||||
|
@ -367,14 +367,14 @@ void Board::getSurroundedPieceCount(Square square, int sideId, int &nPlayerPiece
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::isAllSurrounded(int sideId, int nPiecesOnBoard[], player_t player)
|
bool Board::isAllSurrounded(Color sideToMove, int nPiecesOnBoard[])
|
||||||
{
|
{
|
||||||
// Full
|
// Full
|
||||||
if (nPiecesOnBoard[BLACK] + nPiecesOnBoard[WHITE] >= N_RANKS * N_FILES)
|
if (nPiecesOnBoard[BLACK] + nPiecesOnBoard[WHITE] >= N_RANKS * N_FILES)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Can fly
|
// Can fly
|
||||||
if (nPiecesOnBoard[sideId] <= rule.nPiecesAtLeast &&
|
if (nPiecesOnBoard[sideToMove] <= rule.nPiecesAtLeast &&
|
||||||
rule.allowFlyWhenRemainThreePieces) {
|
rule.allowFlyWhenRemainThreePieces) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -382,7 +382,7 @@ bool Board::isAllSurrounded(int sideId, int nPiecesOnBoard[], player_t player)
|
||||||
Square moveSquare;
|
Square moveSquare;
|
||||||
|
|
||||||
for (Square sq = SQ_BEGIN; sq < SQ_END; sq = (Square)(sq + 1)) {
|
for (Square sq = SQ_BEGIN; sq < SQ_END; sq = (Square)(sq + 1)) {
|
||||||
if (!(player & locationToPlayer(sq))) {
|
if (!(sideToMove & locationToColor(sq))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,12 +54,12 @@ public:
|
||||||
void turn(vector<string> &cmdlist, char *cmdline, int32_t move_, Square square, bool cmdChange = true);
|
void turn(vector<string> &cmdlist, char *cmdline, int32_t move_, Square square, bool cmdChange = true);
|
||||||
void rotate(int degrees, vector<string> &cmdlist, char *cmdline, int32_t move_, Square square, bool cmdChange = true);
|
void rotate(int degrees, vector<string> &cmdlist, char *cmdline, int32_t move_, Square square, bool cmdChange = true);
|
||||||
|
|
||||||
int inHowManyMills(Square square, player_t player, Square squareSelected = SQ_0);
|
int inHowManyMills(Square square, Color c, Square squareSelected = SQ_0);
|
||||||
bool isAllInMills(player_t);
|
bool isAllInMills(Color c);
|
||||||
|
|
||||||
int getSurroundedEmptyLocationCount(int sideId, int nPiecesOnBoard[], Square square, bool includeFobidden);
|
int getSurroundedEmptyLocationCount(Color sideToMove, int nPiecesOnBoard[], Square square, bool includeFobidden);
|
||||||
void getSurroundedPieceCount(Square square, int sideId, int &nPlayerPiece, int &nOpponentPiece, int &nBanned, int &nEmpty);
|
void getSurroundedPieceCount(Square square, Color sideToMove, int &nPlayerPiece, int &nOpponentPiece, int &nBanned, int &nEmpty);
|
||||||
bool isAllSurrounded(int sideId, int nPiecesOnBoard[], player_t ply);
|
bool isAllSurrounded(Color sideToMove, int nPiecesOnBoard[]);
|
||||||
|
|
||||||
int addMills(Square square);
|
int addMills(Square square);
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ public:
|
||||||
|
|
||||||
static void printBoard();
|
static void printBoard();
|
||||||
|
|
||||||
player_t locationToPlayer(Square square);
|
Color locationToColor(Square square);
|
||||||
|
|
||||||
//private:
|
//private:
|
||||||
|
|
||||||
|
|
|
@ -31,29 +31,14 @@ public:
|
||||||
explicit Player();
|
explicit Player();
|
||||||
virtual ~Player();
|
virtual ~Player();
|
||||||
|
|
||||||
player_t getPlayer() const
|
Color getColor() const
|
||||||
{
|
{
|
||||||
return who;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getId() const
|
inline static char colorToCh(Color color)
|
||||||
{
|
{
|
||||||
return id;
|
return static_cast<char>('0' + color);
|
||||||
}
|
|
||||||
|
|
||||||
inline static int toId(player_t player)
|
|
||||||
{
|
|
||||||
return player >> PLAYER_SHIFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static player_t idToPlayer(int id)
|
|
||||||
{
|
|
||||||
return id == 1? PLAYER_BLACK : PLAYER_WHITE;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static char idToCh(int id)
|
|
||||||
{
|
|
||||||
return static_cast<char>('0' + id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static std::string chToStr(char ch)
|
inline static std::string chToStr(char ch)
|
||||||
|
@ -65,19 +50,13 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static player_t getOpponent(player_t player)
|
inline static Color getOpponent(Color c)
|
||||||
{
|
{
|
||||||
return player == PLAYER_BLACK ? PLAYER_WHITE : PLAYER_BLACK;
|
return c == BLACK ? WHITE : BLACK;
|
||||||
}
|
|
||||||
|
|
||||||
inline static int getOpponentById(int id)
|
|
||||||
{
|
|
||||||
return id == 1 ? 2 : 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
player_t who;
|
Color color;
|
||||||
int id;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PLAYER_H
|
#endif // PLAYER_H
|
||||||
|
|
|
@ -89,7 +89,7 @@ bool Position::setPosition(const struct Rule *newRule)
|
||||||
this->moveStep = 0;
|
this->moveStep = 0;
|
||||||
|
|
||||||
phase = PHASE_READY;
|
phase = PHASE_READY;
|
||||||
setSideToMove(PLAYER_BLACK);
|
setSideToMove(BLACK);
|
||||||
action = ACTION_PLACE;
|
action = ACTION_PLACE;
|
||||||
|
|
||||||
memset(board.locations, 0, sizeof(board.locations));
|
memset(board.locations, 0, sizeof(board.locations));
|
||||||
|
@ -103,7 +103,7 @@ bool Position::setPosition(const struct Rule *newRule)
|
||||||
countPiecesInHand();
|
countPiecesInHand();
|
||||||
nPiecesNeedRemove = 0;
|
nPiecesNeedRemove = 0;
|
||||||
board.millListSize = 0;
|
board.millListSize = 0;
|
||||||
winner = PLAYER_NOBODY;
|
winner = NOBODY;
|
||||||
MoveList::create();
|
MoveList::create();
|
||||||
board.createMillTable();
|
board.createMillTable();
|
||||||
currentSquare = SQ_0;
|
currentSquare = SQ_0;
|
||||||
|
@ -137,10 +137,10 @@ bool Position::reset()
|
||||||
moveStep = 0;
|
moveStep = 0;
|
||||||
|
|
||||||
phase = PHASE_READY;
|
phase = PHASE_READY;
|
||||||
setSideToMove(PLAYER_BLACK);
|
setSideToMove(BLACK);
|
||||||
action = ACTION_PLACE;
|
action = ACTION_PLACE;
|
||||||
|
|
||||||
winner = PLAYER_NOBODY;
|
winner = NOBODY;
|
||||||
|
|
||||||
memset(board.locations, 0, sizeof(board.locations));
|
memset(board.locations, 0, sizeof(board.locations));
|
||||||
key = 0;
|
key = 0;
|
||||||
|
@ -207,7 +207,7 @@ bool Position::placePiece(Square square, bool updateCmdlist)
|
||||||
int piece = '\x00';
|
int piece = '\x00';
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
int playerId = Player::toId(sideToMove);
|
int playerId = sideToMove;
|
||||||
|
|
||||||
Bitboard fromTo;
|
Bitboard fromTo;
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ bool Position::placePiece(Square square, bool updateCmdlist)
|
||||||
Board::squareToPolar(square, file, rank);
|
Board::squareToPolar(square, file, rank);
|
||||||
|
|
||||||
if (phase == PHASE_PLACING) {
|
if (phase == PHASE_PLACING) {
|
||||||
piece = (0x01 | sideToMove) + rule.nTotalPiecesEachSide - nPiecesInHand[playerId];
|
piece = (0x01 | (sideToMove << PLAYER_SHIFT)) + rule.nTotalPiecesEachSide - nPiecesInHand[playerId];
|
||||||
nPiecesInHand[playerId]--;
|
nPiecesInHand[playerId]--;
|
||||||
nPiecesOnBoard[playerId]++;
|
nPiecesOnBoard[playerId]++;
|
||||||
|
|
||||||
|
@ -264,9 +264,9 @@ bool Position::placePiece(Square square, bool updateCmdlist)
|
||||||
cleanBannedLocations();
|
cleanBannedLocations();
|
||||||
|
|
||||||
if (rule.isDefenderMoveFirst) {
|
if (rule.isDefenderMoveFirst) {
|
||||||
setSideToMove(PLAYER_WHITE);
|
setSideToMove(WHITE);
|
||||||
} else {
|
} else {
|
||||||
setSideToMove(PLAYER_BLACK);
|
setSideToMove(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkGameOverCondition(updateCmdlist)) {
|
if (checkGameOverCondition(updateCmdlist)) {
|
||||||
|
@ -290,7 +290,7 @@ bool Position::placePiece(Square square, bool updateCmdlist)
|
||||||
// When hase == GAME_MOVING
|
// When hase == GAME_MOVING
|
||||||
|
|
||||||
// if illegal
|
// if illegal
|
||||||
if (nPiecesOnBoard[sideId] > rule.nPiecesAtLeast ||
|
if (nPiecesOnBoard[sideToMove] > rule.nPiecesAtLeast ||
|
||||||
!rule.allowFlyWhenRemainThreePieces) {
|
!rule.allowFlyWhenRemainThreePieces) {
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
if (square == MoveList::moveTable[currentSquare][i])
|
if (square == MoveList::moveTable[currentSquare][i])
|
||||||
|
@ -380,14 +380,14 @@ bool Position::removePiece(Square square, bool updateCmdlist)
|
||||||
|
|
||||||
int seconds = -1;
|
int seconds = -1;
|
||||||
|
|
||||||
int oppId = Player::toId(opponent);
|
int oppId = opponent;
|
||||||
|
|
||||||
// if piece is not opponent's
|
// if piece is not opponent's
|
||||||
if (!(opponent & board.locations[square]))
|
if (!((opponent << PLAYER_SHIFT) & board.locations[square]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!rule.allowRemovePieceInMill &&
|
if (!rule.allowRemovePieceInMill &&
|
||||||
board.inHowManyMills(square, PLAYER_NOBODY) &&
|
board.inHowManyMills(square, NOBODY) &&
|
||||||
!board.isAllInMills(Player::getOpponent(sideToMove))) {
|
!board.isAllInMills(Player::getOpponent(sideToMove))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -404,10 +404,10 @@ bool Position::removePiece(Square square, bool updateCmdlist)
|
||||||
board.locations[square] = '\x00';
|
board.locations[square] = '\x00';
|
||||||
|
|
||||||
board.byTypeBB[ALL_PIECES] ^= square;
|
board.byTypeBB[ALL_PIECES] ^= square;
|
||||||
board.byTypeBB[opponentId] ^= square;
|
board.byTypeBB[opponent] ^= square;
|
||||||
}
|
}
|
||||||
|
|
||||||
nPiecesOnBoard[opponentId]--;
|
nPiecesOnBoard[opponent]--;
|
||||||
|
|
||||||
move = static_cast<Move>(-square);
|
move = static_cast<Move>(-square);
|
||||||
|
|
||||||
|
@ -440,9 +440,9 @@ bool Position::removePiece(Square square, bool updateCmdlist)
|
||||||
cleanBannedLocations();
|
cleanBannedLocations();
|
||||||
|
|
||||||
if (rule.isDefenderMoveFirst) {
|
if (rule.isDefenderMoveFirst) {
|
||||||
setSideToMove(PLAYER_WHITE);
|
setSideToMove(WHITE);
|
||||||
} else {
|
} else {
|
||||||
setSideToMove(PLAYER_BLACK);
|
setSideToMove(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkGameOverCondition(updateCmdlist)) {
|
if (checkGameOverCondition(updateCmdlist)) {
|
||||||
|
@ -481,7 +481,7 @@ bool Position::selectPiece(Square square)
|
||||||
if (action != ACTION_SELECT && action != ACTION_PLACE)
|
if (action != ACTION_SELECT && action != ACTION_PLACE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (board.locations[square] & sideToMove) {
|
if (board.locations[square] & (sideToMove << PLAYER_SHIFT)) {
|
||||||
currentSquare = square;
|
currentSquare = square;
|
||||||
action = ACTION_PLACE;
|
action = ACTION_PLACE;
|
||||||
|
|
||||||
|
@ -496,7 +496,7 @@ bool Position::selectPiece(File file, Rank rank)
|
||||||
return selectPiece(Board::polarToSquare(file, rank));
|
return selectPiece(Board::polarToSquare(file, rank));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Position::giveup(player_t loser)
|
bool Position::giveup(Color loser)
|
||||||
{
|
{
|
||||||
if (phase & PHASE_NOTPLAYING ||
|
if (phase & PHASE_NOTPLAYING ||
|
||||||
phase == PHASE_NONE) {
|
phase == PHASE_NONE) {
|
||||||
|
@ -505,14 +505,14 @@ bool Position::giveup(player_t loser)
|
||||||
|
|
||||||
phase = PHASE_GAMEOVER;
|
phase = PHASE_GAMEOVER;
|
||||||
|
|
||||||
int loserId = Player::toId(loser);
|
Color loserColor = loser;
|
||||||
char loserCh = Player::idToCh(loserId);
|
char loserCh = Player::colorToCh(loserColor);
|
||||||
string loserStr = Player::chToStr(loserCh);
|
string loserStr = Player::chToStr(loserCh);
|
||||||
|
|
||||||
winner = Player::getOpponent(loser);
|
winner = Player::getOpponent(loser);
|
||||||
tips = "玩家" + loserStr + "投子认负";
|
tips = "玩家" + loserStr + "投子认负";
|
||||||
sprintf(cmdline, "Player%d give up!", loserId);
|
sprintf(cmdline, "Player%d give up!", loserColor);
|
||||||
score[Player::toId(winner)]++;
|
score[winner]++;
|
||||||
|
|
||||||
cmdlist.emplace_back(string(cmdline));
|
cmdlist.emplace_back(string(cmdline));
|
||||||
|
|
||||||
|
@ -573,7 +573,7 @@ bool Position::command(const char *cmd)
|
||||||
args = sscanf(cmd, "Player%1u give up!", &t);
|
args = sscanf(cmd, "Player%1u give up!", &t);
|
||||||
|
|
||||||
if (args == 1) {
|
if (args == 1) {
|
||||||
return giveup(Player::idToPlayer(t));
|
return giveup((Color)t);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef THREEFOLD_REPETITION
|
#ifdef THREEFOLD_REPETITION
|
||||||
|
@ -583,7 +583,7 @@ bool Position::command(const char *cmd)
|
||||||
|
|
||||||
if (!strcmp(cmd, "draw")) {
|
if (!strcmp(cmd, "draw")) {
|
||||||
phase = PHASE_GAMEOVER;
|
phase = PHASE_GAMEOVER;
|
||||||
winner = PLAYER_DRAW;
|
winner = DRAW;
|
||||||
score_draw++;
|
score_draw++;
|
||||||
tips = "三次重复局面判和。";
|
tips = "三次重复局面判和。";
|
||||||
sprintf(cmdline, "Threefold Repetition. Draw!");
|
sprintf(cmdline, "Threefold Repetition. Draw!");
|
||||||
|
@ -616,7 +616,7 @@ bool Position::doMove(Move m)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
player_t Position::getWinner() const
|
Color Position::getWinner() const
|
||||||
{
|
{
|
||||||
return winner;
|
return winner;
|
||||||
}
|
}
|
||||||
|
@ -625,8 +625,8 @@ int Position::update()
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int timePoint = -1;
|
int timePoint = -1;
|
||||||
time_t *seconds = &elapsedSeconds[sideId];
|
time_t *seconds = &elapsedSeconds[sideToMove];
|
||||||
time_t opponentSeconds = elapsedSeconds[opponentId];
|
time_t opponentSeconds = elapsedSeconds[opponent];
|
||||||
|
|
||||||
if (!(phase & PHASE_PLAYING)) {
|
if (!(phase & PHASE_PLAYING)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -661,9 +661,9 @@ bool Position::checkGameOverCondition(int8_t updateCmdlist)
|
||||||
for (int i = 1; i <= 2; i++) {
|
for (int i = 1; i <= 2; i++) {
|
||||||
if (elapsedSeconds[i] > rule.maxTimeLedToLose * 60) {
|
if (elapsedSeconds[i] > rule.maxTimeLedToLose * 60) {
|
||||||
elapsedSeconds[i] = rule.maxTimeLedToLose * 60;
|
elapsedSeconds[i] = rule.maxTimeLedToLose * 60;
|
||||||
winner = Player::idToPlayer(Player::getOpponentById(i));
|
winner = Player::getOpponent(Color(i));
|
||||||
tips = "玩家" + Player::chToStr(Player::idToCh(i)) + "超时判负。";
|
tips = "玩家" + Player::chToStr(Player::colorToCh(Color(i))) + "超时判负。";
|
||||||
sprintf(cmdline, "Time over. Player%d win!", Player::getOpponentById(i));
|
sprintf(cmdline, "Time over. Player%d win!", Player::getOpponent(Color(i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,7 +675,7 @@ bool Position::checkGameOverCondition(int8_t updateCmdlist)
|
||||||
|
|
||||||
if (rule.maxStepsLedToDraw > 0 &&
|
if (rule.maxStepsLedToDraw > 0 &&
|
||||||
moveStep > rule.maxStepsLedToDraw) {
|
moveStep > rule.maxStepsLedToDraw) {
|
||||||
winner = PLAYER_DRAW;
|
winner = DRAW;
|
||||||
phase = PHASE_GAMEOVER;
|
phase = PHASE_GAMEOVER;
|
||||||
if (updateCmdlist) {
|
if (updateCmdlist) {
|
||||||
sprintf(cmdline, "Steps over. In draw!");
|
sprintf(cmdline, "Steps over. In draw!");
|
||||||
|
@ -688,11 +688,11 @@ bool Position::checkGameOverCondition(int8_t updateCmdlist)
|
||||||
for (int i = 1; i <= 2; i++)
|
for (int i = 1; i <= 2; i++)
|
||||||
{
|
{
|
||||||
if (nPiecesOnBoard[i] + nPiecesInHand[i] < rule.nPiecesAtLeast) {
|
if (nPiecesOnBoard[i] + nPiecesInHand[i] < rule.nPiecesAtLeast) {
|
||||||
int o = Player::getOpponentById(i);
|
winner = Player::getOpponent(Color(i));
|
||||||
winner = Player::idToPlayer(o);
|
|
||||||
phase = PHASE_GAMEOVER;
|
phase = PHASE_GAMEOVER;
|
||||||
|
|
||||||
if (updateCmdlist) {
|
if (updateCmdlist) {
|
||||||
sprintf(cmdline, "Player%d win!", o);
|
sprintf(cmdline, "Player%d win!", winner);
|
||||||
cmdlist.emplace_back(string(cmdline));
|
cmdlist.emplace_back(string(cmdline));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,7 +704,7 @@ bool Position::checkGameOverCondition(int8_t updateCmdlist)
|
||||||
#if 0
|
#if 0
|
||||||
int diff = nPiecesOnBoard[BLACK] - nPiecesOnBoard[WHITE];
|
int diff = nPiecesOnBoard[BLACK] - nPiecesOnBoard[WHITE];
|
||||||
if (diff > 4) {
|
if (diff > 4) {
|
||||||
winner = PLAYER_BLACK;
|
winner = BLACK;
|
||||||
phase = PHASE_GAMEOVER;
|
phase = PHASE_GAMEOVER;
|
||||||
sprintf(cmdline, "Player1 win!");
|
sprintf(cmdline, "Player1 win!");
|
||||||
cmdlist.emplace_back(string(cmdline));
|
cmdlist.emplace_back(string(cmdline));
|
||||||
|
@ -713,7 +713,7 @@ bool Position::checkGameOverCondition(int8_t updateCmdlist)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diff < -4) {
|
if (diff < -4) {
|
||||||
winner = PLAYER_WHITE;
|
winner = WHITE;
|
||||||
phase = PHASE_GAMEOVER;
|
phase = PHASE_GAMEOVER;
|
||||||
sprintf(cmdline, "Player2 win!");
|
sprintf(cmdline, "Player2 win!");
|
||||||
cmdlist.emplace_back(string(cmdline));
|
cmdlist.emplace_back(string(cmdline));
|
||||||
|
@ -727,12 +727,12 @@ bool Position::checkGameOverCondition(int8_t updateCmdlist)
|
||||||
phase = PHASE_GAMEOVER;
|
phase = PHASE_GAMEOVER;
|
||||||
|
|
||||||
if (rule.isBlackLosebutNotDrawWhenBoardFull) {
|
if (rule.isBlackLosebutNotDrawWhenBoardFull) {
|
||||||
winner = PLAYER_WHITE;
|
winner = WHITE;
|
||||||
if (updateCmdlist) {
|
if (updateCmdlist) {
|
||||||
sprintf(cmdline, "Player2 win!");
|
sprintf(cmdline, "Player2 win!");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
winner = PLAYER_DRAW;
|
winner = DRAW;
|
||||||
if (updateCmdlist) {
|
if (updateCmdlist) {
|
||||||
sprintf(cmdline, "Full. In draw!");
|
sprintf(cmdline, "Full. In draw!");
|
||||||
}
|
}
|
||||||
|
@ -745,7 +745,7 @@ bool Position::checkGameOverCondition(int8_t updateCmdlist)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phase == PHASE_MOVING && action == ACTION_SELECT && board.isAllSurrounded(sideId, nPiecesOnBoard, sideToMove)) {
|
if (phase == PHASE_MOVING && action == ACTION_SELECT && board.isAllSurrounded(sideToMove, nPiecesOnBoard)) {
|
||||||
// TODO: move to next branch
|
// TODO: move to next branch
|
||||||
phase = PHASE_GAMEOVER;
|
phase = PHASE_GAMEOVER;
|
||||||
|
|
||||||
|
@ -753,8 +753,7 @@ bool Position::checkGameOverCondition(int8_t updateCmdlist)
|
||||||
if (updateCmdlist) {
|
if (updateCmdlist) {
|
||||||
tips = "玩家" + Player::chToStr(chSide) + "无子可走被闷";
|
tips = "玩家" + Player::chToStr(chSide) + "无子可走被闷";
|
||||||
winner = Player::getOpponent(sideToMove);
|
winner = Player::getOpponent(sideToMove);
|
||||||
int winnerId = Player::toId(winner);
|
sprintf(cmdline, "Player%d no way to go. Player%d win!", sideToMove, winner);
|
||||||
sprintf(cmdline, "Player%d no way to go. Player%d win!", sideId, winnerId);
|
|
||||||
cmdlist.emplace_back(string(cmdline)); // TODO: memleak
|
cmdlist.emplace_back(string(cmdline)); // TODO: memleak
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,7 +768,7 @@ bool Position::checkGameOverCondition(int8_t updateCmdlist)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Position::getMobilityDiff(player_t turn, int piecesOnBoard[], bool includeFobidden)
|
int Position::getMobilityDiff(Color turn, int piecesOnBoard[], bool includeFobidden)
|
||||||
{
|
{
|
||||||
// TODO: Deal with rule is no ban location
|
// TODO: Deal with rule is no ban location
|
||||||
Location *locations = board.locations;
|
Location *locations = board.locations;
|
||||||
|
@ -814,20 +813,17 @@ void Position::cleanBannedLocations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Position::setSideToMove(player_t player)
|
void Position::setSideToMove(Color c)
|
||||||
{
|
{
|
||||||
sideToMove = player;
|
sideToMove = c;
|
||||||
|
|
||||||
sideId = Player::toId(sideToMove);
|
chSide = Player::colorToCh(sideToMove);
|
||||||
chSide = Player::idToCh(sideId);
|
|
||||||
|
|
||||||
opponent = Player::getOpponent(player);
|
opponent = Player::getOpponent(sideToMove);
|
||||||
|
chOpponent = Player::colorToCh(opponent);
|
||||||
opponentId = Player::toId(opponent);
|
|
||||||
chOpponent = Player::idToCh(opponentId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
player_t Position::getSideToMove()
|
Color Position::getSideToMove()
|
||||||
{
|
{
|
||||||
return sideToMove;
|
return sideToMove;
|
||||||
}
|
}
|
||||||
|
@ -852,7 +848,6 @@ bool Position::undoNullMove()
|
||||||
void Position::setTips()
|
void Position::setTips()
|
||||||
{
|
{
|
||||||
string winnerStr, t;
|
string winnerStr, t;
|
||||||
int winnerId;
|
|
||||||
string turnStr = Player::chToStr(chSide);
|
string turnStr = Player::chToStr(chSide);
|
||||||
|
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
|
@ -863,7 +858,7 @@ void Position::setTips()
|
||||||
|
|
||||||
case PHASE_PLACING:
|
case PHASE_PLACING:
|
||||||
if (action == ACTION_PLACE) {
|
if (action == ACTION_PLACE) {
|
||||||
tips = "轮到玩家" + turnStr + "落子,剩余" + std::to_string(nPiecesInHand[sideId]) + "子";
|
tips = "轮到玩家" + turnStr + "落子,剩余" + std::to_string(nPiecesInHand[sideToMove]) + "子";
|
||||||
} else if (action == ACTION_REMOVE) {
|
} else if (action == ACTION_REMOVE) {
|
||||||
tips = "成三!轮到玩家" + turnStr + "去子,需去" + std::to_string(nPiecesNeedRemove) + "子";
|
tips = "成三!轮到玩家" + turnStr + "去子,需去" + std::to_string(nPiecesNeedRemove) + "子";
|
||||||
}
|
}
|
||||||
|
@ -878,16 +873,15 @@ void Position::setTips()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PHASE_GAMEOVER:
|
case PHASE_GAMEOVER:
|
||||||
if (winner == PLAYER_DRAW) {
|
if (winner == DRAW) {
|
||||||
score_draw++;
|
score_draw++;
|
||||||
tips = "双方平局!比分 " + to_string(score[BLACK]) + ":" + to_string(score[WHITE]) + ", 和棋 " + to_string(score_draw);
|
tips = "双方平局!比分 " + to_string(score[BLACK]) + ":" + to_string(score[WHITE]) + ", 和棋 " + to_string(score_draw);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
winnerId = Player::toId(winner);
|
winnerStr = Player::chToStr(Player::colorToCh(winner));
|
||||||
winnerStr = Player::chToStr(Player::idToCh(winnerId));
|
|
||||||
|
|
||||||
score[winnerId]++;
|
score[winner]++;
|
||||||
|
|
||||||
t = "玩家" + winnerStr + "获胜!比分 " + to_string(score[BLACK]) + ":" + to_string(score[WHITE]) + ", 和棋 " + to_string(score_draw);
|
t = "玩家" + winnerStr + "获胜!比分 " + to_string(score[BLACK]) + ":" + to_string(score[WHITE]) + ", 和棋 " + to_string(score_draw);
|
||||||
|
|
||||||
|
@ -925,7 +919,7 @@ Key Position::updateKey(Square square)
|
||||||
// PieceType is board.locations[square]
|
// PieceType is board.locations[square]
|
||||||
|
|
||||||
// 0b00 - no piece,0b01 = 1 black,0b10 = 2 white,0b11 = 3 ban
|
// 0b00 - no piece,0b01 = 1 black,0b10 = 2 white,0b11 = 3 ban
|
||||||
int pieceType = Player::toId(board.locationToPlayer(square));
|
int pieceType = board.locationToColor(square);
|
||||||
// TODO: this is std, but current code can work
|
// TODO: this is std, but current code can work
|
||||||
//Location loc = board.locations[square];
|
//Location loc = board.locations[square];
|
||||||
//int pieceType = loc == 0x0f? 3 : loc >> PLAYER_SHIFT;
|
//int pieceType = loc == 0x0f? 3 : loc >> PLAYER_SHIFT;
|
||||||
|
@ -947,7 +941,7 @@ Key Position::updateKeyMisc()
|
||||||
key = key << KEY_MISC_BIT >> KEY_MISC_BIT;
|
key = key << KEY_MISC_BIT >> KEY_MISC_BIT;
|
||||||
Key hi = 0;
|
Key hi = 0;
|
||||||
|
|
||||||
if (sideToMove == PLAYER_WHITE) {
|
if (sideToMove == WHITE) {
|
||||||
hi |= 1U;
|
hi |= 1U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -970,7 +964,7 @@ Key Position::getNextPrimaryKey(Move m)
|
||||||
MoveType mt = type_of(m);
|
MoveType mt = type_of(m);
|
||||||
|
|
||||||
if (mt == MOVETYPE_REMOVE) {
|
if (mt == MOVETYPE_REMOVE) {
|
||||||
int pieceType = Player::getOpponentById(Player::toId(sideToMove));
|
int pieceType = Player::getOpponent(sideToMove);
|
||||||
npKey ^= zobrist[sq][pieceType];
|
npKey ^= zobrist[sq][pieceType];
|
||||||
|
|
||||||
if (rule.hasBannedLocations && phase == PHASE_PLACING) {
|
if (rule.hasBannedLocations && phase == PHASE_PLACING) {
|
||||||
|
@ -980,7 +974,7 @@ Key Position::getNextPrimaryKey(Move m)
|
||||||
return npKey;
|
return npKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pieceType = Player::toId(sideToMove);
|
int pieceType = sideToMove;
|
||||||
npKey ^= zobrist[sq][pieceType];
|
npKey ^= zobrist[sq][pieceType];
|
||||||
|
|
||||||
if (mt == MOVETYPE_MOVE) {
|
if (mt == MOVETYPE_MOVE) {
|
||||||
|
|
|
@ -51,12 +51,10 @@ public:
|
||||||
|
|
||||||
enum Phase phase {PHASE_NONE};
|
enum Phase phase {PHASE_NONE};
|
||||||
|
|
||||||
player_t sideToMove {PLAYER_NOBODY};
|
Color sideToMove {NOCOLOR};
|
||||||
int sideId {0};
|
|
||||||
char chSide {'0'};
|
char chSide {'0'};
|
||||||
//string turnStr;
|
//string turnStr;
|
||||||
player_t opponent {PLAYER_NOBODY};
|
Color opponent { NOCOLOR };
|
||||||
int opponentId {0};
|
|
||||||
char chOpponent {'0'};
|
char chOpponent {'0'};
|
||||||
//string opponentStr;
|
//string opponentStr;
|
||||||
|
|
||||||
|
@ -138,13 +136,13 @@ public:
|
||||||
return nPiecesNeedRemove;
|
return nPiecesNeedRemove;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getMobilityDiff(player_t turn, int nPiecesOnBoard[], bool includeFobidden);
|
int getMobilityDiff(Color turn, int nPiecesOnBoard[], bool includeFobidden);
|
||||||
|
|
||||||
bool reset();
|
bool reset();
|
||||||
|
|
||||||
bool start();
|
bool start();
|
||||||
|
|
||||||
bool giveup(player_t loser);
|
bool giveup(Color loser);
|
||||||
|
|
||||||
bool command(const char *cmd);
|
bool command(const char *cmd);
|
||||||
|
|
||||||
|
@ -154,9 +152,9 @@ public:
|
||||||
|
|
||||||
void cleanBannedLocations();
|
void cleanBannedLocations();
|
||||||
|
|
||||||
void setSideToMove(player_t player);
|
void setSideToMove(Color c);
|
||||||
|
|
||||||
player_t getSideToMove();
|
Color getSideToMove();
|
||||||
|
|
||||||
void changeSideToMove();
|
void changeSideToMove();
|
||||||
|
|
||||||
|
@ -165,7 +163,7 @@ public:
|
||||||
bool doNullMove();
|
bool doNullMove();
|
||||||
bool undoNullMove();
|
bool undoNullMove();
|
||||||
|
|
||||||
player_t getWinner() const;
|
Color getWinner() const;
|
||||||
|
|
||||||
bool selectPiece(File file, Rank rank);
|
bool selectPiece(File file, Rank rank);
|
||||||
bool _placePiece(File file, Rank rank);
|
bool _placePiece(File file, Rank rank);
|
||||||
|
@ -224,7 +222,7 @@ private:
|
||||||
|
|
||||||
int countPiecesInHand();
|
int countPiecesInHand();
|
||||||
|
|
||||||
player_t winner;
|
Color winner;
|
||||||
|
|
||||||
Step currentStep {};
|
Step currentStep {};
|
||||||
|
|
||||||
|
|
|
@ -51,22 +51,16 @@ enum MoveType
|
||||||
|
|
||||||
enum Color : uint8_t
|
enum Color : uint8_t
|
||||||
{
|
{
|
||||||
NOCOLOR,
|
NOCOLOR = 0,
|
||||||
BLACK,
|
BLACK = 1,
|
||||||
WHITE,
|
WHITE = 2,
|
||||||
COLOR_NB
|
COLOR_NB = 3,
|
||||||
|
DRAW = 4,
|
||||||
|
NOBODY = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PLAYER_SHIFT 4
|
#define PLAYER_SHIFT 4
|
||||||
|
|
||||||
enum player_t : uint8_t
|
|
||||||
{
|
|
||||||
PLAYER_BLACK = 0x1 << PLAYER_SHIFT,
|
|
||||||
PLAYER_WHITE = 0x2 << PLAYER_SHIFT,
|
|
||||||
PLAYER_DRAW = 0x4 << PLAYER_SHIFT,
|
|
||||||
PLAYER_NOBODY = 0x8 << PLAYER_SHIFT
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Phase : uint16_t
|
enum Phase : uint16_t
|
||||||
{
|
{
|
||||||
PHASE_NONE = 0,
|
PHASE_NONE = 0,
|
||||||
|
|
|
@ -337,18 +337,18 @@ void GameController::setRule(int ruleNo, Step stepLimited /*= -1*/, int timeLimi
|
||||||
gameReset();
|
gameReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameController::setEngine(int id, bool arg)
|
void GameController::setEngine(int color, bool arg)
|
||||||
{
|
{
|
||||||
isAiPlayer[id] = arg;
|
isAiPlayer[color] = arg;
|
||||||
|
|
||||||
if (arg) {
|
if (arg) {
|
||||||
aiThread[id]->setAi(position);
|
aiThread[color]->setAi(position);
|
||||||
if (aiThread[id]->isRunning())
|
if (aiThread[color]->isRunning())
|
||||||
aiThread[id]->resume();
|
aiThread[color]->resume();
|
||||||
else
|
else
|
||||||
aiThread[id]->start();
|
aiThread[color]->start();
|
||||||
} else {
|
} else {
|
||||||
aiThread[id]->stop();
|
aiThread[color]->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,11 +401,11 @@ void GameController::setSound(bool arg)
|
||||||
#endif // TRAINING_MODE
|
#endif // TRAINING_MODE
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameController::playSound(sound_t soundType, player_t player)
|
void GameController::playSound(sound_t soundType, Color c)
|
||||||
{
|
{
|
||||||
string soundDir = ":/sound/resources/sound/";
|
string soundDir = ":/sound/resources/sound/";
|
||||||
string sideStr = player == PLAYER_BLACK ? "B" : "W";
|
string sideStr = c == BLACK ? "B" : "W";
|
||||||
string oppenentStr = player == PLAYER_WHITE? "B" : "W";
|
string oppenentStr = c == WHITE? "B" : "W";
|
||||||
string filename;
|
string filename;
|
||||||
|
|
||||||
switch (soundType) {
|
switch (soundType) {
|
||||||
|
@ -476,7 +476,7 @@ void GameController::playSound(sound_t soundType, player_t player)
|
||||||
filename = "warning.wav";
|
filename = "warning.wav";
|
||||||
break;
|
break;
|
||||||
case GAME_SOUND_WIN:
|
case GAME_SOUND_WIN:
|
||||||
if (player == PLAYER_DRAW) {
|
if (c == DRAW) {
|
||||||
filename = "Draw.wav";
|
filename = "Draw.wav";
|
||||||
} else {
|
} else {
|
||||||
filename = "Win_" + sideStr + ".wav";
|
filename = "Win_" + sideStr + ".wav";
|
||||||
|
@ -683,8 +683,8 @@ void GameController::timerEvent(QTimerEvent *event)
|
||||||
emit time2Changed(qt2.toString("hh:mm:ss"));
|
emit time2Changed(qt2.toString("hh:mm:ss"));
|
||||||
|
|
||||||
// 如果胜负已分
|
// 如果胜负已分
|
||||||
player_t winner = position->getWinner();
|
Color winner = position->getWinner();
|
||||||
if (winner != PLAYER_NOBODY) {
|
if (winner != NOBODY) {
|
||||||
// 停止计时
|
// 停止计时
|
||||||
killTimer(timeID);
|
killTimer(timeID);
|
||||||
|
|
||||||
|
@ -731,7 +731,7 @@ void GameController::timerEvent(QTimerEvent *event)
|
||||||
|
|
||||||
bool GameController::isAIsTurn()
|
bool GameController::isAIsTurn()
|
||||||
{
|
{
|
||||||
return isAiPlayer[position->sideId];
|
return isAiPlayer[position->sideToMove];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关键槽函数,根据QGraphicsScene的信号和状态来执行选子、落子或去子
|
// 关键槽函数,根据QGraphicsScene的信号和状态来执行选子、落子或去子
|
||||||
|
@ -771,7 +771,7 @@ bool GameController::actionPiece(QPointF pos)
|
||||||
manualListModel.removeRows(currentRow + 1, manualListModel.rowCount() - currentRow - 1);
|
manualListModel.removeRows(currentRow + 1, manualListModel.rowCount() - currentRow - 1);
|
||||||
|
|
||||||
// 如果再决出胜负后悔棋,则重新启动计时
|
// 如果再决出胜负后悔棋,则重新启动计时
|
||||||
if (position->getWinner() == PLAYER_NOBODY) {
|
if (position->getWinner() == NOBODY) {
|
||||||
|
|
||||||
// 重新启动计时
|
// 重新启动计时
|
||||||
timeID = startTimer(100);
|
timeID = startTimer(100);
|
||||||
|
@ -863,15 +863,15 @@ bool GameController::actionPiece(QPointF pos)
|
||||||
|
|
||||||
// 播放胜利或失败音效
|
// 播放胜利或失败音效
|
||||||
#ifndef DONOT_PLAY_WIN_SOUND
|
#ifndef DONOT_PLAY_WIN_SOUND
|
||||||
player_t winner = position->getWinner();
|
Color winner = position->getWinner();
|
||||||
if (winner != PLAYER_NOBODY &&
|
if (winner != NOBODY &&
|
||||||
(manualListModel.data(manualListModel.index(currentRow - 1))).toString().contains("Time over."))
|
(manualListModel.data(manualListModel.index(currentRow - 1))).toString().contains("Time over."))
|
||||||
playSound(GAME_SOUND_WIN, winner);
|
playSound(GAME_SOUND_WIN, winner);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// AI设置
|
// AI设置
|
||||||
// 如果还未决出胜负
|
// 如果还未决出胜负
|
||||||
if (position->getWinner() == PLAYER_NOBODY) {
|
if (position->getWinner() == NOBODY) {
|
||||||
resumeAiThreads(position->sideToMove);
|
resumeAiThreads(position->sideToMove);
|
||||||
}
|
}
|
||||||
// 如果已经决出胜负
|
// 如果已经决出胜负
|
||||||
|
@ -911,7 +911,7 @@ bool GameController::giveUp()
|
||||||
manualListModel.setData(manualListModel.index(currentRow), i.c_str());
|
manualListModel.setData(manualListModel.index(currentRow), i.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (position->getWinner() != PLAYER_NOBODY)
|
if (position->getWinner() != NOBODY)
|
||||||
playSound(GAME_SOUND_GIVE_UP, position->getSideToMove());
|
playSound(GAME_SOUND_GIVE_UP, position->getSideToMove());
|
||||||
|
|
||||||
#endif // TRAINING_MODE
|
#endif // TRAINING_MODE
|
||||||
|
@ -997,8 +997,8 @@ bool GameController::command(const QString &cmd, bool update /* = true */)
|
||||||
|
|
||||||
// 播放胜利或失败音效
|
// 播放胜利或失败音效
|
||||||
#ifndef DONOT_PLAY_WIN_SOUND
|
#ifndef DONOT_PLAY_WIN_SOUND
|
||||||
player_t winner = position->getWinner();
|
Color winner = position->getWinner();
|
||||||
if (winner != PLAYER_NOBODY &&
|
if (winner != NOBODY &&
|
||||||
(manualListModel.data(manualListModel.index(currentRow - 1))).toString().contains("Time over.")) {
|
(manualListModel.data(manualListModel.index(currentRow - 1))).toString().contains("Time over.")) {
|
||||||
playSound(GAME_SOUND_WIN, winner);
|
playSound(GAME_SOUND_WIN, winner);
|
||||||
}
|
}
|
||||||
|
@ -1007,7 +1007,7 @@ bool GameController::command(const QString &cmd, bool update /* = true */)
|
||||||
|
|
||||||
// AI设置
|
// AI设置
|
||||||
// 如果还未决出胜负
|
// 如果还未决出胜负
|
||||||
if (position->getWinner() == PLAYER_NOBODY) {
|
if (position->getWinner() == NOBODY) {
|
||||||
resumeAiThreads(position->sideToMove);
|
resumeAiThreads(position->sideToMove);
|
||||||
}
|
}
|
||||||
// 如果已经决出胜负
|
// 如果已经决出胜负
|
||||||
|
@ -1306,7 +1306,7 @@ void GameController::showTestWindow()
|
||||||
|
|
||||||
void GameController::humanGiveUp()
|
void GameController::humanGiveUp()
|
||||||
{
|
{
|
||||||
if (position->getWinner() == PLAYER_NOBODY) {
|
if (position->getWinner() == NOBODY) {
|
||||||
giveUp();
|
giveUp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,7 +186,7 @@ public slots:
|
||||||
void setInvert(bool arg = true);
|
void setInvert(bool arg = true);
|
||||||
|
|
||||||
// id为1时让电脑执先手, id为2时让的电脑执后手
|
// id为1时让电脑执先手, id为2时让的电脑执后手
|
||||||
void setEngine(int id, bool arg = true);
|
void setEngine(int color, bool arg = true);
|
||||||
void setEngine1(bool arg);
|
void setEngine1(bool arg);
|
||||||
void setEngine2(bool arg);
|
void setEngine2(bool arg);
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ public slots:
|
||||||
void setSound(bool arg = true);
|
void setSound(bool arg = true);
|
||||||
|
|
||||||
// 播放声音
|
// 播放声音
|
||||||
static void playSound(sound_t soundType, player_t player);
|
static void playSound(sound_t soundType, Color c);
|
||||||
|
|
||||||
// 是否必败时认输
|
// 是否必败时认输
|
||||||
void setGiveUpIfMostLose(bool enabled);
|
void setGiveUpIfMostLose(bool enabled);
|
||||||
|
@ -296,16 +296,10 @@ public slots:
|
||||||
waitThreads();
|
waitThreads();
|
||||||
}
|
}
|
||||||
|
|
||||||
void resumeAiThreads(player_t sideToMove)
|
void resumeAiThreads(Color sideToMove)
|
||||||
{
|
{
|
||||||
if (sideToMove == PLAYER_BLACK) {
|
if (isAiPlayer[sideToMove]) {
|
||||||
if (isAiPlayer[BLACK]) {
|
aiThread[sideToMove]->resume();
|
||||||
aiThread[BLACK]->resume();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (isAiPlayer[WHITE]) {
|
|
||||||
aiThread[WHITE]->resume();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -609,13 +609,13 @@ void MillGameWindow::on_actionNew_N_triggered()
|
||||||
QString whoWin;
|
QString whoWin;
|
||||||
|
|
||||||
switch (gameController->getPosition()->getWinner()) {
|
switch (gameController->getPosition()->getWinner()) {
|
||||||
case PLAYER_BLACK:
|
case BLACK:
|
||||||
whoWin = "Black-Win";
|
whoWin = "Black-Win";
|
||||||
break;
|
break;
|
||||||
case PLAYER_WHITE:
|
case WHITE:
|
||||||
whoWin = "White-Win";
|
whoWin = "White-Win";
|
||||||
break;
|
break;
|
||||||
case PLAYER_DRAW:
|
case DRAW:
|
||||||
whoWin = "Draw";
|
whoWin = "Draw";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -83,8 +83,8 @@ protected slots:
|
||||||
void rowsInserted(const QModelIndex &parent, int start, int end) {
|
void rowsInserted(const QModelIndex &parent, int start, int end) {
|
||||||
// 调用父类函数,为使滚动条更新,否则scrollToBottom不能正确执行。
|
// 调用父类函数,为使滚动条更新,否则scrollToBottom不能正确执行。
|
||||||
QListView::rowsInserted(parent, start, end);
|
QListView::rowsInserted(parent, start, end);
|
||||||
QModelIndex id = model()->square(end, 0);
|
QModelIndex color = model()->square(end, 0);
|
||||||
setCurrentIndex(id);
|
setCurrentIndex(color);
|
||||||
scrollToBottom();
|
scrollToBottom();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue