public AlphaBetaReturnValue MinValue(CheckersBoard board, int alphaValue, int betaValue, PieceColor color, ref int currentDepth, ref int maxDepth, int maxDepthToSearchFor) { NodesGenerated++; var v = new AlphaBetaReturnValue(PositiveInfinity, null, currentDepth + 1); var moves = board.GetAllAvailableMoves(color).ToList().OrderByDescending(mr => mr.JumpResults.Count()).ToList(); var coTest = CutoffTest(board, currentDepth, maxDepthToSearchFor); if (coTest.HasValue && coTest.Value || !moves.Any()) { v.Value = Evaluate(board, color); v.Depth = currentDepth; return v; } if (!coTest.HasValue) { return null; } for (var i = 0; i < moves.Count; i++) { var m = moves[i]; board.MovePiece(m, color); if (currentDepth == 0 && moves.Count == 1) { v.Move = m; v.Value = Evaluate(board, color); board.RevertMove(m, color); return v; } var newDepth = currentDepth; newDepth++; var retVal = MaxValue(board, alphaValue, betaValue, color == PieceColor.Black ? PieceColor.Red : PieceColor.Black, ref newDepth, ref maxDepth, maxDepthToSearchFor); if (retVal == null) return null; retVal.Move = m; board.RevertMove(m, color); if (retVal.Depth > maxDepth) maxDepth = retVal.Depth; if(retVal.Value < v.Value) { v.Value = retVal.Value; v.Move = retVal.Move; } if (v.Value <= alphaValue) { NumberOfMinPrunes++; return retVal; } betaValue = Math.Min(betaValue, v.Value); } return v; }
// the evaluation function sums up the values of the pieces for each color and the available moves // the available moves is weighted more, and the value of the piece is determined by how close the piece is to the center of the board [favors pieces that are in the center] public int Evaluate(CheckersBoard state, PieceColor color) { int pOne = 0, pTwo = 0; for (var i = 0; i < state.Pieces.AlivePlayerOnePieces.Count; i++) { var piece = state.Pieces.AlivePlayerOnePieces[i]; pOne += 3*(state.TileBoard.Height >> 1 - Math.Abs(state.TileBoard.Height >> 1 - piece.Y)) + 3*(state.TileBoard.Width >> 1 - Math.Abs(state.TileBoard.Width >> 1 - piece.X)); } for (var i = 0; i < state.Pieces.AlivePlayerTwoPieces.Count; i++) { var piece = state.Pieces.AlivePlayerTwoPieces[i]; pTwo += 3*(state.TileBoard.Height >> 1 - Math.Abs(state.TileBoard.Height >> 1 - piece.Y)) + 3*(state.TileBoard.Width >> 1 - Math.Abs(state.TileBoard.Width >> 1 - piece.X)); } pOne += state.GetAllAvailableMoves(PieceColor.Black).Count()*10; pTwo += state.GetAllAvailableMoves(PieceColor.Red).Count()*10; return (Color == PieceColor.Black ? pOne - pTwo : pTwo - pOne); }