//public Dictionary<Point, CheckerPiece> CheckerPieceMap { get; set; }
 //copy constructor
 public CheckerBoard(CheckerBoard other)
 {
     Board = other.Board;
     MustJump = new[] { other.MustJump[0], other.MustJump[1] };
     SelectedPiece = null;
     JumpMade = null;
     AllPieces = new List<CheckerPiece>(other.AllPieces.Count());
     for (var i = 0; i < other.AllPieces.Count(); i++)
     {
         AllPieces.Add(new CheckerPiece(other.AllPieces[i].Row, other.AllPieces[i].Col, other.AllPieces[i].Color, other.AllPieces[i].Status));
         if (other.JumpMade == null) continue;
         if (other.AllPieces[i] == other.JumpMade)
         {
             JumpMade = AllPieces[i];
         }
     }
 }
        public List<MoveSet> CheckJumpMove(CheckerBoard currentBoard, CheckerPiece piece)
        {
            var row = piece.Row;
            var col = piece.Col;

            var jumpMoves = new List<MoveSet>();
            var possibleLocation = new List<Point>{new Point(1, -1), new Point(1, 1), new Point(-1, -1), new Point(-1, 1)};

            //Goes to each adjacent tile
            foreach(var location in possibleLocation)
            {
                //Get the adjacent piece that will be jumped
                var targetPiece = currentBoard.GetCheckerPiece(row + location.X, col + location.Y);

                //if the piece exists and the color is the opposite color
                if (targetPiece != null && targetPiece.Color != piece.Color)
                {
                    //Check if there is a empty space after that piece and there is no piece at the location
                    if (Board.CheckValidTile(row + 2 * location.X, col + 2 * location.Y) && currentBoard.GetCheckerPiece(row + 2 * location.X, col + 2 * location.Y) == null)
                    {
                        var jump = new MoveSet(row + 2 * location.X, col + 2 * location.Y);

                        //Check continuous jumps
                        //Generate a copy of the board

                        var nextBoard = new CheckerBoard(currentBoard);
                        nextBoard.SelectedPiece = nextBoard.GetCheckerPiece(piece.Row, piece.Col);
                        nextBoard.MustJump[piece.Color] = true;
                        //Move
                        nextBoard.HandleMove(row + 2 * location.X, col + 2 * location.Y);

                        //Keep checking for jump moves
                        var nextJumps = CheckJumpMove(nextBoard, nextBoard.SelectedPiece);
                        if (nextJumps.Any())
                        {
                            foreach (var nextJump in nextJumps)
                            {
                                var branch = new MoveSet(jump);
                                branch.MoveList.AddRange(nextJump.MoveList);
                                jumpMoves.Add(branch);
                            }
                        }
                        else
                        {
                            jumpMoves.Add(jump);
                        }
                    }
                }
            }
            return jumpMoves;
        }
        int MinValue(CheckerBoard currentBoard, int depth, int alpha, int beta, int currentPlayer)
        {
            if (_nodeGeneration % 10000 == 0 && _nodeGeneration != 0)
            {
                Console.WriteLine("Max Depth: {0}", _maxDepth);
                Console.WriteLine("# of Pruning in Max: {0}", _maxPruning);
                Console.WriteLine("# of Pruning in Min: {0}", _minPruning);
                Console.WriteLine("# of Node Generated: {0}", _nodeGeneration);
                Console.WriteLine("Time Elapsed: {0}", TimeElapsed);
            }
            CheckerStatus status = currentBoard.GetStatus(_currentTurn);

            if (status != CheckerStatus.Continue)
            {
                return (int) status;
            }

            _maxDepth = Math.Max(_maxDepth, depth);
            if (depth == Difficulty )
                return currentBoard.EvaluateBoard(_currentTurn);
            int v = 999;
            //For each movable piece
            for (var i = 0; i < currentBoard.MovablePieces[currentPlayer].Count(); i++)
            {
                //for each possible positions that the piece can go
                for (var j = 0; j < currentBoard.MoveDict[currentBoard.MovablePieces[currentPlayer][i]].Count(); j++)
                {
                    _nodeGeneration++;
                    //For each possible move make a new checkerboard and move it
                    var newCheckerBoard = new CheckerBoard(currentBoard);
                    var selectedPiece = newCheckerBoard.GetCheckerPiece(currentBoard.MovablePieces[currentPlayer][i].Row, currentBoard.MovablePieces[currentPlayer][i].Col);
                    newCheckerBoard.SelectedPiece = selectedPiece;
                    newCheckerBoard.HandleMove(currentBoard.MoveDict[currentBoard.MovablePieces[currentPlayer][i]][j]);
                    newCheckerBoard.CheckAllAvailableMoves();
                    int nextTurn = newCheckerBoard.AINextTurn(currentPlayer);

                    v = Math.Min(v, MaxValue(newCheckerBoard, depth + 1, alpha, beta, nextTurn));
                    //pruning
                    if (v <= alpha)
                    {
                        _minPruning++;
                        return v;
                    }

                    if (v < beta)
                    {
                        beta = v;
                        if (currentBoard == _checkerBoard)
                        {
                            _bestMoveSet = currentBoard.MoveDict[currentBoard.MovablePieces[currentPlayer][i]][j];
                            _bestPiece = currentBoard.MovablePieces[currentPlayer][i];
                        }
                    }
                }
            }
            return v;
        }
        //Gets the Max Value
        int MaxValue(CheckerBoard currentBoard, int depth, int alpha, int beta, int currentPlayer)
        {
            if (_nodeGeneration % 10000 == 0 && _nodeGeneration !=0)
            {
                Console.WriteLine("Max Depth: {0}", _maxDepth);
                Console.WriteLine("# of Pruning in Max: {0}", _maxPruning);
                Console.WriteLine("# of Pruning in Min: {0}", _minPruning);
                Console.WriteLine("# of Node Generated: {0}", _nodeGeneration);
                Console.WriteLine("Time Elapsed: {0}", TimeElapsed);
            }
            //Checks to see if it is a utility value
            CheckerStatus status = currentBoard.GetStatus(_currentTurn);

            //If it is return the value
            if (status != CheckerStatus.Continue)
            {
                return (int) status;
            }

            _maxDepth = Math.Max(_maxDepth, depth);

            //Depth Limiter
            if (depth == Difficulty )
                return currentBoard.EvaluateBoard(_currentTurn);
            var v = -999;

            //Iterate through every movable pieces
            for (var i = 0; i < currentBoard.MovablePieces[currentPlayer].Count(); i++)
            {
                //Iterate through every possible move for the selected piece
                for (var j = 0; j < currentBoard.MoveDict[currentBoard.MovablePieces[currentPlayer][i]].Count(); j++)
                {
                    //Increment node counter
                    _nodeGeneration++;
                    //For each possible move make a new checkerboard and move it
                    var newCheckerBoard = new CheckerBoard(currentBoard);

                    //Select the piece that will be moved
                    var selectedPiece = newCheckerBoard.GetCheckerPiece(currentBoard.MovablePieces[currentPlayer][i].Row, currentBoard.MovablePieces[currentPlayer][i].Col);
                    newCheckerBoard.SelectedPiece = selectedPiece;

                    //Move the piece to a piece location
                    newCheckerBoard.HandleMove(currentBoard.MoveDict[currentBoard.MovablePieces[currentPlayer][i]][j]);

                    newCheckerBoard.CheckAllAvailableMoves();

                    var nextTurn = newCheckerBoard.AINextTurn(currentPlayer);

                    v = Math.Max(v, MinValue(newCheckerBoard, depth + 1, alpha, beta, nextTurn));

                    if (v >= beta)
                    {
                        _maxPruning++;
                        return v;
                    }

                    if (v > alpha)
                    {
                        alpha = v;
                        if (currentBoard == _checkerBoard)
                        {
                            _bestMoveSet = currentBoard.MoveDict[currentBoard.MovablePieces[currentPlayer][i]][j];
                            _bestPiece = currentBoard.MovablePieces[currentPlayer][i];
                        }
                    }
                }
            }
            return v;
        }
 void AlphaBetaSearch(CheckerBoard currentBoard, int playerColor)
 {
     _maxPruning = 0;
     _minPruning = 0;
     _maxDepth = 0;
     TimeElapsed = 0;
     MaxValue(currentBoard, 0, -999, 999, playerColor);
 }
 /// <summary>
 /// Allows the game to perform any initialization it needs to before starting to run.
 /// This is where it can query for any required services and load any non-graphic
 /// related content.  Calling base.Initialize will enumerate through any components
 /// and initialize them as well.
 /// </summary>
 protected override void Initialize()
 {
     _maxPruning = 0;
     _minPruning = 0;
     _maxDepth = 0;
     _timer = 0;
     _nodeGeneration = 0;
     _checkerBoard = new CheckerBoard(Rows, Cols);
     _cam = new Camera {Pos = new Vector2(0, 0)};
     _particleManager = new ParticleManager();
     _screenManager = new UIScreenManager();
     _setupForm = new SetupForm(this);
     _drawDriver = new DrawDriver();
     base.Initialize();
 }