我目前正在尝试编写国际象棋引擎。我写了一个简单的 AlphaBeta Minimax 和 MaterialBalance 评估(链接如下)。我正在使用 SebLagues Chess Challenge Project 来编程我的国际象棋引擎 (https://github.com/SebLague/Chess-Challenge)。我面临的问题是,深度为 4 时,我的引擎无法预见简单的将死,而深度为 4 时应该可以预见。我找不到错误,所以我认为更多的眼对可以有所帮助。
机器人只是做出奇怪的动作。如果白色获胜,则评估函数返回正值;如果黑色获胜(按预期),则评估函数返回负值,但机器人只是牺牲了所有数字,所以我认为它是搜索类或 Think 方法中的内容
PS:我是为自己做这件事,所以我没有挑战中给出的界限(这就是我上几门课等的原因)
主要课程:
public class TRACER : IChessBot
{
//Constant Variables
private const int DEPTH = 4; //Search depth
//Used classes
Search findMove = new Search();
public Move Think(Board board, Timer timer)
{
//Variables
int moveScore; //Score a certain move has
int bestScore = int.MinValue; //Score of the current best move (low value on start to guarantee update)
int nodeSearched = 0; //Number of nodes searched
Move bestMove; //Current best move to be played
//Generate all legal possible moves
Move[] moves = board.GetLegalMoves();
bestMove = moves[0];
foreach (Move currentMove in moves)
{
//for every move -> make move virtually and evaluate how good it is
board.MakeMove(currentMove);
moveScore = findMove.MiniMaxAB(board, DEPTH, int.MinValue, int.MaxValue, board.IsWhiteToMove);
board.UndoMove(currentMove);
//if the score of this move is better than the current best -> switch
if (moveScore > bestScore)
{
bestScore = moveScore;
bestMove = currentMove;
}
nodeSearched++;
Debug.WriteLine("currentMove:{0} | moveScore:{1}", currentMove, moveScore);
}
Debug.WriteLine("---- bestMove:{0} | bestScore:{1} ----", bestMove, bestScore);
return bestMove;
}
}
搜索类别:
namespace Chess_Challenge.src.TRACER
{
internal class Search
{
//used Classes
Evaluation eval = new Evaluation();
//NegaMax AlphaBeta Pruning Algorith -> returns a high value for the current play (regardless of colour)
public int MiniMaxAB(Board board, int depth, int alpha, int beta, bool maximizingPlayer)
{
//Variables
int moveScore; //score of the current move
//if depth is reached then evaluate position
if (depth == 0)
return eval.EvaluatePosition(board) * (maximizingPlayer ? -1 : 1);
//if player is checkmated return low value (bad for white) or high value (bad for black)
if (board.IsInCheckmate())
return board.IsWhiteToMove ? int.MinValue : int.MaxValue;
//if game is a draw return equal
if (board.IsDraw())
return 0;
//Get all legal moves
Move[] moves = board.GetLegalMoves();
//for every legal move get the best move for black and white
if (maximizingPlayer)
{
moveScore = int.MinValue;
foreach (Move move in moves)
{
board.MakeMove(move);
moveScore = MiniMaxAB(board, depth - 1, alpha, beta, !maximizingPlayer);
board.UndoMove(move);
alpha = Math.Max(alpha, moveScore);
if (beta <= alpha)
break;
}
return moveScore;
}
else
{
moveScore = int.MaxValue;
foreach (Move move in moves)
{
board.MakeMove(move);
moveScore = MiniMaxAB(board, depth - 1, alpha, beta, !maximizingPlayer);
board.UndoMove(move);
beta = Math.Min(beta, moveScore);
if (beta <= alpha)
break;
}
return moveScore;
}
}
}
}
评估班:
namespace Chess_Challenge.src.TRACER
{
internal class Evaluation
{
// Piece values: ., P, K, B, R, Q, K
private static readonly int[] mgPieceValues = { 0, 80, 335, 363, 460, 940, 100000};
private static readonly int[] egPieceValues = { 0, 100, 305, 333, 563, 950, 100000};
//Endgame Transition
private int egT(Board board)
{
return BitOperations.PopCount(board.AllPiecesBitboard);
}
//Get the value of a single piece regarding all parameters .TODO
public int EvaluatePosition(Board board)
{
int whiteMaterial = 0;
int blackMaterial = 0;
for (PieceType pieceType = PieceType.Pawn; pieceType <= PieceType.King; pieceType++)
{
whiteMaterial += mgPieceValues[(int)pieceType] * BitOperations.PopCount(board.GetPieceBitboard(pieceType, true));
blackMaterial += mgPieceValues[(int)pieceType] * BitOperations.PopCount(board.GetPieceBitboard(pieceType, false));
}
return whiteMaterial - blackMaterial;
}
}
}
我知道物料平衡是有效的,我认为它是在搜索功能中我没有找到的东西。或者也许这只是我大脑中的一些逻辑错误。
[引擎决定不保护pawn而是滑车的图片][1] [1]:https://i.stack.imgur.com/z4jQD.png
我认为交换这两个调用的顺序将大大有助于解决您缺少 N 中的伙伴的问题。如果对手的最后一招将死了你,那么你有多少额外的材料都没有关系!
if (board.IsInCheckmate())
return board.IsWhiteToMove ? int.MinValue : int.MaxValue;
if (depth == 0)
return eval.EvaluatePosition(board) * (maximizingPlayer ? -1 : 1);
//if player is checkmated return low value (bad for white) or high value (bad for black)
我还没有尝试过这些特定的测试位置,但它们看起来非常适合您现在所处的测试阶段。 GIT 中心 国际象棋测试位置。
您需要编写一个例程来加载 FEN 板描述,但它提供了一种设置测试位置和查找错误的好方法。然后,您还可以设计自己的测试来检查您的程序是否执行正确的操作。
我找不到我在网上使用的那些,但它们可能有点太难了。它们实际上是一组用 FEN 表示法表示的测试位置,供初学者使用,伴侣为 1,2,3,4,.. 逐渐变得更难(带有答案)。