BOOL _PositionStruct::Checked() const { int i, j, sqSrc, sqDst; int pcSelfSide, pcOppSide, pcDst, nDelta; pcSelfSide = SIDE_TAG(sdPlayer); pcOppSide = OPP_SIDE_TAG(sdPlayer); for (sqSrc = 0; sqSrc < 256; sqSrc ++) { if (ucpcSquares[sqSrc] != pcSelfSide + PIECE_KING) { continue; } if (ucpcSquares[SQUARE_FORWARD(sqSrc, sdPlayer)] == pcOppSide + PIECE_PAWN) { return TRUE; } for (nDelta = -1; nDelta <= 1; nDelta += 2) { if (ucpcSquares[sqSrc + nDelta] == pcOppSide + PIECE_PAWN) { return TRUE; } } for (i = 0; i < 4; i ++) { if (ucpcSquares[sqSrc + ccAdvisorDelta[i]] != 0) { continue; } for (j = 0; j < 2; j ++) { pcDst = ucpcSquares[sqSrc + ccKnightCheckDelta[i][j]]; if (pcDst == pcOppSide + PIECE_KNIGHT) { return TRUE; } } } for (i = 0; i < 4; i ++) { nDelta = ccKingDelta[i]; sqDst = sqSrc + nDelta; while (IN_BOARD(sqDst)) { pcDst = ucpcSquares[sqDst]; if (pcDst != 0) { if (pcDst == pcOppSide + PIECE_ROOK || pcDst == pcOppSide + PIECE_KING) { return TRUE; } break; } sqDst += nDelta; } sqDst += nDelta; while (IN_BOARD(sqDst)) { int pcDst = ucpcSquares[sqDst]; if (pcDst != 0) { if (pcDst == pcOppSide + PIECE_CANNON) { return TRUE; } break; } sqDst += nDelta; } } return FALSE; } return FALSE; }
// “捉”的检测 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; }
int _PositionStruct::GenerateMovesFrom(int sqSrc, int *mvs, BOOL bCapture) const { int i, j, nGenMoves, nDelta, sqDst; int pcSelfSide, pcOppSide, pcSrc, pcDst; nGenMoves = 0; pcSelfSide = SIDE_TAG(sdPlayer); pcOppSide = OPP_SIDE_TAG(sdPlayer); if (sqSrc >= 0 && sqSrc < 256) { pcSrc = ucpcSquares[sqSrc]; if ((pcSrc & pcSelfSide) == 0) { return nGenMoves; } 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 { break; } sqDst += nDelta; } sqDst += nDelta; while (IN_BOARD(sqDst)) { pcDst = ucpcSquares[sqDst]; if (pcDst != 0) { if ((pcDst & pcOppSide) != 0) { mvs[nGenMoves] = MOVE(sqSrc, sqDst); nGenMoves ++; } break; } sqDst += nDelta; } } break; case PIECE_PAWN: sqDst = SQUARE_FORWARD(sqSrc, sdPlayer); if (IN_BOARD(sqDst)) { pcDst = ucpcSquares[sqDst]; if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) { mvs[nGenMoves] = MOVE(sqSrc, sqDst); nGenMoves ++; } } if (AWAY_HALF(sqSrc, sdPlayer)) { for (nDelta = -1; nDelta <= 1; nDelta += 2) { sqDst = sqSrc + nDelta; if (IN_BOARD(sqDst)) { pcDst = ucpcSquares[sqDst]; if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) { mvs[nGenMoves] = MOVE(sqSrc, sqDst); nGenMoves ++; } } } } break; } } return nGenMoves; }
// 吃子着法生成器,按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; }