The negamax algorithm..what's wrong?
I'm trying to program a chess game and have spent days trying to fix the code. I even tried min max but ended with the same result. The AI always starts at the corner, and moves a pawn out of the way then the rook just moves back and forth with each turn. If it get's eaten, the AI moves every piece from one side to the other until all are eaten. Do you know what could be wrong with the following code?
public Move MakeMove(int depth)
{
bestmove.reset();
bestscore = 0;
score = 0;
int maxDepth = depth;
negaMax(depth, maxDepth);
return bestmove;
}
public int EvalGame() //calculates the score from all the pieces on the board
{
int score = 0;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
if (AIboard[i, j].getPiece() != GRID.BLANK)
{
score += EvalPiece(AIboard[i, j].getPiece());
}
}
}
return score;
}
private int negaMax(int depth, int maxDepth)
{
if (depth <= 0)
{
return EvalGame();
}
int max = -200000000;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
for (int k = 0; k < 8; k++)
{
for (int l = 0; l < 8; l++)
{
if(GenerateMove(i, j, k, l)) //generates all possible moves
{
//code to move the piece on the board
board.makemove(nextmove);
score = -negaMax(depth - 1, maxDepth);
if( score > max )
{
max = score;
if (depth == maxDepth)
{
bestmove = nextmove;
}
}
//code to undo the move
board.undomove;
}
}
}
}
}
return max;
}
public bool GenerateMove(int i, int j, int k, int l)
{
Move move;
move.moveFrom.X = i;
move.moveFrom.Y = j;
move.moveTo.X = k;
move.moveTo.Y = l;
if (checkLegalMoves(move.moveTo, move.moveFrom)) //if a legal move
{
nextMove = move;
return true;
}
return false;
}
This code:
public Move MakeMove(int depth)
{
bestscore = 0;
score = 0;
int maxDepth = depth;
negaMax(depth, maxDepth);
return bestmove;
}
Notice that the best move is never set! The return score of negaMax
is compared to move alternatives. You're not even looping over the possible moves.
Also, it's really hard to look for errors, when the code you submit is not fully consistent. The negaMax
method takes two arguments one place in your code, then it take four arguments in the recursive call?
I also recommend better abstraction in your code. Separate board representation, move representation, move generation, and the search algorithm. That will help you a lot. As an example: Why do you need the depth counter in the move generation?
-Øystein
You have two possible issues:
It is somewhat ambiguous as you don't show us your variable declarations, but I think you are using too many global variables. Negamax works by calculating best moves at each node, and so while searching the values and moves should be local. In any case, it is good practice to keep the scope of variables as tight as possible. It is harder to reason about the code when traversing the game tree changes so many variables. However, your search looks like it should return the correct values.
Your evaluation does not appear to discriminate which side is playing. I don't know if EvalPiece
handles this, but in any case evaluation should be from the perspective of whichever side currently has the right to move.
You also have other issues that are not directly to your problem:
Your move generation is scary. You're pairwise traversing every possible pair of from/to squares on the board. This is highly inefficient and I don't understand how such a method would even work. You need only to loop through all the pieces on the board, or for a slower method, every square on the board (instead of 4096 squares).
MakeMove
seems like it may be the place for the root node. Right now, your scheme works, in that the last node the search exits from will be root. However, it is common to use special routines at the root such as iterative deepening, so it may be good to have a separate loop at the root.
下一篇: negamax算法..有什么不对?