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)
|
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)
|
||||||
|
|
|
@ -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:
|
||||||
// 着法顺序表, 后续会被打乱
|
// 着法顺序表, 后续会被打乱
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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},
|
||||||
|
|
|
@ -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 ¤tRule)
|
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}},
|
/* 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 ¤tRule)
|
||||||
/* 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 ¤tRule)
|
||||||
}
|
}
|
||||||
|
|
||||||
#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 ¤tRule)
|
||||||
#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 ¤tRule, int pos)
|
int Board::addMills(const Rule ¤tRule, 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 ¤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>(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 ¤tRule, 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 ¤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;
|
int count = 0;
|
||||||
|
|
||||||
|
@ -337,12 +338,12 @@ int Board::getSurroundedEmptyPosCount(enum Player turn, const Rule ¤tRule,
|
||||||
(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 ¤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 &&
|
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 ¤tRule, 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 ¤tRule, 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 ¤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 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 ¤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 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 ¤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转化为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) {
|
||||||
|
|
|
@ -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 ¤tRule);
|
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);
|
void rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t move_, const Rule ¤tRule, 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 ¤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);
|
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);
|
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);
|
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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// 三连列表
|
// 三连列表
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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:
|
||||||
// 棋局哈希值
|
// 棋局哈希值
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue