Beispiel #1
0
/* 判断获取置换表要符合哪些条件,置换表的分值针对四个不同的区间有不同的处理:
 * 一、如果分值在"WIN_VALUE"以内(即介于"-WIN_VALUE"到"WIN_VALUE"之间,下同),则只获取满足搜索深度要求的局面;
 * 二、如果分值在"WIN_VALUE"和"BAN_VALUE"之间,则不能获取置换表中的值(只能获取最佳着法仅供参考),目的是防止由于长将而导致的“置换表的不稳定性”;
 * 三、如果分值在"BAN_VALUE"以外,则获取局面时不必考虑搜索深度要求,因为这些局面已经被证明是杀棋了;
 * 四、如果分值是"DrawValue()"(是第一种情况的特殊情况),则不能获取置换表中的值(原因与第二种情况相同)。
 * 注意:对于第三种情况,要对杀棋步数进行调整!
 */
inline int ValueAdjust(const PositionStruct &pos, bool &bBanNode, bool &bMateNode, int vl) {
  bBanNode = bMateNode = false;
  if (vl > WIN_VALUE) {
    if (vl <= BAN_VALUE) {
      bBanNode = true;
    } else {
      bMateNode = true;
      vl -= pos.nDistance;
    }
  } else if (vl < -WIN_VALUE) {
    if (vl >= -BAN_VALUE) {
      bBanNode = true;
    } else {
      bMateNode = true;
      vl += pos.nDistance;
    }
  } else if (vl == pos.DrawValue()) {
    bBanNode = true;
  }
  return vl;
}
Beispiel #2
0
// 存储置换表局面信息
void RecordHash(const PositionStruct &pos, int nFlag, int vl, int nDepth, int mv) {
  HashStruct hsh;
  int i, nHashDepth, nMinDepth, nMinLayer;
  // 存储置换表局面信息的过程包括以下几个步骤:

  // 1. 对分值做杀棋步数调整;
  __ASSERT_BOUND(1 - MATE_VALUE, vl, MATE_VALUE - 1);
  __ASSERT(mv == 0 || pos.LegalMove(mv));
  if (vl > WIN_VALUE) {
    if (mv == 0 && vl <= BAN_VALUE) {
      return; // 导致长将的局面(不进行置换裁剪)如果连最佳着法也没有,那么没有必要写入置换表
    }
    vl += pos.nDistance;
  } else if (vl < -WIN_VALUE) {
    if (mv == 0 && vl >= -BAN_VALUE) {
      return; // 同理
    }
    vl -= pos.nDistance;
  } else if (vl == pos.DrawValue() && mv == 0) {
    return;   // 同理
  }

  // 2. 逐层试探置换表;
  nMinDepth = 512;
  nMinLayer = 0;
  for (i = 0; i < HASH_LAYERS; i ++) {
    hsh = HASH_ITEM(pos, i);

    // 3. 如果试探到一样的局面,那么更新置换表信息即可;
    if (HASH_POS_EQUAL(hsh, pos)) {
      // 如果深度更深,或者边界缩小,都可更新置换表的值
      if ((nFlag & HASH_ALPHA) != 0 && (hsh.ucAlphaDepth <= nDepth || hsh.svlAlpha >= vl)) {
        hsh.ucAlphaDepth = nDepth;
        hsh.svlAlpha = vl;
      }
      // Beta结点要注意:不要用Null-Move的结点覆盖正常的结点
      if ((nFlag & HASH_BETA) != 0 && (hsh.ucBetaDepth <= nDepth || hsh.svlBeta <= vl) && (mv != 0 || hsh.wmv == 0)) {
        hsh.ucBetaDepth = nDepth;
        hsh.svlBeta = vl;
      }
      // 最佳着法是始终覆盖的
      if (mv != 0) {
        hsh.wmv = mv;
      }
      HASH_ITEM(pos, i) = hsh;
      return;
    }

    // 4. 如果不是一样的局面,那么获得深度最小的置换表项;
    nHashDepth = MAX((hsh.ucAlphaDepth == 0 ? 0 : hsh.ucAlphaDepth + 256),
        (hsh.wmv == 0 ? hsh.ucBetaDepth : hsh.ucBetaDepth + 256));
    __ASSERT(nHashDepth < 512);
    if (nHashDepth < nMinDepth) {
      nMinDepth = nHashDepth;
      nMinLayer = i;
    }
  }

  // 5. 记录置换表。
  hsh.dwZobristLock0 = pos.zobr.dwLock0;
  hsh.dwZobristLock1 = pos.zobr.dwLock1;
  hsh.wmv = mv;
  hsh.ucAlphaDepth = hsh.ucBetaDepth = 0;
  hsh.svlAlpha = hsh.svlBeta = 0;
  if ((nFlag & HASH_ALPHA) != 0) {
    hsh.ucAlphaDepth = nDepth;
    hsh.svlAlpha = vl;
  }
  if ((nFlag & HASH_BETA) != 0) {
    hsh.ucBetaDepth = nDepth;
    hsh.svlBeta = vl;
  }
  HASH_ITEM(pos, nMinLayer) = hsh;
}
Beispiel #3
0
// 调整型局面评价函数
inline int Evaluate(const PositionStruct &pos, int vlAlpha, int vlBeta) {
  int vl;
  vl = Search.bKnowledge ? pos.Evaluate(vlAlpha, vlBeta) : pos.Material();
  return vl == pos.DrawValue() ? vl - 1 : vl;
}