refactor: 将 positon 重命名为 location

因为术语中 position 是 "局面" 的意思, location 才是表示棋盘上的位置.
This commit is contained in:
CalciteM 2019-09-10 00:50:10 +08:00
parent d2c18f2fed
commit 30b37bc4fa
9 changed files with 237 additions and 235 deletions

View File

@ -28,7 +28,7 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, MillGame &gameTemp,
move_t bestMove) move_t bestMove)
{ {
const int MOVE_PRIORITY_TABLE_SIZE = Board::N_RINGS * Board::N_SEATS; const int MOVE_PRIORITY_TABLE_SIZE = Board::N_RINGS * Board::N_SEATS;
int pos = 0; int location = 0;
size_t newCapacity = 24; size_t newCapacity = 24;
// 留足余量空间避免多次重新分配,此动作本身也占用 CPU/内存 开销 // 留足余量空间避免多次重新分配,此动作本身也占用 CPU/内存 开销
@ -79,18 +79,18 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, MillGame &gameTemp,
// 对于摆子阶段 // 对于摆子阶段
if (gameTemp.context.stage & (GAME_PLACING | GAME_NOTSTARTED)) { if (gameTemp.context.stage & (GAME_PLACING | GAME_NOTSTARTED)) {
for (int i : movePriorityTable) { for (int i : movePriorityTable) {
pos = i; location = i;
if (gameTemp.board_[pos]) { if (gameTemp.board_[location]) {
continue; continue;
} }
if (gameTemp.context.stage != GAME_NOTSTARTED || node != rootNode) { 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 { } else {
// 若为先手,则抢占星位 // 若为先手,则抢占星位
if (MillGame::isStarPoint(pos)) { if (MillGame::isStarPoint(location)) {
ai_ab.addNode(node, MillGameAi_ab::INF_VALUE, pos, bestMove, gameTemp.context.turn); 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) { if (gameTemp.context.stage & GAME_MOVING) {
int newPos, oldPos; int newLocation, oldLocation;
// 尽量走理论上较差的位置的棋子 // 尽量走理论上较差的位置的棋子
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) { 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; continue;
} }
@ -116,17 +116,17 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, MillGame &gameTemp,
// 对于棋盘上还有3个子以上或不允许飞子的情况要求必须在着法表中 // 对于棋盘上还有3个子以上或不允许飞子的情况要求必须在着法表中
for (int moveDirection = MOVE_DIRECTION_CLOCKWISE; moveDirection <= MOVE_DIRECTION_OUTWARD; moveDirection++) { for (int moveDirection = MOVE_DIRECTION_CLOCKWISE; moveDirection <= MOVE_DIRECTION_OUTWARD; moveDirection++) {
// 对于原有位置,遍历四个方向的着法,如果棋盘上为空位就加到结点列表中 // 对于原有位置,遍历四个方向的着法,如果棋盘上为空位就加到结点列表中
newPos = moveTable[oldPos][moveDirection]; newLocation = moveTable[oldLocation][moveDirection];
if (newPos && !gameTemp.board_[newPos]) { if (newLocation && !gameTemp.board_[newLocation]) {
int move = (oldPos << 8) + newPos; int move = (oldLocation << 8) + newLocation;
ai_ab.addNode(node, 0, move, bestMove, gameTemp.context.turn); // (12%) ai_ab.addNode(node, 0, move, bestMove, gameTemp.context.turn); // (12%)
} }
} }
} else { } else {
// 对于棋盘上还有不到3个字但允许飞子的情况不要求在着法表中是空位就行 // 对于棋盘上还有不到3个字但允许飞子的情况不要求在着法表中是空位就行
for (newPos = Board::POS_BEGIN; newPos < Board::POS_END; newPos++) { for (newLocation = Board::LOCATION_BEGIN; newLocation < Board::LOCATION_END; newLocation++) {
if (!gameTemp.board_[newPos]) { if (!gameTemp.board_[newLocation]) {
int move = (oldPos << 8) + newPos; int move = (oldLocation << 8) + newLocation;
ai_ab.addNode(node, 0, move, bestMove, gameTemp.context.turn); 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)) { if (gameTemp.context.board.isAllInMills(opponent)) {
// 全成三的情况 // 全成三的情况
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) { for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
pos = movePriorityTable[i]; location = movePriorityTable[i];
if (gameTemp.board_[pos] & opponent) { if (gameTemp.board_[location] & opponent) {
ai_ab.addNode(node, 0, -pos, bestMove, gameTemp.context.turn); ai_ab.addNode(node, 0, -location, bestMove, gameTemp.context.turn);
} }
} }
break; 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--) { for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
pos = movePriorityTable[i]; location = movePriorityTable[i];
if (gameTemp.board_[pos] & opponent) { if (gameTemp.board_[location] & opponent) {
if (gameTemp.getRule()->allowRemoveMill || !gameTemp.context.board.isInMills(pos)) { if (gameTemp.getRule()->allowRemoveMill || !gameTemp.context.board.inHowManyMills(location)) {
ai_ab.addNode(node, 0, -pos, bestMove, gameTemp.context.turn); 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) void MoveList::createMoveTable(MillGame &game)
{ {
#if 1 #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}, /* 0 */ {0, 0, 0, 0},
/* 1 */ {0, 0, 0, 0}, /* 1 */ {0, 0, 0, 0},
/* 2 */ {0, 0, 0, 0}, /* 2 */ {0, 0, 0, 0},
@ -214,7 +214,7 @@ void MoveList::createMoveTable(MillGame &game)
/* 39 */ {0, 0, 0, 0}, /* 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}, /* 0 */ {0, 0, 0, 0},
/* 1 */ {0, 0, 0, 0}, /* 1 */ {0, 0, 0, 0},
/* 2 */ {0, 0, 0, 0}, /* 2 */ {0, 0, 0, 0},
@ -261,7 +261,7 @@ void MoveList::createMoveTable(MillGame &game)
/* 39 */ {0, 0, 0, 0}, /* 39 */ {0, 0, 0, 0},
}; };
#else #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}, {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} {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}, /* 0 */ {0, 0, 0, 0},
/* 1 */ {0, 0, 0, 0}, /* 1 */ {0, 0, 0, 0},
/* 2 */ {0, 0, 0, 0}, /* 2 */ {0, 0, 0, 0},
@ -364,7 +364,7 @@ void MoveList::createMoveTable(MillGame &game)
#ifdef DEBUG_MODE #ifdef DEBUG_MODE
int sum = 0; int sum = 0;
for (int i = 0; i < Board::N_POINTS; i++) { for (int i = 0; i < Board::N_LOCATIONS; i++) {
loggerDebug("/* %d */ {", i); loggerDebug("/* %d */ {", i);
for (int j = 0; j < N_MOVE_DIRECTIONS; j++) { for (int j = 0; j < N_MOVE_DIRECTIONS; j++) {
if (j == N_MOVE_DIRECTIONS - 1) if (j == N_MOVE_DIRECTIONS - 1)

View File

@ -45,7 +45,7 @@ public:
static void shuffleMovePriorityTable(MillGame &game); static void shuffleMovePriorityTable(MillGame &game);
// 着法表 // TODO: Move to private // 着法表 // 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: private:
// 着法顺序表, 后续会被打乱 // 着法顺序表, 后续会被打乱

View File

@ -39,7 +39,7 @@ HashMap<hash_t, MillGameAi_ab::HashValue> bookHashMap(bookHashsize);
vector<hash_t> openingBook; vector<hash_t> openingBook;
#endif // BOOK_LEARNING #endif // BOOK_LEARNING
// 用于检测重复局面 // 用于检测重复局面 (Position)
vector<hash_t> positions; vector<hash_t> positions;
MillGameAi_ab::MillGameAi_ab() MillGameAi_ab::MillGameAi_ab()
@ -156,15 +156,15 @@ struct MillGameAi_ab::Node *MillGameAi_ab::addNode(
char cmd[32] = { 0 }; char cmd[32] = { 0 };
if (move < 0) { if (move < 0) {
gameTemp.context.board.pos2rs(-move, r, s); gameTemp.context.board.locationToPolar(-move, r, s);
sprintf(cmd, "-(%1u,%1u)", r, s); sprintf(cmd, "-(%1u,%1u)", r, s);
} else if (move & 0x7f00) { } else if (move & 0x7f00) {
int r1, s1; int r1, s1;
gameTemp.context.board.pos2rs(move >> 8, r1, s1); gameTemp.context.board.locationToPolar(move >> 8, r1, s1);
gameTemp.context.board.pos2rs(move & 0x00ff, r, s); gameTemp.context.board.locationToPolar(move & 0x00ff, r, s);
sprintf(cmd, "(%1u,%1u)->(%1u,%1u)", r1, s1, r, s); sprintf(cmd, "(%1u,%1u)->(%1u,%1u)", r1, s1, r, s);
} else { } else {
gameTemp.context.board.pos2rs(move & 0x007f, r, s); gameTemp.context.board.locationToPolar(move & 0x007f, r, s);
sprintf(cmd, "(%1u,%1u)", r, s); sprintf(cmd, "(%1u,%1u)", r, s);
} }
@ -747,15 +747,15 @@ const char *MillGameAi_ab::move2string(move_t move)
int r, s; int r, s;
if (move < 0) { if (move < 0) {
gameTemp.context.board.pos2rs(-move, r, s); gameTemp.context.board.locationToPolar(-move, r, s);
sprintf(cmdline, "-(%1u,%1u)", r, s); sprintf(cmdline, "-(%1u,%1u)", r, s);
} else if (move & 0x7f00) { } else if (move & 0x7f00) {
int r1, s1; int r1, s1;
gameTemp.context.board.pos2rs(move >> 8, r1, s1); gameTemp.context.board.locationToPolar(move >> 8, r1, s1);
gameTemp.context.board.pos2rs(move & 0x00ff, r, s); gameTemp.context.board.locationToPolar(move & 0x00ff, r, s);
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u)", r1, s1, r, s); sprintf(cmdline, "(%1u,%1u)->(%1u,%1u)", r1, s1, r, s);
} else { } else {
gameTemp.context.board.pos2rs(move & 0x007f, r, s); gameTemp.context.board.locationToPolar(move & 0x007f, r, s);
sprintf(cmdline, "(%1u,%1u)", r, s); sprintf(cmdline, "(%1u,%1u)", r, s);
} }

View File

@ -22,7 +22,7 @@
#include "millgame.h" #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 #ifdef TRANSPOSITION_TABLE_CUTDOWN
{0x4E421A00, 0x3962FF00, 0x6DB6EE00, 0x219AE100}, {0x4E421A00, 0x3962FF00, 0x6DB6EE00, 0x219AE100},
{0x1F3DE200, 0xD9AACB00, 0xD5173300, 0xD3F9EA00}, {0x1F3DE200, 0xD9AACB00, 0xD5173300, 0xD3F9EA00},

View File

@ -23,7 +23,7 @@
#include "movegen.h" #include "movegen.h"
// 名义上是个数组,实际上相当于一个判断是否在棋盘上的函数 // 名义上是个数组,实际上相当于一个判断是否在棋盘上的函数
const int Board::onBoard[N_POINTS] = { const int Board::onBoard[N_LOCATIONS] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
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() Board::Board()
{ {
@ -50,7 +50,7 @@ Board &Board::operator= (const Board &other)
if (this == &other) if (this == &other)
return *this; return *this;
memcpy(this->board_, other.board_, sizeof(this->board_)); memcpy(this->locations, other.locations, sizeof(this->locations));
if (!millList.empty()) { if (!millList.empty()) {
millList.clear(); millList.clear();
@ -67,7 +67,7 @@ Board &Board::operator= (const Board &other)
void Board::createMillTable(const Rule &currentRule) void Board::createMillTable(const Rule &currentRule)
{ {
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}}, /* 0 */ {{0, 0}, {0, 0}, {0, 0}},
/* 1 */ {{0, 0}, {0, 0}, {0, 0}}, /* 1 */ {{0, 0}, {0, 0}, {0, 0}},
/* 2 */ {{0, 0}, {0, 0}, {0, 0}}, /* 2 */ {{0, 0}, {0, 0}, {0, 0}},
@ -114,7 +114,7 @@ void Board::createMillTable(const Rule &currentRule)
/* 39 */ {{0, 0}, {0, 0}, {0, 0}} /* 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}}, /* 0 */ {{0, 0}, {0, 0}, {0, 0}},
/* 1 */ {{0, 0}, {0, 0}, {0, 0}}, /* 1 */ {{0, 0}, {0, 0}, {0, 0}},
/* 2 */ {{0, 0}, {0, 0}, {0, 0}}, /* 2 */ {{0, 0}, {0, 0}, {0, 0}},
@ -168,7 +168,7 @@ void Board::createMillTable(const Rule &currentRule)
} }
#ifdef DEBUG_MODE #ifdef DEBUG_MODE
for (int i = 0; i < N_POINTS; i++) { for (int i = 0; i < N_LOCATIONS; i++) {
loggerDebug("/* %d */ {", i); loggerDebug("/* %d */ {", i);
for (int j = 0; j < N_DIRECTIONS; j++) { for (int j = 0; j < N_DIRECTIONS; j++) {
loggerDebug("{"); loggerDebug("{");
@ -192,57 +192,58 @@ void Board::createMillTable(const Rule &currentRule)
#endif /* DEBUG_MODE */ #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; //r = location / N_SEATS;
//s = pos % N_SEATS + 1; //s = location % N_SEATS + 1;
r = pos >> 3; r = location >> 3;
s = (pos & 0x07) + 1; 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 0;
}
return r * N_SEATS + s - 1; return r * N_SEATS + s - 1;
} }
int Board::isInMills(int pos, bool test) int Board::inHowManyMills(int location)
{ {
int n = 0; int n = 0;
int pos1, pos2; int location1, location2;
int m = test ? INT32_MAX : board_[pos] & '\x30';
for (int i = 0; i < 3; i++) { for (int d = 0; d < N_DIRECTIONS; d++) {
pos1 = millTable[pos][i][0]; location1 = millTable[location][d][0];
pos2 = millTable[pos][i][1]; location2 = millTable[location][d][1];
if (m & board_[pos1] & board_[pos2]) if ((locations[location] & 0x30) & locations[location1] & locations[location2]) {
n++; n++;
}
} }
return n; return n;
} }
int Board::addMills(const Rule &currentRule, int pos) int Board::addMills(const Rule &currentRule, int location)
{ {
// 成三用一个64位整数了规则如下 // 成三用一个64位整数了规则如下
// 0x 00 00 00 00 00 00 00 00 // 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按照序号从小到大顺序排放 // piece1、piece2、piece3按照序号从小到大顺序排放
uint64_t mill = 0; uint64_t mill = 0;
int n = 0; int n = 0;
int p[3], min, temp; int p[3], min, temp;
char m = board_[pos] & '\x30'; char m = locations[location] & '\x30';
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
p[0] = pos; p[0] = location;
p[1] = millTable[pos][i][0]; p[1] = millTable[location][i][0];
p[2] = millTable[pos][i][1]; p[2] = millTable[location][i][1];
// 如果没有成三 // 如果没有成三
if (!(m & board_[p[1]] & board_[p[2]])) { if (!(m & locations[p[1]] & locations[p[2]])) {
continue; continue;
} }
@ -267,11 +268,11 @@ int Board::addMills(const Rule &currentRule, 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>(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>(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]); + static_cast<uint64_t>(p[2]);
// 如果允许相同三连反复去子 // 如果允许相同三连反复去子
@ -303,9 +304,9 @@ int Board::addMills(const Rule &currentRule, int pos)
bool Board::isAllInMills(char ch) bool Board::isAllInMills(char ch)
{ {
for (int i = POS_BEGIN; i < POS_END; i++) { for (int i = LOCATION_BEGIN; i < LOCATION_END; i++) {
if (board_[i] & ch) { if (locations[i] & ch) {
if (!isInMills(i)) { if (!inHowManyMills(i)) {
return false; return false;
} }
} }
@ -329,7 +330,7 @@ bool Board::isAllInMills(enum Player player)
} }
// 判断玩家的棋子周围有几个空位 // 判断玩家的棋子周围有几个空位
int Board::getSurroundedEmptyPosCount(enum Player turn, const Rule &currentRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int pos, bool includeFobidden) int Board::getSurroundedEmptyLocationCount(enum Player turn, const Rule &currentRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int location, bool includeFobidden)
{ {
int count = 0; int count = 0;
@ -337,12 +338,12 @@ int Board::getSurroundedEmptyPosCount(enum Player turn, const Rule &currentRule,
(nPiecesOnBoard_1 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces)) || (nPiecesOnBoard_1 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces)) ||
(turn == PLAYER2 && (turn == PLAYER2 &&
(nPiecesOnBoard_2 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces))) { (nPiecesOnBoard_2 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces))) {
int d, movePos; int d, moveLocation;
for (d = 0; d < N_MOVE_DIRECTIONS; d++) { for (d = 0; d < N_MOVE_DIRECTIONS; d++) {
movePos = MoveList::moveTable[pos][d]; moveLocation = MoveList::moveTable[location][d];
if (movePos) { if (moveLocation) {
if (board_[movePos] == 0x00 || if (locations[moveLocation] == 0x00 ||
(includeFobidden && board_[movePos] == 0x0F)) { (includeFobidden && locations[moveLocation] == 0x0F)) {
count++; count++;
} }
} }
@ -353,17 +354,17 @@ int Board::getSurroundedEmptyPosCount(enum Player turn, const Rule &currentRule,
} }
// 判断玩家的棋子是否被围 // 判断玩家的棋子是否被围
bool Board::isSurrounded(enum Player turn, const Rule &currentRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int pos) bool Board::isSurrounded(enum Player turn, const Rule &currentRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int location)
{ {
// 判断pos处的棋子是否被“闷” // 判断location处的棋子是否被“闷”
if ((turn == PLAYER1 && if ((turn == PLAYER1 &&
(nPiecesOnBoard_1 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces)) || (nPiecesOnBoard_1 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces)) ||
(turn == PLAYER2 && (turn == PLAYER2 &&
(nPiecesOnBoard_2 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces))) { (nPiecesOnBoard_2 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces))) {
int i, movePos; int i, moveLocation;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
movePos = MoveList::moveTable[pos][i]; moveLocation = MoveList::moveTable[location][i];
if (movePos && !board_[movePos]) if (moveLocation && !locations[moveLocation])
break; break;
} }
// 被围住 // 被围住
@ -389,15 +390,15 @@ bool Board::isAllSurrounded(enum Player turn, const Rule &currentRule, int nPiec
} }
// 查询整个棋盘 // 查询整个棋盘
int movePos; int moveLocation;
for (int i = 1; i < N_SEATS * (N_RINGS + 1); i++) { for (int i = 1; i < N_SEATS * (N_RINGS + 1); i++) {
if (!(ch & board_[i])) { if (!(ch & locations[i])) {
continue; continue;
} }
for (int d = 0; d < N_MOVE_DIRECTIONS; d++) { for (int d = 0; d < N_MOVE_DIRECTIONS; d++) {
movePos = MoveList::moveTable[i][d]; moveLocation = MoveList::moveTable[i][d];
if (movePos && !board_[movePos]) if (moveLocation && !locations[moveLocation])
return false; return false;
} }
} }
@ -420,12 +421,12 @@ bool Board::isAllSurrounded(enum Player turn, const Rule &currentRule, int nPiec
enum Player Board::getWhosPiece(int r, int s) 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; return PLAYER1;
if (board_[pos] & '\x20') if (locations[location] & '\x20')
return PLAYER2; return PLAYER2;
return PLAYER_NOBODY; return PLAYER_NOBODY;
@ -449,9 +450,9 @@ bool Board::getPieceRS(const Player &player, const int &number, int &r, int &s,
else else
return false; return false;
for (int i = POS_BEGIN; i < POS_END; i++) { for (int i = LOCATION_BEGIN; i < LOCATION_END; i++) {
if (board_[i] == piece) { if (locations[i] == piece) {
pos2rs(i, r, s); locationToPolar(i, r, s);
return true; 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; return false;
int p = board_[currentPos]; int p = locations[location];
if (p & 0x10) { if (p & 0x10) {
player = PLAYER1; player = PLAYER1;
@ -480,7 +481,7 @@ bool Board::getCurrentPiece(Player &player, int &number, int currentPos)
return true; return true;
} }
void Board::mirror(list <string> &cmdlist, char* cmdline, int32_t move_, struct Rule &currentRule, int currentPos, bool cmdChange /*= true*/) void Board::mirror(list <string> &cmdlist, char* cmdline, int32_t move_, struct Rule &currentRule, int location, bool cmdChange /*= true*/)
{ {
int ch; int ch;
int r, s; 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 (r = 1; r <= N_RINGS; r++) {
for (s = 1; s < N_SEATS / 2; s++) { for (s = 1; s < N_SEATS / 2; s++) {
ch = board_[r * N_SEATS + s]; ch = locations[r * N_SEATS + s];
board_[r * N_SEATS + s] = board_[(r + 1) * N_SEATS - s]; locations[r * N_SEATS + s] = locations[(r + 1) * N_SEATS - s];
//updateHash(i * N_SEATS + j); //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); //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])); move_ = static_cast<int16_t>(((llp[0] << 8) | llp[1]));
} }
if (currentPos != 0) { if (location != 0) {
r = currentPos / N_SEATS; r = location / N_SEATS;
s = currentPos % N_SEATS; s = location % N_SEATS;
s = (N_SEATS - s) % N_SEATS; s = (N_SEATS - s) % N_SEATS;
currentPos = r * N_SEATS + s; location = r * N_SEATS + s;
} }
if (currentRule.allowRemovePiecesRepeatedly) { 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 &currentRule, int currentPos, bool cmdChange /*= true*/) void Board::turn(list <string> &cmdlist, char *cmdline, int32_t move_, const Rule &currentRule, int location, bool cmdChange /*= true*/)
{ {
int ch; int ch;
int r, s; int r, s;
int i; int i;
for (s = 0; s < N_SEATS; s++) { for (s = 0; s < N_SEATS; s++) {
ch = board_[N_SEATS + s]; ch = locations[N_SEATS + s];
board_[N_SEATS + s] = board_[N_SEATS * N_RINGS + s]; locations[N_SEATS + s] = locations[N_SEATS * N_RINGS + s];
//updateHash(N_SEATS + 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); //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])); move_ = static_cast<int16_t>(((llp[0] << 8) | llp[1]));
} }
if (currentPos != 0) { if (location != 0) {
r = currentPos / N_SEATS; r = location / N_SEATS;
s = currentPos % N_SEATS; s = location % N_SEATS;
if (r == 1) if (r == 1)
r = N_RINGS; r = N_RINGS;
else if (r == N_RINGS) else if (r == N_RINGS)
r = 1; r = 1;
currentPos = r * N_SEATS + s; location = r * N_SEATS + s;
} }
if (currentRule.allowRemovePiecesRepeatedly) { 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 &currentRule, int currentPos, bool cmdChange /*= true*/) void Board::rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t move_, const Rule &currentRule, int location, bool cmdChange /*= true*/)
{ {
// 将degrees转化为0~359之间的数 // 将degrees转化为0~359之间的数
degrees = degrees % 360; degrees = degrees % 360;
@ -776,40 +777,40 @@ void Board::rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t m
if (degrees == 2) { if (degrees == 2) {
for (r = 1; r <= N_RINGS; r++) { for (r = 1; r <= N_RINGS; r++) {
ch1 = board_[r * N_SEATS]; ch1 = locations[r * N_SEATS];
ch2 = board_[r * N_SEATS + 1]; ch2 = locations[r * N_SEATS + 1];
for (s = 0; s < N_SEATS - 2; s++) { 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); //updateHash(i * N_SEATS + 6);
board_[r * N_SEATS + 7] = ch2; locations[r * N_SEATS + 7] = ch2;
//updateHash(i * N_SEATS + 7); //updateHash(i * N_SEATS + 7);
} }
} else if (degrees == 6) { } else if (degrees == 6) {
for (r = 1; r <= N_RINGS; r++) { for (r = 1; r <= N_RINGS; r++) {
ch1 = board_[r * N_SEATS + 7]; ch1 = locations[r * N_SEATS + 7];
ch2 = board_[r * N_SEATS + 6]; ch2 = locations[r * N_SEATS + 6];
for (s = N_SEATS - 1; s >= 2; s--) { 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); //updateHash(i * N_SEATS + j);
} }
board_[r * N_SEATS + 1] = ch1; locations[r * N_SEATS + 1] = ch1;
//updateHash(i * N_SEATS + 1); //updateHash(i * N_SEATS + 1);
board_[r * N_SEATS] = ch2; locations[r * N_SEATS] = ch2;
//updateHash(i * N_SEATS); //updateHash(i * N_SEATS);
} }
} else if (degrees == 4) { } else if (degrees == 4) {
for (r = 1; r <= N_RINGS; r++) { for (r = 1; r <= N_RINGS; r++) {
for (s = 0; s < N_SEATS / 2; s++) { for (s = 0; s < N_SEATS / 2; s++) {
ch1 = board_[r * N_SEATS + s]; ch1 = locations[r * N_SEATS + s];
board_[r * N_SEATS + s] = board_[r * N_SEATS + s + 4]; locations[r * N_SEATS + s] = locations[r * N_SEATS + s + 4];
//updateHash(i * N_SEATS + j); //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); //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])); move_ = static_cast<int16_t>(((llp[0] << 8) | llp[1]));
} }
if (currentPos != 0) { if (location != 0) {
r = currentPos / N_SEATS; r = location / N_SEATS;
s = currentPos % N_SEATS; s = location % N_SEATS;
s = (s + N_SEATS - degrees) % N_SEATS; s = (s + N_SEATS - degrees) % N_SEATS;
currentPos = r * N_SEATS + s; location = r * N_SEATS + s;
} }
if (currentRule.allowRemovePiecesRepeatedly) { if (currentRule.allowRemovePiecesRepeatedly) {

View File

@ -49,18 +49,18 @@ public:
static const int N_DIRECTIONS = 3; static const int N_DIRECTIONS = 3;
// 棋盘点的个数40 // 棋盘点的个数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) // 遍历棋盘点所用的起始位置,即 [8, 32)
static const int POS_BEGIN = N_SEATS; static const int LOCATION_BEGIN = N_SEATS;
static const int POS_END = ((N_RINGS + 1) * 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 &currentRule); void createMillTable(const Rule &currentRule);
@ -74,18 +74,18 @@ public:
// 局面逆时针旋转 // 局面逆时针旋转
void rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t move_, const Rule &currentRule, int currentPos, bool cmdChange = true); void rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t move_, const Rule &currentRule, int currentPos, bool cmdChange = true);
// 判断棋盘pos处的棋子处于几个“三连”中 // 判断棋盘location处的棋子处于几个“三连”中
int isInMills(int pos, bool test = false); int inHowManyMills(int location);
// 判断玩家的所有棋子是否都处于“三连”状态 // 判断玩家的所有棋子是否都处于“三连”状态
bool isAllInMills(char ch); bool isAllInMills(char ch);
bool isAllInMills(enum Player); bool isAllInMills(enum Player);
// 判断玩家的棋子周围有几个空位 // 判断玩家的棋子周围有几个空位
int getSurroundedEmptyPosCount(enum Player turn, const Rule &currentRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int pos, bool includeFobidden); int getSurroundedEmptyLocationCount(enum Player turn, const Rule &currentRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int location, bool includeFobidden);
// 判断玩家的棋子是否被围 // 判断玩家的棋子是否被围
bool isSurrounded(enum Player turn, const Rule &currentRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int pos); bool isSurrounded(enum Player turn, const Rule &currentRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, int location);
// 判断玩家的棋子是否全部被围 // 判断玩家的棋子是否全部被围
bool isAllSurrounded(enum Player turn, const Rule &currentRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, char ch); bool isAllSurrounded(enum Player turn, const Rule &currentRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, char ch);
@ -93,7 +93,7 @@ public:
bool isAllSurrounded(enum Player turn, const Rule &currentRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, enum Player ply); bool isAllSurrounded(enum Player turn, const Rule &currentRule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, enum Player ply);
// 三连加入列表 // 三连加入列表
int addMills(const Rule &currentRule, int pos); int addMills(const Rule &currentRule, int location);
// 获取位置点棋子的归属人 // 获取位置点棋子的归属人
enum Player getWhosPiece(int r, int s); enum Player getWhosPiece(int r, int s);
@ -104,10 +104,10 @@ public:
bool getCurrentPiece(Player &player, int &number, int currentPos); bool getCurrentPiece(Player &player, int &number, int currentPos);
// 将棋盘下标形式转化为第r圈第s位r和s下标都从1开始 // 将棋盘下标形式转化为第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开始 // 将第c圈第p位转化为棋盘下标形式r和s下标都从1开始
int rs2Pos(int r, int s); int polarToLocation(int r, int s);
//private: //private:
@ -120,22 +120,22 @@ public:
(board[i] & 0x10) (board[i] & 0x10)
(board[i] & 0x20) (board[i] & 0x20)
*/ */
int board_[N_POINTS]{}; int locations[N_LOCATIONS]{};
/* /*
struct Mill { struct Mill {
char piece1; // “三连”中最小的棋子 char piece1; // “三连”中最小的棋子
char pos1; // 最小棋子的位置 char location1; // 最小棋子的位置
char piece2; // 次小的棋子 char piece2; // 次小的棋子
char pos2; // 次小棋子的位置 char location2; // 次小棋子的位置
char piece3; // 最大的棋子 char piece3; // 最大的棋子
char pos3; // 最大棋子的位置 char location3; // 最大棋子的位置
}; };
64 64
0x 00 00 00 00 00 00 00 00 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
*/ */
// 三连列表 // 三连列表

View File

@ -27,7 +27,7 @@
MillGame::MillGame() MillGame::MillGame()
{ {
// 单独提出 board 等数据,免得每次都写 context.board; // 单独提出 board 等数据,免得每次都写 context.board;
board_ = context.board.board_; board_ = context.board.locations;
// 创建哈希数据 // 创建哈希数据
constructHash(); constructHash();
@ -62,8 +62,8 @@ MillGame &MillGame::operator= (const MillGame &game)
moveStep = game.moveStep; moveStep = game.moveStep;
randomMove_ = game.randomMove_; randomMove_ = game.randomMove_;
giveUpIfMostLose_ = game.giveUpIfMostLose_; giveUpIfMostLose_ = game.giveUpIfMostLose_;
board_ = context.board.board_; board_ = context.board.locations;
currentPos = game.currentPos; currentLocation = game.currentLocation;
winner = game.winner; winner = game.winner;
startTime = game.startTime; startTime = game.startTime;
currentTime = game.currentTime; currentTime = game.currentTime;
@ -170,10 +170,10 @@ bool MillGame::setContext(const struct Rule *rule, step_t maxStepsLedToDraw, int
// 当前棋局3×8 // 当前棋局3×8
if (board == nullptr) { if (board == nullptr) {
memset(context.board.board_, 0, sizeof(context.board.board_)); memset(context.board.locations, 0, sizeof(context.board.locations));
context.hash = 0; context.hash = 0;
} else { } 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 r = 1; r < Board::N_RINGS + 2; r++) {
for (int s = 0; s < Board::N_SEATS; s++) { for (int s = 0; s < Board::N_SEATS; s++) {
int pos = r * Board::N_SEATS + s; int location = r * Board::N_SEATS + s;
if (context.board.board_[pos] & 0x10) { if (context.board.locations[location] & 0x10) {
context.nPiecesOnBoard_1++; context.nPiecesOnBoard_1++;
} else if (context.board.board_[pos] & 0x20) { } else if (context.board.locations[location] & 0x20) {
context.nPiecesOnBoard_2++; 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); context.board.createMillTable(currentRule);
// 不选中棋子 // 不选中棋子
currentPos = 0; currentLocation = 0;
// 用时置零 // 用时置零
elapsedSeconds_1 = elapsedSeconds_2 = 0; elapsedSeconds_1 = elapsedSeconds_2 = 0;
@ -319,7 +319,7 @@ bool MillGame::reset()
} }
// 不选中棋子 // 不选中棋子
currentPos = 0; currentLocation = 0;
// 用时置零 // 用时置零
elapsedSeconds_1 = elapsedSeconds_2 = 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 // 如果局面为“结局”返回false
if (context.stage == GAME_OVER) if (context.stage == GAME_OVER)
@ -389,13 +389,13 @@ bool MillGame::place(int pos, int time_p, int8_t rs)
return false; return false;
// 如果落子位置在棋盘外、已有子点或禁点返回false // 如果落子位置在棋盘外、已有子点或禁点返回false
if (!context.board.onBoard[pos] || board_[pos]) if (!context.board.onBoard[location] || board_[location])
return false; return false;
// 格式转换 // 格式转换
int r = 0; int r = 0;
int s = 0; int s = 0;
context.board.pos2rs(pos, r, s); context.board.locationToPolar(location, r, s);
// 时间的临时变量 // 时间的临时变量
int player_ms = -1; int player_ms = -1;
@ -418,11 +418,11 @@ bool MillGame::place(int pos, int time_p, int8_t rs)
context.nPiecesOnBoard_2++; context.nPiecesOnBoard_2++;
} }
board_[pos] = piece; board_[location] = piece;
updateHash(pos); updateHash(location);
move_ = pos; move_ = location;
if (rs) { if (rs) {
player_ms = update(time_p); player_ms = update(time_p);
@ -432,9 +432,9 @@ bool MillGame::place(int pos, int time_p, int8_t rs)
currentStep++; currentStep++;
} }
currentPos = pos; currentLocation = location;
n = context.board.addMills(currentRule, currentPos); n = context.board.addMills(currentRule, currentLocation);
// 开局阶段未成三 // 开局阶段未成三
if (n == 0) { if (n == 0) {
@ -494,7 +494,7 @@ bool MillGame::place(int pos, int time_p, int8_t rs)
int i; int i;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (pos == MoveList::moveTable[currentPos][i]) if (location == MoveList::moveTable[currentLocation][i])
break; 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) { if (rs) {
player_ms = update(time_p); 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); r, s, player_ms / 60, player_ms % 60);
cmdlist.emplace_back(string(cmdline)); cmdlist.emplace_back(string(cmdline));
currentStep++; currentStep++;
moveStep++; 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; currentLocation = location;
n = context.board.addMills(currentRule, currentPos); n = context.board.addMills(currentRule, currentLocation);
// 中局阶段未成三 // 中局阶段未成三
if (n == 0) { if (n == 0) {
@ -558,21 +558,21 @@ out:
bool MillGame::_place(int r, int s, int time_p) bool MillGame::_place(int r, int s, int time_p)
{ {
// 转换为 pos // 转换为 location
int pos = context.board.rs2Pos(r, s); 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) bool MillGame::_capture(int r, int s, int time_p)
{ {
// 转换为 pos // 转换为 location
int pos = context.board.rs2Pos(r, s); 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 // 如果局面为"未开局"或“结局”返回false
if (context.stage == GAME_NOTSTARTED || context.stage == GAME_OVER) 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 r = 0;
int s = 0; int s = 0;
context.board.pos2rs(pos, r, s); context.board.locationToPolar(location, r, s);
// 时间的临时变量 // 时间的临时变量
int player_ms = -1; 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; char opponent = context.turn == PLAYER1 ? 0x20 : 0x10;
// 判断去子是不是对手棋 // 判断去子是不是对手棋
if (!(opponent & board_[pos])) if (!(opponent & board_[location]))
return false; return false;
// 如果当前子是否处于“三连”之中,且对方还未全部处于“三连”之中 // 如果当前子是否处于“三连”之中,且对方还未全部处于“三连”之中
if (!currentRule.allowRemoveMill && if (!currentRule.allowRemoveMill &&
context.board.isInMills(pos) && !context.board.isAllInMills(opponent)) { context.board.inHowManyMills(location) &&
!context.board.isAllInMills(opponent)) {
return false; return false;
} }
// 去子(设置禁点) // 去子(设置禁点)
if (currentRule.hasForbiddenPoint && context.stage == GAME_PLACING) { if (currentRule.hasForbiddenPoint && context.stage == GAME_PLACING) {
revertHash(pos); revertHash(location);
board_[pos] = '\x0f'; board_[location] = '\x0f';
updateHash(pos); updateHash(location);
} else { // 去子 } else { // 去子
revertHash(pos); revertHash(location);
board_[pos] = '\x00'; board_[location] = '\x00';
} }
if (context.turn == PLAYER1) if (context.turn == PLAYER1)
@ -622,7 +623,7 @@ bool MillGame::capture(int pos, int time_p, int8_t cp)
else if (context.turn == PLAYER2) else if (context.turn == PLAYER2)
context.nPiecesOnBoard_1--; context.nPiecesOnBoard_1--;
move_ = -pos; move_ = -location;
if (cp) { if (cp) {
player_ms = update(time_p); player_ms = update(time_p);
@ -632,9 +633,9 @@ bool MillGame::capture(int pos, int time_p, int8_t cp)
moveStep = 0; moveStep = 0;
} }
currentPos = 0; currentLocation = 0;
context.nPiecesNeedRemove--; context.nPiecesNeedRemove--;
updateHash(pos); updateHash(location);
// 去子完成 // 去子完成
@ -713,7 +714,7 @@ out:
return true; return true;
} }
bool MillGame::choose(int pos) bool MillGame::choose(int location)
{ {
// 如果局面不是"中局”返回false // 如果局面不是"中局”返回false
if (context.stage != GAME_MOVING) if (context.stage != GAME_MOVING)
@ -726,14 +727,14 @@ bool MillGame::choose(int pos)
char t = context.turn == PLAYER1 ? 0x10 : 0x20; char t = context.turn == PLAYER1 ? 0x10 : 0x20;
// 判断选子是否可选 // 判断选子是否可选
if (board_[pos] & t) { if (board_[location] & t) {
// 判断pos处的棋子是否被“闷” // 判断location处的棋子是否被“闷”
if (context.board.isSurrounded(context.turn, currentRule, context.nPiecesOnBoard_1, context.nPiecesOnBoard_2, pos)) { if (context.board.isSurrounded(context.turn, currentRule, context.nPiecesOnBoard_1, context.nPiecesOnBoard_2, location)) {
return false; return false;
} }
// 选子 // 选子
currentPos = pos; currentLocation = location;
// 选子完成,进入落子状态 // 选子完成,进入落子状态
context.action = ACTION_PLACE; context.action = ACTION_PLACE;
@ -746,7 +747,7 @@ bool MillGame::choose(int pos)
bool MillGame::choose(int r, int s) 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) bool MillGame::giveup(Player loser)
@ -1044,14 +1045,14 @@ bool MillGame::win(bool forceDraw)
// 计算玩家1和玩家2的棋子活动能力之差 // 计算玩家1和玩家2的棋子活动能力之差
int MillGame::getMobilityDiff(enum Player turn, const Rule &rule, int nPiecesOnBoard_1, int nPiecesOnBoard_2, bool includeFobidden) 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 mobility1 = 0;
int mobility2 = 0; int mobility2 = 0;
int diff = 0; int diff = 0;
int n = 0; int n = 0;
for (int i = Board::POS_BEGIN; i < Board::POS_END; i++) { for (int i = Board::LOCATION_BEGIN; i < Board::LOCATION_END; i++) {
n = context.board.getSurroundedEmptyPosCount(turn, rule, nPiecesOnBoard_1, nPiecesOnBoard_2, i, includeFobidden); n = context.board.getSurroundedEmptyLocationCount(turn, rule, nPiecesOnBoard_1, nPiecesOnBoard_2, i, includeFobidden);
if (board[i] & 0x10) { if (board[i] & 0x10) {
mobility1 += n; mobility1 += n;
@ -1067,15 +1068,15 @@ int MillGame::getMobilityDiff(enum Player turn, const Rule &rule, int nPiecesOnB
void MillGame::cleanForbiddenPoints() void MillGame::cleanForbiddenPoints()
{ {
int pos = 0; int location = 0;
for (int r = 1; r <= Board::N_RINGS; r++) { for (int r = 1; r <= Board::N_RINGS; r++) {
for (int s = 0; s < Board::N_SEATS; s++) { 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') { if (board_[location] == '\x0f') {
revertHash(pos); revertHash(location);
board_[pos] = '\x00'; board_[location] = '\x00';
} }
} }
} }
@ -1178,7 +1179,7 @@ void MillGame::constructHash()
context.hash = 0; context.hash = 0;
#include "zobrist.h" #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() hash_t MillGame::getHash()
@ -1189,22 +1190,22 @@ hash_t MillGame::getHash()
return context.hash; 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 表示禁点 // 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; 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() hash_t MillGame::updateHashMisc()

View File

@ -45,7 +45,7 @@ public:
hash_t hash{}; hash_t hash{};
// Zobrist 数组 // Zobrist 数组
hash_t zobrist[Board::N_POINTS][POINT_TYPE_COUNT]{}; hash_t zobrist[Board::N_LOCATIONS][POINT_TYPE_COUNT]{};
// 局面阶段标识 // 局面阶段标识
enum GameStage stage; enum GameStage stage;
@ -148,19 +148,19 @@ public:
// 获取棋盘数据 // 获取棋盘数据
const int *getBoard() const 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 command(int move);
bool choose(int pos); bool choose(int location);
bool place(int pos, int time_p = -1, int8_t cp = 0); bool place(int location, int time_p = -1, int8_t cp = 0);
bool capture(int pos, int time_p = -1, int8_t cp = 0); bool capture(int location, int time_p = -1, int8_t cp = 0);
// hash 相关 // hash 相关
hash_t getHash(); hash_t getHash();
hash_t revertHash(int pos); hash_t revertHash(int location);
hash_t updateHash(int pos); hash_t updateHash(int location);
hash_t updateHashMisc(); hash_t updateHashMisc();
public: /* TODO: move to private */ public: /* TODO: move to private */
@ -347,7 +347,7 @@ public: /* TODO: move to private */
/* /*
AI会用到 AI会用到
0x 00 00 0x 00 00
pos1 pos2 location1 location2
0x00???? 0x00????
0x__??__为移动前的位置?? 0x__??__为移动前的位置??
0xFF???? 0xFF????
@ -367,7 +367,7 @@ public: /* TODO: move to private */
int32_t move_{}; int32_t move_{};
// 选中的棋子在board中的位置 // 选中的棋子在board中的位置
int currentPos{}; int currentLocation{};
private: private:
// 棋局哈希值 // 棋局哈希值

View File

@ -398,8 +398,8 @@ void GameController::flip()
ai2.wait(); 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);
game_.context.board.rotate(180, game_.cmdlist, game_.cmdline, game_.move_, game_.currentRule, game_.currentPos); game_.context.board.rotate(180, game_.cmdlist, game_.cmdline, game_.move_, game_.currentRule, game_.currentLocation);
gameTemp = game_; gameTemp = game_;
// 更新棋谱 // 更新棋谱
@ -438,7 +438,7 @@ void GameController::mirror()
ai2.wait(); 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_; gameTemp = game_;
// 更新棋谱 // 更新棋谱
@ -480,7 +480,7 @@ void GameController::turnRight()
ai2.wait(); 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_; gameTemp = game_;
// 更新棋谱 // 更新棋谱
@ -520,7 +520,7 @@ void GameController::turnLeft()
ai2.wait(); 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_; gameTemp = game_;
// 更新棋谱 // 更新棋谱
@ -1004,7 +1004,7 @@ bool GameController::updateScence(MillGame &game)
int j; 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) { if (board[j] == key) {
pos = scene.rs2pos(j / Board::N_SEATS, j % Board::N_SEATS + 1); pos = scene.rs2pos(j / Board::N_SEATS, j % Board::N_SEATS + 1);
if (piece->pos() != pos) { if (piece->pos() != pos) {
@ -1062,7 +1062,7 @@ bool GameController::updateScence(MillGame &game)
// 添加摆棋阶段禁子点 // 添加摆棋阶段禁子点
if (game.getRule()->hasForbiddenPoint && game.getStage() == GAME_PLACING) { 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) { if (board[j] == 0x0F) {
pos = scene.rs2pos(j / Board::N_SEATS, j % Board::N_SEATS + 1); pos = scene.rs2pos(j / Board::N_SEATS, j % Board::N_SEATS + 1);
if (nTotalPieces < pieceList.size()) { if (nTotalPieces < pieceList.size()) {
@ -1088,9 +1088,9 @@ bool GameController::updateScence(MillGame &game)
} }
// 选中当前棋子 // 选中当前棋子
int ipos = game.getCurrentPos(); int ipos = game.getCurrentLocation();
if (ipos) { if (ipos) {
key = board[game.getCurrentPos()]; key = board[game.getCurrentLocation()];
ipos = key & 0x10 ? (key - 0x11) * 2 : (key - 0x21) * 2 + 1; ipos = key & 0x10 ? (key - 0x11) * 2 : (key - 0x21) * 2 + 1;
if (ipos >= 0 && ipos < nTotalPieces) { if (ipos >= 0 && ipos < nTotalPieces) {
currentPiece = pieceList.at(ipos); currentPiece = pieceList.at(ipos);