C# 国际象棋静止搜索太广泛

C# 国际象棋静止搜索太广泛,c#,algorithm,chess,alpha-beta-pruning,C#,Algorithm,Chess,Alpha Beta Pruning,上个月,我一直在用c#创建一个简单的国际象棋引擎,并在这方面取得了一些不错的进展。它使用一个简单的Alpha-Beta算法 为了纠正地平线效应,我尝试实现静止搜索(在它工作之前失败了好几次)。发动机的强度似乎有了一些改进,但速度非常慢 以前,我可以在160秒内搜索到一个6层的深度(在游戏中期的某个地方),使用静态搜索,计算机大约需要80秒才能进入搜索深度3 强力节点计数器在深度3处约为20000个节点,而静态节点计数器高达2000万个 由于这是我的第一个国际象棋引擎,我真的不知道这些数字是否正常

上个月,我一直在用c#创建一个简单的国际象棋引擎,并在这方面取得了一些不错的进展。它使用一个简单的Alpha-Beta算法

为了纠正地平线效应,我尝试实现静止搜索(在它工作之前失败了好几次)。发动机的强度似乎有了一些改进,但速度非常慢

以前,我可以在160秒内搜索到一个6层的深度(在游戏中期的某个地方),使用静态搜索,计算机大约需要80秒才能进入搜索深度3

强力节点计数器在深度3处约为20000个节点,而静态节点计数器高达2000万个

由于这是我的第一个国际象棋引擎,我真的不知道这些数字是否正常,或者我是否可能在静止算法中犯了错误。如果更有经验的人能告诉我BF节点/静态节点的通常比率,我将不胜感激

顺便说一句,请看一下: (只要searchdepth为0,BF树就会调用此方法)

公共静态int-QuiescentValue(棋盘、int-Alpha、int-Beta)
{
静止节点++;
int MinMax=Board.WhoseMove;//1=maximierend,-1=minimierend
int计数器=0;
int最大计数;
int tempValue=0;
int currentAlpha=α;
int currentBeta=Beta;
int QuietWorth=chEvaluation.Evaluate(董事会);
if(MinMax==1)//Max
{
如果(QuietWorth>=currentBeta)
返回电流β;
如果(静态>当前Alpha)
currentAlpha=QuietWorth;
}
else//Min
{
如果(QuietWorth=currentBeta)
{
返回电流β;
}
如果(tempValue>currentAlpha)
{
currentAlpha=温度值;
}
}
else//minimierend
{

如果(tempValue我不熟悉英语术语,那么,
HitMove
是从板上移除一块的动作吗

在这种情况下,我觉得您可以使用
GetAllHitMoves
来获取“嘈杂”列表静止搜索的移动,然后比通常的3层或6层进行更深入的计算。这是递归调用的,因此只要有可能剩余的命中移动,就可以反复计算。对静止搜索进行限制应该可以解决性能问题

至于选择静止搜索的限制,wiki声明:

现代国际象棋引擎可以搜索比最小值深2到3倍的某些棋步


你看了吗?有一条评论并不是针对静态搜索的:对于像国际象棋这样的游戏,修改同一个棋盘然后撤销移动通常要快得多,而不是为每个探测复制整个棋盘。@DeadZone:我确实看了链接的帖子,但问题似乎是这个家伙在静态中生成了所有移动Scene search(我没有)。@内部服务器错误:谢谢你的建议,这可能会对以后有所帮助。现在,我不认为复制电路板有什么关系,因为我估计每秒可以复制大约25000次电路板(虽然我的整个引擎目前正在以每秒72万个节点进行搜索。谢谢,这似乎是我一直在寻找的。我将静止搜索限制为4 plys,搜索突然又快了很多!我将标记你的答案。编辑:你能告诉我有限静止搜索对搜索结果的影响有多严重吗?TY在哪种情况下注意?通过设置静止搜索的限制,显然可以在静止层限制附近再次产生某种地平线效应。但是,除非您评估每一个可能的移动(接近您之前所做的),否则您将无法避免这种情况.关于性能的另一个注意事项-您是每回合重新评估整个电路板,还是将计算结果存储在某个位置,以便只需评估每个节点的一次移动?如果存储结果,您可能能够增加铺层深度,同时将运行时保持在2-3分钟左右(或者只是将时间减少很多)@H W:1)是的,我有点担心搜索限制带来的地平线效应。但这似乎还没有发生。2)我想你脑子里有哈希表/转置表,以便对移动进行排序?这肯定是下一步的一步,但我必须进一步研究。不过谢谢你的建议。
public static int QuiescentValue(chessBoard Board, int Alpha, int Beta)
    {
        QuiescentNodes++;

        int MinMax = Board.WhoseMove; // 1 = maximierend, -1 = minimierend
        int Counter = 0;
        int maxCount;


        int tempValue = 0;
        int currentAlpha = Alpha;
        int currentBeta = Beta;
        int QuietWorth = chEvaluation.Evaluate(Board);

        if(MinMax == 1) //Max
        {
            if (QuietWorth >= currentBeta)
                return currentBeta;
            if (QuietWorth > currentAlpha)
                currentAlpha = QuietWorth;
        }

        else            //Min
        {
            if (QuietWorth <= currentAlpha)
                return currentAlpha;
            if (QuietWorth < currentBeta)
                currentBeta = QuietWorth;
        }




        List<chMove> HitMoves = GetAllHitMoves(Board);
        maxCount = HitMoves.Count;

        if(maxCount == 0)
            return chEvaluation.Evaluate(Board);


        chessBoard tempBoard;

        while (Counter < maxCount)
        {
            tempBoard = new chessBoard(Board);
            tempBoard.Move(HitMoves[Counter]);
            tempValue = QuiescentValue(tempBoard, currentAlpha, currentBeta);

            if (MinMax == 1) //maximierend
            {
                if (tempValue >= currentBeta)
                {
                    return currentBeta;
                }

                if (tempValue > currentAlpha)
                {
                    currentAlpha = tempValue;
                }

            }

            else            //minimierend
            {
                if (tempValue <= currentAlpha)
                {
                    return currentAlpha;
                }
                if (tempValue < currentBeta)
                {
                    currentBeta = tempValue;
                }
            }

            Counter++;
        }

        if (MinMax == 1)
            return currentAlpha;
        else
            return currentBeta;

    }