📄 xqwl04.cpp
字号:
inline BOOL SAME_HALF(int sqSrc, int sqDst) {
return ((sqSrc ^ sqDst) & 0x80) == 0;
}
// 是否在同一行
inline BOOL SAME_RANK(int sqSrc, int sqDst) {
return ((sqSrc ^ sqDst) & 0xf0) == 0;
}
// 是否在同一列
inline BOOL SAME_FILE(int sqSrc, int sqDst) {
return ((sqSrc ^ sqDst) & 0x0f) == 0;
}
// 获得红黑标记(红子是8,黑子是16)
inline int SIDE_TAG(int sd) {
return 8 + (sd << 3);
}
// 获得对方红黑标记
inline int OPP_SIDE_TAG(int sd) {
return 16 - (sd << 3);
}
// 获得走法的起点
inline int SRC(int mv) {
return mv & 255;
}
// 获得走法的终点
inline int DST(int mv) {
return mv >> 8;
}
// 根据起点和终点获得走法
inline int MOVE(int sqSrc, int sqDst) {
return sqSrc + sqDst * 256;
}
// 走法水平镜像
inline int MIRROR_MOVE(int mv) {
return MOVE(MIRROR_SQUARE(SRC(mv)), MIRROR_SQUARE(DST(mv)));
}
// RC4密码流生成器
struct RC4Struct {
BYTE s[256];
int x, y;
void InitZero(void); // 用空密钥初始化密码流生成器
BYTE NextByte(void) { // 生成密码流的下一个字节
BYTE uc;
x = (x + 1) & 255;
y = (y + s[x]) & 255;
uc = s[x];
s[x] = s[y];
s[y] = uc;
return s[(s[x] + s[y]) & 255];
}
DWORD NextLong(void) { // 生成密码流的下四个字节
BYTE uc0, uc1, uc2, uc3;
uc0 = NextByte();
uc1 = NextByte();
uc2 = NextByte();
uc3 = NextByte();
return uc0 + (uc1 << 8) + (uc2 << 16) + (uc3 << 24);
}
};
// 用空密钥初始化密码流生成器
void RC4Struct::InitZero(void) {
int i, j;
BYTE uc;
x = y = j = 0;
for (i = 0; i < 256; i ++) {
s[i] = i;
}
for (i = 0; i < 256; i ++) {
j = (j + s[i]) & 255;
uc = s[i];
s[i] = s[j];
s[j] = uc;
}
}
// Zobrist结构
struct ZobristStruct {
DWORD dwKey, dwLock0, dwLock1;
void InitZero(void) { // 用零填充Zobrist
dwKey = dwLock0 = dwLock1 = 0;
}
void InitRC4(RC4Struct &rc4) { // 用密码流填充Zobrist
dwKey = rc4.NextLong();
dwLock0 = rc4.NextLong();
dwLock1 = rc4.NextLong();
}
void Xor(const ZobristStruct &zobr) { // 执行XOR操作
dwKey ^= zobr.dwKey;
dwLock0 ^= zobr.dwLock0;
dwLock1 ^= zobr.dwLock1;
}
void Xor(const ZobristStruct &zobr1, const ZobristStruct &zobr2) {
dwKey ^= zobr1.dwKey ^ zobr2.dwKey;
dwLock0 ^= zobr1.dwLock0 ^ zobr2.dwLock0;
dwLock1 ^= zobr1.dwLock1 ^ zobr2.dwLock1;
}
};
// Zobrist表
static struct {
ZobristStruct Player;
ZobristStruct Table[14][256];
} Zobrist;
// 初始化Zobrist表
static void InitZobrist(void) {
int i, j;
RC4Struct rc4;
rc4.InitZero();
Zobrist.Player.InitRC4(rc4);
for (i = 0; i < 14; i ++) {
for (j = 0; j < 256; j ++) {
Zobrist.Table[i][j].InitRC4(rc4);
}
}
}
// 历史走法信息(占4字节)
struct MoveStruct {
WORD wmv;
BYTE ucpcCaptured, ucbCheck;
DWORD dwKey;
void Set(int mv, int pcCaptured, BOOL bCheck, DWORD dwKey_) {
wmv = mv;
ucpcCaptured = pcCaptured;
ucbCheck = bCheck;
dwKey = dwKey_;
}
}; // mvs
// 局面结构
struct PositionStruct {
int sdPlayer; // 轮到谁走,0=红方,1=黑方
BYTE ucpcSquares[256]; // 棋盘上的棋子
int vlWhite, vlBlack; // 红、黑双方的子力价值
int nDistance, nMoveNum; // 距离根节点的步数,历史走法数
MoveStruct mvsList[MAX_MOVES]; // 历史走法信息列表
ZobristStruct zobr; // Zobrist
void SetIrrev(void) { // 清空(初始化)历史走法信息
mvsList[0].Set(0, 0, Checked(), zobr.dwKey);
nMoveNum = 1;
}
void Startup(void); // 初始化棋盘
void ChangeSide(void) { // 交换走子方
sdPlayer = 1 - sdPlayer;
zobr.Xor(Zobrist.Player);
}
void AddPiece(int sq, int pc) { // 在棋盘上放一枚棋子
ucpcSquares[sq] = pc;
// 红方加分,黑方(注意"cucvlPiecePos"取值要颠倒)减分
if (pc < 16) {
vlWhite += cucvlPiecePos[pc - 8][sq];
zobr.Xor(Zobrist.Table[pc - 8][sq]);
} else {
vlBlack += cucvlPiecePos[pc - 16][SQUARE_FLIP(sq)];
zobr.Xor(Zobrist.Table[pc - 9][sq]);
}
}
void DelPiece(int sq, int pc) { // 从棋盘上拿走一枚棋子
ucpcSquares[sq] = 0;
// 红方减分,黑方(注意"cucvlPiecePos"取值要颠倒)加分
if (pc < 16) {
vlWhite -= cucvlPiecePos[pc - 8][sq];
zobr.Xor(Zobrist.Table[pc - 8][sq]);
} else {
vlBlack -= cucvlPiecePos[pc - 16][SQUARE_FLIP(sq)];
zobr.Xor(Zobrist.Table[pc - 9][sq]);
}
}
int Evaluate(void) const { // 局面评价函数
return (sdPlayer == 0 ? vlWhite - vlBlack : vlBlack - vlWhite) + ADVANCED_VALUE;
}
BOOL InCheck(void) const { // 是否被将军
return mvsList[nMoveNum - 1].ucbCheck;
}
BOOL Captured(void) const { // 上一步是否吃子
return mvsList[nMoveNum - 1].ucpcCaptured != 0;
}
int MovePiece(int mv); // 搬一步棋的棋子
void UndoMovePiece(int mv, int pcCaptured); // 撤消搬一步棋的棋子
BOOL MakeMove(int mv); // 走一步棋
void UndoMakeMove(void) { // 撤消走一步棋
nDistance --;
nMoveNum --;
ChangeSide();
UndoMovePiece(mvsList[nMoveNum].wmv, mvsList[nMoveNum].ucpcCaptured);
}
void NullMove(void) { // 走一步空步
DWORD dwKey;
dwKey = zobr.dwKey;
ChangeSide();
mvsList[nMoveNum].Set(0, 0, FALSE, dwKey);
nMoveNum ++;
nDistance ++;
}
void UndoNullMove(void) { // 撤消走一步空步
nDistance --;
nMoveNum --;
ChangeSide();
}
// 生成所有走法,如果"bCapture"为"TRUE"则只生成吃子走法
int GenerateMoves(int *mvs, BOOL bCapture = FALSE) const;
BOOL LegalMove(int mv) const; // 判断走法是否合理
BOOL Checked(void) const; // 判断是否被将军
BOOL IsMate(void); // 判断是否被杀
int RepStatus(int nRecur = 1) const; // 检测重复局面
int RepValue(int nRepStatus) const { // 重复局面分值
int vlReturn;
vlReturn = ((nRepStatus & 2) == 0 ? 0 : nDistance - MATE_VALUE) +
((nRepStatus & 4) == 0 ? 0 : MATE_VALUE - nDistance);
return vlReturn == 0 ? -DRAW_VALUE : vlReturn;
}
BOOL NullOkay(void) const { // 判断是否允许空步裁剪
return (sdPlayer == 0 ? vlWhite : vlBlack) > NULL_MARGIN;
}
};
// 初始化棋盘
void PositionStruct::Startup(void) {
int sq, pc;
sdPlayer = vlWhite = vlBlack = nDistance = 0;
memset(ucpcSquares, 0, 256);
zobr.InitZero();
for (sq = 0; sq < 256; sq ++) {
pc = cucpcStartup[sq];
if (pc != 0) {
AddPiece(sq, pc);
}
}
SetIrrev();
}
// 搬一步棋的棋子
int PositionStruct::MovePiece(int mv) {
int sqSrc, sqDst, pc, pcCaptured;
sqSrc = SRC(mv);
sqDst = DST(mv);
pcCaptured = ucpcSquares[sqDst];
if (pcCaptured != 0) {
DelPiece(sqDst, pcCaptured);
}
pc = ucpcSquares[sqSrc];
DelPiece(sqSrc, pc);
AddPiece(sqDst, pc);
return pcCaptured;
}
// 撤消搬一步棋的棋子
void PositionStruct::UndoMovePiece(int mv, int pcCaptured) {
int sqSrc, sqDst, pc;
sqSrc = SRC(mv);
sqDst = DST(mv);
pc = ucpcSquares[sqDst];
DelPiece(sqDst, pc);
AddPiece(sqSrc, pc);
if (pcCaptured != 0) {
AddPiece(sqDst, pcCaptured);
}
}
// 走一步棋
BOOL PositionStruct::MakeMove(int mv) {
int pcCaptured;
DWORD dwKey;
dwKey = zobr.dwKey;
pcCaptured = MovePiece(mv);
if (Checked()) {
UndoMovePiece(mv, pcCaptured);
return FALSE;
}
ChangeSide();
mvsList[nMoveNum].Set(mv, pcCaptured, Checked(), dwKey);
nMoveNum ++;
nDistance ++;
return TRUE;
}
// "GenerateMoves"参数
const BOOL GEN_CAPTURE = TRUE;
// 生成所有走法,如果"bCapture"为"TRUE"则只生成吃子走法
int PositionStruct::GenerateMoves(int *mvs, BOOL bCapture) const {
int i, j, nGenMoves, nDelta, sqSrc, sqDst;
int pcSelfSide, pcOppSide, pcSrc, pcDst;
// 生成所有走法,需要经过以下几个步骤:
nGenMoves = 0;
pcSelfSide = SIDE_TAG(sdPlayer);
pcOppSide = OPP_SIDE_TAG(sdPlayer);
for (sqSrc = 0; sqSrc < 256; sqSrc ++) {
// 1. 找到一个本方棋子,再做以下判断:
pcSrc = ucpcSquares[sqSrc];
if ((pcSrc & pcSelfSide) == 0) {
continue;
}
// 2. 根据棋子确定走法
switch (pcSrc - pcSelfSide) {
case PIECE_KING:
for (i = 0; i < 4; i ++) {
sqDst = sqSrc + ccKingDelta[i];
if (!IN_FORT(sqDst)) {
continue;
}
pcDst = ucpcSquares[sqDst];
if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) {
mvs[nGenMoves] = MOVE(sqSrc, sqDst);
nGenMoves ++;
}
}
break;
case PIECE_ADVISOR:
for (i = 0; i < 4; i ++) {
sqDst = sqSrc + ccAdvisorDelta[i];
if (!IN_FORT(sqDst)) {
continue;
}
pcDst = ucpcSquares[sqDst];
if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) {
mvs[nGenMoves] = MOVE(sqSrc, sqDst);
nGenMoves ++;
}
}
break;
case PIECE_BISHOP:
for (i = 0; i < 4; i ++) {
sqDst = sqSrc + ccAdvisorDelta[i];
if (!(IN_BOARD(sqDst) && HOME_HALF(sqDst, sdPlayer) && ucpcSquares[sqDst] == 0)) {
continue;
}
sqDst += ccAdvisorDelta[i];
pcDst = ucpcSquares[sqDst];
if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) {
mvs[nGenMoves] = MOVE(sqSrc, sqDst);
nGenMoves ++;
}
}
break;
case PIECE_KNIGHT:
for (i = 0; i < 4; i ++) {
sqDst = sqSrc + ccKingDelta[i];
if (ucpcSquares[sqDst] != 0) {
continue;
}
for (j = 0; j < 2; j ++) {
sqDst = sqSrc + ccKnightDelta[i][j];
if (!IN_BOARD(sqDst)) {
continue;
}
pcDst = ucpcSquares[sqDst];
if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) {
mvs[nGenMoves] = MOVE(sqSrc, sqDst);
nGenMoves ++;
}
}
}
break;
case PIECE_ROOK:
for (i = 0; i < 4; i ++) {
nDelta = ccKingDelta[i];
sqDst = sqSrc + nDelta;
while (IN_BOARD(sqDst)) {
pcDst = ucpcSquares[sqDst];
if (pcDst == 0) {
if (!bCapture) {
mvs[nGenMoves] = MOVE(sqSrc, sqDst);
nGenMoves ++;
}
} else {
if ((pcDst & pcOppSide) != 0) {
mvs[nGenMoves] = MOVE(sqSrc, sqDst);
nGenMoves ++;
}
break;
}
sqDst += nDelta;
}
}
break;
case PIECE_CANNON:
for (i = 0; i < 4; i ++) {
nDelta = ccKingDelta[i];
sqDst = sqSrc + nDelta;
while (IN_BOARD(sqDst)) {
pcDst = ucpcSquares[sqDst];
if (pcDst == 0) {
if (!bCapture) {
mvs[nGenMoves] = MOVE(sqSrc, sqDst);
nGenMoves ++;
}
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -