refactor: 将 positon 重命名为 location
因为术语中 position 是 "局面" 的意思, location 才是表示棋盘上的位置.
This commit is contained in:
parent
d2c18f2fed
commit
30b37bc4fa
|
@ -28,7 +28,7 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, MillGame &gameTemp,
|
|||
move_t bestMove)
|
||||
{
|
||||
const int MOVE_PRIORITY_TABLE_SIZE = Board::N_RINGS * Board::N_SEATS;
|
||||
int pos = 0;
|
||||
int location = 0;
|
||||
size_t newCapacity = 24;
|
||||
|
||||
// 留足余量空间避免多次重新分配,此动作本身也占用 CPU/内存 开销
|
||||
|
@ -79,18 +79,18 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, MillGame &gameTemp,
|
|||
// 对于摆子阶段
|
||||
if (gameTemp.context.stage & (GAME_PLACING | GAME_NOTSTARTED)) {
|
||||
for (int i : movePriorityTable) {
|
||||
pos = i;
|
||||
location = i;
|
||||
|
||||
if (gameTemp.board_[pos]) {
|
||||
if (gameTemp.board_[location]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gameTemp.context.stage != GAME_NOTSTARTED || node != rootNode) {
|
||||
ai_ab.addNode(node, 0, pos, bestMove, gameTemp.context.turn);
|
||||
ai_ab.addNode(node, 0, location, bestMove, gameTemp.context.turn);
|
||||
} else {
|
||||
// 若为先手,则抢占星位
|
||||
if (MillGame::isStarPoint(pos)) {
|
||||
ai_ab.addNode(node, MillGameAi_ab::INF_VALUE, pos, bestMove, gameTemp.context.turn);
|
||||
if (MillGame::isStarPoint(location)) {
|
||||
ai_ab.addNode(node, MillGameAi_ab::INF_VALUE, location, bestMove, gameTemp.context.turn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,13 +99,13 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, MillGame &gameTemp,
|
|||
|
||||
// 对于移子阶段
|
||||
if (gameTemp.context.stage & GAME_MOVING) {
|
||||
int newPos, oldPos;
|
||||
int newLocation, oldLocation;
|
||||
|
||||
// 尽量走理论上较差的位置的棋子
|
||||
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
|
||||
oldPos = movePriorityTable[i];
|
||||
oldLocation = movePriorityTable[i];
|
||||
|
||||
if (!gameTemp.choose(oldPos)) {
|
||||
if (!gameTemp.choose(oldLocation)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -116,17 +116,17 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, MillGame &gameTemp,
|
|||
// 对于棋盘上还有3个子以上,或不允许飞子的情况,要求必须在着法表中
|
||||
for (int moveDirection = MOVE_DIRECTION_CLOCKWISE; moveDirection <= MOVE_DIRECTION_OUTWARD; moveDirection++) {
|
||||
// 对于原有位置,遍历四个方向的着法,如果棋盘上为空位就加到结点列表中
|
||||
newPos = moveTable[oldPos][moveDirection];
|
||||
if (newPos && !gameTemp.board_[newPos]) {
|
||||
int move = (oldPos << 8) + newPos;
|
||||
newLocation = moveTable[oldLocation][moveDirection];
|
||||
if (newLocation && !gameTemp.board_[newLocation]) {
|
||||
int move = (oldLocation << 8) + newLocation;
|
||||
ai_ab.addNode(node, 0, move, bestMove, gameTemp.context.turn); // (12%)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 对于棋盘上还有不到3个字,但允许飞子的情况,不要求在着法表中,是空位就行
|
||||
for (newPos = Board::POS_BEGIN; newPos < Board::POS_END; newPos++) {
|
||||
if (!gameTemp.board_[newPos]) {
|
||||
int move = (oldPos << 8) + newPos;
|
||||
for (newLocation = Board::LOCATION_BEGIN; newLocation < Board::LOCATION_END; newLocation++) {
|
||||
if (!gameTemp.board_[newLocation]) {
|
||||
int move = (oldLocation << 8) + newLocation;
|
||||
ai_ab.addNode(node, 0, move, bestMove, gameTemp.context.turn);
|
||||
}
|
||||
}
|
||||
|
@ -140,9 +140,9 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, MillGame &gameTemp,
|
|||
if (gameTemp.context.board.isAllInMills(opponent)) {
|
||||
// 全成三的情况
|
||||
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
|
||||
pos = movePriorityTable[i];
|
||||
if (gameTemp.board_[pos] & opponent) {
|
||||
ai_ab.addNode(node, 0, -pos, bestMove, gameTemp.context.turn);
|
||||
location = movePriorityTable[i];
|
||||
if (gameTemp.board_[location] & opponent) {
|
||||
ai_ab.addNode(node, 0, -location, bestMove, gameTemp.context.turn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -150,10 +150,10 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, MillGame &gameTemp,
|
|||
|
||||
// 不是全成三的情况
|
||||
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
|
||||
pos = movePriorityTable[i];
|
||||
if (gameTemp.board_[pos] & opponent) {
|
||||
if (gameTemp.getRule()->allowRemoveMill || !gameTemp.context.board.isInMills(pos)) {
|
||||
ai_ab.addNode(node, 0, -pos, bestMove, gameTemp.context.turn);
|
||||
location = movePriorityTable[i];
|
||||
if (gameTemp.board_[location] & opponent) {
|
||||
if (gameTemp.getRule()->allowRemoveMill || !gameTemp.context.board.inHowManyMills(location)) {
|
||||
ai_ab.addNode(node, 0, -location, bestMove, gameTemp.context.turn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, MillGame &gameTemp,
|
|||
void MoveList::createMoveTable(MillGame &game)
|
||||
{
|
||||
#if 1
|
||||
const int moveTable_obliqueLine[Board::N_POINTS][N_MOVE_DIRECTIONS] = {
|
||||
const int moveTable_obliqueLine[Board::N_LOCATIONS][N_MOVE_DIRECTIONS] = {
|
||||
/* 0 */ {0, 0, 0, 0},
|
||||
/* 1 */ {0, 0, 0, 0},
|
||||
/* 2 */ {0, 0, 0, 0},
|
||||
|
@ -214,7 +214,7 @@ void MoveList::createMoveTable(MillGame &game)
|
|||
/* 39 */ {0, 0, 0, 0},
|
||||
};
|
||||
|
||||
const int moveTable_noObliqueLine[Board::N_POINTS][N_MOVE_DIRECTIONS] = {
|
||||
const int moveTable_noObliqueLine[Board::N_LOCATIONS][N_MOVE_DIRECTIONS] = {
|
||||
/* 0 */ {0, 0, 0, 0},
|
||||
/* 1 */ {0, 0, 0, 0},
|
||||
/* 2 */ {0, 0, 0, 0},
|
||||
|
@ -261,7 +261,7 @@ void MoveList::createMoveTable(MillGame &game)
|
|||
/* 39 */ {0, 0, 0, 0},
|
||||
};
|
||||
#else
|
||||
const int moveTable_obliqueLine[Board::N_POINTS][N_MOVE_DIRECTIONS] = {
|
||||
const int moveTable_obliqueLine[Board::N_LOCATIONS][N_MOVE_DIRECTIONS] = {
|
||||
{0, 0, 0, 0},
|
||||
{0, 0, 0, 0},
|
||||
{0, 0, 0, 0},
|
||||
|
@ -308,7 +308,7 @@ void MoveList::createMoveTable(MillGame &game)
|
|||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
const int moveTable_noObliqueLine[Board::N_POINTS][N_MOVE_DIRECTIONS] = {
|
||||
const int moveTable_noObliqueLine[Board::N_LOCATIONS][N_MOVE_DIRECTIONS] = {
|
||||
/* 0 */ {0, 0, 0, 0},
|
||||
/* 1 */ {0, 0, 0, 0},
|
||||
/* 2 */ {0, 0, 0, 0},
|
||||
|
@ -364,7 +364,7 @@ void MoveList::createMoveTable(MillGame &game)
|
|||
|
||||
#ifdef DEBUG_MODE
|
||||
int sum = 0;
|
||||
for (int i = 0; i < Board::N_POINTS; i++) {
|
||||
for (int i = 0; i < Board::N_LOCATIONS; i++) {
|
||||
loggerDebug("/* %d */ {", i);
|
||||
for (int j = 0; j < N_MOVE_DIRECTIONS; j++) {
|
||||
if (j == N_MOVE_DIRECTIONS - 1)
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
static void shuffleMovePriorityTable(MillGame &game);
|
||||
|
||||
// 着法表 // TODO: Move to private
|
||||
inline static int moveTable[Board::N_POINTS][N_MOVE_DIRECTIONS] = { {0} };
|
||||
inline static int moveTable[Board::N_LOCATIONS][N_MOVE_DIRECTIONS] = { {0} };
|
||||
|
||||
private:
|
||||
// 着法顺序表, 后续会被打乱
|
||||
|
|
|
@ -39,7 +39,7 @@ HashMap<hash_t, MillGameAi_ab::HashValue> bookHashMap(bookHashsize);
|
|||
vector<hash_t> openingBook;
|
||||
#endif // BOOK_LEARNING
|
||||
|
||||
// 用于检测重复局面
|
||||
// 用于检测重复局面 (Position)
|
||||
vector<hash_t> positions;
|
||||
|
||||
MillGameAi_ab::MillGameAi_ab()
|
||||
|
@ -156,15 +156,15 @@ struct MillGameAi_ab::Node *MillGameAi_ab::addNode(
|
|||
char cmd[32] = { 0 };
|
||||
|
||||
if (move < 0) {
|
||||
gameTemp.context.board.pos2rs(-move, r, s);
|
||||
gameTemp.context.board.locationToPolar(-move, r, s);
|
||||
sprintf(cmd, "-(%1u,%1u)", r, s);
|
||||
} else if (move & 0x7f00) {
|
||||
int r1, s1;
|
||||
gameTemp.context.board.pos2rs(move >> 8, r1, s1);
|
||||
gameTemp.context.board.pos2rs(move & 0x00ff, r, s);
|
||||
gameTemp.context.board.locationToPolar(move >> 8, r1, s1);
|
||||
gameTemp.context.board.locationToPolar(move & 0x00ff, r, s);
|
||||
sprintf(cmd, "(%1u,%1u)->(%1u,%1u)", r1, s1, r, s);
|
||||
} else {
|
||||
gameTemp.context.board.pos2rs(move & 0x007f, r, s);
|
||||
gameTemp.context.board.locationToPolar(move & 0x007f, r, s);
|
||||
sprintf(cmd, "(%1u,%1u)", r, s);
|
||||
}
|
||||
|
||||
|
@ -747,15 +747,15 @@ const char *MillGameAi_ab::move2string(move_t move)
|
|||
int r, s;
|
||||
|
||||
if (move < 0) {
|
||||
gameTemp.context.board.pos2rs(-move, r, s);
|
||||
gameTemp.context.board.locationToPolar(-move, r, s);
|
||||
sprintf(cmdline, "-(%1u,%1u)", r, s);
|
||||
} else if (move & 0x7f00) {
|
||||
int r1, s1;
|
||||
gameTemp.context.board.pos2rs(move >> 8, r1, s1);
|
||||
gameTemp.context.board.pos2rs(move & 0x00ff, r, s);
|
||||
gameTemp.context.board.locationToPolar(move >> 8, r1, s1);
|
||||
gameTemp.context.board.locationToPolar(move & 0x00ff, r, s);
|
||||
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u)", r1, s1, r, s);
|
||||
} else {
|
||||
gameTemp.context.board.pos2rs(move & 0x007f, r, s);
|
||||
gameTemp.context.board.locationToPolar(move & 0x007f, r, s);
|
||||
sprintf(cmdline, "(%1u,%1u)", r, s);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "millgame.h"
|
||||
|
||||
static const hash_t zobrist0[Board::N_POINTS][POINT_TYPE_COUNT] = {
|
||||
static const hash_t zobrist0[Board::N_LOCATIONS][POINT_TYPE_COUNT] = {
|
||||
#ifdef TRANSPOSITION_TABLE_CUTDOWN
|
||||
{0x4E421A00, 0x3962FF00, 0x6DB6EE00, 0x219AE100},
|
||||
{0x1F3DE200, 0xD9AACB00, 0xD5173300, 0xD3F9EA00},
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "movegen.h"
|
||||
|
||||
// 名义上是个数组,实际上相当于一个判断是否在棋盘上的函数
|
||||
const int Board::onBoard[N_POINTS] = {
|
||||
const int Board::onBoard[N_LOCATIONS] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
|
@ -32,7 +32,7 @@ const int Board::onBoard[N_POINTS] = {
|
|||
};
|
||||
|
||||
// 成三表
|
||||
int Board::millTable[N_POINTS][N_DIRECTIONS][N_RINGS - 1] = { {{0}} };
|
||||
int Board::millTable[N_LOCATIONS][N_DIRECTIONS][N_RINGS - 1] = { {{0}} };
|
||||
|
||||
Board::Board()
|
||||
{
|
||||
|
@ -50,7 +50,7 @@ Board &Board::operator= (const Board &other)
|
|||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
memcpy(this->board_, other.board_, sizeof(this->board_));
|
||||
memcpy(this->locations, other.locations, sizeof(this->locations));
|
||||
|
||||
if (!millList.empty()) {
|
||||
millList.clear();
|
||||
|
@ -67,7 +67,7 @@ Board &Board::operator= (const Board &other)
|
|||
|
||||
void Board::createMillTable(const Rule ¤tRule)
|
||||
{
|
||||
const int millTable_noObliqueLine[Board::N_POINTS][Board::N_DIRECTIONS][2] = {
|
||||
const int millTable_noObliqueLine[Board::N_LOCATIONS][Board::N_DIRECTIONS][2] = {
|
||||
/* 0 */ {{0, 0}, {0, 0}, {0, 0}},
|
||||
/* 1 */ {{0, 0}, {0, 0}, {0, 0}},
|
||||
/* 2 */ {{0, 0}, {0, 0}, {0, 0}},
|
||||
|
@ -114,7 +114,7 @@ void Board::createMillTable(const Rule ¤tRule)
|
|||
/* 39 */ {{0, 0}, {0, 0}, {0, 0}}
|
||||
};
|
||||
|
||||
const int millTable_hasObliqueLines[Board::N_POINTS][Board::N_DIRECTIONS][2] = {
|
||||
const int millTable_hasObliqueLines[Board::N_LOCATIONS][Board::N_DIRECTIONS][2] = {
|
||||
/* 0 */ {{0, 0}, {0, 0}, {0, 0}},
|
||||
/* 1 */ {{0, 0}, {0, 0}, {0, 0}},
|
||||
/* 2 */ {{0, 0}, {0, 0}, {0, 0}},
|
||||
|
@ -168,7 +168,7 @@ void Board::createMillTable(const Rule ¤tRule)
|
|||
}
|
||||
|
||||
#ifdef DEBUG_MODE
|
||||
for (int i = 0; i < N_POINTS; i++) {
|
||||
for (int i = 0; i < N_LOCATIONS; i++) {
|
||||
loggerDebug("/* %d */ {", i);
|
||||
for (int j = 0; j < N_DIRECTIONS; j++) {
|
||||
loggerDebug("{");
|
||||
|
@ -192,57 +192,58 @@ void Board::createMillTable(const Rule ¤tRule)
|
|||
#endif /* DEBUG_MODE */
|
||||
}
|
||||
|
||||
void Board::pos2rs(const int pos, int &r, int &s)
|
||||
void Board::locationToPolar(const int location, int &r, int &s)
|
||||
{
|
||||
//r = pos / N_SEATS;
|
||||
//s = pos % N_SEATS + 1;
|
||||
r = pos >> 3;
|
||||
s = (pos & 0x07) + 1;
|
||||
//r = location / N_SEATS;
|
||||
//s = location % N_SEATS + 1;
|
||||
r = location >> 3;
|
||||
s = (location & 0x07) + 1;
|
||||
}
|
||||
|
||||
int Board::rs2Pos(int r, int s)
|
||||
int Board::polarToLocation(int r, int s)
|
||||
{
|
||||
if (r < 1 || r > N_RINGS || s < 1 || s > N_SEATS)
|
||||
if (r < 1 || r > N_RINGS || s < 1 || s > N_SEATS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r * N_SEATS + s - 1;
|
||||
}
|
||||
|
||||
|
||||
int Board::isInMills(int pos, bool test)
|
||||
int Board::inHowManyMills(int location)
|
||||
{
|
||||
int n = 0;
|
||||
int pos1, pos2;
|
||||
int m = test ? INT32_MAX : board_[pos] & '\x30';
|
||||
int location1, location2;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
pos1 = millTable[pos][i][0];
|
||||
pos2 = millTable[pos][i][1];
|
||||
if (m & board_[pos1] & board_[pos2])
|
||||
for (int d = 0; d < N_DIRECTIONS; d++) {
|
||||
location1 = millTable[location][d][0];
|
||||
location2 = millTable[location][d][1];
|
||||
if ((locations[location] & 0x30) & locations[location1] & locations[location2]) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int Board::addMills(const Rule ¤tRule, int pos)
|
||||
int Board::addMills(const Rule ¤tRule, int location)
|
||||
{
|
||||
// 成三用一个64位整数了,规则如下
|
||||
// 0x 00 00 00 00 00 00 00 00
|
||||
// unused unused piece1 pos1 piece2 pos2 piece3 pos3
|
||||
// unused unused piece1 location1 piece2 location2 piece3 pos3
|
||||
// piece1、piece2、piece3按照序号从小到大顺序排放
|
||||
uint64_t mill = 0;
|
||||
int n = 0;
|
||||
int p[3], min, temp;
|
||||
char m = board_[pos] & '\x30';
|
||||
char m = locations[location] & '\x30';
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
p[0] = pos;
|
||||
p[1] = millTable[pos][i][0];
|
||||
p[2] = millTable[pos][i][1];
|
||||
p[0] = location;
|
||||
p[1] = millTable[location][i][0];
|
||||
p[2] = millTable[location][i][1];
|
||||
|
||||
// 如果没有成三
|
||||
if (!(m & board_[p[1]] & board_[p[2]])) {
|
||||
if (!(m & locations[p[1]] & locations[p[2]])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -267,11 +268,11 @@ int Board::addMills(const Rule ¤tRule, int pos)
|
|||
}
|
||||
|
||||
// 成三
|
||||
mill = (static_cast<uint64_t>(board_[p[0]]) << 40)
|
||||
mill = (static_cast<uint64_t>(locations[p[0]]) << 40)
|
||||
+ (static_cast<uint64_t>(p[0]) << 32)
|
||||
+ (static_cast<uint64_t>(board_[p[1]]) << 24)
|
||||
+ (static_cast<uint64_t>(locations[p[1]]) << 24)
|
||||
+ (static_cast<uint64_t>(p[1]) << 16)
|
||||
+ (static_cast<uint64_t>(board_[p[2]]) << 8)
|
||||
+ (static_cast<uint64_t>(locations[p[2]]) << 8)
|
||||
+ static_cast<uint64_t>(p[2]);
|
||||
|
||||
// 如果允许相同三连反复去子
|
||||
|
@ -303,9 +304,9 @@ int Board::addMills(const Rule ¤tRule, int pos)
|
|||
|
||||
bool Board::isAllInMills(char ch)
|
||||
{
|
||||
for (int i = POS_BEGIN; i < POS_END; i++) {
|
||||
if (board_[i] & ch) {
|
||||
if (!isInMills(i)) {
|
||||
for (int i = LOCATION_BEGIN; i < LOCATION_END; i++) {
|
||||
if (locations[i] & ch) {
|
||||
if (!inHowManyMills(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +330,7 @@ bool Board::isAllInMills(enum Player player)
|
|||
}
|
||||
|
||||
// 判断玩家的棋子周围有几个空位
|
||||
int Board::getSurroundedEmptyPosCount(enum Player turn, const Rule ¤tRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int pos, bool includeFobidden)
|
||||
int Board::getSurroundedEmptyLocationCount(enum Player turn, const Rule ¤tRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int location, bool includeFobidden)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
|
@ -337,12 +338,12 @@ int Board::getSurroundedEmptyPosCount(enum Player turn, const Rule ¤tRule,
|
|||
(nPiecesOnBoard_1 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces)) ||
|
||||
(turn == PLAYER2 &&
|
||||
(nPiecesOnBoard_2 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces))) {
|
||||
int d, movePos;
|
||||
int d, moveLocation;
|
||||
for (d = 0; d < N_MOVE_DIRECTIONS; d++) {
|
||||
movePos = MoveList::moveTable[pos][d];
|
||||
if (movePos) {
|
||||
if (board_[movePos] == 0x00 ||
|
||||
(includeFobidden && board_[movePos] == 0x0F)) {
|
||||
moveLocation = MoveList::moveTable[location][d];
|
||||
if (moveLocation) {
|
||||
if (locations[moveLocation] == 0x00 ||
|
||||
(includeFobidden && locations[moveLocation] == 0x0F)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
@ -353,17 +354,17 @@ int Board::getSurroundedEmptyPosCount(enum Player turn, const Rule ¤tRule,
|
|||
}
|
||||
|
||||
// 判断玩家的棋子是否被围
|
||||
bool Board::isSurrounded(enum Player turn, const Rule ¤tRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int pos)
|
||||
bool Board::isSurrounded(enum Player turn, const Rule ¤tRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int location)
|
||||
{
|
||||
// 判断pos处的棋子是否被“闷”
|
||||
// 判断location处的棋子是否被“闷”
|
||||
if ((turn == PLAYER1 &&
|
||||
(nPiecesOnBoard_1 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces)) ||
|
||||
(turn == PLAYER2 &&
|
||||
(nPiecesOnBoard_2 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces))) {
|
||||
int i, movePos;
|
||||
int i, moveLocation;
|
||||
for (i = 0; i < 4; i++) {
|
||||
movePos = MoveList::moveTable[pos][i];
|
||||
if (movePos && !board_[movePos])
|
||||
moveLocation = MoveList::moveTable[location][i];
|
||||
if (moveLocation && !locations[moveLocation])
|
||||
break;
|
||||
}
|
||||
// 被围住
|
||||
|
@ -389,15 +390,15 @@ bool Board::isAllSurrounded(enum Player turn, const Rule ¤tRule, int nPiec
|
|||
}
|
||||
|
||||
// 查询整个棋盘
|
||||
int movePos;
|
||||
int moveLocation;
|
||||
for (int i = 1; i < N_SEATS * (N_RINGS + 1); i++) {
|
||||
if (!(ch & board_[i])) {
|
||||
if (!(ch & locations[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int d = 0; d < N_MOVE_DIRECTIONS; d++) {
|
||||
movePos = MoveList::moveTable[i][d];
|
||||
if (movePos && !board_[movePos])
|
||||
moveLocation = MoveList::moveTable[i][d];
|
||||
if (moveLocation && !locations[moveLocation])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -420,12 +421,12 @@ bool Board::isAllSurrounded(enum Player turn, const Rule ¤tRule, int nPiec
|
|||
|
||||
enum Player Board::getWhosPiece(int r, int s)
|
||||
{
|
||||
int pos = rs2Pos(r, s);
|
||||
int location = polarToLocation(r, s);
|
||||
|
||||
if (board_[pos] & '\x10')
|
||||
if (locations[location] & '\x10')
|
||||
return PLAYER1;
|
||||
|
||||
if (board_[pos] & '\x20')
|
||||
if (locations[location] & '\x20')
|
||||
return PLAYER2;
|
||||
|
||||
return PLAYER_NOBODY;
|
||||
|
@ -449,9 +450,9 @@ bool Board::getPieceRS(const Player &player, const int &number, int &r, int &s,
|
|||
else
|
||||
return false;
|
||||
|
||||
for (int i = POS_BEGIN; i < POS_END; i++) {
|
||||
if (board_[i] == piece) {
|
||||
pos2rs(i, r, s);
|
||||
for (int i = LOCATION_BEGIN; i < LOCATION_END; i++) {
|
||||
if (locations[i] == piece) {
|
||||
locationToPolar(i, r, s);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -460,12 +461,12 @@ bool Board::getPieceRS(const Player &player, const int &number, int &r, int &s,
|
|||
}
|
||||
|
||||
// 获取当前棋子
|
||||
bool Board::getCurrentPiece(Player &player, int &number, int currentPos)
|
||||
bool Board::getCurrentPiece(Player &player, int &number, int location)
|
||||
{
|
||||
if (!onBoard[currentPos])
|
||||
if (!onBoard[location])
|
||||
return false;
|
||||
|
||||
int p = board_[currentPos];
|
||||
int p = locations[location];
|
||||
|
||||
if (p & 0x10) {
|
||||
player = PLAYER1;
|
||||
|
@ -480,7 +481,7 @@ bool Board::getCurrentPiece(Player &player, int &number, int currentPos)
|
|||
return true;
|
||||
}
|
||||
|
||||
void Board::mirror(list <string> &cmdlist, char* cmdline, int32_t move_, struct Rule ¤tRule, int currentPos, bool cmdChange /*= true*/)
|
||||
void Board::mirror(list <string> &cmdlist, char* cmdline, int32_t move_, struct Rule ¤tRule, int location, bool cmdChange /*= true*/)
|
||||
{
|
||||
int ch;
|
||||
int r, s;
|
||||
|
@ -488,10 +489,10 @@ void Board::mirror(list <string> &cmdlist, char* cmdline, int32_t move_, struct
|
|||
|
||||
for (r = 1; r <= N_RINGS; r++) {
|
||||
for (s = 1; s < N_SEATS / 2; s++) {
|
||||
ch = board_[r * N_SEATS + s];
|
||||
board_[r * N_SEATS + s] = board_[(r + 1) * N_SEATS - s];
|
||||
ch = locations[r * N_SEATS + s];
|
||||
locations[r * N_SEATS + s] = locations[(r + 1) * N_SEATS - s];
|
||||
//updateHash(i * N_SEATS + j);
|
||||
board_[(r + 1) * N_SEATS - s] = ch;
|
||||
locations[(r + 1) * N_SEATS - s] = ch;
|
||||
//updateHash((i + 1) * N_SEATS - j);
|
||||
}
|
||||
}
|
||||
|
@ -517,11 +518,11 @@ void Board::mirror(list <string> &cmdlist, char* cmdline, int32_t move_, struct
|
|||
move_ = static_cast<int16_t>(((llp[0] << 8) | llp[1]));
|
||||
}
|
||||
|
||||
if (currentPos != 0) {
|
||||
r = currentPos / N_SEATS;
|
||||
s = currentPos % N_SEATS;
|
||||
if (location != 0) {
|
||||
r = location / N_SEATS;
|
||||
s = location % N_SEATS;
|
||||
s = (N_SEATS - s) % N_SEATS;
|
||||
currentPos = r * N_SEATS + s;
|
||||
location = r * N_SEATS + s;
|
||||
}
|
||||
|
||||
if (currentRule.allowRemovePiecesRepeatedly) {
|
||||
|
@ -592,17 +593,17 @@ void Board::mirror(list <string> &cmdlist, char* cmdline, int32_t move_, struct
|
|||
}
|
||||
}
|
||||
|
||||
void Board::turn(list <string> &cmdlist, char *cmdline, int32_t move_, const Rule ¤tRule, int currentPos, bool cmdChange /*= true*/)
|
||||
void Board::turn(list <string> &cmdlist, char *cmdline, int32_t move_, const Rule ¤tRule, int location, bool cmdChange /*= true*/)
|
||||
{
|
||||
int ch;
|
||||
int r, s;
|
||||
int i;
|
||||
|
||||
for (s = 0; s < N_SEATS; s++) {
|
||||
ch = board_[N_SEATS + s];
|
||||
board_[N_SEATS + s] = board_[N_SEATS * N_RINGS + s];
|
||||
ch = locations[N_SEATS + s];
|
||||
locations[N_SEATS + s] = locations[N_SEATS * N_RINGS + s];
|
||||
//updateHash(N_SEATS + s);
|
||||
board_[N_SEATS * N_RINGS + s] = ch;
|
||||
locations[N_SEATS * N_RINGS + s] = ch;
|
||||
//updateHash(N_SEATS * N_RINGS + s);
|
||||
}
|
||||
|
||||
|
@ -637,16 +638,16 @@ void Board::turn(list <string> &cmdlist, char *cmdline, int32_t move_, const Rul
|
|||
move_ = static_cast<int16_t>(((llp[0] << 8) | llp[1]));
|
||||
}
|
||||
|
||||
if (currentPos != 0) {
|
||||
r = currentPos / N_SEATS;
|
||||
s = currentPos % N_SEATS;
|
||||
if (location != 0) {
|
||||
r = location / N_SEATS;
|
||||
s = location % N_SEATS;
|
||||
|
||||
if (r == 1)
|
||||
r = N_RINGS;
|
||||
else if (r == N_RINGS)
|
||||
r = 1;
|
||||
|
||||
currentPos = r * N_SEATS + s;
|
||||
location = r * N_SEATS + s;
|
||||
}
|
||||
|
||||
if (currentRule.allowRemovePiecesRepeatedly) {
|
||||
|
@ -757,7 +758,7 @@ void Board::turn(list <string> &cmdlist, char *cmdline, int32_t move_, const Rul
|
|||
}
|
||||
}
|
||||
|
||||
void Board::rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t move_, const Rule ¤tRule, int currentPos, bool cmdChange /*= true*/)
|
||||
void Board::rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t move_, const Rule ¤tRule, int location, bool cmdChange /*= true*/)
|
||||
{
|
||||
// 将degrees转化为0~359之间的数
|
||||
degrees = degrees % 360;
|
||||
|
@ -776,40 +777,40 @@ void Board::rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t m
|
|||
|
||||
if (degrees == 2) {
|
||||
for (r = 1; r <= N_RINGS; r++) {
|
||||
ch1 = board_[r * N_SEATS];
|
||||
ch2 = board_[r * N_SEATS + 1];
|
||||
ch1 = locations[r * N_SEATS];
|
||||
ch2 = locations[r * N_SEATS + 1];
|
||||
|
||||
for (s = 0; s < N_SEATS - 2; s++) {
|
||||
board_[r * N_SEATS + s] = board_[r * N_SEATS + s + 2];
|
||||
locations[r * N_SEATS + s] = locations[r * N_SEATS + s + 2];
|
||||
}
|
||||
|
||||
board_[r * N_SEATS + 6] = ch1;
|
||||
locations[r * N_SEATS + 6] = ch1;
|
||||
//updateHash(i * N_SEATS + 6);
|
||||
board_[r * N_SEATS + 7] = ch2;
|
||||
locations[r * N_SEATS + 7] = ch2;
|
||||
//updateHash(i * N_SEATS + 7);
|
||||
}
|
||||
} else if (degrees == 6) {
|
||||
for (r = 1; r <= N_RINGS; r++) {
|
||||
ch1 = board_[r * N_SEATS + 7];
|
||||
ch2 = board_[r * N_SEATS + 6];
|
||||
ch1 = locations[r * N_SEATS + 7];
|
||||
ch2 = locations[r * N_SEATS + 6];
|
||||
|
||||
for (s = N_SEATS - 1; s >= 2; s--) {
|
||||
board_[r * N_SEATS + s] = board_[r * N_SEATS + s - 2];
|
||||
locations[r * N_SEATS + s] = locations[r * N_SEATS + s - 2];
|
||||
//updateHash(i * N_SEATS + j);
|
||||
}
|
||||
|
||||
board_[r * N_SEATS + 1] = ch1;
|
||||
locations[r * N_SEATS + 1] = ch1;
|
||||
//updateHash(i * N_SEATS + 1);
|
||||
board_[r * N_SEATS] = ch2;
|
||||
locations[r * N_SEATS] = ch2;
|
||||
//updateHash(i * N_SEATS);
|
||||
}
|
||||
} else if (degrees == 4) {
|
||||
for (r = 1; r <= N_RINGS; r++) {
|
||||
for (s = 0; s < N_SEATS / 2; s++) {
|
||||
ch1 = board_[r * N_SEATS + s];
|
||||
board_[r * N_SEATS + s] = board_[r * N_SEATS + s + 4];
|
||||
ch1 = locations[r * N_SEATS + s];
|
||||
locations[r * N_SEATS + s] = locations[r * N_SEATS + s + 4];
|
||||
//updateHash(i * N_SEATS + j);
|
||||
board_[r * N_SEATS + s + 4] = ch1;
|
||||
locations[r * N_SEATS + s + 4] = ch1;
|
||||
//updateHash(i * N_SEATS + j + 4);
|
||||
}
|
||||
}
|
||||
|
@ -838,11 +839,11 @@ void Board::rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t m
|
|||
move_ = static_cast<int16_t>(((llp[0] << 8) | llp[1]));
|
||||
}
|
||||
|
||||
if (currentPos != 0) {
|
||||
r = currentPos / N_SEATS;
|
||||
s = currentPos % N_SEATS;
|
||||
if (location != 0) {
|
||||
r = location / N_SEATS;
|
||||
s = location % N_SEATS;
|
||||
s = (s + N_SEATS - degrees) % N_SEATS;
|
||||
currentPos = r * N_SEATS + s;
|
||||
location = r * N_SEATS + s;
|
||||
}
|
||||
|
||||
if (currentRule.allowRemovePiecesRepeatedly) {
|
||||
|
|
|
@ -49,18 +49,18 @@ public:
|
|||
static const int N_DIRECTIONS = 3;
|
||||
|
||||
// 棋盘点的个数:40
|
||||
static const int N_POINTS = (Board::N_RINGS + 2) * Board::N_SEATS;
|
||||
static const int N_LOCATIONS = (Board::N_RINGS + 2) * Board::N_SEATS;
|
||||
|
||||
// 遍历棋盘点所用的起始位置,即 [8, 32)
|
||||
static const int POS_BEGIN = N_SEATS;
|
||||
static const int POS_END = ((N_RINGS + 1) * N_SEATS);
|
||||
static const int LOCATION_BEGIN = N_SEATS;
|
||||
static const int LOCATION_END = ((N_RINGS + 1) * N_SEATS);
|
||||
|
||||
// 空棋盘点位,用于判断一个棋子位置是否在棋盘上
|
||||
static const int onBoard[N_POINTS];
|
||||
static const int onBoard[N_LOCATIONS];
|
||||
|
||||
// 成三表,表示棋盘上各个位置有成三关系的对应位置表
|
||||
// 这个表跟规则有关,一旦规则改变需要重新修改
|
||||
static int millTable[N_POINTS][N_DIRECTIONS][N_RINGS - 1];
|
||||
static int millTable[N_LOCATIONS][N_DIRECTIONS][N_RINGS - 1];
|
||||
|
||||
// 生成成三表
|
||||
void createMillTable(const Rule ¤tRule);
|
||||
|
@ -74,18 +74,18 @@ public:
|
|||
// 局面逆时针旋转
|
||||
void rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t move_, const Rule ¤tRule, int currentPos, bool cmdChange = true);
|
||||
|
||||
// 判断棋盘pos处的棋子处于几个“三连”中
|
||||
int isInMills(int pos, bool test = false);
|
||||
// 判断棋盘location处的棋子处于几个“三连”中
|
||||
int inHowManyMills(int location);
|
||||
|
||||
// 判断玩家的所有棋子是否都处于“三连”状态
|
||||
bool isAllInMills(char ch);
|
||||
bool isAllInMills(enum Player);
|
||||
|
||||
// 判断玩家的棋子周围有几个空位
|
||||
int getSurroundedEmptyPosCount(enum Player turn, const Rule ¤tRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int pos, bool includeFobidden);
|
||||
int getSurroundedEmptyLocationCount(enum Player turn, const Rule ¤tRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int location, bool includeFobidden);
|
||||
|
||||
// 判断玩家的棋子是否被围
|
||||
bool isSurrounded(enum Player turn, const Rule ¤tRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int pos);
|
||||
bool isSurrounded(enum Player turn, const Rule ¤tRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int location);
|
||||
|
||||
// 判断玩家的棋子是否全部被围
|
||||
bool isAllSurrounded(enum Player turn, const Rule ¤tRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, char ch);
|
||||
|
@ -93,7 +93,7 @@ public:
|
|||
bool isAllSurrounded(enum Player turn, const Rule ¤tRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, enum Player ply);
|
||||
|
||||
// 三连加入列表
|
||||
int addMills(const Rule ¤tRule, int pos);
|
||||
int addMills(const Rule ¤tRule, int location);
|
||||
|
||||
// 获取位置点棋子的归属人
|
||||
enum Player getWhosPiece(int r, int s);
|
||||
|
@ -104,10 +104,10 @@ public:
|
|||
bool getCurrentPiece(Player &player, int &number, int currentPos);
|
||||
|
||||
// 将棋盘下标形式转化为第r圈,第s位,r和s下标都从1开始
|
||||
void pos2rs(int pos, int &r, int &s);
|
||||
void locationToPolar(int location, int &r, int &s);
|
||||
|
||||
// 将第c圈,第p位转化为棋盘下标形式,r和s下标都从1开始
|
||||
int rs2Pos(int r, int s);
|
||||
int polarToLocation(int r, int s);
|
||||
|
||||
//private:
|
||||
|
||||
|
@ -120,22 +120,22 @@ public:
|
|||
判断棋子是先手的用 (board[i] & 0x10)
|
||||
判断棋子是后手的用 (board[i] & 0x20)
|
||||
*/
|
||||
int board_[N_POINTS]{};
|
||||
int locations[N_LOCATIONS]{};
|
||||
|
||||
/*
|
||||
本打算用如下的结构体来表示“三连”
|
||||
struct Mill {
|
||||
char piece1; // “三连”中最小的棋子
|
||||
char pos1; // 最小棋子的位置
|
||||
char location1; // 最小棋子的位置
|
||||
char piece2; // 次小的棋子
|
||||
char pos2; // 次小棋子的位置
|
||||
char location2; // 次小棋子的位置
|
||||
char piece3; // 最大的棋子
|
||||
char pos3; // 最大棋子的位置
|
||||
char location3; // 最大棋子的位置
|
||||
};
|
||||
|
||||
但为了提高执行效率改用一个64位整数了,规则如下
|
||||
0x 00 00 00 00 00 00 00 00
|
||||
unused unused piece1 pos1 piece2 pos2 piece3 pos3
|
||||
unused unused piece1 location1 piece2 location2 piece3 location3
|
||||
*/
|
||||
|
||||
// 三连列表
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
MillGame::MillGame()
|
||||
{
|
||||
// 单独提出 board 等数据,免得每次都写 context.board;
|
||||
board_ = context.board.board_;
|
||||
board_ = context.board.locations;
|
||||
|
||||
// 创建哈希数据
|
||||
constructHash();
|
||||
|
@ -62,8 +62,8 @@ MillGame &MillGame::operator= (const MillGame &game)
|
|||
moveStep = game.moveStep;
|
||||
randomMove_ = game.randomMove_;
|
||||
giveUpIfMostLose_ = game.giveUpIfMostLose_;
|
||||
board_ = context.board.board_;
|
||||
currentPos = game.currentPos;
|
||||
board_ = context.board.locations;
|
||||
currentLocation = game.currentLocation;
|
||||
winner = game.winner;
|
||||
startTime = game.startTime;
|
||||
currentTime = game.currentTime;
|
||||
|
@ -170,10 +170,10 @@ bool MillGame::setContext(const struct Rule *rule, step_t maxStepsLedToDraw, int
|
|||
|
||||
// 当前棋局(3×8)
|
||||
if (board == nullptr) {
|
||||
memset(context.board.board_, 0, sizeof(context.board.board_));
|
||||
memset(context.board.locations, 0, sizeof(context.board.locations));
|
||||
context.hash = 0;
|
||||
} else {
|
||||
memcpy(context.board.board_, board, sizeof(context.board.board_));
|
||||
memcpy(context.board.locations, board, sizeof(context.board.locations));
|
||||
}
|
||||
|
||||
// 计算盘面子数
|
||||
|
@ -190,12 +190,12 @@ bool MillGame::setContext(const struct Rule *rule, step_t maxStepsLedToDraw, int
|
|||
|
||||
for (int r = 1; r < Board::N_RINGS + 2; r++) {
|
||||
for (int s = 0; s < Board::N_SEATS; s++) {
|
||||
int pos = r * Board::N_SEATS + s;
|
||||
if (context.board.board_[pos] & 0x10) {
|
||||
int location = r * Board::N_SEATS + s;
|
||||
if (context.board.locations[location] & 0x10) {
|
||||
context.nPiecesOnBoard_1++;
|
||||
} else if (context.board.board_[pos] & 0x20) {
|
||||
} else if (context.board.locations[location] & 0x20) {
|
||||
context.nPiecesOnBoard_2++;
|
||||
} else if (context.board.board_[pos] & 0x0F) {
|
||||
} else if (context.board.locations[location] & 0x0F) {
|
||||
// 不计算盘面子数
|
||||
}
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ bool MillGame::setContext(const struct Rule *rule, step_t maxStepsLedToDraw, int
|
|||
context.board.createMillTable(currentRule);
|
||||
|
||||
// 不选中棋子
|
||||
currentPos = 0;
|
||||
currentLocation = 0;
|
||||
|
||||
// 用时置零
|
||||
elapsedSeconds_1 = elapsedSeconds_2 = 0;
|
||||
|
@ -319,7 +319,7 @@ bool MillGame::reset()
|
|||
}
|
||||
|
||||
// 不选中棋子
|
||||
currentPos = 0;
|
||||
currentLocation = 0;
|
||||
|
||||
// 用时置零
|
||||
elapsedSeconds_1 = elapsedSeconds_2 = 0;
|
||||
|
@ -374,7 +374,7 @@ bool MillGame::start()
|
|||
}
|
||||
}
|
||||
|
||||
bool MillGame::place(int pos, int time_p, int8_t rs)
|
||||
bool MillGame::place(int location, int time_p, int8_t rs)
|
||||
{
|
||||
// 如果局面为“结局”,返回false
|
||||
if (context.stage == GAME_OVER)
|
||||
|
@ -389,13 +389,13 @@ bool MillGame::place(int pos, int time_p, int8_t rs)
|
|||
return false;
|
||||
|
||||
// 如果落子位置在棋盘外、已有子点或禁点,返回false
|
||||
if (!context.board.onBoard[pos] || board_[pos])
|
||||
if (!context.board.onBoard[location] || board_[location])
|
||||
return false;
|
||||
|
||||
// 格式转换
|
||||
int r = 0;
|
||||
int s = 0;
|
||||
context.board.pos2rs(pos, r, s);
|
||||
context.board.locationToPolar(location, r, s);
|
||||
|
||||
// 时间的临时变量
|
||||
int player_ms = -1;
|
||||
|
@ -418,11 +418,11 @@ bool MillGame::place(int pos, int time_p, int8_t rs)
|
|||
context.nPiecesOnBoard_2++;
|
||||
}
|
||||
|
||||
board_[pos] = piece;
|
||||
board_[location] = piece;
|
||||
|
||||
updateHash(pos);
|
||||
updateHash(location);
|
||||
|
||||
move_ = pos;
|
||||
move_ = location;
|
||||
|
||||
if (rs) {
|
||||
player_ms = update(time_p);
|
||||
|
@ -432,9 +432,9 @@ bool MillGame::place(int pos, int time_p, int8_t rs)
|
|||
currentStep++;
|
||||
}
|
||||
|
||||
currentPos = pos;
|
||||
currentLocation = location;
|
||||
|
||||
n = context.board.addMills(currentRule, currentPos);
|
||||
n = context.board.addMills(currentRule, currentLocation);
|
||||
|
||||
// 开局阶段未成三
|
||||
if (n == 0) {
|
||||
|
@ -494,7 +494,7 @@ bool MillGame::place(int pos, int time_p, int8_t rs)
|
|||
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (pos == MoveList::moveTable[currentPos][i])
|
||||
if (location == MoveList::moveTable[currentLocation][i])
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -505,26 +505,26 @@ bool MillGame::place(int pos, int time_p, int8_t rs)
|
|||
}
|
||||
|
||||
// 移子
|
||||
move_ = (currentPos << 8) + pos;
|
||||
move_ = (currentLocation << 8) + location;
|
||||
if (rs) {
|
||||
player_ms = update(time_p);
|
||||
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u) %02u:%02u", currentPos / Board::N_SEATS, currentPos % Board::N_SEATS + 1,
|
||||
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u) %02u:%02u", currentLocation / Board::N_SEATS, currentLocation % Board::N_SEATS + 1,
|
||||
r, s, player_ms / 60, player_ms % 60);
|
||||
cmdlist.emplace_back(string(cmdline));
|
||||
currentStep++;
|
||||
moveStep++;
|
||||
}
|
||||
|
||||
board_[pos] = board_[currentPos];
|
||||
board_[location] = board_[currentLocation];
|
||||
|
||||
updateHash(pos);
|
||||
updateHash(location);
|
||||
|
||||
board_[currentPos] = '\x00';
|
||||
board_[currentLocation] = '\x00';
|
||||
|
||||
revertHash(currentPos);
|
||||
revertHash(currentLocation);
|
||||
|
||||
currentPos = pos;
|
||||
n = context.board.addMills(currentRule, currentPos);
|
||||
currentLocation = location;
|
||||
n = context.board.addMills(currentRule, currentLocation);
|
||||
|
||||
// 中局阶段未成三
|
||||
if (n == 0) {
|
||||
|
@ -558,21 +558,21 @@ out:
|
|||
|
||||
bool MillGame::_place(int r, int s, int time_p)
|
||||
{
|
||||
// 转换为 pos
|
||||
int pos = context.board.rs2Pos(r, s);
|
||||
// 转换为 location
|
||||
int location = context.board.polarToLocation(r, s);
|
||||
|
||||
return place(pos, time_p, true);
|
||||
return place(location, time_p, true);
|
||||
}
|
||||
|
||||
bool MillGame::_capture(int r, int s, int time_p)
|
||||
{
|
||||
// 转换为 pos
|
||||
int pos = context.board.rs2Pos(r, s);
|
||||
// 转换为 location
|
||||
int location = context.board.polarToLocation(r, s);
|
||||
|
||||
return capture(pos, time_p, 1);
|
||||
return capture(location, time_p, 1);
|
||||
}
|
||||
|
||||
bool MillGame::capture(int pos, int time_p, int8_t cp)
|
||||
bool MillGame::capture(int location, int time_p, int8_t cp)
|
||||
{
|
||||
// 如果局面为"未开局"或“结局”,返回false
|
||||
if (context.stage == GAME_NOTSTARTED || context.stage == GAME_OVER)
|
||||
|
@ -589,7 +589,7 @@ bool MillGame::capture(int pos, int time_p, int8_t cp)
|
|||
// 格式转换
|
||||
int r = 0;
|
||||
int s = 0;
|
||||
context.board.pos2rs(pos, r, s);
|
||||
context.board.locationToPolar(location, r, s);
|
||||
|
||||
// 时间的临时变量
|
||||
int player_ms = -1;
|
||||
|
@ -598,23 +598,24 @@ bool MillGame::capture(int pos, int time_p, int8_t cp)
|
|||
char opponent = context.turn == PLAYER1 ? 0x20 : 0x10;
|
||||
|
||||
// 判断去子是不是对手棋
|
||||
if (!(opponent & board_[pos]))
|
||||
if (!(opponent & board_[location]))
|
||||
return false;
|
||||
|
||||
// 如果当前子是否处于“三连”之中,且对方还未全部处于“三连”之中
|
||||
if (!currentRule.allowRemoveMill &&
|
||||
context.board.isInMills(pos) && !context.board.isAllInMills(opponent)) {
|
||||
context.board.inHowManyMills(location) &&
|
||||
!context.board.isAllInMills(opponent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 去子(设置禁点)
|
||||
if (currentRule.hasForbiddenPoint && context.stage == GAME_PLACING) {
|
||||
revertHash(pos);
|
||||
board_[pos] = '\x0f';
|
||||
updateHash(pos);
|
||||
revertHash(location);
|
||||
board_[location] = '\x0f';
|
||||
updateHash(location);
|
||||
} else { // 去子
|
||||
revertHash(pos);
|
||||
board_[pos] = '\x00';
|
||||
revertHash(location);
|
||||
board_[location] = '\x00';
|
||||
}
|
||||
|
||||
if (context.turn == PLAYER1)
|
||||
|
@ -622,7 +623,7 @@ bool MillGame::capture(int pos, int time_p, int8_t cp)
|
|||
else if (context.turn == PLAYER2)
|
||||
context.nPiecesOnBoard_1--;
|
||||
|
||||
move_ = -pos;
|
||||
move_ = -location;
|
||||
|
||||
if (cp) {
|
||||
player_ms = update(time_p);
|
||||
|
@ -632,9 +633,9 @@ bool MillGame::capture(int pos, int time_p, int8_t cp)
|
|||
moveStep = 0;
|
||||
}
|
||||
|
||||
currentPos = 0;
|
||||
currentLocation = 0;
|
||||
context.nPiecesNeedRemove--;
|
||||
updateHash(pos);
|
||||
updateHash(location);
|
||||
|
||||
// 去子完成
|
||||
|
||||
|
@ -713,7 +714,7 @@ out:
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MillGame::choose(int pos)
|
||||
bool MillGame::choose(int location)
|
||||
{
|
||||
// 如果局面不是"中局”,返回false
|
||||
if (context.stage != GAME_MOVING)
|
||||
|
@ -726,14 +727,14 @@ bool MillGame::choose(int pos)
|
|||
char t = context.turn == PLAYER1 ? 0x10 : 0x20;
|
||||
|
||||
// 判断选子是否可选
|
||||
if (board_[pos] & t) {
|
||||
// 判断pos处的棋子是否被“闷”
|
||||
if (context.board.isSurrounded(context.turn, currentRule, context.nPiecesOnBoard_1, context.nPiecesOnBoard_2, pos)) {
|
||||
if (board_[location] & t) {
|
||||
// 判断location处的棋子是否被“闷”
|
||||
if (context.board.isSurrounded(context.turn, currentRule, context.nPiecesOnBoard_1, context.nPiecesOnBoard_2, location)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 选子
|
||||
currentPos = pos;
|
||||
currentLocation = location;
|
||||
|
||||
// 选子完成,进入落子状态
|
||||
context.action = ACTION_PLACE;
|
||||
|
@ -746,7 +747,7 @@ bool MillGame::choose(int pos)
|
|||
|
||||
bool MillGame::choose(int r, int s)
|
||||
{
|
||||
return choose(context.board.rs2Pos(r, s));
|
||||
return choose(context.board.polarToLocation(r, s));
|
||||
}
|
||||
|
||||
bool MillGame::giveup(Player loser)
|
||||
|
@ -1044,14 +1045,14 @@ bool MillGame::win(bool forceDraw)
|
|||
// 计算玩家1和玩家2的棋子活动能力之差
|
||||
int MillGame::getMobilityDiff(enum Player turn, const Rule &rule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, bool includeFobidden)
|
||||
{
|
||||
int *board = context.board.board_;
|
||||
int *board = context.board.locations;
|
||||
int mobility1 = 0;
|
||||
int mobility2 = 0;
|
||||
int diff = 0;
|
||||
int n = 0;
|
||||
|
||||
for (int i = Board::POS_BEGIN; i < Board::POS_END; i++) {
|
||||
n = context.board.getSurroundedEmptyPosCount(turn, rule, nPiecesOnBoard_1, nPiecesOnBoard_2, i, includeFobidden);
|
||||
for (int i = Board::LOCATION_BEGIN; i < Board::LOCATION_END; i++) {
|
||||
n = context.board.getSurroundedEmptyLocationCount(turn, rule, nPiecesOnBoard_1, nPiecesOnBoard_2, i, includeFobidden);
|
||||
|
||||
if (board[i] & 0x10) {
|
||||
mobility1 += n;
|
||||
|
@ -1067,15 +1068,15 @@ int MillGame::getMobilityDiff(enum Player turn, const Rule &rule, int nPiecesOnB
|
|||
|
||||
void MillGame::cleanForbiddenPoints()
|
||||
{
|
||||
int pos = 0;
|
||||
int location = 0;
|
||||
|
||||
for (int r = 1; r <= Board::N_RINGS; r++) {
|
||||
for (int s = 0; s < Board::N_SEATS; s++) {
|
||||
pos = r * Board::N_SEATS + s;
|
||||
location = r * Board::N_SEATS + s;
|
||||
|
||||
if (board_[pos] == '\x0f') {
|
||||
revertHash(pos);
|
||||
board_[pos] = '\x00';
|
||||
if (board_[location] == '\x0f') {
|
||||
revertHash(location);
|
||||
board_[location] = '\x00';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1178,7 +1179,7 @@ void MillGame::constructHash()
|
|||
context.hash = 0;
|
||||
|
||||
#include "zobrist.h"
|
||||
memcpy(context.zobrist, zobrist0, sizeof(hash_t) * Board::N_POINTS * POINT_TYPE_COUNT);
|
||||
memcpy(context.zobrist, zobrist0, sizeof(hash_t) * Board::N_LOCATIONS * POINT_TYPE_COUNT);
|
||||
}
|
||||
|
||||
hash_t MillGame::getHash()
|
||||
|
@ -1189,22 +1190,22 @@ hash_t MillGame::getHash()
|
|||
return context.hash;
|
||||
}
|
||||
|
||||
hash_t MillGame::updateHash(int pos)
|
||||
hash_t MillGame::updateHash(int location)
|
||||
{
|
||||
// PieceType is board_[pos]
|
||||
// PieceType is board_[location]
|
||||
|
||||
// 0b00 表示空白,0b01 = 1 表示先手棋子,0b10 = 2 表示后手棋子,0b11 = 3 表示禁点
|
||||
int pointType = (board_[pos] & 0x30) >> 4;
|
||||
int pointType = (board_[location] & 0x30) >> 4;
|
||||
|
||||
// 清除或者放置棋子
|
||||
context.hash ^= context.zobrist[pos][pointType];
|
||||
context.hash ^= context.zobrist[location][pointType];
|
||||
|
||||
return context.hash;
|
||||
}
|
||||
|
||||
hash_t MillGame::revertHash(int pos)
|
||||
hash_t MillGame::revertHash(int location)
|
||||
{
|
||||
return updateHash(pos);
|
||||
return updateHash(location);
|
||||
}
|
||||
|
||||
hash_t MillGame::updateHashMisc()
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
hash_t hash{};
|
||||
|
||||
// Zobrist 数组
|
||||
hash_t zobrist[Board::N_POINTS][POINT_TYPE_COUNT]{};
|
||||
hash_t zobrist[Board::N_LOCATIONS][POINT_TYPE_COUNT]{};
|
||||
|
||||
// 局面阶段标识
|
||||
enum GameStage stage;
|
||||
|
@ -148,19 +148,19 @@ public:
|
|||
// 获取棋盘数据
|
||||
const int *getBoard() const
|
||||
{
|
||||
return context.board.board_;
|
||||
return context.board.locations;
|
||||
}
|
||||
|
||||
// 获取当前棋子位置点
|
||||
int getCurrentPos() const
|
||||
int getCurrentLocation() const
|
||||
{
|
||||
return currentPos;
|
||||
return currentLocation;
|
||||
}
|
||||
|
||||
// 判断位置点是否为星位 (星位是经常会先占的位置)
|
||||
static bool isStarPoint(int pos)
|
||||
static bool isStarPoint(int location)
|
||||
{
|
||||
return (pos == 17 || pos == 19 || pos == 21 || pos == 23);
|
||||
return (location == 17 || location == 19 || location == 21 || location == 23);
|
||||
}
|
||||
|
||||
// 获取当前步数
|
||||
|
@ -316,14 +316,14 @@ public:
|
|||
|
||||
// 下面几个函数没有算法无关判断和无关操作,节约算法时间
|
||||
bool command(int move);
|
||||
bool choose(int pos);
|
||||
bool place(int pos, int time_p = -1, int8_t cp = 0);
|
||||
bool capture(int pos, int time_p = -1, int8_t cp = 0);
|
||||
bool choose(int location);
|
||||
bool place(int location, int time_p = -1, int8_t cp = 0);
|
||||
bool capture(int location, int time_p = -1, int8_t cp = 0);
|
||||
|
||||
// hash 相关
|
||||
hash_t getHash();
|
||||
hash_t revertHash(int pos);
|
||||
hash_t updateHash(int pos);
|
||||
hash_t revertHash(int location);
|
||||
hash_t updateHash(int location);
|
||||
hash_t updateHashMisc();
|
||||
|
||||
public: /* TODO: move to private */
|
||||
|
@ -347,7 +347,7 @@ public: /* TODO: move to private */
|
|||
/*
|
||||
当前着法,AI会用到,如下表示
|
||||
0x 00 00
|
||||
pos1 pos2
|
||||
location1 location2
|
||||
开局落子:0x00??,??为棋盘上的位置
|
||||
移子:0x__??,__为移动前的位置,??为移动后的位置
|
||||
去子:0xFF??,??取位置补码,即为负数
|
||||
|
@ -367,7 +367,7 @@ public: /* TODO: move to private */
|
|||
int32_t move_{};
|
||||
|
||||
// 选中的棋子在board中的位置
|
||||
int currentPos{};
|
||||
int currentLocation{};
|
||||
|
||||
private:
|
||||
// 棋局哈希值
|
||||
|
|
|
@ -398,8 +398,8 @@ void GameController::flip()
|
|||
ai2.wait();
|
||||
}
|
||||
|
||||
game_.context.board.mirror(game_.cmdlist, game_.cmdline, game_.move_, game_.currentRule, game_.currentPos);
|
||||
game_.context.board.rotate(180, game_.cmdlist, game_.cmdline, game_.move_, game_.currentRule, game_.currentPos);
|
||||
game_.context.board.mirror(game_.cmdlist, game_.cmdline, game_.move_, game_.currentRule, game_.currentLocation);
|
||||
game_.context.board.rotate(180, game_.cmdlist, game_.cmdline, game_.move_, game_.currentRule, game_.currentLocation);
|
||||
gameTemp = game_;
|
||||
|
||||
// 更新棋谱
|
||||
|
@ -438,7 +438,7 @@ void GameController::mirror()
|
|||
ai2.wait();
|
||||
}
|
||||
|
||||
game_.context.board.mirror(game_.cmdlist, game_.cmdline, game_.move_, game_.currentRule, game_.currentPos);
|
||||
game_.context.board.mirror(game_.cmdlist, game_.cmdline, game_.move_, game_.currentRule, game_.currentLocation);
|
||||
gameTemp = game_;
|
||||
|
||||
// 更新棋谱
|
||||
|
@ -480,7 +480,7 @@ void GameController::turnRight()
|
|||
ai2.wait();
|
||||
}
|
||||
|
||||
game_.context.board.rotate(-90, game_.cmdlist, game_.cmdline, game_.move_, game_.currentRule, game_.currentPos);
|
||||
game_.context.board.rotate(-90, game_.cmdlist, game_.cmdline, game_.move_, game_.currentRule, game_.currentLocation);
|
||||
gameTemp = game_;
|
||||
|
||||
// 更新棋谱
|
||||
|
@ -520,7 +520,7 @@ void GameController::turnLeft()
|
|||
ai2.wait();
|
||||
}
|
||||
|
||||
game_.context.board.rotate(90, game_.cmdlist, game_.cmdline, game_.move_, game_.currentRule, game_.currentPos);
|
||||
game_.context.board.rotate(90, game_.cmdlist, game_.cmdline, game_.move_, game_.currentRule, game_.currentLocation);
|
||||
gameTemp = game_;
|
||||
|
||||
// 更新棋谱
|
||||
|
@ -1004,7 +1004,7 @@ bool GameController::updateScence(MillGame &game)
|
|||
int j;
|
||||
|
||||
// 遍历棋盘,查找并放置棋盘上的棋子
|
||||
for (j = Board::POS_BEGIN; j < Board::POS_END; j++) {
|
||||
for (j = Board::LOCATION_BEGIN; j < Board::LOCATION_END; j++) {
|
||||
if (board[j] == key) {
|
||||
pos = scene.rs2pos(j / Board::N_SEATS, j % Board::N_SEATS + 1);
|
||||
if (piece->pos() != pos) {
|
||||
|
@ -1062,7 +1062,7 @@ bool GameController::updateScence(MillGame &game)
|
|||
|
||||
// 添加摆棋阶段禁子点
|
||||
if (game.getRule()->hasForbiddenPoint && game.getStage() == GAME_PLACING) {
|
||||
for (int j = Board::POS_BEGIN; j < Board::POS_END; j++) {
|
||||
for (int j = Board::LOCATION_BEGIN; j < Board::LOCATION_END; j++) {
|
||||
if (board[j] == 0x0F) {
|
||||
pos = scene.rs2pos(j / Board::N_SEATS, j % Board::N_SEATS + 1);
|
||||
if (nTotalPieces < pieceList.size()) {
|
||||
|
@ -1088,9 +1088,9 @@ bool GameController::updateScence(MillGame &game)
|
|||
}
|
||||
|
||||
// 选中当前棋子
|
||||
int ipos = game.getCurrentPos();
|
||||
int ipos = game.getCurrentLocation();
|
||||
if (ipos) {
|
||||
key = board[game.getCurrentPos()];
|
||||
key = board[game.getCurrentLocation()];
|
||||
ipos = key & 0x10 ? (key - 0x11) * 2 : (key - 0x21) * 2 + 1;
|
||||
if (ipos >= 0 && ipos < nTotalPieces) {
|
||||
currentPiece = pieceList.at(ipos);
|
||||
|
|
Loading…
Reference in New Issue