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(); }
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_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>(); }
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)); }
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>(); }
public void SpillFlood_BoundsDoNotStartFromZero_LambdasAreCalledForCorrectPosition(FloodSpiller floodSpiller) { int startX = -5; int startY = 5; var bounds = new FloodBounds(startX, startY, 1, 1); int[,] markMatrix = new int[1, 1]; bool qualifierCalled = false; bool neighbourStopConditionCalled = false; bool neighbourProcessorCalled = false; bool spreadingPositionStopConditionCalled = false; bool spreadingPositionVisitorCalled = false; var parametersCheckingIfLambdasAreExecutedForStartingPosition = new FloodParameters(startX, startY) { BoundsRestriction = bounds, ProcessStartAsFirstNeighbour = true, // make first position be both processed as a neighbour and as a visited spreading position. Qualifier = (x, y) => { if (x == startX && y == startY) { qualifierCalled = true; } return(true); }, NeighbourStopCondition = (x, y) => { if (x == startX && y == startY) { neighbourStopConditionCalled = true; } return(false); }, NeighbourProcessor = (x, y, mark) => { if (x == startX && y == startY) { neighbourProcessorCalled = true; } }, SpreadingPositionStopCondition = (x, y) => { if (x == startX && y == startY) { spreadingPositionStopConditionCalled = true; } return(false); }, SpreadingPositionVisitor = (x, y) => { if (x == startX && y == startY) { spreadingPositionVisitorCalled = true; } } }; floodSpiller.SpillFlood(parametersCheckingIfLambdasAreExecutedForStartingPosition, markMatrix); qualifierCalled.Should().BeTrue(); neighbourStopConditionCalled.Should().BeTrue(); neighbourProcessorCalled.Should().BeTrue(); spreadingPositionStopConditionCalled.Should().BeTrue(); spreadingPositionVisitorCalled.Should().BeTrue(); }