コード例 #1
0
ファイル: Search.cs プロジェクト: tacthgin/Games
    /// <summary>
    /// 超出边界(Fail-Soft)的Alpha-Beta搜索过程
    /// </summary>
    /// <param name="alpha"></param>
    /// <param name="beta"></param>
    /// <param name="depth"></param>
    /// <param name="noNull"></param>
    /// <returns></returns>
    public int SearchFull(int alpha, int beta, int depth, bool noNull = false)
    {
        //一个Alpha-Beta完全搜索分为以下几个阶段
        int value  = 0;
        int mvHash = 0;

        if (situation.Distance > 0)
        {
            //1.到达水平线,则调用静态搜索(注意:由于空步裁剪,深度可能小于零)
            if (depth <= 0)
            {
                return(SearchQuiesc(alpha, beta));
            }

            //1-1.检查重复局面(注意:不要再根节点检查,否则就没有走法了)
            value = situation.RepStatus();
            if (value != 0)
            {
                return(situation.RepValue(value));
            }

            //1-2.到达极限深度就返回局面评价
            if (situation.Distance == LIMIT_DEPTH)
            {
                return(situation.Evaluate());
            }

            //1-3.尝试置换表裁剪,并得到置换表走法
            value = ProbeHash(alpha, beta, depth, out mvHash);
            if (value > -ChessLogic.MATE_VALUE)
            {
                return(value);
            }

            //1-5.尝试空步裁剪(根节点的Beta值是"MATE_VALUE",所以不可能发生空步裁剪)
            if (!noNull && !situation.InCheck() && situation.NullOkey())
            {
                situation.NullMove();
                value = -SearchFull(-beta, 1 - beta, depth - ChessLogic.NULL_DEPTH - 1, true);
                situation.UndoNullMove();
                if (value > beta)
                {
                    return(value);
                }
            }
        }
        else
        {
            mvHash = 0;
        }

        //2.初始化最佳值和最佳走法
        int bestValue = -ChessLogic.MATE_VALUE; //是否一个走法都没走过(杀棋)
        int mvBest    = 0;                      //是否搜索到了Beta走法或pv走法,以便保存到历史表
        int hashFlag  = HASH_ALPHA;

        //3.初始化走法排序结构
        SortInfo sort = new SortInfo();

        sort.Init(mvHash, this);

        //4.遍历走法
        int mv = 0;

        while ((mv = sort.Next()) != 0)
        {
            if (situation.MakeMove(mv))
            {
                //将军延伸
                value = -SearchFull(-beta, -alpha, situation.InCheck() ? depth : depth - 1);
                situation.UndoMakeMove();

                //5.进行Alpha-Beta大小判断和截断
                if (value > bestValue) //找到最佳值(但不确定是Alpha、PV还是Beta走法)
                {
                    bestValue = value; //bestValue就是目前要返回的最佳值,可能超出Alpha-Beta边界

                    if (value >= beta) //找到一个Beta走法
                    {
                        mvBest = mv;
                        break;
                    }

                    if (value > alpha) //找到一个PV走法
                    {
                        mvBest = mv;   //PV走法要保存到历史表
                        alpha  = value;
                    }
                }
            }
        }

        //6.所有走法都搜索完了,把最佳走法(不能是Alpha走法)保存到历史表,返回最佳值
        if (bestValue == -ChessLogic.MATE_VALUE)
        {
            //如果是杀棋,就根据最佳走法保存到历史表
            return(situation.Distance - ChessLogic.MATE_VALUE);
        }

        //记录到置换表
        RecordHash(hashFlag, bestValue, depth, mvBest);

        if (mvBest != 0)
        {
            //如果不是Alpha走法,就将最佳走法保存到历史表中
            SetBestMove(mvBest, depth);
            if (situation.Distance == 0)
            {
                //搜索根节点时,总是有一个最佳走法(因为全窗口搜索不会超出边界),将这个走法保存下来
                mvResult = mvBest;
            }
        }

        return(bestValue);
    }