/* 计算MVV(LVA)值的函数 * * MVV(LVA)指的是:如果被吃子无保护,那么取值MVV,否则取值MVV-LVA。 * 由于ElephantEye的MVV(LVA)值在计算完毕后再加了1,并且有其它考虑,因此有以下几种含义: * a. MVV(LVA)大于1,说明被吃子价值大于攻击子(表面上是赚的),这种吃子将首先搜索,静态搜索也将考虑这种吃子; * b. MVV(LVA)等于1,说明被吃子有一定价值(吃车马炮或吃过河兵卒,即便表面上是亏的,也值得一试),静态搜索也将考虑这种吃子; * c. MVV(LVA)等于0,说明被吃子没有价值,静态搜索将不考虑这种吃子。 * * MVV价值表"SIMPLE_VALUE"是按照帅(将)=5、车=4、马炮=3、兵(卒)=2、仕(士)相(象)=1设定的; * LVA价值直接体现在吃子着法生成器中。 */ int PositionStruct::MvvLva(int sqDst, int pcCaptured, int nLva) const { int nMvv, nLvaAdjust; nMvv = SIMPLE_VALUE(pcCaptured); nLvaAdjust = (Protected(OPP_SIDE(sdPlayer), sqDst) ? nLva : 0); if (nMvv >= nLvaAdjust) { return nMvv - nLvaAdjust + 1; } else { return (nMvv >= 3 || HOME_HALF(sqDst, sdPlayer)) ? 1 : 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; }
// 棋子保护判断 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; }