// “捉”的检测 int PositionStruct::ChasedBy(int mv) const { int i, nSideTag, pcMoved, pcCaptured; int sqSrc, sqDst, x, y; uint8_t *lpucsqDst, *lpucsqPin; SlideMoveStruct *lpsmv; sqSrc = DST(mv); pcMoved = this->ucpcSquares[sqSrc]; nSideTag = SIDE_TAG(this->sdPlayer); __ASSERT_SQUARE(sqSrc); __ASSERT_PIECE(pcMoved); __ASSERT_BOUND(0, pcMoved - OPP_SIDE_TAG(this->sdPlayer), 15); // “捉”的判断包括以下几部分内容: switch (pcMoved - OPP_SIDE_TAG(this->sdPlayer)) { // 1. 走了马,判断是否捉车或捉有根的炮兵(卒) case KNIGHT_FROM: case KNIGHT_TO: // 逐一检测马踩的八个位置 lpucsqDst = PreGen.ucsqKnightMoves[sqSrc]; lpucsqPin = PreGen.ucsqKnightPins[sqSrc]; sqDst = *lpucsqDst; while (sqDst != 0) { __ASSERT_SQUARE(sqDst); if (ucpcSquares[*lpucsqPin] == 0) { pcCaptured = this->ucpcSquares[sqDst]; if ((pcCaptured & nSideTag) != 0) { pcCaptured -= nSideTag; __ASSERT_BOUND(0, pcCaptured, 15); // 技巧:优化兵种判断的分枝 if (pcCaptured <= ROOK_TO) { // 马捉仕(士)、相(象)和马的情况不予考虑 if (pcCaptured >= ROOK_FROM) { // 马捉到了车 return pcCaptured; } } else { if (pcCaptured <= CANNON_TO) { // 马捉到了炮,要判断炮是否受保护 if (!Protected(this->sdPlayer, sqDst)) { return pcCaptured; } } else { // 马捉到了兵(卒),要判断兵(卒)是否过河并受保护 if (AWAY_HALF(sqDst, sdPlayer) && !Protected(this->sdPlayer, sqDst)) { return pcCaptured; } } } } } lpucsqDst ++; sqDst = *lpucsqDst; lpucsqPin ++; } break; // 2. 走了车,判断是否捉有根的马炮兵(卒) case ROOK_FROM: case ROOK_TO: x = FILE_X(sqSrc); y = RANK_Y(sqSrc); if (((SRC(mv) ^ sqSrc) & 0xf) == 0) { // 如果车纵向移动了,则判断车横向吃到的子 lpsmv = RankMovePtr(x, y); for (i = 0; i < 2; i ++) { sqDst = lpsmv->ucRookCap[i] + RANK_DISP(y); __ASSERT_SQUARE(sqDst); if (sqDst != sqSrc) { pcCaptured = this->ucpcSquares[sqDst]; if ((pcCaptured & nSideTag) != 0) { pcCaptured -= nSideTag; __ASSERT_BOUND(0, pcCaptured, 15); // 技巧:优化兵种判断的分枝 if (pcCaptured <= ROOK_TO) { // 车捉仕(士)、相(象)的情况不予考虑 if (pcCaptured >= KNIGHT_FROM) { if (pcCaptured <= KNIGHT_TO) { // 车捉到了马,要判断马是否受保护 if (!Protected(this->sdPlayer, sqDst)) { return pcCaptured; } } // 车捉车的情况不予考虑 } } else { if (pcCaptured <= CANNON_TO) { // 车捉到了炮,要判断炮是否受保护 if (!Protected(this->sdPlayer, sqDst)) { return pcCaptured; } } else { // 车捉到了兵(卒),要判断兵(卒)是否过河并受保护 if (AWAY_HALF(sqDst, sdPlayer) && !Protected(this->sdPlayer, sqDst)) { return pcCaptured; } } } } } } } else { // 如果车横向移动了,则判断车纵向吃到的子 lpsmv = FileMovePtr(x, y); for (i = 0; i < 2; i ++) { sqDst = lpsmv->ucRookCap[i] + FILE_DISP(x); __ASSERT_SQUARE(sqDst); if (sqDst != sqSrc) { pcCaptured = this->ucpcSquares[sqDst]; if ((pcCaptured & nSideTag) != 0) { pcCaptured -= nSideTag; __ASSERT_BOUND(0, pcCaptured, 15); // 技巧:优化兵种判断的分枝 if (pcCaptured <= ROOK_TO) { // 车捉仕(士)、相(象)的情况不予考虑 if (pcCaptured >= KNIGHT_FROM) { if (pcCaptured <= KNIGHT_TO) { // 车捉到了马,要判断马是否受保护 if (!Protected(this->sdPlayer, sqDst)) { return pcCaptured; } } // 车捉车的情况不予考虑 } } else { if (pcCaptured <= CANNON_TO) { // 车捉到了炮,要判断炮是否受保护 if (!Protected(this->sdPlayer, sqDst)) { return pcCaptured; } } else { // 车捉到了兵(卒),要判断兵(卒)是否过河并受保护 if (AWAY_HALF(sqDst, sdPlayer) && !Protected(this->sdPlayer, sqDst)) { return pcCaptured; } } } } } } } break; // 3. 走了炮,判断是否捉车或捉有根的马兵(卒) case CANNON_FROM: case CANNON_TO: x = FILE_X(sqSrc); y = RANK_Y(sqSrc); if (((SRC(mv) ^ sqSrc) & 0xf) == 0) { // 如果炮纵向移动了,则判断炮横向吃到的子 lpsmv = RankMovePtr(x, y); for (i = 0; i < 2; i ++) { sqDst = lpsmv->ucCannonCap[i] + RANK_DISP(y); __ASSERT_SQUARE(sqDst); if (sqDst != sqSrc) { pcCaptured = this->ucpcSquares[sqDst]; if ((pcCaptured & nSideTag) != 0) { pcCaptured -= nSideTag; __ASSERT_BOUND(0, pcCaptured, 15); // 技巧:优化兵种判断的分枝 if (pcCaptured <= ROOK_TO) { // 炮捉仕(士)、相(象)的情况不予考虑 if (pcCaptured >= KNIGHT_FROM) { if (pcCaptured <= KNIGHT_TO) { // 炮捉到了马,要判断马是否受保护 if (!Protected(this->sdPlayer, sqDst)) { return pcCaptured; } } else { // 炮捉到了车 return pcCaptured; } } } else { // 炮捉炮的情况不予考虑 if (pcCaptured >= PAWN_FROM) { // 炮捉到了兵(卒),要判断兵(卒)是否过河并受保护 if (AWAY_HALF(sqDst, sdPlayer) && !Protected(this->sdPlayer, sqDst)) { return pcCaptured; } } } } } } } else { // 如果炮横向移动了,则判断炮纵向吃到的子 lpsmv = FileMovePtr(x, y); for (i = 0; i < 2; i ++) { sqDst = lpsmv->ucCannonCap[i] + FILE_DISP(x); __ASSERT_SQUARE(sqDst); if (sqDst != sqSrc) { pcCaptured = this->ucpcSquares[sqDst]; if ((pcCaptured & nSideTag) != 0) { pcCaptured -= nSideTag; __ASSERT_BOUND(0, pcCaptured, 15); // 技巧:优化兵种判断的分枝 if (pcCaptured <= ROOK_TO) { // 炮捉仕(士)、相(象)的情况不予考虑 if (pcCaptured >= KNIGHT_FROM) { if (pcCaptured <= KNIGHT_TO) { // 炮捉到了马,要判断马是否受保护 if (!Protected(this->sdPlayer, sqDst)) { return pcCaptured; } } else { // 炮捉到了车 return pcCaptured; } } } else { // 炮捉炮的情况不予考虑 if (pcCaptured >= PAWN_FROM) { // 炮捉到了兵(卒),要判断兵(卒)是否过河并受保护 if (AWAY_HALF(sqDst, sdPlayer) && !Protected(this->sdPlayer, sqDst)) { return pcCaptured; } } } } } } } break; } return 0; }
// 吃子着法生成器,按MVV(LVA)设定分值 int PositionStruct::GenCapMoves(MoveStruct *lpmvs) const { int i, sqSrc, sqDst, pcCaptured; int x, y, nSideTag, nOppSideTag; bool bCanPromote; SlideMoveStruct *lpsmv; uint8_t *lpucsqDst, *lpucsqPin; MoveStruct *lpmvsCurr; // 生成吃子着法的过程包括以下几个步骤: lpmvsCurr = lpmvs; nSideTag = SIDE_TAG(sdPlayer); nOppSideTag = OPP_SIDE_TAG(sdPlayer); bCanPromote = PreEval.bPromotion && CanPromote(); // 1. 生成帅(将)的着法 sqSrc = ucsqPieces[nSideTag + KING_FROM]; if (sqSrc != 0) { __ASSERT_SQUARE(sqSrc); lpucsqDst = PreGen.ucsqKingMoves[sqSrc]; sqDst = *lpucsqDst; while (sqDst != 0) { __ASSERT_SQUARE(sqDst); // 找到一个着法后,首先判断吃到的棋子是否是对方棋子,技巧是利用"nOppSideTag"的标志(16和32颠倒), // 如果是对方棋子,则保存MVV(LVA)值,即如果被吃子无保护,则只记MVV,否则记MVV-LVA(如果MVV>LVA的话)。 pcCaptured = ucpcSquares[sqDst]; if ((pcCaptured & nOppSideTag) != 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->wmv = MOVE(sqSrc, sqDst); lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 5); // 帅(将)的价值是5 lpmvsCurr ++; } lpucsqDst ++; sqDst = *lpucsqDst; } } // 2. 生成仕(士)的着法 for (i = ADVISOR_FROM; i <= ADVISOR_TO; i ++) { sqSrc = ucsqPieces[nSideTag + i]; if (sqSrc != 0) { __ASSERT_SQUARE(sqSrc); lpucsqDst = PreGen.ucsqAdvisorMoves[sqSrc]; sqDst = *lpucsqDst; while (sqDst != 0) { __ASSERT_SQUARE(sqDst); pcCaptured = ucpcSquares[sqDst]; if ((pcCaptured & nOppSideTag) != 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->wmv = MOVE(sqSrc, sqDst); lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 1); // 仕(士)的价值是1 lpmvsCurr ++; } lpucsqDst ++; sqDst = *lpucsqDst; } if (bCanPromote && CAN_PROMOTE(sqSrc)) { lpmvsCurr->wmv = MOVE(sqSrc, sqSrc); lpmvsCurr->wvl = 0; lpmvsCurr ++; } } } // 3. 生成相(象)的着法 for (i = BISHOP_FROM; i <= BISHOP_TO; i ++) { sqSrc = ucsqPieces[nSideTag + i]; if (sqSrc != 0) { __ASSERT_SQUARE(sqSrc); lpucsqDst = PreGen.ucsqBishopMoves[sqSrc]; lpucsqPin = PreGen.ucsqBishopPins[sqSrc]; sqDst = *lpucsqDst; while (sqDst != 0) { __ASSERT_SQUARE(sqDst); if (ucpcSquares[*lpucsqPin] == 0) { pcCaptured = ucpcSquares[sqDst]; if ((pcCaptured & nOppSideTag) != 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->wmv = MOVE(sqSrc, sqDst); lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 1); // 相(象)的价值是1 lpmvsCurr ++; } } lpucsqDst ++; sqDst = *lpucsqDst; lpucsqPin ++; } if (bCanPromote && CAN_PROMOTE(sqSrc)) { lpmvsCurr->wmv = MOVE(sqSrc, sqSrc); lpmvsCurr->wvl = 0; lpmvsCurr ++; } } } // 4. 生成马的着法 for (i = KNIGHT_FROM; i <= KNIGHT_TO; i ++) { sqSrc = ucsqPieces[nSideTag + i]; if (sqSrc != 0) { __ASSERT_SQUARE(sqSrc); lpucsqDst = PreGen.ucsqKnightMoves[sqSrc]; lpucsqPin = PreGen.ucsqKnightPins[sqSrc]; sqDst = *lpucsqDst; while (sqDst != 0) { __ASSERT_SQUARE(sqDst); if (ucpcSquares[*lpucsqPin] == 0) { pcCaptured = ucpcSquares[sqDst]; if ((pcCaptured & nOppSideTag) != 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->wmv = MOVE(sqSrc, sqDst); lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 3); // 马的价值是3 lpmvsCurr ++; } } lpucsqDst ++; sqDst = *lpucsqDst; lpucsqPin ++; } } } // 5. 生成车的着法 for (i = ROOK_FROM; i <= ROOK_TO; i ++) { sqSrc = ucsqPieces[nSideTag + i]; if (sqSrc != 0) { __ASSERT_SQUARE(sqSrc); x = FILE_X(sqSrc); y = RANK_Y(sqSrc); lpsmv = RankMovePtr(x, y); sqDst = lpsmv->ucRookCap[0] + RANK_DISP(y); __ASSERT_SQUARE(sqDst); if (sqDst != sqSrc) { pcCaptured = ucpcSquares[sqDst]; if ((pcCaptured & nOppSideTag) != 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->wmv = MOVE(sqSrc, sqDst); lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 4); // 车的价值是4 lpmvsCurr ++; } } sqDst = lpsmv->ucRookCap[1] + RANK_DISP(y); __ASSERT_SQUARE(sqDst); if (sqDst != sqSrc) { pcCaptured = ucpcSquares[sqDst]; if ((pcCaptured & nOppSideTag) != 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->wmv = MOVE(sqSrc, sqDst); lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 4); // 车的价值是4 lpmvsCurr ++; } } lpsmv = FileMovePtr(x, y); sqDst = lpsmv->ucRookCap[0] + FILE_DISP(x); __ASSERT_SQUARE(sqDst); if (sqDst != sqSrc) { pcCaptured = ucpcSquares[sqDst]; if ((pcCaptured & nOppSideTag) != 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->wmv = MOVE(sqSrc, sqDst); lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 4); // 车的价值是4 lpmvsCurr ++; } } sqDst = lpsmv->ucRookCap[1] + FILE_DISP(x); __ASSERT_SQUARE(sqDst); if (sqDst != sqSrc) { pcCaptured = ucpcSquares[sqDst]; if ((pcCaptured & nOppSideTag) != 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->wmv = MOVE(sqSrc, sqDst); lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 4); // 车的价值是4 lpmvsCurr ++; } } } } // 6. 生成炮的着法 for (i = CANNON_FROM; i <= CANNON_TO; i ++) { sqSrc = ucsqPieces[nSideTag + i]; if (sqSrc != 0) { __ASSERT_SQUARE(sqSrc); x = FILE_X(sqSrc); y = RANK_Y(sqSrc); lpsmv = RankMovePtr(x, y); sqDst = lpsmv->ucCannonCap[0] + RANK_DISP(y); __ASSERT_SQUARE(sqDst); if (sqDst != sqSrc) { pcCaptured = ucpcSquares[sqDst]; if ((pcCaptured & nOppSideTag) != 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->wmv = MOVE(sqSrc, sqDst); lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 3); // 炮的价值是3 lpmvsCurr ++; } } sqDst = lpsmv->ucCannonCap[1] + RANK_DISP(y); __ASSERT_SQUARE(sqDst); if (sqDst != sqSrc) { pcCaptured = ucpcSquares[sqDst]; if ((pcCaptured & nOppSideTag) != 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->wmv = MOVE(sqSrc, sqDst); lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 3); // 炮的价值是3 lpmvsCurr ++; } } lpsmv = FileMovePtr(x, y); sqDst = lpsmv->ucCannonCap[0] + FILE_DISP(x); __ASSERT_SQUARE(sqDst); if (sqDst != sqSrc) { pcCaptured = ucpcSquares[sqDst]; if ((pcCaptured & nOppSideTag) != 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->wmv = MOVE(sqSrc, sqDst); lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 3); // 炮的价值是3 lpmvsCurr ++; } } sqDst = lpsmv->ucCannonCap[1] + FILE_DISP(x); __ASSERT_SQUARE(sqDst); if (sqDst != sqSrc) { pcCaptured = ucpcSquares[sqDst]; if ((pcCaptured & nOppSideTag) != 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->wmv = MOVE(sqSrc, sqDst); lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 3); // 炮的价值是3 lpmvsCurr ++; } } } } // 7. 生成兵(卒)的着法 for (i = PAWN_FROM; i <= PAWN_TO; i ++) { sqSrc = ucsqPieces[nSideTag + i]; if (sqSrc != 0) { __ASSERT_SQUARE(sqSrc); lpucsqDst = PreGen.ucsqPawnMoves[sdPlayer][sqSrc]; sqDst = *lpucsqDst; while (sqDst != 0) { __ASSERT_SQUARE(sqDst); pcCaptured = ucpcSquares[sqDst]; if ((pcCaptured & nOppSideTag) != 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->wmv = MOVE(sqSrc, sqDst); lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 2); // 兵(卒)的价值是2 lpmvsCurr ++; } lpucsqDst ++; sqDst = *lpucsqDst; } } } return lpmvsCurr - lpmvs; }
// 不吃子着法生成器 int PositionStruct::GenNonCapMoves(MoveStruct *lpmvs) const { int i, sqSrc, sqDst, x, y, nSideTag; SlideMoveStruct *lpsmv; uint8_t *lpucsqDst, *lpucsqPin; MoveStruct *lpmvsCurr; // 生成不吃子着法的过程包括以下几个步骤: lpmvsCurr = lpmvs; nSideTag = SIDE_TAG(sdPlayer); // 1. 生成帅(将)的着法 sqSrc = ucsqPieces[nSideTag + KING_FROM]; if (sqSrc != 0) { __ASSERT_SQUARE(sqSrc); lpucsqDst = PreGen.ucsqKingMoves[sqSrc]; sqDst = *lpucsqDst; while (sqDst != 0) { __ASSERT_SQUARE(sqDst); // 找到一个着法后,首先判断是否吃到棋子 if (ucpcSquares[sqDst] == 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); lpmvsCurr ++; } lpucsqDst ++; sqDst = *lpucsqDst; } } // 2. 生成仕(士)的着法 for (i = ADVISOR_FROM; i <= ADVISOR_TO; i ++) { sqSrc = ucsqPieces[nSideTag + i]; if (sqSrc != 0) { __ASSERT_SQUARE(sqSrc); lpucsqDst = PreGen.ucsqAdvisorMoves[sqSrc]; sqDst = *lpucsqDst; while (sqDst != 0) { __ASSERT_SQUARE(sqDst); if (ucpcSquares[sqDst] == 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); lpmvsCurr ++; } lpucsqDst ++; sqDst = *lpucsqDst; } } } // 3. 生成相(象)的着法 for (i = BISHOP_FROM; i <= BISHOP_TO; i ++) { sqSrc = ucsqPieces[nSideTag + i]; if (sqSrc != 0) { __ASSERT_SQUARE(sqSrc); lpucsqDst = PreGen.ucsqBishopMoves[sqSrc]; lpucsqPin = PreGen.ucsqBishopPins[sqSrc]; sqDst = *lpucsqDst; while (sqDst != 0) { __ASSERT_SQUARE(sqDst); if (ucpcSquares[*lpucsqPin] == 0 && ucpcSquares[sqDst] == 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); lpmvsCurr ++; } lpucsqDst ++; sqDst = *lpucsqDst; lpucsqPin ++; } } } // 4. 生成马的着法 for (i = KNIGHT_FROM; i <= KNIGHT_TO; i ++) { sqSrc = ucsqPieces[nSideTag + i]; if (sqSrc != 0) { __ASSERT_SQUARE(sqSrc); lpucsqDst = PreGen.ucsqKnightMoves[sqSrc]; lpucsqPin = PreGen.ucsqKnightPins[sqSrc]; sqDst = *lpucsqDst; while (sqDst != 0) { __ASSERT_SQUARE(sqDst); if (ucpcSquares[*lpucsqPin] == 0 && ucpcSquares[sqDst] == 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); lpmvsCurr ++; } lpucsqDst ++; sqDst = *lpucsqDst; lpucsqPin ++; } } } // 5. 生成车和炮的着法,没有必要判断是否吃到本方棋子 for (i = ROOK_FROM; i <= CANNON_TO; i ++) { sqSrc = ucsqPieces[nSideTag + i]; if (sqSrc != 0) { __ASSERT_SQUARE(sqSrc); x = FILE_X(sqSrc); y = RANK_Y(sqSrc); lpsmv = RankMovePtr(x, y); sqDst = lpsmv->ucNonCap[0] + RANK_DISP(y); __ASSERT_SQUARE(sqDst); while (sqDst != sqSrc) { __ASSERT(ucpcSquares[sqDst] == 0); __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); lpmvsCurr ++; sqDst --; } sqDst = lpsmv->ucNonCap[1] + RANK_DISP(y); __ASSERT_SQUARE(sqDst); while (sqDst != sqSrc) { __ASSERT(ucpcSquares[sqDst] == 0); __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); lpmvsCurr ++; sqDst ++; } lpsmv = FileMovePtr(x, y); sqDst = lpsmv->ucNonCap[0] + FILE_DISP(x); __ASSERT_SQUARE(sqDst); while (sqDst != sqSrc) { __ASSERT(ucpcSquares[sqDst] == 0); __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); lpmvsCurr ++; sqDst -= 16; } sqDst = lpsmv->ucNonCap[1] + FILE_DISP(x); __ASSERT_SQUARE(sqDst); while (sqDst != sqSrc) { __ASSERT(ucpcSquares[sqDst] == 0); __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); lpmvsCurr ++; sqDst += 16; } } } // 6. 生成兵(卒)的着法 for (i = PAWN_FROM; i <= PAWN_TO; i ++) { sqSrc = ucsqPieces[nSideTag + i]; if (sqSrc != 0) { __ASSERT_SQUARE(sqSrc); lpucsqDst = PreGen.ucsqPawnMoves[sdPlayer][sqSrc]; sqDst = *lpucsqDst; while (sqDst != 0) { __ASSERT_SQUARE(sqDst); if (ucpcSquares[sqDst] == 0) { __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); lpmvsCurr ++; } lpucsqDst ++; sqDst = *lpucsqDst; } } } return lpmvsCurr - lpmvs; }
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; // 缺省是不允许升变的 }