Пример #1
0
        // Gets the move from minimax, then makes the move, returns the board at every stage of the move
        public List <Board> MakeMove(Board board, BackgroundWorker worker, ref int CountSinceLastTake)
        {
            CalculatedMove Move = NegaMax(DepthOfSearch, IsWhite ? 1 : -1, float.MinValue, float.MaxValue, board, worker);

            if (Move.MoveFrom.CouldBeTakeMove(Move.Moveset.First()))
            {
                CountSinceLastTake = 0;
            }
            else
            {
                CountSinceLastTake++;
            }

            // if the search has failed, this should never run
            if (!Move.MoveFrom.InBoard())
            {
                return(new List <Board>());
            }
            else
            {
                // Generate and return boards
                List <Board> Boardstates = new List <Board>();
                Piece        MovingPiece = board.GetPiece(Move.MoveFrom);
                foreach (Position move in Move.Moveset.Moves)
                {
                    board.MovePeice(MovingPiece.CurrentPosition, move);
                    Boardstates.Add(board.MakeNewCopyOf());
                }
                return(Boardstates);
            }
        }
Пример #2
0
        // Searches Depth moves ahead in the game and finds the best move
        private CalculatedMove NegaMax(int Depth, int PlayerColour, float alpha, float beta, Board board, BackgroundWorker worker)
        {
            // Setup
            float          BestValue       = float.MinValue;
            bool           FoundTakeMove   = false;
            bool           AppliedTakeMove = false;
            List <MoveSet> possibleMovesets;

            List <Position> usablepieces = new List <Position>();

            if (PlayerColour == 1)
            {
                usablepieces = board.GetWhitePositions();
            }
            else
            {
                usablepieces = board.GetBlackPositions();
            }

            //Show the tree (to the console)
            if (Debug && Depth > 0)
            {
                Console.WriteLine();
                for (int p = 0; p < (DepthOfSearch - Depth); p++)
                {
                    Console.Write("\t");
                }

                if ((DepthOfSearch % 2 == Depth % 2 && IsWhite) || (DepthOfSearch % 2 != Depth % 2 && !IsWhite))
                {
                    Console.Write("> MAX | ");
                }
                else
                {
                    Console.Write("> MIN | ");
                }

                Console.Write("Depth: " + Depth.ToString());
                Console.WriteLine();
            }
            if (Debug)
            {
                ShowBoard(board, Depth + 1);
            }

            // detect if we should stop
            if (Depth == 0 || usablepieces.Count == 0 || board.WhiteHasWon() || board.BlackHasWon())
            {
                return(new CalculatedMove(PlayerColour * board.EvaluateBoard(), new Position(-1, -1), new MoveSet()));
            }

            // If we can carry on searching, setup BestPiece and BestMoveset with first valid move we come accross
            Position BestPiecePosition = new Position(-1, -1);
            MoveSet  BestMoveset       = new MoveSet();

            foreach (Position p in usablepieces)
            {
                BestPiecePosition = p;
                if (board.GetPiece(p).GetMoves(board).Count > 0)
                {
                    BestMoveset = board.GetPiece(p).GetMoves(board).First();
                    break;
                }
            }

            // Counts the number of pieces we have searched
            int piececount = 0;

            foreach (Position pieceposition in usablepieces)
            {
                if (Debug)
                {
                    Console.WriteLine();
                    for (int p = -1; p < (DepthOfSearch - Depth); p++)
                    {
                        Console.Write("\t");
                    }
                    Console.WriteLine("NEW PIECE at " + pieceposition.ToString());
                }

                // generate all possible take movesets
                possibleMovesets = board.GetPiece(pieceposition).GetTakeMovesOnly(board);
                if (possibleMovesets.Count > 0)
                {
                    if (!FoundTakeMove && !AppliedTakeMove)
                    {
                        // if this is the first piece that has take movesets, mark it so that every move is better than what we had.
                        FoundTakeMove = true;
                    }
                }
                else if (!FoundTakeMove)
                {
                    possibleMovesets = board.GetPiece(pieceposition).GetMoves(board);
                }

                if (Debug)
                {
                    for (int p = 0; p < (DepthOfSearch - Depth); p++)
                    {
                        Console.Write("\t");
                    }
                    Console.WriteLine("Take Moves found: " + FoundTakeMove);
                }

                bool BreakOuterLoop = false;
                foreach (MoveSet moveset in possibleMovesets)
                {
                    // Make test board
                    Board testboard = board.MakeNewCopyOf();

                    // Make move
                    Position oldpos = pieceposition;
                    foreach (Position move in moveset.Moves)
                    {
                        testboard.MovePeice(oldpos, move);
                        oldpos = move;
                    }

                    // Run the search
                    CalculatedMove Move = NegaMax(Depth - 1, -PlayerColour, -beta, -alpha, testboard, worker);

                    // Change the best result if we need to
                    if (BestValue < Move.Value || (FoundTakeMove && !AppliedTakeMove))
                    {
                        if (FoundTakeMove && !AppliedTakeMove)
                        {
                            AppliedTakeMove = true;
                        }

                        BestMoveset       = moveset;
                        BestPiecePosition = pieceposition;

                        if (Debug && Move.Moveset.NumberOfStages() > 0)
                        {
                            for (int p = 0; p < (DepthOfSearch - Depth); p++)
                            {
                                Console.Write("\t");
                            }
                            Console.WriteLine("New best move from " + Move.MoveFrom.ToString() + " to " + Move.Moveset.Last().ToString() + " with score of: " + Move.Value.ToString() + " breating previous of: " + BestValue.ToString());
                        }
                        BestValue = Move.Value;
                    }
                    alpha = Math.Max(alpha, BestValue);

                    if (Debug)
                    {
                        for (int p = -1; p < (DepthOfSearch - Depth); p++)
                        {
                            Console.Write("\t");
                        }
                        Console.WriteLine(" | Current Board Score: " + (PlayerColour * testboard.EvaluateBoard()).ToString() + " | Best Value: " + BestValue.ToString());
                    }

                    if (alpha >= beta && UsePruning)
                    {
                        if (Debug)
                        {
                            for (int p = 0; p < (DepthOfSearch - Depth); p++)
                            {
                                Console.Write("\t");
                            }
                            Console.WriteLine(alpha.ToString() + " " + beta.ToString() + "Broke");
                        }
                        BreakOuterLoop = true;
                        break;
                    }
                }

                // If its the first call (highest depth) and we have finished a piece, report back to the worker our progress
                if (Depth == DepthOfSearch)
                {
                    worker.ReportProgress((int)(100f * piececount) / usablepieces.Count);
                }
                piececount++;

                if (BreakOuterLoop)
                {
                    break;
                }
            }
            return(new CalculatedMove(BestValue, BestPiecePosition, BestMoveset));
        }