// 棋子保护判断 bool PositionStruct::Protected(int sd, int sqSrc, int sqExcept) const { // 参数"sqExcept"表示排除保护的棋子(指格子编号),考虑被牵制子的保护时,需要排除牵制目标子的保护 int i, sqDst, sqPin, pc, x, y, nSideTag; SlideMaskStruct *lpsmsRank, *lpsmsFile; // 棋子保护判断包括以下几个步骤: __ASSERT_SQUARE(sqSrc); nSideTag = SIDE_TAG(sd); if (HOME_HALF(sqSrc, sd)) { if (IN_FORT(sqSrc)) { // 1. 判断受到帅(将)的保护 sqDst = ucsqPieces[nSideTag + KING_FROM]; if (sqDst != 0 && sqDst != sqExcept) { __ASSERT_SQUARE(sqDst); if (KING_SPAN(sqSrc, sqDst)) { return true; } } // 2. 判断受到仕(士)的保护 for (i = ADVISOR_FROM; i <= ADVISOR_TO; i ++) { sqDst = ucsqPieces[nSideTag + i]; if (sqDst != 0 && sqDst != sqExcept) { __ASSERT_SQUARE(sqDst); if (ADVISOR_SPAN(sqSrc, sqDst)) { return true; } } } } // 3. 判断受到相(象)的保护 for (i = BISHOP_FROM; i <= BISHOP_TO; i ++) { sqDst = ucsqPieces[nSideTag + i]; if (sqDst != 0 && sqDst != sqExcept) { __ASSERT_SQUARE(sqDst); if (BISHOP_SPAN(sqSrc, sqDst) && ucpcSquares[BISHOP_PIN(sqSrc, sqDst)] == 0) { return true; } } } } else { // 4. 判断受到过河兵(卒)横向的保护 for (sqDst = sqSrc - 1; sqDst <= sqSrc + 1; sqDst += 2) { // 如果棋子在边线,那么断言不成立 // __ASSERT_SQUARE(sqDst); if (sqDst != sqExcept) { pc = ucpcSquares[sqDst]; if ((pc & nSideTag) != 0 && PIECE_INDEX(pc) >= PAWN_FROM) { return true; } } } } // 5. 判断受到兵(卒)纵向的保护 sqDst = SQUARE_BACKWARD(sqSrc, sd); // 如果棋子在底线,那么断言不成立 // __ASSERT_SQUARE(sqDst); if (sqDst != sqExcept) { pc = ucpcSquares[sqDst]; if ((pc & nSideTag) != 0 && PIECE_INDEX(pc) >= PAWN_FROM) { return true; } } // 6. 判断受到马的保护 for (i = KNIGHT_FROM; i <= KNIGHT_TO; i ++) { sqDst = ucsqPieces[nSideTag + i]; if (sqDst != 0 && sqDst != sqExcept) { __ASSERT_SQUARE(sqDst); sqPin = KNIGHT_PIN(sqDst, sqSrc); // 注意,sqSrc和sqDst是反的! if (sqPin != sqDst && ucpcSquares[sqPin] == 0) { return true; } } } x = FILE_X(sqSrc); y = RANK_Y(sqSrc); lpsmsRank = RankMaskPtr(x, y); lpsmsFile = FileMaskPtr(x, y); // 7. 判断受到车的保护,参阅"position.cpp"里的"CheckedBy()"函数 for (i = ROOK_FROM; i <= ROOK_TO; i ++) { sqDst = ucsqPieces[nSideTag + i]; if (sqDst != 0 && sqDst != sqSrc && sqDst != sqExcept) { if (x == FILE_X(sqDst)) { if ((lpsmsFile->wRookCap & PreGen.wBitFileMask[sqDst]) != 0) { return true; } } else if (y == RANK_Y(sqDst)) { if ((lpsmsRank->wRookCap & PreGen.wBitRankMask[sqDst]) != 0) { return true; } } } } // 8. 判断受到炮的保护,参阅"position.cpp"里的"CheckedBy()"函数 for (i = CANNON_FROM; i <= CANNON_TO; i ++) { sqDst = ucsqPieces[nSideTag + i]; if (sqDst && sqDst != sqSrc && sqDst != sqExcept) { if (x == FILE_X(sqDst)) { if ((lpsmsFile->wCannonCap & PreGen.wBitFileMask[sqDst]) != 0) { return true; } } else if (y == RANK_Y(sqDst)) { if ((lpsmsRank->wCannonCap & PreGen.wBitRankMask[sqDst]) != 0) { return true; } } } } return false; }
BOOL _PositionStruct::LegalMove(int mv) const { int sqSrc, sqDst, sqPin; int pcSelfSide, pcSrc, pcDst, nDelta; sqSrc = SRC(mv); pcSrc = ucpcSquares[sqSrc]; pcSelfSide = SIDE_TAG(sdPlayer); if ((pcSrc & pcSelfSide) == 0) { return FALSE; } sqDst = DST(mv); pcDst = ucpcSquares[sqDst]; if ((pcDst & pcSelfSide) != 0) { return FALSE; } switch (pcSrc - pcSelfSide) { case PIECE_KING: return IN_FORT(sqDst) && KING_SPAN(sqSrc, sqDst); case PIECE_ADVISOR: return IN_FORT(sqDst) && ADVISOR_SPAN(sqSrc, sqDst); case PIECE_BISHOP: return SAME_HALF(sqSrc, sqDst) && BISHOP_SPAN(sqSrc, sqDst) && ucpcSquares[BISHOP_PIN(sqSrc, sqDst)] == 0; case PIECE_KNIGHT: sqPin = KNIGHT_PIN(sqSrc, sqDst); return sqPin != sqSrc && ucpcSquares[sqPin] == 0; case PIECE_ROOK: case PIECE_CANNON: if (SAME_RANK(sqSrc, sqDst)) { nDelta = (sqDst < sqSrc ? -1 : 1); } else if (SAME_FILE(sqSrc, sqDst)) { nDelta = (sqDst < sqSrc ? -16 : 16); } else { return FALSE; } sqPin = sqSrc + nDelta; while (sqPin != sqDst && ucpcSquares[sqPin] == 0) { sqPin += nDelta; } if (sqPin == sqDst) { return pcDst == 0 || pcSrc - pcSelfSide == PIECE_ROOK; } else if (pcDst != 0 && pcSrc - pcSelfSide == PIECE_CANNON) { sqPin += nDelta; while (sqPin != sqDst && ucpcSquares[sqPin] == 0) { sqPin += nDelta; } return sqPin == sqDst; } else { return FALSE; } case PIECE_PAWN: if (AWAY_HALF(sqDst, sdPlayer) && (sqDst == sqSrc - 1 || sqDst == sqSrc + 1)) { return TRUE; } return sqDst == SQUARE_FORWARD(sqSrc, sdPlayer); default: return FALSE; } }
void PreGenInit(void) { int i, j, k, n, sqSrc, sqDst; RC4Struct rc4; SlideMoveStruct smv; SlideMaskStruct sms; // 首先初始化Zobrist键值表 rc4.InitZero(); PreGen.zobrPlayer.InitRC4(rc4); for (i = 0; i < 14; i ++) { for (j = 0; j < 256; j ++) { PreGen.zobrTable[i][j].InitRC4(rc4); } } // 然后初始化屏蔽位行和屏蔽位列 // 注:位行和位列不包括棋盘以外的位,所以就会频繁使用"+/- RANK_TOP/FILE_LEFT" for (sqSrc = 0; sqSrc < 256; sqSrc ++) { if (IN_BOARD(sqSrc)) { PreGen.wBitRankMask[sqSrc] = 1 << (FILE_X(sqSrc) - FILE_LEFT); PreGen.wBitFileMask[sqSrc] = 1 << (RANK_Y(sqSrc) - RANK_TOP); } else { PreGen.wBitRankMask[sqSrc] = 0; PreGen.wBitFileMask[sqSrc] = 0; } } // 然后生成车炮横向的预置数组(数组的应用参阅"pregen.h") for (i = 0; i < 9; i ++) { for (j = 0; j < 512; j ++) { // 初始化借助于“位行”的车和炮的着法预生成数组,包括以下几个步骤: // 1. 初始化临时变量"SlideMoveTab",假设没有着法,用起始格填充 smv.ucNonCap[0] = smv.ucNonCap[1] = smv.ucRookCap[0] = smv.ucRookCap[1] = smv.ucCannonCap[0] = smv.ucCannonCap[1] = smv.ucSuperCap[0] = smv.ucSuperCap[1] = i + FILE_LEFT; sms.wNonCap = sms.wRookCap = sms.wCannonCap = sms.wSuperCap = 0; // 提示:参阅"pregen.h",...[0]表示最大一格,向右移动和下移动都用[0],反之亦然 // 2. 考虑向右移动的目标格,填充...[0], for (k = i + 1; k <= 8; k ++) { if ((j & (1 << k)) != 0) { smv.ucRookCap[0] = FILE_DISP(k + FILE_LEFT); sms.wRookCap |= 1 << k; break; } smv.ucNonCap[0] = FILE_DISP(k + FILE_LEFT); sms.wNonCap |= 1 << k; } for (k ++; k <= 8; k ++) { if ((j & (1 << k)) != 0) { smv.ucCannonCap[0] = FILE_DISP(k + FILE_LEFT); sms.wCannonCap |= 1 << k; break; } } for (k ++; k <= 8; k ++) { if ((j & (1 << k)) != 0) { smv.ucSuperCap[0] = FILE_DISP(k + FILE_LEFT); sms.wSuperCap |= 1 << k; break; } } // 3. 考虑向左移动的目标格,填充...[1] for (k = i - 1; k >= 0; k --) { if ((j & (1 << k)) != 0) { smv.ucRookCap[1] = FILE_DISP(k + FILE_LEFT); sms.wRookCap |= 1 << k; break; } smv.ucNonCap[1] = FILE_DISP(k + FILE_LEFT); sms.wNonCap |= 1 << k; } for (k --; k >= 0; k --) { if ((j & (1 << k)) != 0) { smv.ucCannonCap[1] = FILE_DISP(k + FILE_LEFT); sms.wCannonCap |= 1 << k; break; } } for (k --; k >= 0; k --) { if ((j & (1 << k)) != 0) { smv.ucSuperCap[1] = FILE_DISP(k + FILE_LEFT); sms.wSuperCap |= 1 << k; break; } } // 4. 为"smv"和"sms"的值作断言 __ASSERT_BOUND_2(3, smv.ucNonCap[1], smv.ucNonCap[0], 11); __ASSERT_BOUND_2(3, smv.ucRookCap[1], smv.ucRookCap[0], 11); __ASSERT_BOUND_2(3, smv.ucCannonCap[1], smv.ucCannonCap[0], 11); __ASSERT_BOUND_2(3, smv.ucSuperCap[1], smv.ucSuperCap[0], 11); __ASSERT_BITRANK(sms.wNonCap); __ASSERT_BITRANK(sms.wRookCap); __ASSERT_BITRANK(sms.wCannonCap); __ASSERT_BITRANK(sms.wSuperCap); // 5. 将临时变量"smv"和"sms"拷贝到着法预生成数组中 PreGen.smvRankMoveTab[i][j] = smv; PreGen.smsRankMaskTab[i][j] = sms; } } // 然后生成车炮纵向的预置数组(数组的应用参阅"pregen.h") for (i = 0; i < 10; i ++) { for (j = 0; j < 1024; j ++) { // 初始化借助于“位列”的车和炮的着法预生成数组,包括以下几个步骤: // 1. 初始化临时变量"smv",假设没有着法,用起始格填充 smv.ucNonCap[0] = smv.ucNonCap[1] = smv.ucRookCap[0] = smv.ucRookCap[1] = smv.ucCannonCap[0] = smv.ucCannonCap[1] = smv.ucSuperCap[0] = smv.ucSuperCap[1] = (i + RANK_TOP) * 16; sms.wNonCap = sms.wRookCap = sms.wCannonCap = sms.wSuperCap = 0; // 2. 考虑向下移动的目标格,填充...[0] for (k = i + 1; k <= 9; k ++) { if ((j & (1 << k)) != 0) { smv.ucRookCap[0] = RANK_DISP(k + RANK_TOP); sms.wRookCap |= 1 << k; break; } smv.ucNonCap[0] = RANK_DISP(k + RANK_TOP); sms.wNonCap |= 1 << k; } for (k ++; k <= 9; k ++) { if ((j & (1 << k)) != 0) { smv.ucCannonCap[0] = RANK_DISP(k + RANK_TOP); sms.wCannonCap |= 1 << k; break; } } for (k ++; k <= 9; k ++) { if ((j & (1 << k)) != 0) { smv.ucSuperCap[0] = RANK_DISP(k + RANK_TOP); sms.wSuperCap |= 1 << k; break; } } // 3. 考虑向上移动的目标格,填充...[1] for (k = i - 1; k >= 0; k --) { if ((j & (1 << k)) != 0) { smv.ucRookCap[1] = RANK_DISP(k + RANK_TOP); sms.wRookCap |= 1 << k; break; } smv.ucNonCap[1] = RANK_DISP(k + RANK_TOP); sms.wNonCap |= 1 << k; } for (k --; k >= 0; k --) { if ((j & (1 << k)) != 0) { smv.ucCannonCap[1] = RANK_DISP(k + RANK_TOP); sms.wCannonCap |= 1 << k; break; } } for (k --; k >= 0; k --) { if ((j & (1 << k)) != 0) { smv.ucSuperCap[1] = RANK_DISP(k + RANK_TOP); sms.wSuperCap |= 1 << k; break; } } // 4. 为"smv"和"sms"的值作断言 __ASSERT_BOUND_2(3, smv.ucNonCap[1] >> 4, smv.ucNonCap[0] >> 4, 12); __ASSERT_BOUND_2(3, smv.ucRookCap[1] >> 4, smv.ucRookCap[0] >> 4, 12); __ASSERT_BOUND_2(3, smv.ucCannonCap[1] >> 4, smv.ucCannonCap[0] >> 4, 12); __ASSERT_BOUND_2(3, smv.ucSuperCap[1] >> 4, smv.ucSuperCap[0] >> 4, 12); __ASSERT_BITFILE(sms.wNonCap); __ASSERT_BITFILE(sms.wRookCap); __ASSERT_BITFILE(sms.wCannonCap); __ASSERT_BITFILE(sms.wSuperCap); // 5. 将临时变量"smv"和"sms"拷贝到着法预生成数组中 PreGen.smvFileMoveTab[i][j] = smv; PreGen.smsFileMaskTab[i][j] = sms; } } // 接下来生成着法预生成数组,连同将军预判数组 for (sqSrc = 0; sqSrc < 256; sqSrc ++) { if (IN_BOARD(sqSrc)) { // 生成帅(将)的着法预生成数组 n = 0; for (i = 0; i < 4; i ++) { sqDst = sqSrc + cnKingMoveTab[i]; if (IN_FORT(sqDst)) { PreGen.ucsqKingMoves[sqSrc][n] = sqDst; n ++; } } __ASSERT(n <= 4); PreGen.ucsqKingMoves[sqSrc][n] = 0; // 生成仕(士)的着法预生成数组 n = 0; for (i = 0; i < 4; i ++) { sqDst = sqSrc + cnAdvisorMoveTab[i]; if (IN_FORT(sqDst)) { PreGen.ucsqAdvisorMoves[sqSrc][n] = sqDst; n ++; } } __ASSERT(n <= 4); PreGen.ucsqAdvisorMoves[sqSrc][n] = 0; // 生成相(象)的着法预生成数组,包括象眼数组 n = 0; for (i = 0; i < 4; i ++) { sqDst = sqSrc + cnBishopMoveTab[i]; if (IN_BOARD(sqDst) && SAME_HALF(sqSrc, sqDst)) { PreGen.ucsqBishopMoves[sqSrc][n] = sqDst; PreGen.ucsqBishopPins[sqSrc][n] = BISHOP_PIN(sqSrc, sqDst); n ++; } } __ASSERT(n <= 4); PreGen.ucsqBishopMoves[sqSrc][n] = 0; // 生成马的着法预生成数组,包括马腿数组 n = 0; for (i = 0; i < 8; i ++) { sqDst = sqSrc + cnKnightMoveTab[i]; if (IN_BOARD(sqDst)) { PreGen.ucsqKnightMoves[sqSrc][n] = sqDst; PreGen.ucsqKnightPins[sqSrc][n] = KNIGHT_PIN(sqSrc, sqDst); n ++; } } __ASSERT(n <= 8); PreGen.ucsqKnightMoves[sqSrc][n] = 0; // 生成兵(卒)的着法预生成数组 for (i = 0; i < 2; i ++) { n = 0; sqDst = SQUARE_FORWARD(sqSrc, i); sqDst = sqSrc + (i == 0 ? -16 : 16); if (IN_BOARD(sqDst)) { PreGen.ucsqPawnMoves[i][sqSrc][n] = sqDst; n ++; } if (AWAY_HALF(sqSrc, i)) { for (j = -1; j <= 1; j += 2) { sqDst = sqSrc + j; if (IN_BOARD(sqDst)) { PreGen.ucsqPawnMoves[i][sqSrc][n] = sqDst; n ++; } } } __ASSERT(n <= 3); PreGen.ucsqPawnMoves[i][sqSrc][n] = 0; } } } // 最后清空局面预评价结构 memset(&PreEval, 0, sizeof(PreEvalStruct)); PreEval.bPromotion = false; // 缺省是不允许升变的 }