public static TimeSpan TimeForNSourcesLighting(int mapWidth, int mapHeight, int lightRadius, int iterations, int lights) { Stopwatch s = new Stopwatch(); var map = rectangleMap(mapWidth, mapHeight); var fov = new SenseMap(map); Coord c = Coord.Get(5, 6); for (int i = 0; i < lights; i++) { fov.AddSenseSource(new SenseSource(SourceType.RIPPLE, c, lightRadius, Radius.CIRCLE)); c += 5; } // Warm-up for processor, stabilizes cache performance. Also makes it a fair test against // fov since we have to do this to force the first memory allocation fov.Calculate(); // Calculate and test s.Start(); for (int i = 0; i < iterations; i++) { fov.Calculate(); } s.Stop(); return(s.Elapsed); }
public void SenseMapCurrentHash() { var map = new BoxResMap(50, 50); var senseMap = new SenseMap(map); senseMap.AddSenseSource(new SenseSource(SourceType.RIPPLE, Coord.Get(20, 20), 10, Radius.CIRCLE)); senseMap.Calculate(); // Inefficient copy but fine for testing HashSet <Coord> currentSenseMap = new HashSet <Coord>(senseMap.CurrentSenseMap); for (int x = 0; x < map.Width; x++) { for (int y = 0; y < map.Height; y++) { if (senseMap[x, y] > 0.0) { Assert.AreEqual(true, currentSenseMap.Contains(Coord.Get(x, y))); } else { Assert.AreEqual(false, currentSenseMap.Contains(Coord.Get(x, y))); } } } }
public void RippleCircleValue() { int MAP_SIZE = 30; int RADIUS = 10; Radius RAD_TYPE = Radius.CIRCLE; Coord SOURCE_POS = Coord.Get(15, 15); BoxResMap resMap = new BoxResMap(MAP_SIZE, MAP_SIZE); SenseMap senseMap = new SenseMap(resMap); var source = new SenseSource(SourceType.RIPPLE, SOURCE_POS, RADIUS, RAD_TYPE); senseMap.AddSenseSource(source); senseMap.Calculate(); Console.WriteLine("Map on 10x10, light source at (2, 3), 3 circle radius, using ripple is: "); for (int x = 0; x < MAP_SIZE; x++) { for (int y = 0; y < MAP_SIZE; y++) { Console.Write($"{senseMap[x, y].ToString("N4")} "); } Console.WriteLine(); } }
private void CreateSenseMap() { // Create sense map of rectangular area var wallFloor = new Generator(MapSize, MapSize) .ConfigAndGenerateSafe(gen => gen.AddSteps(DefaultAlgorithms.RectangleMapSteps())) .Context.GetFirst <IGridView <bool> >("WallFloor"); var resMap = new ArrayView <double>(wallFloor.Width, wallFloor.Height); resMap.ApplyOverlay(pos => wallFloor[pos] ? 0.0 : 1.0); _senseMap = new SenseMap(resMap); }
public static long MemorySingleLightSourceLighting(int mapWidth, int mapHeight, int lightRadius) { SenseMap fov; long startingMem, endingMem; ArrayMap <double> map = rectangleMap(mapWidth, mapHeight); // Start mem test startingMem = GC.GetTotalMemory(true); fov = new SenseMap(map); fov.AddSenseSource(new SenseSource(SourceType.SHADOW, Coord.Get(5, 6), lightRadius, Radius.CIRCLE)); endingMem = GC.GetTotalMemory(true); return(endingMem - startingMem); }
public void CircleRadius() { var testResMap = new EmptyResMap(17, 17); var myFov = new FOV(testResMap); var myLighting = new SenseMap(testResMap); // Circle at 8, 8; radius 7 myLighting.AddSenseSource(new SenseSource(SourceType.SHADOW, Coord.Get(8, 8), 7, Radius.CIRCLE)); myFov.Calculate(8, 8, 7, Radius.CIRCLE); myLighting.Calculate(); for (int x = 0; x < testResMap.Width; x++) { for (int y = 0; y < testResMap.Height; y++) { Console.Write(myLighting[x, y].ToString("0.00") + " "); Assert.AreEqual(myFov[x, y], myLighting[x, y]); // Both got the same results } Console.WriteLine(); } }
public static TimeSpan TimeForSingleLightSourceLighting(int mapWidth, int mapHeight, SourceType sourceType, int lightRadius, Radius radiusStrat, int iterations) { Stopwatch s = new Stopwatch(); var map = rectangleMap(mapWidth, mapHeight); var fov = new SenseMap(map); fov.AddSenseSource(new SenseSource(sourceType, new Coord(5, 6), lightRadius, radiusStrat)); // Warm-up for processor, stabilizes cache performance. Also makes it a fair test against // fov since we have to do this to force the first memory allocation fov.Calculate(); // Calculate and test s.Start(); for (int i = 0; i < iterations; i++) { fov.Calculate(); } s.Stop(); return(s.Elapsed); }
private bool testSenseMap(SourceType algorithm, Radius shape) { var map = rectResMap(MAP_WIDTH, MAP_HEIGHT); // Start out at false bool[,] radiusMap = new bool[MAP_WIDTH, MAP_HEIGHT]; bool[,] losMap = new bool[MAP_WIDTH, MAP_HEIGHT]; var los = new SenseMap(map); var lightSource = new SenseSource(algorithm, CENTER, RADIUS_LEGNTH, shape); los.AddSenseSource(lightSource); los.Calculate(); for (int x = 0; x < MAP_WIDTH; x++) { for (int y = 0; y < MAP_HEIGHT; y++) { if (los[x, y] > 0) { losMap[x, y] = true; } } } var radArea = new RadiusAreaProvider(CENTER, RADIUS_LEGNTH, shape); foreach (var pos in radArea.CalculatePositions()) { radiusMap[pos.X, pos.Y] = true; } Console.WriteLine("Radius Shape: "); printArray(radiusMap); Console.WriteLine("LOS Shape: "); printArray(losMap); return(equivalentArrays(radiusMap, losMap)); }
public void EqualLargeMap() { var testResMap = TestResMap(17, 17); var testFOVMap = new LambdaTranslationMap <double, bool>(testResMap, d => d >= 1.0 ? false : true); testResMap[8, 8] = 0.0; // Make sure start is free var myFov = new FOV(testFOVMap); var myLighting = new SenseMap(testResMap); // Circle at 8, 8; radius 7 myLighting.AddSenseSource(new SenseSource(SourceType.SHADOW, (8, 8), 7, Radius.CIRCLE)); myFov.Calculate(8, 8, 7, Radius.CIRCLE); myLighting.Calculate(); Console.WriteLine("LOS: "); for (int x = 0; x < testResMap.Width; x++) { for (int y = 0; y < testResMap.Height; y++) { Console.Write($"{myFov[x, y].ToString("N2")}\t"); } Console.WriteLine(); } Console.WriteLine("\nLighting:"); for (int x = 0; x < testResMap.Width; x++) { for (int y = 0; y < testResMap.Height; y++) { Console.Write($"{myLighting[x, y].ToString("N2")}\t"); } Console.WriteLine(); } for (int x = 0; x < testResMap.Width; x++) { for (int y = 0; y < testResMap.Height; y++) { System.Console.WriteLine($"We have ({x},{y}) fov {myFov[x, y]}, lighting {myLighting[(x, y)]}"); Assert.AreEqual(myFov[x, y], myLighting[x, y]); // Both got the same results } } }
public void ManualPrintSenseMap() { var map = new ArrayMap <bool>(30, 30); QuickGenerators.GenerateRectangleMap(map); var resMap = new ResMap(map); var senseMap = new SenseMap(resMap); var source = new SenseSource(SourceType.SHADOW, 12, 15, 10, Radius.CIRCLE); var source2 = new SenseSource(SourceType.SHADOW, 18, 15, 10, Radius.CIRCLE); senseMap.AddSenseSource(source); senseMap.AddSenseSource(source2); senseMap.Calculate(); Console.WriteLine(senseMap); Console.WriteLine(); Console.WriteLine(senseMap.ToString(3)); Console.WriteLine(); Console.WriteLine(source); }
public void FOVSenseMapEquivalency() { ArrayMap <bool> map = new ArrayMap <bool>(100, 100); QuickGenerators.GenerateRectangleMap(map); var positions = Enumerable.Range(0, 100).Select(x => map.RandomPosition(true)).ToList(); // Make 2-layer thick walls to verify wall-lighting is working properly foreach (var pos in map.Positions()) { if (pos.X == 1 || pos.Y == 1 || pos.X == map.Width - 2 || pos.Y == map.Height - 2) { map[pos] = false; } } var fov = new FOV(map); var senseMap = new SenseMap(new LambdaTranslationMap <bool, double>(map, x => x ? 0.0 : 1.0)); var senseSource = new SenseSource(SourceType.SHADOW, map.RandomPosition(true), 5, Distance.EUCLIDEAN); senseMap.AddSenseSource(senseSource); foreach (var curPos in positions) { if (!map[curPos]) { continue; } senseSource.Position = curPos; fov.Calculate(senseSource.Position, senseSource.Radius, senseSource.DistanceCalc); senseMap.Calculate(); foreach (var pos in map.Positions()) { bool success = fov.BooleanFOV[pos] == (senseMap[pos] > 0.0 ? true : false); if (!success) { Console.WriteLine($"Failed on pos {pos} with source at {senseSource.Position}."); Console.WriteLine($"FOV: {fov[pos]}, SenseMap: {senseMap[pos]}"); Console.WriteLine($"Distance between source and fail point: {Distance.EUCLIDEAN.Calculate(senseSource.Position, pos)}, source radius: {senseSource.Radius}"); } Assert.AreEqual(true, success); } } var degreesList = Enumerable.Range(0, 360).ToList(); degreesList.FisherYatesShuffle(); var spanList = Enumerable.Range(1, 359).ToList(); spanList.FisherYatesShuffle(); var degrees = degreesList.Take(30).ToList(); var spans = spanList.Take(30).ToList(); senseSource.IsAngleRestricted = true; // Test angle-based shadowcasting foreach (var curPos in positions.Take(1)) { if (!map[curPos]) { continue; } foreach (var degree in degrees) { foreach (var span in spans) { senseSource.Angle = degree; senseSource.Span = span; senseSource.Position = curPos; fov.Calculate(senseSource.Position, senseSource.Radius, senseSource.DistanceCalc, senseSource.Angle, senseSource.Span); senseMap.Calculate(); foreach (var pos in map.Positions()) { bool success = fov.BooleanFOV[pos] == (senseMap[pos] > 0.0 ? true : false); if (!success) { Console.WriteLine($"Failed on pos {pos} with source at {senseSource.Position}, angle: {senseSource.Angle}, span: {senseSource.Span}."); Console.WriteLine($"FOV: {fov[pos]}, SenseMap: {senseMap[pos]}"); Console.WriteLine($"Distance between source and fail point: {Distance.EUCLIDEAN.Calculate(senseSource.Position, pos)}, source radius: {senseSource.Radius}"); } Assert.AreEqual(true, success); } } } } }