コード例 #1
0
        private long CalculatePlacementCount(BoardState board, PieceBitmap justPlacedBitmap, int justPlacedX, int justPlacedY, List <PieceDefinition> plannedFuturePieces, int depth)
        {
            long placementCount = PowCache[depth];

            //We are as deep as we are allowed to go, or we are out of pieces to place
            if (_depth == depth || plannedFuturePieces.Count == depth)
            {
                return(placementCount);
            }

            board.Place(justPlacedBitmap, justPlacedX, justPlacedY);


            //Now calculate how many placements the next piece can have
            var nextPiece = plannedFuturePieces[depth];

            for (var index = 0; index < nextPiece.PossibleOrientations.Length; index++)
            {
                var bitmap = nextPiece.PossibleOrientations[index];
                for (int x = 0; x < BoardState.Width - bitmap.Width + 1; x++)
                {
                    for (int y = 0; y < BoardState.Height - bitmap.Height + 1; y++)
                    {
                        if (board.CanPlace(bitmap, x, y))
                        {
                            placementCount += CalculatePlacementCount(board, bitmap, x, y, plannedFuturePieces, depth + 1);
                        }
                    }
                }
            }

            return(placementCount);
        }
コード例 #2
0
            public override void Reset()
            {
                base.Reset();

                PieceToPurchase = null;
                PlaceBitmap     = null;
                PlaceX          = -1;
                PlaceY          = -1;
            }
コード例 #3
0
        public Preplacement Preplace(BoardState board, List <PieceDefinition> plannedFuturePieces)
        {
            PieceBitmap resultBitmap = null;
            int         resultX      = -1;
            int         resultY      = -1;

            //How many placements the next future piece has for our best found placement (more is better)
            long bestPlacementCount = -1;
            //Tie break when there is a draw, based on distance to 0,0 (less is better)
            int bestTieBreaker = -1;

            foreach (var bitmap in plannedFuturePieces[0].PossibleOrientations)
            {
                for (int x = 0; x < BoardState.Width - bitmap.Width + 1; x++)
                {
                    for (int y = 0; y < BoardState.Height - bitmap.Height + 1; y++)
                    {
                        if (board.CanPlace(bitmap, x, y))
                        {
                            long placementCount = CalculatePlacementCount(board, bitmap, x, y, plannedFuturePieces, 1);

                            var tieBreaker = x + y;
                            if (placementCount > bestPlacementCount || (placementCount == bestPlacementCount && tieBreaker < bestTieBreaker))
                            {
                                bestPlacementCount = placementCount;
                                bestTieBreaker     = tieBreaker;

                                resultBitmap = bitmap;
                                resultX      = x;
                                resultY      = y;
                            }
                        }
                    }
                }
            }

            if (resultBitmap == null)
            {
                throw new Exception("Cannot place the first piece");
            }

            return(new Preplacement(resultBitmap, resultX, resultY));
        }
        private void TryPlacement(BoardState board, PieceBitmap bitmap, int x, int y, ref PieceBitmap resultBitmap, ref int resultX, ref int resultY, ref int bestLeastHoles, ref int bestLargestHole, ref int bestDistance, List <int> holes)
        {
            board.Place(bitmap, x, y);

            holes.Clear();
            PlacementHelper.HoleCount(board, ref holes);

            //TODO: Remove LINQ
            var distance = x + y;             //TODO: Try direct

            if (holes.Count < bestLeastHoles || (holes.Count == bestLeastHoles && holes.Max() > bestLargestHole) || (holes.Count == bestLeastHoles && holes.Max() == bestLargestHole && distance < bestDistance))
            {
                bestLeastHoles  = holes.Count;
                bestLargestHole = holes.Max();
                bestDistance    = distance;

                resultBitmap = bitmap;
                resultX      = x;
                resultY      = y;
            }
        }
コード例 #5
0
        private static void CalculateScore(BoardState board, PieceBitmap bitmap, int placeX, int placeY, bool doubler, out int score)
        {
            board.Place(bitmap, placeX, placeY);

            score = CalculateScore(board, doubler, 0, BoardState.Width, 0, BoardState.Height);
        }
コード例 #6
0
        protected override bool TryPlacePiece(BoardState board, PieceDefinition piece, out PieceBitmap resultBitmap, out int resultX, out int resultY)
        {
            resultBitmap = null;
            resultX      = -1;
            resultY      = -1;

            //TODO: We could do better with a good tiebreaker
            int bestScore       = int.MaxValue;
            int tieBreakerScore = int.MaxValue;
            int tiedForBest     = 0;

            foreach (var bitmap in piece.PossibleOrientations)
            {
                for (int x = 0; x < BoardState.Width - bitmap.Width + 1; x++)
                {
                    for (int y = 0; y < BoardState.Height - bitmap.Height + 1; y++)
                    {
                        if (board.CanPlace(bitmap, x, y))
                        {
                            CalculateScore(board, bitmap, x, y, _doubler, out var score);
                            if (score < bestScore)
                            {
                                bestScore       = score;
                                tieBreakerScore = x + y;

                                resultBitmap = bitmap;
                                resultX      = x;
                                resultY      = y;
                                tiedForBest  = 0;
                            }
                            else if (score == bestScore)
                            {
                                tiedForBest++;

                                int ourTieBreaker = x + y;

                                if (ourTieBreaker < tieBreakerScore)
                                {
                                    //Console.WriteLine("Beat the tie");
                                    tieBreakerScore = ourTieBreaker;

                                    resultBitmap = bitmap;
                                    resultX      = x;
                                    resultY      = y;
                                }
                            }
                        }
                    }
                }
            }

            //if (tiedForBest > 0)
            //	Console.WriteLine($"{_doubler} {tiedForBest}");

            return(resultBitmap != null);
        }
コード例 #7
0
        protected override bool TryPlacePiece(BoardState board, PieceDefinition piece, out PieceBitmap resultBitmap, out int resultX, out int resultY)
        {
            int smallestSize = BoardState.Height * BoardState.Width + 1;

            resultBitmap = null;
            resultX      = 0;
            resultY      = 0;

            //TODO: If we weren't a singleton we could track our used Width/Height
            int currentHeight = CalcUsedHeight(ref board);
            int currentWidth  = CalcUsedWidth(ref board);

            //Console.WriteLine($"Current {currentWidth}x{currentHeight}");

            for (var x = 0; x < BoardState.Width; x++)
            {
                for (var y = 0; y < BoardState.Height; y++)
                {
                    foreach (var bitmap in piece.PossibleOrientations)
                    {
                        var size = Math.Max(currentWidth, x + bitmap.Width) * Math.Max(currentHeight, y + bitmap.Height);

                        if (size < smallestSize && x + bitmap.Width <= BoardState.Width && y + bitmap.Height <= BoardState.Height && board.CanPlace(bitmap, x, y))
                        {
                            smallestSize = size;
                            resultBitmap = bitmap;
                            resultX      = x;
                            resultY      = y;
                        }
                    }
                }
            }

            return(resultBitmap != null);
        }
コード例 #8
0
        protected override bool TryPlacePiece(BoardState board, PieceDefinition piece, out PieceBitmap resultBitmap, out int resultX, out int resultY)
        {
            foreach (var bitmap in piece.PossibleOrientations)
            {
                for (var y = 0; y <= BoardState.Height - bitmap.Height; y++)
                {
                    for (var x = 0; x <= BoardState.Width - bitmap.Width; x++)
                    {
                        if (board.CanPlace(bitmap, x, y))
                        {
                            resultBitmap = bitmap;
                            resultX      = x;
                            resultY      = y;
                            return(true);
                        }
                    }
                }
            }

            resultBitmap = null;
            resultX      = -1;
            resultY      = -1;
            return(false);
        }
コード例 #9
0
        public void PlayerPlacedPiece(int player, PieceDefinition piece, int x, int y, PieceBitmap bitmap)
        {
            Console.WriteLine($"Player {player} placed {piece.Name} at {x},{y}");

            if (PrintBoardsAfterPlacement)
            {
                PrintBoards(true);
            }
        }
コード例 #10
0
 public Preplacement(PieceBitmap bitmap, int x, int y)
 {
     Bitmap = bitmap;
     X      = x;
     Y      = y;
 }
コード例 #11
0
        protected override bool TryPlacePiece(BoardState board, PieceDefinition piece, out PieceBitmap resultBitmap, out int resultX, out int resultY)
        {
            var holes = new List <int>();

            int leastHoles      = BoardState.Width * BoardState.Height;
            int largestHoleSize = 0;

            resultBitmap = null;
            resultX      = -1;
            resultY      = -1;


            //TODO: Distance could be < the piece size too
            for (var distance = 0; distance < BoardState.Width + BoardState.Height; distance++)
            {
                //TODO: Min(distance, Width - bitmap.MinSideSize) ?
                for (var x = 0; x <= distance; x++)
                {
                    var y = distance - x;

                    foreach (var bitmap in piece.PossibleOrientations)
                    {
                        if (x + bitmap.Width <= BoardState.Width && y + bitmap.Height <= BoardState.Height && board.CanPlace(bitmap, x, y))
                        {
                            var clone = board;
                            clone.Place(bitmap, x, y);

                            holes.Clear();
                            PlacementHelper.HoleCount(clone, ref holes);

                            //TODO: No Linq
                            if (holes.Count < leastHoles || (holes.Count == leastHoles && holes.Max() > largestHoleSize))
                            {
                                leastHoles      = holes.Count;
                                largestHoleSize = holes.Max();

                                resultBitmap = bitmap;
                                resultX      = x;
                                resultY      = y;
                            }
                        }
                    }
                }

                if (resultBitmap != null)
                {
                    return(true);
                }
            }

            return(false);
        }
        protected override bool TryPlacePiece(BoardState board, PieceDefinition piece, out PieceBitmap resultBitmap, out int resultX, out int resultY)
        {
            resultBitmap = null;
            resultX      = -1;
            resultY      = -1;

            int bestLeastHoles  = BoardState.Width * BoardState.Height + 1;
            int bestLargestHole = BoardState.Width * BoardState.Height + 1;
            int bestDistance    = BoardState.Width * BoardState.Height + 1;
            var holes           = new List <int>();

            foreach (var bitmap in piece.PossibleOrientations)
            {
                //TODO: Try at 0, 0
                if (board.CanPlace(bitmap, 0, 0))
                {
                    TryPlacement(board, bitmap, 0, 0, ref resultBitmap, ref resultX, ref resultY, ref bestLeastHoles, ref bestLargestHole, ref bestDistance, holes);
                }

                for (var x = 0; x <= BoardState.Width - bitmap.Width; x++)
                {
                    //You can only place in a position if you couldn't place in the previous position, or if you can't place in the next position
                    bool couldPlaceBefore = true;

                    for (var y = 0; y <= BoardState.Height - bitmap.Height; y++)
                    {
                        var canPlaceNow = board.CanPlace(bitmap, x, y);

                        if (!couldPlaceBefore && canPlaceNow)
                        {
                            //Try here
                            TryPlacement(board, bitmap, x, y, ref resultBitmap, ref resultX, ref resultY, ref bestLeastHoles, ref bestLargestHole, ref bestDistance, holes);
                        }
                        if (couldPlaceBefore && !canPlaceNow && y > 0)
                        {
                            //try at previous place
                            // TODO May have already been tried (optimization, record the last tried place?)
                            TryPlacement(board, bitmap, x, y - 1, ref resultBitmap, ref resultX, ref resultY, ref bestLeastHoles, ref bestLargestHole, ref bestDistance, holes);
                        }

                        couldPlaceBefore = canPlaceNow;
                    }
                }

                //Do a y then x loop as well
                for (var y = 0; y <= BoardState.Height - bitmap.Height; y++)
                {
                    //You can only place in a position if you couldn't place in the previous position, or if you can't place in the next position
                    bool couldPlaceBefore = true;

                    for (var x = 0; x <= BoardState.Width - bitmap.Width; x++)
                    {
                        var canPlaceNow = board.CanPlace(bitmap, x, y);

                        if (!couldPlaceBefore && canPlaceNow)
                        {
                            //Try here
                            //TODO May have already tried this in the x,y loop above
                            TryPlacement(board, bitmap, x, y, ref resultBitmap, ref resultX, ref resultY, ref bestLeastHoles, ref bestLargestHole, ref bestDistance, holes);
                        }
                        if (couldPlaceBefore && !canPlaceNow && x > 0)
                        {
                            //try at previous place
                            // TODO May have already been tried (optimization, record the last tried place?)
                            //TODO May have already tried this in the x,y loop above
                            TryPlacement(board, bitmap, x - 1, y, ref resultBitmap, ref resultX, ref resultY, ref bestLeastHoles, ref bestLargestHole, ref bestDistance, holes);
                        }

                        couldPlaceBefore = canPlaceNow;
                    }
                }
            }

            return(resultBitmap != null);
        }
コード例 #13
0
 public void PlayerPlacedPiece(int player, PieceDefinition piece, int x, int y, PieceBitmap bitmap)
 {
 }
コード例 #14
0
        protected override bool TryPlacePiece(BoardState board, PieceDefinition piece, out PieceBitmap resultBitmap, out int resultX, out int resultY)
        {
            _evaluator.BeginEvaluation(board);

            resultBitmap = null;
            resultX      = -1;
            resultY      = -1;

            int bestScore = int.MinValue;

            //Exhaustively place it and make new child nodes
            for (var index = 0; index < piece.PossibleOrientations.Length; index++)
            {
                var bitmap       = piece.PossibleOrientations[index];
                var searchWidth  = BoardState.Width - bitmap.Width + 1;
                var searchHeight = BoardState.Height - bitmap.Height + 1;

                //TODO? If this is the first piece, remove mirrors/rotations from the children
                //if (isFirstPiece)
                //{
                //	//TODO: This doesn't stop diagonal mirrors
                //	searchWidth = (BoardState.Width - bitmap.Width) / 2 + 1;
                //	searchHeight = (BoardState.Height - bitmap.Height) / 2 + 1;
                //}

                for (int x = 0; x < searchWidth; x++)
                {
                    for (int y = 0; y < searchHeight; y++)
                    {
                        if (board.CanPlace(bitmap, x, y))
                        {
                            var clone = board;
                            clone.Place(bitmap, x, y);

                            var score = _evaluator.Evaluate(in clone, x, x + bitmap.Width, y, y + bitmap.Height);
                            if (score > bestScore)
                            {
                                resultBitmap = bitmap;
                                resultX      = x;
                                resultY      = y;

                                bestScore = score;
                            }
                        }
                    }
                }
            }

            return(resultBitmap != null);
        }
コード例 #15
0
ファイル: Helpers.cs プロジェクト: danzel/PatchworkSim
        /// <summary>
        /// Finds a placement (Not guaranteed to be any good) for the given piece on the given board
        /// </summary>
        public static void GetFirstPlacement(BoardState board, PieceDefinition piece, out PieceBitmap bitmap, out int x, out int y)
        {
            for (var index = 0; index < piece.PossibleOrientations.Length; index++)
            {
                bitmap = piece.PossibleOrientations[index];
                for (y = BoardState.Height - bitmap.Height; y >= 0; y--)
                {
                    for (x = BoardState.Width - bitmap.Width; x >= 0; x--)
                    {
                        if (board.CanPlace(bitmap, x, y))
                        {
                            return;
                        }
                    }
                }
            }

            throw new Exception("GetFirstPlacement couldn't find a placement");
        }
コード例 #16
0
        protected override bool TryPlacePiece(BoardState board, PieceDefinition piece, out PieceBitmap resultBitmap, out int x, out int y)
        {
            for (var oppositeWallGap = 0; oppositeWallGap < BoardState.Width; oppositeWallGap++)
            {
                //TODO: Could use the minimum of the size of the sides of the bitmap in this gap < part to skip some wasteful loops
                for (var gap = 0; gap < BoardState.Height; gap++)
                {
                    foreach (var bitmap in piece.PossibleOrientations)
                    {
                        //Try place in x direction
                        if (gap + bitmap.Width <= BoardState.Width && oppositeWallGap + bitmap.Height <= BoardState.Height && board.CanPlace(bitmap, gap, oppositeWallGap))
                        {
                            resultBitmap = bitmap;
                            x            = gap;
                            y            = oppositeWallGap;
                            return(true);
                        }

                        //Try place in y direction
                        if (oppositeWallGap + bitmap.Width <= BoardState.Width && gap + bitmap.Height <= BoardState.Height && board.CanPlace(bitmap, oppositeWallGap, gap))
                        {
                            resultBitmap = bitmap;
                            x            = oppositeWallGap;
                            y            = gap;
                            return(true);
                        }
                    }
                }
            }

            resultBitmap = null;
            x            = -1;
            y            = -1;
            return(false);
        }