コード例 #1
0
ファイル: genmoves.cpp プロジェクト: QiuleiWang/eleeye
// “捉”的检测
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;
}
コード例 #2
0
ファイル: genmoves.cpp プロジェクト: QiuleiWang/eleeye
// 不吃子着法生成器
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;
}
コード例 #3
0
ファイル: genmoves.cpp プロジェクト: QiuleiWang/eleeye
// 吃子着法生成器,按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;
}
コード例 #4
0
ファイル: genmoves.cpp プロジェクト: QiuleiWang/eleeye
// 棋子保护判断
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;
}
コード例 #5
0
ファイル: preeval.cpp プロジェクト: StevenLOL/ChessQ
void PositionStruct::PreEvaluate(void) {
  int i, sq, nMidgameValue, nWhiteAttacks, nBlackAttacks, nWhiteSimpleValue, nBlackSimpleValue;
  uint8_t ucvlPawnPiecesAttacking[256], ucvlPawnPiecesAttackless[256];

  if (!bInit) {
    bInit = true;
    // 初始化"PreEvalEx.cPopCnt16"数组,只需要初始化一次
    for (i = 0; i < 65536; i ++) {
      PreEvalEx.cPopCnt16[i] = PopCnt16(i);
    }
  }

  // 首先判断局势处于开中局还是残局阶段,方法是计算各种棋子的数量,按照车=6、马炮=3、其它=1相加。
  nMidgameValue = PopCnt32(this->dwBitPiece & BOTH_BITPIECE(ADVISOR_BITPIECE | BISHOP_BITPIECE | PAWN_BITPIECE)) * OTHER_MIDGAME_VALUE;
  nMidgameValue += PopCnt32(this->dwBitPiece & BOTH_BITPIECE(KNIGHT_BITPIECE | CANNON_BITPIECE)) * KNIGHT_CANNON_MIDGAME_VALUE;
  nMidgameValue += PopCnt32(this->dwBitPiece & BOTH_BITPIECE(ROOK_BITPIECE)) * ROOK_MIDGAME_VALUE;
  // 使用二次函数,子力很少时才认为接近残局
  nMidgameValue = (2 * TOTAL_MIDGAME_VALUE - nMidgameValue) * nMidgameValue / TOTAL_MIDGAME_VALUE;
  __ASSERT_BOUND(0, nMidgameValue, TOTAL_MIDGAME_VALUE);
  PreEval.vlAdvanced = (TOTAL_ADVANCED_VALUE * nMidgameValue + TOTAL_ADVANCED_VALUE / 2) / TOTAL_MIDGAME_VALUE;
  __ASSERT_BOUND(0, PreEval.vlAdvanced, TOTAL_ADVANCED_VALUE);
  for (sq = 0; sq < 256; sq ++) {
    if (IN_BOARD(sq)) {
      PreEval.ucvlWhitePieces[0][sq] = PreEval.ucvlBlackPieces[0][SQUARE_FLIP(sq)] = (uint8_t)
          ((cucvlKingPawnMidgameAttacking[sq] * nMidgameValue + cucvlKingPawnEndgameAttacking[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE);
      PreEval.ucvlWhitePieces[3][sq] = PreEval.ucvlBlackPieces[3][SQUARE_FLIP(sq)] = (uint8_t)
          ((cucvlKnightMidgame[sq] * nMidgameValue + cucvlKnightEndgame[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE);
      PreEval.ucvlWhitePieces[4][sq] = PreEval.ucvlBlackPieces[4][SQUARE_FLIP(sq)] = (uint8_t)
          ((cucvlRookMidgame[sq] * nMidgameValue + cucvlRookEndgame[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE);
      PreEval.ucvlWhitePieces[5][sq] = PreEval.ucvlBlackPieces[5][SQUARE_FLIP(sq)] = (uint8_t)
          ((cucvlCannonMidgame[sq] * nMidgameValue + cucvlCannonEndgame[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE);
      ucvlPawnPiecesAttacking[sq] = PreEval.ucvlWhitePieces[0][sq];
      ucvlPawnPiecesAttackless[sq] = (uint8_t)
          ((cucvlKingPawnMidgameAttackless[sq] * nMidgameValue + cucvlKingPawnEndgameAttackless[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE);
    }
  }
  for (i = 0; i < 16; i ++) {
    PreEvalEx.vlHollowThreat[i] = cvlHollowThreat[i] * (nMidgameValue + TOTAL_MIDGAME_VALUE) / (TOTAL_MIDGAME_VALUE * 2);
    __ASSERT_BOUND(0, PreEvalEx.vlHollowThreat[i], cvlHollowThreat[i]);
    PreEvalEx.vlCentralThreat[i] = cvlCentralThreat[i];
  }

  // 然后判断各方是否处于进攻状态,方法是计算各种过河棋子的数量,按照车马2炮兵1相加。
  nWhiteAttacks = nBlackAttacks = 0;
  for (i = SIDE_TAG(0) + KNIGHT_FROM; i <= SIDE_TAG(0) + ROOK_TO; i ++) {
    if (this->ucsqPieces[i] != 0 && BLACK_HALF(this->ucsqPieces[i])) {
      nWhiteAttacks += 2;
    }
  }
  for (i = SIDE_TAG(0) + CANNON_FROM; i <= SIDE_TAG(0) + PAWN_TO; i ++) {
    if (this->ucsqPieces[i] != 0 && BLACK_HALF(this->ucsqPieces[i])) {
      nWhiteAttacks ++;
    }
  }
  for (i = SIDE_TAG(1) + KNIGHT_FROM; i <= SIDE_TAG(1) + ROOK_TO; i ++) {
    if (this->ucsqPieces[i] != 0 && WHITE_HALF(this->ucsqPieces[i])) {
      nBlackAttacks += 2;
    }
  }
  for (i = SIDE_TAG(1) + CANNON_FROM; i <= SIDE_TAG(1) + PAWN_TO; i ++) {
    if (this->ucsqPieces[i] != 0 && WHITE_HALF(this->ucsqPieces[i])) {
      nBlackAttacks ++;
    }
  }
  // 如果本方轻子数比对方多,那么每多一个轻子(车算2个轻子)威胁值加2。威胁值最多不超过8。
  nWhiteSimpleValue = PopCnt16(this->wBitPiece[0] & ROOK_BITPIECE) * 2 + PopCnt16(this->wBitPiece[0] & (KNIGHT_BITPIECE | CANNON_BITPIECE));
  nBlackSimpleValue = PopCnt16(this->wBitPiece[1] & ROOK_BITPIECE) * 2 + PopCnt16(this->wBitPiece[1] & (KNIGHT_BITPIECE | CANNON_BITPIECE));
  if (nWhiteSimpleValue > nBlackSimpleValue) {
    nWhiteAttacks += (nWhiteSimpleValue - nBlackSimpleValue) * 2;
  } else {
    nBlackAttacks += (nBlackSimpleValue - nWhiteSimpleValue) * 2;
  }
  nWhiteAttacks = MIN(nWhiteAttacks, TOTAL_ATTACK_VALUE);
  nBlackAttacks = MIN(nBlackAttacks, TOTAL_ATTACK_VALUE);
  PreEvalEx.vlBlackAdvisorLeakage = TOTAL_ADVISOR_LEAKAGE * nWhiteAttacks / TOTAL_ATTACK_VALUE;
  PreEvalEx.vlWhiteAdvisorLeakage = TOTAL_ADVISOR_LEAKAGE * nBlackAttacks / TOTAL_ATTACK_VALUE;
  __ASSERT_BOUND(0, nWhiteAttacks, TOTAL_ATTACK_VALUE);
  __ASSERT_BOUND(0, nBlackAttacks, TOTAL_ATTACK_VALUE);
  __ASSERT_BOUND(0, PreEvalEx.vlBlackAdvisorLeakage, TOTAL_ADVISOR_LEAKAGE);
  __ASSERT_BOUND(0, PreEvalEx.vlBlackAdvisorLeakage, TOTAL_ADVISOR_LEAKAGE);
  for (sq = 0; sq < 256; sq ++) {
    if (IN_BOARD(sq)) {
      PreEval.ucvlWhitePieces[1][sq] = PreEval.ucvlWhitePieces[2][sq] = (uint8_t) ((cucvlAdvisorBishopThreatened[sq] * nBlackAttacks +
          (PreEval.bPromotion ? cucvlAdvisorBishopPromotionThreatless[sq] : cucvlAdvisorBishopThreatless[sq]) * (TOTAL_ATTACK_VALUE - nBlackAttacks)) / TOTAL_ATTACK_VALUE);
      PreEval.ucvlBlackPieces[1][sq] = PreEval.ucvlBlackPieces[2][sq] = (uint8_t) ((cucvlAdvisorBishopThreatened[SQUARE_FLIP(sq)] * nWhiteAttacks +
          (PreEval.bPromotion ? cucvlAdvisorBishopPromotionThreatless[SQUARE_FLIP(sq)] : cucvlAdvisorBishopThreatless[SQUARE_FLIP(sq)]) * (TOTAL_ATTACK_VALUE - nWhiteAttacks)) / TOTAL_ATTACK_VALUE);
      PreEval.ucvlWhitePieces[6][sq] = (uint8_t) ((ucvlPawnPiecesAttacking[sq] * nWhiteAttacks +
          ucvlPawnPiecesAttackless[sq] * (TOTAL_ATTACK_VALUE - nWhiteAttacks)) / TOTAL_ATTACK_VALUE);
      PreEval.ucvlBlackPieces[6][sq] = (uint8_t) ((ucvlPawnPiecesAttacking[SQUARE_FLIP(sq)] * nBlackAttacks +
          ucvlPawnPiecesAttackless[SQUARE_FLIP(sq)] * (TOTAL_ATTACK_VALUE - nBlackAttacks)) / TOTAL_ATTACK_VALUE);
    }
  }
  for (i = 0; i < 16; i ++) {
    PreEvalEx.vlWhiteBottomThreat[i] = cvlBottomThreat[i] * nBlackAttacks / TOTAL_ATTACK_VALUE;
    PreEvalEx.vlBlackBottomThreat[i] = cvlBottomThreat[i] * nWhiteAttacks / TOTAL_ATTACK_VALUE;
  }

  // 检查预评价是否对称
#ifndef NDEBUG
  for (sq = 0; sq < 256; sq ++) {
    if (IN_BOARD(sq)) {
      for (i = 0; i < 7; i ++) {
        __ASSERT(PreEval.ucvlWhitePieces[i][sq] == PreEval.ucvlWhitePieces[i][SQUARE_MIRROR(sq)]);
        __ASSERT(PreEval.ucvlBlackPieces[i][sq] == PreEval.ucvlBlackPieces[i][SQUARE_MIRROR(sq)]);
      }
    }
  }
  for (i = FILE_LEFT; i <= FILE_RIGHT; i ++) {
    __ASSERT(PreEvalEx.vlWhiteBottomThreat[i] == PreEvalEx.vlWhiteBottomThreat[FILE_FLIP(i)]);
    __ASSERT(PreEvalEx.vlBlackBottomThreat[i] == PreEvalEx.vlBlackBottomThreat[FILE_FLIP(i)]);
  }
#endif

  // 调整不受威胁方少掉的仕(士)相(象)分值
  this->vlWhite = ADVISOR_BISHOP_ATTACKLESS_VALUE * (TOTAL_ATTACK_VALUE - nBlackAttacks) / TOTAL_ATTACK_VALUE;
  this->vlBlack = ADVISOR_BISHOP_ATTACKLESS_VALUE * (TOTAL_ATTACK_VALUE - nWhiteAttacks) / TOTAL_ATTACK_VALUE;
  // 如果允许升变,那么不受威胁的仕(士)相(象)分值就少了一半
  if (PreEval.bPromotion) {
    this->vlWhite /= 2;
    this->vlBlack /= 2;
  }
  // 最后重新计算子力位置分
  for (i = 16; i < 32; i ++) {
    sq = this->ucsqPieces[i];
    if (sq != 0) {
      __ASSERT_SQUARE(sq);
      this->vlWhite += PreEval.ucvlWhitePieces[PIECE_TYPE(i)][sq];
    }
  }
  for (i = 32; i < 48; i ++) {
    sq = this->ucsqPieces[i];
    if (sq != 0) {
      __ASSERT_SQUARE(sq);
      this->vlBlack += PreEval.ucvlBlackPieces[PIECE_TYPE(i)][sq];
    }
  }
}