public List <Move> AllPosiblePiecePlays(Board board, BoardLogic boardLogic, PieceBase piece, List <Move> AllMoves, double actualValue)
        {
            board = boardLogic.GoTo(board.TurnNumber, board);
            int x = piece.Position.PositionX;
            int y = piece.Position.PositionY;

            foreach (Position position in piece.ValidMoves(board))
            {
                if (boardLogic.FinallyMove(x, y, position.x1, position.y1, board, boardLogic, false))
                {
                    // solo lo guardo si no empeora la situacion (cuanto ams negativo mejor para la pc
                    double Eval = EvaluateBoard(board);

                    if (Eval <= actualValue)
                    {
                        //actualValue = EvaluateBoard(board);
                        AllMoves.Add(new Move {
                            x1 = x, y1 = y, x2 = position.x1, y2 = position.y1
                        });
                    }
                    // back to previous board
                    board = boardLogic.GoTo(board.TurnNumber - 1, board);
                    boardLogic.futureMoves.Clear();
                }
                //}
            }
            return(AllMoves);
        }
        /// <summary>
        /// devuelve la mejor jugada que debe hacer la compu tras probar 4 movidas hacia adelante. Metodo minimax de los rústicos
        /// </summary>
        /// <param name="board"></param>
        /// <returns></returns>
        public Move BestComputerMoveDepth4(Board board, BoardLogic boardLogic)
        {
            bool Turno = board.Turn;

            board = boardLogic.GoTo(board.TurnNumber, board);
            double value = EvaluateBoard(board);

            Console.WriteLine("calculó EvaluateBoard");
            Move        BestComputerMove = null;
            List <Move> allMove1         = AllPosiblePlays(board, boardLogic);

            Console.WriteLine("calculó las AllPosiblePlays");
            foreach (Move move1 in allMove1)
            {
                if (boardLogic.FinallyMove(move1.x1, move1.y1, move1.x2, move1.y2, board, boardLogic, false))
                {
                    Move moveResponse = BestResponse(board, boardLogic);
                    boardLogic.FinallyMove(moveResponse.x1, moveResponse.y1, moveResponse.x2, moveResponse.y2, board, boardLogic, false);

                    Console.WriteLine("movio y calculo la Best Response");
                    List <Move> allMove3 = AllPosiblePlays(board, boardLogic);
                    Console.WriteLine("calculó las AllPosiblePlays luego de mover y repsonder");

                    foreach (Move move3 in allMove3)
                    {
                        if (boardLogic.FinallyMove(move3.x1, move3.y1, move3.x2, move3.y2, board, boardLogic, false))
                        {
                            Move moveResponse2 = BestResponse(board, boardLogic);
                            boardLogic.FinallyMove(moveResponse2.x1, moveResponse2.y1, moveResponse2.x2, moveResponse2.y2, board, boardLogic, false);

                            double Eval = EvaluateBoard(board);
                            if (Eval <= value)
                            {
                                value            = EvaluateBoard(board);
                                BestComputerMove = move1; //me quedo con la move1 que produce la menor bestresponse
                            }
                            // back to previous board
                            board = boardLogic.GoTo(board.TurnNumber - 2, board);
                            boardLogic.futureMoves.Clear();
                        }
                    }

                    board = boardLogic.GoTo(board.TurnNumber - 2, board);
                    boardLogic.futureMoves.Clear();
                }
            }
            if (BestComputerMove != null)
            {
                return(BestComputerMove);
            }
            Console.WriteLine("Algo raro, falla BestComputerMoveDepth4");
            return(BestResponse(board, boardLogic));
        }
        // devuelve una movida que minimiza el score y el score
        public double[] Minimize(Board board, BoardLogic boardLogic, int depth)
        {
            double minScore = 10000;

            double[] result = new double[] { 0, 0, 0, 0, EvaluateBoard(board) };
            if (Math.Abs(EvaluateBoard(board)) > 500 || depth > Constants.depthLimit)
            {
                result = new double[] { 0, 0, 0, 0, EvaluateBoard(board) };
                return(result);
            }
            HashSet <PieceBase> BackupWhitePiecesAPP = board.CloneWhitePieces();
            HashSet <PieceBase> BackupBlackPiecesAPP = board.CloneBlackPieces();
            var hashSet = board.Turn ? BackupWhitePiecesAPP : BackupBlackPiecesAPP;

            foreach (PieceBase piece in hashSet)
            {
                board = boardLogic.GoTo(board.TurnNumber, board);
                int x = piece.Position.PositionX;
                int y = piece.Position.PositionY;
                foreach (Position position in piece.ValidMoves(board))
                {
                    if (boardLogic.FinallyMove(x, y, position.x1, position.y1, board, boardLogic, false))
                    {
                        double[] maximized = Maximize(board, boardLogic, depth + 1);
                        double   Eval      = maximized[4];
                        if (Eval <= minScore)
                        {
                            minScore  = Eval;
                            result[0] = x;
                            result[1] = y;
                            result[2] = position.x1;
                            result[3] = position.y1;
                            result[4] = minScore;
                        }
                        // back to previous board
                        board = boardLogic.GoTo(board.TurnNumber - 1, board);
                        boardLogic.futureMoves.Clear();
                    }
                }
            }
            return(result);
        }
        /// <summary>
        /// devuelve la movida que mas aumenta el puntaje de un estado del tablero (o si es negativo que lo hace menos negativo) Es un metodo para simular la movida del humano
        /// </summary>
        /// <param name="board"></param>
        /// <returns></returns>
        public Move BestResponse(Board board, BoardLogic boardLogic)
        {
            bool Turno = board.Turn;

            board = boardLogic.GoTo(board.TurnNumber, board);
            double actualValue     = EvaluateBoard(board);
            Move   response        = new Move();
            Move   responseNotNull = new Move();

            HashSet <PieceBase> BackupWhitePieces = board.CloneWhitePieces();
            HashSet <PieceBase> BackupBlackPieces = board.CloneBlackPieces();
            var hashSet = board.Turn ? BackupWhitePieces : BackupBlackPieces;

            foreach (PieceBase piece in hashSet)
            {
                int i = piece.Position.PositionX;
                int j = piece.Position.PositionY;
                foreach (Position position in piece.ValidMoves(board))
                {
                    var removedPiece = board.GetPiece(position.x1, position.y1);
                    if (boardLogic.FinallyMove(i, j, position.x1, position.y1, board, boardLogic, false))
                    {
                        responseNotNull.x1 = i;
                        responseNotNull.y1 = j;
                        responseNotNull.x2 = position.x1;
                        responseNotNull.y2 = position.y1;

                        // si movió el de abajo
                        if (board.player1 != board.Turn) // va != porque el finally me lo acaba de cambiar a turn
                        {                                // guardo la mejor movida
                            double Eval = EvaluateBoard(board);
                            if (Eval >= actualValue)
                            {
                                actualValue = Eval;
                                response.x1 = i;
                                response.y1 = j;
                                response.x2 = position.x1;
                                response.y2 = position.y1;
                            }
                        }
                        else
                        {   // mueve el de arriba
                            if (EvaluateBoard(board) <= actualValue)
                            {
                                actualValue = EvaluateBoard(board);
                                response.x1 = i;
                                response.y1 = j;
                                response.x2 = position.x1;
                                response.y2 = position.y1;
                            }
                        }
                        // back to previous board
                        board = boardLogic.GoTo(board.TurnNumber - 1, board);
                        boardLogic.futureMoves.Clear();
                    }
                }
            }

            if (response != null)
            {
                return(response);
            }
            Console.WriteLine("Algo raro, falla bestResponse");
            return(responseNotNull);
        }