public void Setup()
        {
            _markMatrix = new int[AreaSize, AreaSize];

            switch (ChosenAreaType)
            {
            case AreaType.Open:
                _wallMatrix = new bool[AreaSize, AreaSize]; break;

            case AreaType.WithUnwalkableCircles:
                _wallMatrix = CreateMatrixWithCircles(AreaSize); break;

            case AreaType.WithSparseUnwalkablePillars:
            default:
                _wallMatrix = CreateMatrixWithPillars(AreaSize); break;
            }

            _boundsRestriction = new FloodBounds(AreaSize, AreaSize);
            _qualifier         = (x, y) => !_wallMatrix[x, y];

            int startX = AreaSize == 20 ? 0 : AreaSize / 2;             // gives a non-wall position for area sizes 20, 200 and 2000.
            int startY = startX;

            if (_wallMatrix[startX, startY])
            {
                throw new InvalidOperationException($"{startX}, {startY} is a wall. You shouldn't start benchmark from a wall.");
            }
            _parameters = new FloodParameters(startX, startY)
            {
                BoundsRestriction = _boundsRestriction,
                Qualifier         = _qualifier,
            };

            _floodSpiller = UsingScanline ? (FloodSpiller) new FloodScanlineSpiller() : new FloodSpiller();
        }
Пример #2
0
        public void SpreadingPositionStopCondition()
        {
            var markMatrix = new int[10, 5];
            Action <int, int, int> neighbourProcessor =
                (x, y, mark) => Console.WriteLine($"Processing {x}, {y} as a neighbour with {mark} mark.");
            Action <int, int> positionVisitor =
                (x, y) => Console.WriteLine($"Visiting {x}, {y}");
            Predicate <int, int> spreadingPositionStopCondition = (x, y) =>
            {
                if (x > 1)
                {
                    Console.WriteLine($"{x}, {y} causing stop!");
                    return(true);
                }
                return(false);
            };
            var floodParameters = new FloodParameters(0, 0)
            {
                NeighbourProcessor             = neighbourProcessor,
                SpreadingPositionVisitor       = positionVisitor,
                SpreadingPositionStopCondition = spreadingPositionStopCondition
            };

            new FloodSpiller().SpillFlood(floodParameters, markMatrix);

            string representation = MarkMatrixVisualiser.Visualise(markMatrix);

            Console.WriteLine(representation);
        }
Пример #3
0
        public void SpillFlood_EigthDirectionsNeighbourHood_AllPositionsReachableByDiagonalsGetMarked(FloodSpiller floodSpiller)
        {
            var result        = new int[4, 5];
            var startPosition = new Position(1, 1);
            Predicate <int, int> qualifierMatchingEverySecondPosition = (x, y) =>
                                                                        (x + y) % 2 == 0;

            var parameters = new FloodParameters(new LifoPositionQueue(), startPosition.X, startPosition.Y)
            {
                Qualifier         = qualifierMatchingEverySecondPosition,
                NeighbourhoodType = NeighbourhoodType.Eight
            };

            floodSpiller.SpillFlood(parameters, result);

            result[0, 0].Should().Be(1);
            result[1, 0].Should().Be(int.MaxValue);
            result[2, 0].Should().Be(1);
            result[0, 1].Should().Be(int.MaxValue);
            result[1, 1].Should().Be(0);
            result[2, 1].Should().Be(int.MaxValue);
            result[0, 2].Should().Be(1);
            result[1, 2].Should().Be(int.MaxValue);
            result[2, 2].Should().Be(1);
        }
Пример #4
0
        public void SpillFlood_FirstProcessedNeighbourMeetsStopCondition_AlgorithmStopsAfterProcessingAllNeighbours(FloodSpiller spiller)
        {
            // arrange
            var startingPoint                = new Position(1, 1);
            int visitedPositionsCount        = 0;
            int processedNeighbourCount      = 0;
            Predicate <int, int>   qualifier = (x, y) => true;
            Predicate <int, int>   neighbourStopCondition   = (x, y) => true;
            Action <int, int, int> neighbourProcessor       = (x, y, mark) => ++ processedNeighbourCount;
            Action <int, int>      spreadingPositionVisitor = (x, y) => ++ visitedPositionsCount;

            // act
            int[,] result = new int[4, 4];
            var parameters = new FloodParameters(startingPoint.X, startingPoint.Y)
            {
                Qualifier                = qualifier,
                NeighbourProcessor       = neighbourProcessor,
                NeighbourStopCondition   = neighbourStopCondition,
                SpreadingPositionVisitor = spreadingPositionVisitor
            };
            bool wasStopped = spiller.SpillFlood(parameters, result);

            // assert
            wasStopped.Should().BeTrue();
            visitedPositionsCount.Should().Be(1);              // only starting position should be visited
            // assert that reached positions got correct numbers
            processedNeighbourCount.Should().BeGreaterThan(1); // it depends on implementation how many neighbours we reach,
            // but for sure there should be more than one
            // even if first processed neighbour caused stop
        }
Пример #5
0
        public void SpillFlood_BoundsDoNotStartFromZero_GivesCorrectMarksRespectingBounds(FloodSpiller floodSpiller)
        {
            // arrange
            int resultArraySize = 4;
            var startingPoint   = new Position(-5, -5);
            var bounds          = new FloodBounds(-5, -5, 2, 2);

            int[,] markMatrix = new int[resultArraySize, resultArraySize];
            var parameters = new FloodParameters(startingPoint.X, startingPoint.Y)
            {
                Qualifier         = (x, y) => y == -5,
                BoundsRestriction = bounds
            };

            // act
            floodSpiller.SpillFlood(parameters, markMatrix);

            Console.WriteLine(MarkMatrixVisualiser.Visualise(markMatrix));

            // assert that reached positions got correct numbers
            markMatrix[0, 0].Should().Be(0);
            markMatrix[1, 0].Should().Be(1);
            markMatrix[2, 0].Should().Be(int.MaxValue);             // out of bounds
            markMatrix[0, 1].Should().Be(int.MaxValue);             // unreachable
            markMatrix[1, 1].Should().Be(int.MaxValue);             // unreachable
        }
        public void SpillFlood_CheckboardWalls_ScanlineAndFifoPerformanceComparison()
        {
            int size   = 1000;
            var result = new int[size, size];

            var walkability = new bool[size, size];

            // checkboard should be INOPTIMAL for scanline because it skips opening nodes when going vertically
            for (int x = 0; x < size; x++)
            {
                for (int y = 0; y < size; y++)
                {
                    if ((x + y) % 2 == 0)
                    {
                        walkability[x, y] = true;
                    }
                }
            }

            var startPosition = new Position(size / 5, size / 5);

            Predicate <int, int> qualifier = (x, y) => walkability[x, y];
            var parameters = new FloodParameters(new LifoPositionQueue(), startPosition.X, startPosition.Y)
            {
                Qualifier = qualifier
            };

            var stopwatch = Stopwatch.StartNew();

            new FloodScanlineSpiller().SpillFlood(parameters, result);
            Console.WriteLine("scanline:" + stopwatch.ElapsedMilliseconds + " ms");
            stopwatch.Restart();
            new FloodSpiller().SpillFlood(parameters, result);
            Console.WriteLine("normal:" + stopwatch.ElapsedMilliseconds + " ms");
        }
Пример #7
0
        public void SpillFlood_CorrectMarksAppearAtWalkablePositions(FloodSpiller floodSpiller)
        {
            int size          = 4;
            var result        = new int[size, size];
            var startPosition = new Position(1, 1);
            Predicate <int, int> isAtPerimeter = (x, y) => x == 0 || x == size - 1 || y == 0 || y == size - 1;
            Predicate <int, int> qualifier     = (x, y) => !isAtPerimeter(x, y);

            var parameters = new FloodParameters(new LifoPositionQueue(), startPosition.X, startPosition.Y)
            {
                Qualifier = qualifier
            };

            floodSpiller.SpillFlood(parameters, result);

            for (int x = 0; x < result.GetLength(0); x++)
            {
                for (int y = 0; y < result.GetLength(1); y++)
                {
                    if (isAtPerimeter(x, y))
                    {
                        result[x, y].Should().Be(int.MaxValue);
                    }
                    else
                    {
                        result[x, y].Should().BeLessThan(int.MaxValue);
                    }
                }
            }
        }
        public void Visit_FloodSpillerAnd3x3OpenArea_All9PositionsAreAddedToResultAndFirstElementIsStartingPosition()
        {
            var startingPosition = new Position(1, 1);

            int[,] matrix = new int[3, 3];
            int positionsCount                = matrix.Length;
            var addToListProcessor            = new AddToListPositionVisitor();
            Action <int, int> positionVisitor = addToListProcessor.Visit;
            var parameters = new FloodParameters(startingPosition.X, startingPosition.Y)
            {
                ProcessStartAsFirstNeighbour = true,
                SpreadingPositionVisitor     = positionVisitor
            };
            FloodSpiller spiller = new FloodSpiller();

            spiller.SpillFlood(parameters, matrix);

            addToListProcessor.Result.Count.Should().Be(positionsCount);
            addToListProcessor.Result.First().Should().Be(startingPosition);
            for (int x = 0; x < matrix.GetLength(0); x++)
            {
                for (int y = 0; y < matrix.GetLength(1); y++)
                {
                    addToListProcessor.Result.Should().Contain(new Position(x, y));
                }
            }
        }
Пример #9
0
        public void PopulateMapBoundaryList()
        {
            // Add all boundaries to x,y grid
            // Then add those to the list somehow
            mapBoundaryList.Clear();
            int width           = processedFullSizeMapDataForPathFinding.GetLength(0);
            int height          = processedFullSizeMapDataForPathFinding.GetLength(1);
            var pathFindingGrid = processedFullSizeMapDataForPathFinding;
            var markArray       = new int[width, height];

            var outlineArray = new int[width, height];
            var floodSpiller = new FloodSpiller();
            var startTime    = DateTime.Now;
            Predicate <int, int> positionQualifier = (x, y) =>
            {
                if (pathFindingGrid[x, y] == 1)
                {
                    outlineArray[x, y] = 1;
                    if (mapBoundaryList.Count > 0)
                    {
                        var current = new Vector2(x, y);
                        var count   = mapBoundaryList.Where(vec => vec.DistanceSquared(current) < 10).Count();
                        if (count == 0)
                        {
                            mapBoundaryList.Add(new Vector2(x, y));
                        }
                        //var lastAdded = mapBoundaryList.Last();
                        //if (lastAdded.DistanceSquared(current) > 100)
                        //{
                        //    mapBoundaryList.Add(new Vector2(x, y));
                        //}
                    }
                    else
                    {
                        mapBoundaryList.Add(new Vector2(x, y));
                    }
                    return(false);
                }
                else
                {
                    return(true);
                }
            };
            var floodParameters = new FloodParameters(startX: 0, startY: 0)
            {
                ProcessStartAsFirstNeighbour = true,
                NeighbourhoodType            = NeighbourhoodType.Eight,
                Qualifier          = positionQualifier,
                NeighbourProcessor = (x, y, mark) =>
                {
                },
            };

            floodSpiller.SpillFlood(floodParameters, markArray);
            // Remove
            var endTime = DateTime.Now;

            Console.WriteLine("elapsed boundary time: {0}", endTime.Subtract(startTime).TotalMilliseconds);
        }
Пример #10
0
        public void SpillFlood_NoStopConditionIsMet_ReturnsFalse(FloodSpiller spiller)
        {
            int[,] result = new int[3, 3];

            var  parameters = new FloodParameters(0, 0);
            bool wasStopped = spiller.SpillFlood(parameters, result);

            wasStopped.Should().BeFalse();
        }
Пример #11
0
        public void SpillFlood_QueueIsNotEmptyAtBeginning_ThrowsArgumentException(FloodSpiller floodSpiller)
        {
            var parameters = new FloodParameters(123, 456);

            parameters.PositionsToVisitQueue.Enqueue(1, 1);

            Action action = () => floodSpiller.SpillFlood(parameters, new int[10, 10]);

            action.Should().Throw <ArgumentException>();
        }
Пример #12
0
        public void FloodSpill_LakeSituationWithPriorityQueue_CorrectlySpillsLake()
        {
            string heightInput = "98999" + Environment.NewLine + //.....
                                 "95799" + Environment.NewLine + //.l...	   l - expected lake
/*start position is at 2 --> */ "92789" + Environment.NewLine +  //.l...	   . - expected land
                                 "93499" + Environment.NewLine + //.ll..
                                 "96999" + Environment.NewLine + //.l...
                                 "94999";                        //.L...       L - last lake position which will become a new river

            //		       bottom-left corner is 0,0
            // water should spill to lowest positions adjacent to flood: 2, 3, 4, 5, 6, 4
            float[,] heightMap = CreateHeightMapFromString(heightInput);

            var      markMatrix       = new int[5, 6];
            Position startingPosition = new Position(1, 3);

            float lakeSurfaceHeight = heightMap[startingPosition.X, startingPosition.Y];
            Predicate <int, int> stopConditionForVisited = (x, y) => heightMap[x, y] < lakeSurfaceHeight;
            var lakePositions = new List <Position>();
            Action <int, int> positionVisitorWithSurfaceAdjustmentAndListBuilding = (currentX, currentY) =>
            {
                float positionHeight = heightMap[currentX, currentY];
                if (positionHeight > lakeSurfaceHeight)
                {
                    lakeSurfaceHeight = positionHeight;
                }

                lakePositions.Add(new Position(currentX, currentY));
            };

            Func <Position, Position, int> positionComparerByHeight =
                (first, second) => heightMap[first.X, first.Y].CompareTo(heightMap[second.X, second.Y]);

            var parameters = new FloodParameters(new PriorityPositionQueue(positionComparerByHeight), startingPosition.X, startingPosition.Y)
            {
                SpreadingPositionVisitor       = positionVisitorWithSurfaceAdjustmentAndListBuilding,
                SpreadingPositionStopCondition = stopConditionForVisited
            };

            // act
            new FloodSpiller().SpillFlood(parameters, markMatrix);

            // assert lakePositions are calculated correctly and have proper marks
            Position[] expectedLakePositions =
            {
                new Position(1, 0),
                new Position(1, 1),
                new Position(1, 2),
                new Position(2, 2),
                new Position(1, 3),
                new Position(1, 4),
            };
            lakePositions.Should().BeEquivalentTo(expectedLakePositions);
            Console.WriteLine(MarkMatrixVisualiser.Visualise(markMatrix));
        }
Пример #13
0
        public void NoWalls_Fifo()
        {
            var markMatrix      = new int[10, 5];
            var floodParameters = new FloodParameters(startX: 1, startY: 1);

            new FloodSpiller().SpillFlood(floodParameters, markMatrix);

            string representation = MarkMatrixVisualiser.Visualise(markMatrix);

            Console.WriteLine(representation);
        }
Пример #14
0
        public void NoWalls_Lifo()
        {
            var markMatrix      = new int[10, 5];
            var floodParameters = new FloodParameters(new LifoPositionQueue(), 1, 1);

            new FloodSpiller().SpillFlood(floodParameters, markMatrix);

            string representation = MarkMatrixVisualiser.Visualise(markMatrix);

            Console.WriteLine(representation);
        }
Пример #15
0
        public void Scanline_NoWalls_Fifo()
        {
            var markMatrix      = new int[8, 10];
            var floodParameters = new FloodParameters(4, 2);

            new FloodScanlineSpiller().SpillFlood(floodParameters, markMatrix);

            string representation = MarkMatrixVisualiser.Visualise(markMatrix);

            Console.WriteLine(representation);
        }
Пример #16
0
        public void SpillFlood_FloodDoesNotReachPositionsThatAreValidButBlockedByUnreachablePositions(FloodSpiller spiller)
        {
            float seaLevel = 0.5f;
            var   heights  = new float[4, 4];
            var   positionsToSetUnderThreshold = new[]
            {
                new Position(0, 0), new Position(1, 0),
                new Position(0, 1), new Position(3, 1),
                new Position(0, 2),
                new Position(0, 3), new Position(1, 3), new Position(2, 0), new Position(3, 3)
            };
            var positionsToSetAboveThreshold = new[]
            {
                new Position(2, 0), new Position(3, 0),
                new Position(1, 1), new Position(2, 1),
                new Position(1, 2), new Position(2, 2), new Position(3, 2)
            };

            foreach (Position positionUnder in positionsToSetUnderThreshold)
            {
                heights[positionUnder.X, positionUnder.Y] = 0f;
            }
            foreach (Position positionAbove in positionsToSetAboveThreshold)
            {
                heights[positionAbove.X, positionAbove.Y] = 1f;
            }

            Predicate <int, int> isBelowSeaLevel = (x, y) => heights[x, y] < seaLevel;

            var result     = new int[4, 4];
            var parameters = new FloodParameters(0, 0)
            {
                Qualifier = isBelowSeaLevel
            };

            spiller.SpillFlood(parameters, result);
            Console.WriteLine(MarkMatrixVisualiser.Visualise(result));

            result[0, 0].Should().Be(0);             // starting position
            result[1, 0].Should().BeLessThan(int.MaxValue);
            result[0, 1].Should().BeLessThan(int.MaxValue);
            result[0, 2].Should().BeLessThan(int.MaxValue);
            result[0, 3].Should().BeLessThan(int.MaxValue);
            result[1, 3].Should().BeLessThan(int.MaxValue);
            result[2, 3].Should().BeLessThan(int.MaxValue);
            result[3, 3].Should().BeLessThan(int.MaxValue);
            result[1, 1].Should().Be(int.MaxValue);             // above threshold
            result[2, 2].Should().Be(int.MaxValue);             // above threshold
            result[3, 1].Should().Be(int.MaxValue);             // under threshold, unreachable
        }
Пример #17
0
        public void SpillFlood_DiagonalNeighbourhoodAllowed_ReturnsCorrectResultArray()
        {
            // arrange
            int size   = 4;
            var center = new Position(0, 1);

            bool[,] walkabilityArray = new bool[size, size];
            walkabilityArray[0, 1]   = true;
            walkabilityArray[1, 1]   = true;
            walkabilityArray[2, 1]   = true;
            walkabilityArray[2, 2]   = true;
            walkabilityArray[2, 3]   = true;

            Predicate <int, int> qualifier = (x, y) => walkabilityArray[x, y];

            int[,] result = new int[size, size];

            var parameters = new FloodParameters(center.X, center.Y)
            {
                Qualifier         = qualifier,
                NeighbourhoodType = NeighbourhoodType.Eight,
            };

            // act
            new FloodSpiller().SpillFlood(parameters, result);

            // assert that reached positions got correct numbers
            result[0, 1].Should().Be(0);
            result[1, 1].Should().Be(1);
            result[2, 1].Should().Be(2);
            result[2, 2].Should().Be(2);
            result[2, 3].Should().Be(3);

            // assert that unvisited positions didn't get marks
            result[0, 0].Should().Be(int.MaxValue);
            result[1, 0].Should().Be(int.MaxValue);
            result[2, 0].Should().Be(int.MaxValue);
            result[3, 0].Should().Be(int.MaxValue);

            result[3, 1].Should().Be(int.MaxValue);

            result[0, 2].Should().Be(int.MaxValue);
            result[1, 2].Should().Be(int.MaxValue);

            result[3, 2].Should().Be(int.MaxValue);

            result[0, 3].Should().Be(int.MaxValue);
            result[1, 3].Should().Be(int.MaxValue);
            result[3, 3].Should().Be(int.MaxValue);
        }
Пример #18
0
        public void SpillFlood_NoBoundsAndStartingPositionIsOutOfMarkMatrix_ThrowsArgumentException(FloodSpiller floodSpiller)
        {
            var startingPoint = new Position(5, 4);

            int[,] markMatrix = new int[5, 5];

            Action action = () =>
            {
                var parameters = new FloodParameters(startingPoint.X, startingPoint.Y);
                floodSpiller.SpillFlood(parameters, markMatrix);
            };

            action.Should().Throw <ArgumentException>();
        }
Пример #19
0
        public void NegativeBounds()
        {
            var markMatrix      = new int[10, 5];
            var floodParameters = new FloodParameters(-99, -99)
            {
                BoundsRestriction = new FloodBounds(minX: -100, minY: -100, sizeX: 10, sizeY: 5)
            };

            new FloodSpiller().SpillFlood(floodParameters, markMatrix);

            string representation = MarkMatrixVisualiser.Visualise(markMatrix);

            Console.WriteLine(representation);
        }
Пример #20
0
        public void DisallowDiagonalNeighbourhood()
        {
            var markMatrix      = new int[10, 5];
            var floodParameters = new FloodParameters(1, 1)
            {
                NeighbourhoodType = NeighbourhoodType.Four
            };

            new FloodSpiller().SpillFlood(floodParameters, markMatrix);

            string representation = MarkMatrixVisualiser.Visualise(markMatrix);

            Console.WriteLine(representation);
        }
Пример #21
0
        /// <summary>
        /// Marking
        /// </summary>
        private void MarkIsolatedAreas(IOsnowaContext context)
        {
            var           floodSpiller  = new FloodSpiller();
            PositionFlags positionFlags = context.PositionFlags;
            var           stopwatch     = Stopwatch.StartNew();

            byte areaIndex        = 0;
            byte biggestAreaIndex = 0;
            int  maxArea          = 0;

            for (int probeX = 0; probeX < context.PositionFlags.XSize; probeX += 10)
            {
                for (int probeY = 0; probeY < context.PositionFlags.YSize; probeY += 10)
                {
                    bool     isFine       = false;
                    int      totalVisited = 0;
                    Position start        = new Position(probeX, probeY);
                    var      parameters   = new FloodParameters(start.x, start.y)
                    {
                        Qualifier =
                            (x, y) => positionFlags.IsWalkable(x, y),
                        NeighbourProcessor = (x, y, mark) =>
                        {
                            if (!isFine)
                            {
                                isFine     = true;
                                areaIndex += 1;
                            }
                            totalVisited += 1;
                        }
                    };
                    int[,] markMatrix = new int[context.PositionFlags.XSize, context.PositionFlags.YSize];
                    floodSpiller.SpillFlood(parameters, markMatrix);
                    if (totalVisited > 50)
                    {
                        // BUG looks like areas are not isolated, all are of same size of the whole island!
                        // Debug.Log("visited " + totalVisited + "from " + start.x + ", " + start.y + " with index " + areaIndex);
                    }
                    if (totalVisited > maxArea)
                    {
                        maxArea          = totalVisited;
                        biggestAreaIndex = areaIndex;
                    }
                }
            }
            Debug.Log("biggest isolated area index: " + biggestAreaIndex);
            Debug.Log("biggest isolated area index: " + maxArea);
            Debug.Log("marking isolated areas took: " + stopwatch.ElapsedMilliseconds);
        }
Пример #22
0
        public void NoWalls_PriorityQueue()
        {
            var      markMatrix = new int[10, 10];
            Position center     = new Position(5, 5);
            Func <Position, Position, int> distanceToCenterComparer =            // favours positions closer to center
                                                                      (first, second) => Position.Distance(center, first).CompareTo(Position.Distance(center, second));
            var priorityQueue   = new PriorityPositionQueue(distanceToCenterComparer);
            var floodParameters = new FloodParameters(priorityQueue, 1, 1);

            new FloodSpiller().SpillFlood(floodParameters, markMatrix);

            string representation = MarkMatrixVisualiser.Visualise(markMatrix);

            Console.WriteLine(representation);
        }
Пример #23
0
        public void Bounds()
        {
            var markMatrix      = new int[10, 5];
            var floodParameters = new FloodParameters(7, 7)
            {
                BoundsRestriction = new FloodBounds(minX: 5, minY: 5, sizeX: 5, sizeY: 3)
                                    // markMatrix will be accessed with offset, so that we don't have IndexOutOfRangeExceptions
            };

            new FloodSpiller().SpillFlood(floodParameters, markMatrix);

            string representation = MarkMatrixVisualiser.Visualise(markMatrix);

            Console.WriteLine(representation);
        }
Пример #24
0
        public void CallbacksForProcessingNeighboursAndVisitingPositions()
        {
            var markMatrix = new int[3, 2];
            Action <int, int, int> neighbourProcessor =
                (x, y, mark) => Console.WriteLine($"Processing {x}, {y} as a neighbour with {mark} mark.");
            Action <int, int> positionVisitor =
                (x, y) => Console.WriteLine($"Visiting {x}, {y}");
            var floodParameters = new FloodParameters(0, 0)
            {
                NeighbourProcessor       = neighbourProcessor,
                SpreadingPositionVisitor = positionVisitor
            };

            new FloodSpiller().SpillFlood(floodParameters, markMatrix);
        }
Пример #25
0
    private int[,] HighlightCells()
    {
        var cellGrid = FindObjectOfType <CellGrid>();

        int thisX = 0;
        int thisZ = 0;

        foreach (var cell in cellGrid.cells)
        {
            int cellX = (int)cell.x;
            int cellZ = (int)cell.z;

            if (cellX == (int)startX &&
                cellZ == (int)startZ)
            {
                thisX = cell.x;
                thisZ = cell.z;
            }
        }
        var markMatrix      = new int[cellGrid.width, cellGrid.height];
        var floodParameters = new FloodParameters(thisX, thisZ)
        {
            NeighbourhoodType = NeighbourhoodType.Four
        };

        new FloodSpiller().SpillFlood(floodParameters, markMatrix);

        for (int x = 0; x < cellGrid.width; x++)
        {
            for (int z = 0; z < cellGrid.height; z++)
            {
                int spilledCell = markMatrix[x, z];
                if (spilledCell <= selectedUnit.maxMovements)
                {
                    foreach (var cell in cellGrid.cells)
                    {
                        if (cell.x == x && cell.z == z)
                        {
                            cell.Material.SetColor("_Color", Color.blue);
                            cell.Material.SetFloat("_Alpha", 0.500f);
                        }
                    }
                }
            }
        }

        return(markMatrix);
    }
Пример #26
0
        public void Process_NoNeighbours_ReturnsMinPositionAndZeroMark()
        {
            var startingPosition = new Position(0, 0);

            int[,] result = new int[1, 1];
            var findHighestMark = new FindHighestMarkNeighbourProcessor();
            var parameters      = new FloodParameters(startingPosition.X, startingPosition.Y)
            {
                NeighbourProcessor = findHighestMark.Process
            };

            new FloodSpiller().SpillFlood(parameters, result);

            findHighestMark.PositionWithHighestMark.Should().Be(Position.MinValue);
            findHighestMark.HighestMark.Should().Be(0);
        }
        public override IEnumerator Recalculating()
        {
            Position                middle = new Position(Values.XSize / 2, Values.YSize / 2);
            float                   furthestDistanceToMiddle = Position.Distance(Position.MinValue, middle);
            float                   noiseScale            = _config.Scale;
            AnimationCurve          toCenterFalloffCurve  = _config.MaxFactorDistanceFromCenterToFalloff;
            Dictionary <int, float> afterNoiseAdjustments = InitializeAfterNoiseAdjustments(_config.Octaves);

            foreach (Position position in Values.AllCellMiddles())
            {
                Position probedPositionForNoise = position + _noiseOffset;

                float persistence01 = 0.5f;

                float heightValue = Perlin.Noise(probedPositionForNoise.x * noiseScale, probedPositionForNoise.y * noiseScale,
                                                 _config.Octaves, persistence01);
                int adjustmentKey = (int)Math.Round(persistence01 * 10);
                heightValue *= afterNoiseAdjustments[adjustmentKey];

                float distanceToMiddle         = Position.Distance(position, middle);
                float relativeDistanceToMiddle = distanceToMiddle / furthestDistanceToMiddle;
                heightValue *= toCenterFalloffCurve.Evaluate(relativeDistanceToMiddle);
                Values.Set(position, heightValue);
            }

            float cutOffValue = CalculateSeaLevelToMatchGroundPercentage();

            GameContext.SeaLevel = cutOffValue;

            bool Qualifier(int x, int y) => Values.Get(x, y) < cutOffValue;

            var bounds     = new FloodBounds(Values.XSize, Values.YSize);
            var parameters = new FloodParameters(0, 0)
            {
                Qualifier         = Qualifier,
                BoundsRestriction = bounds,
                NeighbourhoodType = NeighbourhoodType.Four
            };

            int[,] closedSeaPositions = new int[bounds.SizeX, bounds.SizeY];
            new FloodSpiller().SpillFlood(parameters, closedSeaPositions);

            BuryDepressions(cutOffValue, closedSeaPositions);

            yield return(new WaitForSeconds(0.1f));
        }
Пример #28
0
        public void SpillFlood_ExplicitBoundsDoNotContainStartingPosition_ThrowsArgumentException(FloodSpiller floodSpiller)
        {
            var startingPoint = new Position(5, 5);
            var bounds        = new FloodBounds(2, 2, 2, 2);

            int[,] markMatrix = new int[100, 100];
            Action action = () =>
            {
                var parameters = new FloodParameters(startingPoint.X, startingPoint.Y)
                {
                    BoundsRestriction = bounds
                };
                floodSpiller.SpillFlood(parameters, markMatrix);
            };

            action.Should().Throw <ArgumentException>();
        }
Пример #29
0
        private List <Position> FindPlaceForHouse()
        {
            var spiller = new FloodSpiller();

            int[,] markMatrix = new int[Values.XSize, Values.YSize];
            var             startingPoint = _rng.NextPosition(new Bounds(0, 0, Values.XSize, Values.YSize));
            FloodParameters parameters    = new FloodParameters(Values.XSize / 2, Values.YSize / 2)
            {
                BoundsRestriction = new FloodBounds(0, 0, Values.XSize, Values.YSize)
            };

            spiller.SpillFlood(parameters, markMatrix);

            return(new List <Position> {
                new Position(50, 50)
            });
        }
Пример #30
0
        public void SpillFlood_ResultArrayIsSmallerThanGivenBounds_ThrowsArgumentException(FloodSpiller floodSpiller)
        {
            int boundsSize = 4;
            var bounds     = new FloodBounds(-10, -10, boundsSize, boundsSize);

            int[,] result = new int[boundsSize - 1, boundsSize];

            Action action = () =>
            {
                var parameters = new FloodParameters(0, 0)
                {
                    BoundsRestriction = bounds
                };
                floodSpiller.SpillFlood(parameters, result);
            };

            action.Should().Throw <ArgumentException>();
        }