C# 国际象棋静止搜索太广泛
上个月,我一直在用c#创建一个简单的国际象棋引擎,并在这方面取得了一些不错的进展。它使用一个简单的Alpha-Beta算法 为了纠正地平线效应,我尝试实现静止搜索(在它工作之前失败了好几次)。发动机的强度似乎有了一些改进,但速度非常慢 以前,我可以在160秒内搜索到一个6层的深度(在游戏中期的某个地方),使用静态搜索,计算机大约需要80秒才能进入搜索深度3 强力节点计数器在深度3处约为20000个节点,而静态节点计数器高达2000万个 由于这是我的第一个国际象棋引擎,我真的不知道这些数字是否正常,或者我是否可能在静止算法中犯了错误。如果更有经验的人能告诉我BF节点/静态节点的通常比率,我将不胜感激 顺便说一句,请看一下: (只要searchdepth为0,BF树就会调用此方法)C# 国际象棋静止搜索太广泛,c#,algorithm,chess,alpha-beta-pruning,C#,Algorithm,Chess,Alpha Beta Pruning,上个月,我一直在用c#创建一个简单的国际象棋引擎,并在这方面取得了一些不错的进展。它使用一个简单的Alpha-Beta算法 为了纠正地平线效应,我尝试实现静止搜索(在它工作之前失败了好几次)。发动机的强度似乎有了一些改进,但速度非常慢 以前,我可以在160秒内搜索到一个6层的深度(在游戏中期的某个地方),使用静态搜索,计算机大约需要80秒才能进入搜索深度3 强力节点计数器在深度3处约为20000个节点,而静态节点计数器高达2000万个 由于这是我的第一个国际象棋引擎,我真的不知道这些数字是否正常
公共静态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;
}