Hello guys,
I (attempted to) incorporate the alpha-beta pruning functionality with Negamax in C# and was wondering if you could review my included code for any obvious errors?
Negamax Function:
public int NegaMax(int[,] board, int depth, int alpha, int beta)
{
Interlocked.Increment(ref _negaMaxCtr);
if (depth == 0)
{
Interlocked.Increment(ref _zeroCtr);
return EvaluateBoard(board);
}
int[,] legalMoves = GetLegalMoves(board);
var possMoveList = new List<int[]>();
int bestScore = -Int32.MaxValue;
for (int r = 0; r < 8; r++)
for (int c = 0; c < 8; c++)
if (legalMoves[r, c] == 1) possMoveList.Add(new [] { r, c });
int n = possMoveList.Count;
if (n == 0) return (EvaluateBoard(board));
for (int z = 0; z < n; z++)
{
if (_parentForm.Bgw.CancellationPending) break;
int[,] boardCopy = GetBoard(board);
int[] theMove = possMoveList[z];
MakeMove(theMove[0], theMove[1], boardCopy);
int newScore = (-1) * NegaMax(board, depth - 1, Math.Max(alpha, bestScore), -beta);
UnMakeMove(boardCopy);
if (newScore >= bestScore)
{
bestScore = newScore;
}
if (bestScore >= beta) return bestScore;
if (newScore > alpha)
alpha = newScore;
}
return alpha;
}
Evaluate Board Method:
private int EvaluateBoard(int[,] board)
{
int boardValue = 0;
const int edgePieceValue = 9;
const int cornerPieceValue = 13;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
switch (board[i, j])
{
case 1:
boardValue++;
break;
case -1:
boardValue--;
break;
}
}
}
//Corner piece evaluation
if (board[0, 0] == -1)
boardValue += cornerPieceValue;
if (board[0, 0] == 1)
boardValue -= cornerPieceValue;
if (board[0, 7] == -1)
boardValue += cornerPieceValue;
if (board[0, 7] == 1)
boardValue -= cornerPieceValue;
if (board[7, 0] == -1)
boardValue += cornerPieceValue;
if (board[7, 0] == 1)
boardValue -= cornerPieceValue;
if (board[7, 7] == -1)
boardValue += cornerPieceValue;
if (board[7, 7] == 1)
boardValue -= cornerPieceValue;
//Edge piece evaluation
for (int i = 0; i < 8; i++)
{
if (board[i, 0] == -1)
boardValue += edgePieceValue;
if (board[i, 0] == 1)
boardValue -= edgePieceValue;
if (board[i, 8 - 1] == -1)
boardValue += edgePieceValue;
if (board[i, 8 - 1] == 1)
boardValue -= edgePieceValue;
}
for (int i = 0; i < 8; i++)
{
if (board[0, i] == -1)
boardValue += edgePieceValue;
if (board[0, 0] == 1)
boardValue -= edgePieceValue;
if (board[8 - 1, i] == -1)
boardValue += edgePieceValue;
if (board[8 - 1, i] == 1)
boardValue -= edgePieceValue;
}
return boardValue;
}
FindGoodMove Method:
public int[] FindGoodMove(int depth)
{
var x = new Stopwatch();
x.Start();
Debug.Print("Started");
_zeroCtr = 0;
_negaMaxCtr = 0;
int[,] legalMoves = GetLegalMoves();
var possMoveList = new List<int[]>();
// Extract moves that are legal as a list of coordinates.
for (int r = 0; r < 8; r++)
for (int c = 0; c < 8; c++)
if (legalMoves[r, c] == 1) possMoveList.Add(new [] { r, c });
int n = possMoveList.Count;
if (n == 0) return new [] { -1, -1 }; // This shouldn't be possible!
var moveValueList = new List<int>();
for (int i = 0; i < n; i++)
{
if (_parentForm.Bgw.CancellationPending) break;
// make copy of board position
int[,] boardCopy = GetBoard();
// make the move
int[] theMove = possMoveList[i];
MakeMove(theMove[0], theMove[1], boardCopy);
moveValueList.Add(NegaMax(boardCopy, depth, -Int32.MaxValue, Int32.MaxValue));
UnMakeMove(boardCopy);
}
// Find maximum value move
x.Stop();
Debug.Print("Ended: {0}ms. Zeroes: {1}. NegaMax Entered: {2}", x.ElapsedMilliseconds, _zeroCtr, _negaMaxCtr);
var indexAtMax = moveValueList.IndexOf(moveValueList.Max());
return possMoveList[indexAtMax];
}
Please ignore the counters and debug outputs :)
Thanks for the assistance!
~ AWSLC