Ejemplo n.º 1
0
        public static void findQueenMate()
        {
            /*
             * Starting position (White to play)
             +---------------+
             |_ k _ _ _ _ _ _| 8
             |p p p p _ p p p| 7
             |_ _ _ _ _ _ _ _| 6
             |_ _ _ _ Q _ _ _| 5
             |_ _ _ _ _ _ _ _| 4
             |_ _ _ _ _ _ _ _| 3
             |_ _ _ _ _ _ _ _| 2
             |_ _ K _ _ _ _ _| 1
             +---------------+
             * A B C D E F G H
             */
            var board = BoardFactory.LoadBoardFromFen("1k6/pppp1ppp/8/4Q3/8/8/8/2K5 w - - 0 1");

            var           moves     = board.GetMoves();
            var           bestMove  = moves.FindTargetPosition(BoardStateOffset.E8);
            var           minmax    = new MinMaxAI();
            EvaluatedMove foundMove = minmax.MinMaxList(board, 1)[0];

            Assert.AreEqual(bestMove.targetPosition, foundMove.move.targetPosition);
        }
Ejemplo n.º 2
0
        public void keepPlayingEvenWhenLostSimpler()
        {
            /*
             * Starting position (Black to play)
             +---------------+
             |_ _ _ _ _ _ _ k| 8
             |p R p _ _ _ p _| 7
             |P p P _ _ _ P _| 6
             |_ P _ _ _ _ p _| 5
             |_ _ _ _ _ _ _ _| 4
             |_ _ _ _ _ _ _ _| 3
             |_ _ _ _ _ _ _ _| 2
             |_ _ _ _ _ _ _ _| 1
             +---------------+
             * A B C D E F G H
             */
            var board = BoardFactory.LoadBoardFromFen("7k/pRp3p1/PpP3P1/1P4p1/8/8/8/8 b - - 0 1");

            var moves = board.GetMoves();

            var           minmax    = new MinMaxAI();
            EvaluatedMove foundMove = minmax.MinMaxList(board, 2)[0];

            Assert.IsTrue(MoveHelper.isValidMove(foundMove.move));
        }
Ejemplo n.º 3
0
        public static void findMateIn2()
        {
            /*
             * Starting position (White to play)
             +---------------+
             |r n b k _ _ r _| 8
             |p p p p _ p B p| 7
             |_ _ _ q _ _ _ _| 6
             |_ _ _ _ _ _ _ _| 5
             |_ _ B _ _ _ Q _| 4
             |_ _ _ _ _ _ _ _| 3
             |P _ _ _ _ _ P P| 2
             |R _ _ _ R _ K _| 1
             +---------------+
             * A B C D E F G H
             */
            var board = BoardFactory.LoadBoardFromFen("rnbk2r1/pppp1pBp/3q4/8/2B3Q1/8/P5PP/R3R1K1 w - - 0 1");

            var moves = board.GetMoves();

            var           minmax    = new MinMaxAI();
            EvaluatedMove foundMove = minmax.MinMaxList(board, 3)[0];

            Assert.AreEqual(BoardStateOffset.F6, foundMove.move.targetPosition);
        }
Ejemplo n.º 4
0
        public void MinMaxTest()
        {
            var board  = BoardFactory.LoadBoardFromFen("r1b2rk1/ppq1bppp/2nppn2/8/2B1PP2/1NN1B3/PPP3PP/R2Q1RK1 w - - 0 1");
            var minmax = new MinMaxAI();

            minmax.MinMaxList(board, 5);
        }
Ejemplo n.º 5
0
        private static void AiWorker()
        {
            while (true)
            {
                if (aiWorking)
                {
                    var ai = new MinMaxAI();

                    // do actions on  virtual board for safety
                    var virtualBoard = game.Copy();

                    var aiMoves = ai.MinMaxList(virtualBoard.GetBoard(), 5, virtualBoard.AboutToTiePositions());


                    // trying alternative ways of iteration moves
                    foreach (var move in aiMoves)
                    {
                        Console.WriteLine(game.board.StandardAlgebraicNotation(move.move));
                        game.Move(move.move);
                        break;
                    }

                    aiWorking = false;
                }

                Thread.Sleep(100);
            }
        }
Ejemplo n.º 6
0
        public static void defendAgainstMate()
        {
            /*
             * Starting position (White to play)
             +---------------+
             |_ _ _ _ _ _ k _| 8
             |_ _ _ _ _ _ _ _| 7
             |_ _ _ _ _ _ _ _| 6
             |_ _ _ r _ _ _ _| 5
             |_ _ _ _ _ _ _ _| 4
             |_ _ _ _ p _ p _| 3
             |_ _ _ _ P _ P _| 2
             |_ _ N _ _ _ K _| 1
             +---------------+
             * A B C D E F G H
             * C1 -> D3 (expected line to protect against mate on D1)
             +---------------+
             |_ _ _ _ _ _ k _| 8
             |_ _ _ _ _ _ _ _| 7
             |_ _ _ _ _ _ _ _| 6
             |_ _ _ r _ _ _ _| 5
             |_ _ _ _ _ _ _ _| 4
             |_ _ _ N p _ p _| 3
             |_ _ _ _ P _ P _| 2
             |_ _ _ _ _ _ K _| 1
             +---------------+
             * A B C D E F G H
             * D5 -> D3
             +---------------+
             |_ _ _ _ _ _ k _| 8
             |_ _ _ _ _ _ _ _| 7
             |_ _ _ _ _ _ _ _| 6
             |_ _ _ _ _ _ _ _| 5
             |_ _ _ _ _ _ _ _| 4
             |_ _ _ r p _ p _| 3
             |_ _ _ _ P _ P _| 2
             |_ _ _ _ _ _ K _| 1
             +---------------+
             * A B C D E F G H
             */
            var board = BoardFactory.LoadBoardFromFen("6k1/8/8/3r4/8/4p1p1/4P1P1/2N3K1 w - - 0 1");

            var           moves     = board.GetMoves();
            var           minmax    = new MinMaxAI();
            EvaluatedMove foundMove = minmax.MinMaxList(board, 3)[0];

            // the rook has to move to e3 to defend against mate(d4->e2)
            Assert.AreEqual(BoardStateOffset.D3, foundMove.move.targetPosition);
        }
        public void Test_XMLWrite()
        {
            IArtificialIntelligence _computerIntelligence = new MinMaxAI();
            Game game = new Game(_computerIntelligence);

            game.CreateNewGame();
            string path = Path.GetDirectoryName(Path.GetDirectoryName(TestContext.TestDir)) + @"\Reversi.TestProject\Resources\TestGame.xml";

            try
            {
                XmlSerializer serializer = new XmlSerializer();
                serializer.Serialize(game.GetState(), path);
            }
            catch (Exception ex)
            {
                Assert.IsTrue(false, "Can`t write or load from xml");
            }
        }
        public void Test_XmlReadGoodPath()
        {
            IArtificialIntelligence _computerIntelligence = new MinMaxAI();
            Game game = new Game(_computerIntelligence);

            game.CreateNewGame();
            string path = Path.GetDirectoryName(Path.GetDirectoryName(TestContext.TestDir)) + @"\Reversi.TestProject\Resources\SavedGame.xml";

            try
            {
                XmlSerializer serializer = new XmlSerializer();
                GameState     state      = serializer.Deserialize(path);
                game.RestoreState(state);
            }
            catch (Exception ex)
            {
                Assert.IsTrue(false, "Can`t load from good path");
            }
        }
Ejemplo n.º 9
0
        public static void findKnightMate()
        {
            /*
             * Starting position (White to play)
             +---------------+
             |r k r _ _ _ _ _| 8
             |p p p _ _ p p p| 7
             |_ _ _ _ _ _ _ _| 6
             |_ _ _ _ N _ _ _| 5
             |_ _ _ _ _ _ _ _| 4
             |_ _ _ _ _ _ _ _| 3
             |_ _ _ _ _ _ _ _| 2
             |_ _ K _ _ _ _ _| 1
             +---------------+
             * A B C D E F G H
             */
            var board = BoardFactory.LoadBoardFromFen("rkr5/ppp2ppp/8/4N3/8/8/8/2K5 w - - 0 1");

            var           moves     = board.GetMoves();
            var           minmax    = new MinMaxAI();
            EvaluatedMove foundMove = minmax.MinMaxList(board, 1)[0];

            Assert.AreEqual(BoardStateOffset.D7, foundMove.move.targetPosition);
        }
Ejemplo n.º 10
0
        public void MinMaxDoesNotChangeAnything()
        {
            /*
             * Starting position (White to play)
             +---------------+
             |r n b q k b n r| 8
             |p p p p p p p p| 7
             |_ _ _ _ _ _ _ _| 6
             |_ _ _ _ _ _ _ _| 5
             |_ _ _ _ P _ _ _| 4
             |_ _ _ _ _ _ _ _| 3
             |P P P P _ P P P| 2
             |R N B Q K B N R| 1
             +---------------+
             * A B C D E F G H
             */
            var           board     = BoardFactory.LoadBoardFromFen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2");
            var           original  = board.CreateCopy();
            var           moves     = board.GetMoves();
            var           minmax    = new MinMaxAI();
            EvaluatedMove foundMove = minmax.MinMaxList(board, 5)[0];

            everyThingIsEqual(original, board);
        }
Ejemplo n.º 11
0
        public void keepPlayingEvenWhenLost()
        {
            /*
             * Starting position (Black to play)
             +---------------+
             |B _ _ _ _ _ _ _| 8
             |_ _ _ _ _ P R p| 7
             |_ _ _ _ N _ _ k| 6
             |_ _ _ p _ _ p _| 5
             |_ _ _ _ _ _ _ _| 4
             |_ _ _ _ P _ P _| 3
             |P _ _ _ _ _ K _| 2
             |_ _ _ _ _ _ _ _| 1
             +---------------+
             * A B C D E F G H
             */
            var board = BoardFactory.LoadBoardFromFen("B7/5PRp/4N2k/3p2p1/8/4P1P1/P5K1/8 b - - 0 2");

            var           moves     = board.GetMoves();
            var           minmax    = new MinMaxAI();
            EvaluatedMove foundMove = minmax.MinMaxList(board, 5)[0];

            Assert.IsTrue(MoveHelper.isValidMove(foundMove.move));
        }
Ejemplo n.º 12
0
        public static async Task MainAsync(string[] args)
        {
            EvalBoard.initThreadStaticVariables();
            var ai = new AIWorkerManager();
            //var history = new Stack<Move>();

            var game = ChessGame.StartGame();

            ai.spawnWorkers(3);

            //var board = BoardFactory.LoadBoardFromFen();
            bool hasCheated = false;
            int  difficulty = 5;
            bool debug      = false;

            do
            {
                Console.WriteLine(ChessOutput.AsciiBoard(game.board));
                List <Move> moves  = game.Moves().Select(move => move.move).ToList();
                Winner      winner = game.Winner();
                if (winner == Winner.WINNER_WHITE)
                {
                    Console.WriteLine("White wins");
                    break;
                }
                else if (winner == Winner.WINNER_BLACK)
                {
                    Console.WriteLine("Black wins");
                    break;
                }
                else if (winner == Winner.DRAW)
                {
                    Console.WriteLine("Its a draw!");
                    break;
                }
                do
                {
                    try {
                        Console.WriteLine("Make a move (example: \"A1 A3)\"");
                        var readLineOriginal = Console.ReadLine();
                        var readLine         = readLineOriginal.ToUpper().Split(" ").ToList();


                        switch (readLine[0])
                        {
                        case "":
                        case "HELP":
                            Console.WriteLine(@"Available commands are:
 - help                     * help
 - Cheat [depth=5]          * uses eval to find best available move(at least according to AI)
 - moves                    * lists all available moves
 - board                    * Draw the board
 - debug [y/n=y]            * enable / disable debugging
 - difficulty [number=5]    * sets difficulty (above 6 is not recommended because it is slow)
 - switch                   * Switch sides
 - botez gambit             * the best gambit
 - fen [fen]                * load Forsyth-Edwards Notation 
 - undo                     * Undo the last move
 - eval                     * get the current evaluation of the board
 - workers [workerCount]    * Specify how many worker threads the computer should use (should be less than the amount of processors you have)
 - workers                  * Read how many workers are currently being used
 - [from=D5]                * list moves for a specific field
 - [from=E2] [to=e4]        * play a move
 - [from=E7] [to=e8] [promotion=Q/R/B/N] * play a move and choose which piece you want to promote to");
                            continue;

                        case "MOVES":
                            Console.WriteLine("All available moves");
                            //var allMoves = game.board.GetMoves().Where(move => game.board.IsLegalMove(move)).ToList();
                            var allMoves = game.Moves().Select(move => move.move).ToList();
                            foreach (var move in allMoves)
                            {
                                Console.WriteLine($" - {MoveHelper.ReadableMove(move)}");
                            }
                            Console.WriteLine(ChessOutput.AsciiBoard(game.board, allMoves, true));
                            continue;

                        case "BOARD":
                            Console.WriteLine(ChessOutput.AsciiBoard(game.board));
                            continue;

                        case "BOTEZ":     // alias fall through
                        case "BOTEZ_GAMBIT":
                            if (botezGambit(game))
                            {
                                Console.WriteLine("Botez gambit found!");
                                Console.WriteLine(ChessOutput.AsciiBoard(game.board));
                                goto switchSides;
                            }
                            else
                            {
                                Console.WriteLine("Botez gambit unavailable");
                                continue;
                            }

                        case "DIFFICULTY":
                            if (readLine.Count() > 1)
                            {
                                difficulty = int.Parse(readLine[1]);
                                Console.WriteLine($"AI will now look {difficulty} moves ahead");
                            }
                            else
                            {
                                Console.WriteLine($"Current difficulty is {difficulty}");
                                continue;
                            }
                            continue;

                        case "SWITCH":
                            goto switchSides;     // the almighty goto to skip current move and the the ai make the next move, which also switches sides as a side effect

                        case "EVAL":
                            var evalMoves = game.board.GetMoves().Where(move => game.board.IsLegalMove(move)).ToList();
                            var score     = EvalBoard.evalBoard(game.board, evalMoves);
                            Console.WriteLine($"current score is: {score}");
                            continue;

                        case "FEN":
                            var fenList = readLineOriginal.Split(" ").ToList();
                            fenList.RemoveAt(0);
                            var fen = String.Join(" ", fenList);
                            //board = BoardFactory.LoadBoardFromFen(fen);
                            game = ChessGame.ContinueFromFEN(fen);
                            Console.WriteLine($"Loaded board {fen}");
                            Console.WriteLine(ChessOutput.AsciiBoard(game.board));
                            continue;

                        case "DEBUG":
                            debug = true;
                            if (readLine.Count() > 1 && readLine[1] == "N")
                            {
                                debug = false;
                                Console.WriteLine("disabled debug");
                            }
                            else
                            {
                                Console.WriteLine("enabled debug");
                            }
                            continue;

                        case "WORKERS":
                            int workerCount = 3;
                            if (readLine.Count() > 1)
                            {
                                workerCount = int.Parse(readLine[1]);
                                ai.killWorkers();
                                ai.spawnWorkers(workerCount);
                            }
                            else
                            {
                                workerCount = ai.CountWorkers();
                            }
                            Console.WriteLine($"Using {workerCount} workers");
                            continue;

                        case "UNDO":
                            hasCheated = true;

                            if (!game.UndoTurn())
                            {
                                Console.WriteLine("There is not history to undo, sorry");
                            }

                            Console.WriteLine("Undo done (cheater :p)");
                            Console.WriteLine(ChessOutput.AsciiBoard(game.board));
                            continue;

                        case "CHEAT":
                            Console.WriteLine("NOTE everything after the best move is probably not accurate");
                            int depth = 5;
                            if (readLine.Count() > 1)
                            {
                                depth = int.Parse(readLine[1]);
                            }

                            hasCheated = true;

                            List <EvaluatedMove> cheatMoves;
                            using (var progressbar = new ProgressBar()) {
                                cheatMoves = await ai.analyzeBoard(game.board, depth, game.moveHistory(), onProgress : (progress) => {
                                    progressbar.Report((double)((double)progress.progress / (double)progress.total));
                                });
                            }

                            foreach (var cheat in cheatMoves)
                            {
                                Console.WriteLine($" - {MoveHelper.ReadableMove(cheat.move)} (score: {cheat.score})");
                            }
                            continue;

                        case "CHEAT2":
                            Console.WriteLine("NOTE everything after the best move is probably not accurate");
                            int depth2 = 5;
                            if (readLine.Count() > 1)
                            {
                                depth2 = int.Parse(readLine[1]);
                            }

                            hasCheated = true;



                            //using (var progressbar = new ProgressBar()) {
                            //    cheatMoves2 = await ai.analyzeBoard(board, depth2, (progress) => {
                            //        progressbar.Report((double)((double)progress.progress / (double)progress.total));
                            //    });
                            //}
                            var minmax = new MinMaxAI();
                            List <EvaluatedMove> cheatMoves2 = minmax.MinMaxList(game.board, depth2);
                            //var cheatMoves = ParallelChess.AI.MinMaxAI.MinMaxList(board, depth);
                            foreach (var cheat in cheatMoves2)
                            {
                                Console.WriteLine($" - {MoveHelper.ReadableMove(cheat.move)} (score: {cheat.score})");
                            }
                            continue;

                        default:
                            break;
                        }

                        var fromPosition = BoardPosition.ArrayPosition(readLine[0]);
                        if (readLine.Count() == 1)
                        {
                            var positionMoves = game.board.GetMovesForPosition(fromPosition);
                            Console.WriteLine(ChessOutput.AsciiBoard(game.board, positionMoves));
                            Console.WriteLine("Legal moves:");
                            foreach (var move in positionMoves)
                            {
                                if (game.board.IsLegalMove(move))
                                {
                                    Console.WriteLine($" - {MoveHelper.ReadableMove(move)}");
                                }
                            }
                            continue;
                        }
                        var toPosition = BoardPosition.ArrayPosition(readLine[1]);
                        var promotion  = Piece.EMPTY;
                        if (readLine.Count() > 2)
                        {
                            switch (readLine[2])
                            {
                            case "Q":
                                promotion = Piece.QUEEN;
                                break;

                            case "R":
                                promotion = Piece.ROOK;
                                break;

                            case "N":
                                promotion = Piece.KNIGHT;
                                break;

                            case "B":
                                promotion = Piece.BISHOP;
                                break;

                            default:
                                Console.WriteLine("You can only promote to Queen(Q), Rook(R), Knight(N) or Bishop(B)");
                                continue;
                            }
                        }
                        var moveMade = game.Move(fromPosition, toPosition, promotion);
                        if (MoveHelper.isValidMove(moveMade.move))
                        {
                            break;
                        }
                        else
                        {
                            Console.WriteLine("invalid Move");
                        }
                    } catch (Exception e) {
                        Console.WriteLine(e.Message);
                    }
                } while(true);

                Console.WriteLine("Moved to");
switchSides:
                Console.WriteLine(ChessOutput.AsciiBoard(game.board));
                //moves = board.GetMoves();
                winner = game.Winner();
                if (winner == Winner.WINNER_WHITE)
                {
                    if (hasCheated)
                    {
                        Console.WriteLine("Cheater :D");
                    }
                    Console.WriteLine("White wins");
                    break;
                }
                else if (winner == Winner.WINNER_BLACK)
                {
                    if (hasCheated)
                    {
                        Console.WriteLine("Cheater :D");
                    }
                    Console.WriteLine("Black wins");
                    break;
                }
                else if (winner == Winner.DRAW)
                {
                    Console.WriteLine("Its a draw!");
                    break;
                }

                Console.WriteLine("AI Finding move...");
                //var bestMove = ParallelChess.AI.MinMaxAI.MinMaxList(board, 5)[0];

                if (debug)
                {
                    await ai.analyzeBoard(game.board, difficulty, game.moveHistory(), onProgress : (progress) => {
                        Console.WriteLine($"[depth {progress.depth}] {progress.progress}/{progress.total} foundScore: {progress.foundScore} on move {MoveHelper.ReadableMove(progress.move.move.move)}, found by worker {progress.move.taskId} {{ duration {progress.move.durationMS}ms }} began from score {progress.move.startFromMin}");
                    });
                }
                else
                {
                    using (var progressbar = new ProgressBar()) {
                        await ai.analyzeBoard(game.board, difficulty, game.moveHistory(), onProgress : (progress) => {
                            progressbar.Report((double)((double)progress.progress / (double)progress.total));
                        });
                    }
                }


                var bestMove = ai.GetBestMove();
                game.Move(bestMove.move);

                Console.WriteLine($"AI found move with score {bestMove.score}");
                Console.WriteLine($"AI will play {MoveHelper.ReadableMove(bestMove.move)}");
                Console.WriteLine($"FEN: {game.FEN}");
            } while (true);


            Console.WriteLine("End of game!");

            Console.ReadKey();
        }
Ejemplo n.º 13
0
    private IEnumerator handleMinMaxAi()
    {
        mmai = new MinMaxAI(redTanks, blueTanks, gs, tankSet1, tankSet2);
        CoordinateSet aiLocation;
        CoordinateSet playerLocation;
        CoordinateSet targetLocation;
        GameObject    blue;
        GameObject    red;

        targetLocation = mmai.MinMaxTurn();
        blue           = mmai.getAITank();
        red            = mmai.getPlayerTank();
        aiLocation     = new CoordinateSet((int)blue.transform.position.x, (int)blue.transform.position.z);
        tankClicked    = blue;
        tankClicked2   = red;
        bool canAt = true;

        if (!handleAttack(false))
        {
            Tank aiTank = gs.getPlayerTank(PlayerColors.Blue, aiLocation);

            Vector3    startPos = blue.transform.position;
            Vector3    endPos   = new Vector3(0, 0, 0);
            Quaternion startRot = blue.transform.rotation;
            Quaternion endRot   = Quaternion.Euler(0f, 0f, 0f);
            if (aiTank is CannonTank)
            {
                endPos = new Vector3(targetLocation.getX(), 1f, targetLocation.getY());
            }
            else
            {
                endPos = new Vector3(targetLocation.getX(), 0.8f, targetLocation.getY());
            }

            if (endPos.x > startPos.x)
            {
                endRot = Quaternion.Euler(0f, 90f, 0f);
            }
            else if (endPos.x < startPos.x)
            {
                endRot = Quaternion.Euler(0f, 270f, 0f);
            }
            else if (endPos.z > startPos.z)
            {
                endRot = Quaternion.Euler(0f, 0f, 0f);
            }
            else if (endPos.z < startPos.z)
            {
                endRot = Quaternion.Euler(0f, 180f, 0f);
            }
            else
            {
                endRot = blue.transform.rotation;
            }
            float rotStep = tankMoveSpeed * Time.fixedDeltaTime;
            float rotT    = 0;
            while (rotT <= 1.0f)
            {
                rotT += rotStep;
                blue.transform.rotation = Quaternion.Lerp(startRot, endRot, rotT);
                yield return(new WaitForFixedUpdate());
            }
            blue.transform.rotation = endRot;

            float step = (tankMoveSpeed / (startPos - endPos).magnitude) * Time.fixedDeltaTime;
            float t    = 0;
            while (t <= 1.0f)
            {
                t += step;
                blue.transform.position = Vector3.Lerp(startPos, endPos, t);
                yield return(new WaitForFixedUpdate());
            }
            blue.transform.position = endPos;

            rotT = 0;
            if (aiTank is SniperTank)
            {
                while (rotT <= 1.0f)
                {
                    rotT += rotStep;
                    blue.transform.rotation = Quaternion.Lerp(endRot, startRot, rotT);
                    yield return(new WaitForFixedUpdate());
                }
            }

            gs.checkValidMove(PlayerColors.Blue, aiLocation, targetLocation, true);

            canAt = false;
        }

        handleAttack(true);
        if (canAt)
        {
            // AI will game 1/5 of the time if it moves
            System.Random randomNumberGenerator = new System.Random();
            int           randomNumber          = randomNumberGenerator.Next(1, 3);
            if (randomNumber == 1)
            {
                CoordinateSet gambleCoordinates;
                Tank          tempTank = gs.getPlayerTank(PlayerColors.Blue, targetLocation);

                if (tempTank is EmptyTankSlot)
                {
                    gambleCoordinates = aiLocation;
                }
                else
                {
                    gambleCoordinates = targetLocation;
                }

                string powerup = gs.playerGamble(playerTurn, gambleCoordinates);
                Debug.Log("Player " + playerTurn + "'s gamble results in: " + powerup);
            }
        }
        changeTurns();
        round = Rounds.Move;
        gs.updatePlayerHealthBars(hpController);
        numGambles++;
        updateTooltips("Move1");
        aiMove = false;
    }
Ejemplo n.º 14
0
        public static void findMateIn3()
        {
            /*
             * Starting position (White to play)
             +---------------+
             |r _ b _ n _ _ r| 8
             |_ q _ n N p b k| 7
             |_ p _ p _ _ p _| 6
             |p _ _ N p P P p| 5
             |_ _ P _ P _ _ P| 4
             |_ _ _ B B _ _ _| 3
             |P P _ _ _ _ _ _| 2
             |R _ _ Q K _ _ R| 1
             +---------------+
             * A B C D E F G H
             * D1 -> H5
             +---------------+
             |r _ b _ n _ _ r| 8
             |_ q _ n N p b k| 7
             |_ p _ p _ _ p _| 6
             |p _ _ N p P P Q| 5
             |_ _ P _ P _ _ P| 4
             |_ _ _ B B _ _ _| 3
             |P P _ _ _ _ _ _| 2
             |R _ _ _ K _ _ R| 1
             +---------------+
             * A B C D E F G H
             * G6 -> H5
             +---------------+
             |r _ b _ n _ _ r| 8
             |_ q _ n N p b k| 7
             |_ p _ p _ _ _ _| 6
             |p _ _ N p P P p| 5
             |_ _ P _ P _ _ P| 4
             |_ _ _ B B _ _ _| 3
             |P P _ _ _ _ _ _| 2
             |R _ _ _ K _ _ R| 1
             +---------------+
             * A B C D E F G H
             * G5 -> G6
             +---------------+
             |r _ b _ n _ _ r| 8
             |_ q _ n N p b k| 7
             |_ p _ p _ _ P _| 6
             |p _ _ N p P _ p| 5
             |_ _ P _ P _ _ P| 4
             |_ _ _ B B _ _ _| 3
             |P P _ _ _ _ _ _| 2
             |R _ _ _ K _ _ R| 1
             +---------------+
             * A B C D E F G H
             * F7 -> G6
             +---------------+
             |r _ b _ n _ _ r| 8
             |_ q _ n N _ b k| 7
             |_ p _ p _ _ p _| 6
             |p _ _ N p P _ p| 5
             |_ _ P _ P _ _ P| 4
             |_ _ _ B B _ _ _| 3
             |P P _ _ _ _ _ _| 2
             |R _ _ _ K _ _ R| 1
             +---------------+
             * A B C D E F G H
             * F5 -> G6 (Mate)
             +---------------+
             |r _ b _ n _ _ r| 8
             |_ q _ n N _ b k| 7
             |_ p _ p _ _ P _| 6
             |p _ _ N p _ _ p| 5
             |_ _ P _ P _ _ P| 4
             |_ _ _ B B _ _ _| 3
             |P P _ _ _ _ _ _| 2
             |R _ _ _ K _ _ R| 1
             +---------------+
             * A B C D E F G H
             */
            var board = BoardFactory.LoadBoardFromFen("r1b1n2r/1q1nNpbk/1p1p2p1/p2NpPPp/2P1P2P/3BB3/PP6/R2QK2R w - - 0 1");

            var           minmax    = new MinMaxAI();
            EvaluatedMove foundMove = minmax.MinMaxList(board, 5)[0];

            //Assert.AreEqual(BoardStateOffset.H5, foundMove.move.targetPosition);
            if (!(foundMove.move.targetPosition == BoardStateOffset.H5 || foundMove.move.targetPosition == BoardStateOffset.G6))
            {
                Assert.Fail("ai has to find the move H5 or G6");
            }
        }