public void FOVTest() { var testMap = new ArrayMap <bool>(5, 5); foreach (Coord coord in testMap.Positions()) { testMap[coord] = true; } var centre = new Coord(2, 2); foreach (Coord coord in new RadiusAreaProvider(centre, 2, Radius.CIRCLE).CalculatePositions()) { testMap[coord] = false; } foreach (Coord coord in new RadiusAreaProvider(centre, 1, Distance.EUCLIDEAN).CalculatePositions()) { testMap[coord] = true; } var resMap = new ArrayMap <bool>(5, 5); foreach (Coord coord in testMap.Positions()) { resMap[coord] = testMap[coord]; } var FOV = new FOV(resMap); FOV.Calculate(centre, 1, Distance.EUCLIDEAN); Coord[] calculated = FOV.CurrentFOV.OrderBy(p => p.X).ThenBy(p => p.Y).ToArray(); Assert.True(calculated.SequenceEqual(new[] { new Coord(1, 2), new Coord(2, 1), new Coord(2, 2), new Coord(2, 3), new Coord(3, 2) })); }
public static ArrayMap <T> RotateArrayMap <T>(ArrayMap <T> arrayMap, RotateType rotateType) { ArrayMap <T> newPattern = null; switch (rotateType) { case RotateType.DEG90: newPattern = new ArrayMap <T>(arrayMap.Height, arrayMap.Width); foreach (var pos in arrayMap.Positions()) { newPattern[pos.Y, arrayMap.Width - 1 - pos.X] = arrayMap[pos.X, pos.Y]; } return(newPattern); case RotateType.DEG180: newPattern = new ArrayMap <T>(arrayMap.Width, arrayMap.Height); foreach (var pos in arrayMap.Positions()) { newPattern[arrayMap.Width - 1 - pos.Y, arrayMap.Height - 1 - pos.X] = arrayMap[pos.X, pos.Y]; } return(newPattern); case RotateType.DEG270: newPattern = new ArrayMap <T>(arrayMap.Height, arrayMap.Width); foreach (var pos in arrayMap.Positions()) { newPattern[arrayMap.Height - 1 - pos.Y, pos.X] = arrayMap[pos.X, pos.Y]; } return(newPattern); default: return(newPattern); } }
public static int[] GetStats(int height, int width, int tries, ArrayMap <bool> pattern) { StandardGenerator random = new StandardGenerator(); var wMap = new ArrayMap <bool>(height, width); int[] hits = new int[tries]; for (int i = 0; i < tries; i++) { QuickGenerators.GenerateCellularAutomataMap(wMap, random); var pMap = new ArrayMap <bool>(height, width); while (TryGetFirstPatternMatch(wMap, pMap, pattern, out Coord coord)) { foreach (var pos in pattern.Positions()) { pMap[pos.X + coord.X, pos.Y + coord.Y] = true; } hits[i] += 1; } } return(hits); }
public static bool TryGetFirstPatternMatch(ArrayMap <bool> map, ArrayMap <bool> pMap, ArrayMap <bool> pattern, out Coord startCoord) { startCoord = new Coord(); foreach (var pos in map.Positions()) { startCoord = pos; var match = true; foreach (var patPos in pattern.Positions()) { var xShift = pos.X + patPos.X; var yShift = pos.Y + patPos.Y; if (map.Width <= xShift || // check map width limits map.Height <= yShift || // check map height limits map[xShift, yShift] != pattern[patPos.X, patPos.Y] || // check if the pattern matches here with the walk map pMap[xShift, yShift] // check if the pattern map already has a pattern at this point ) { match = false; break; } } if (match) { return(true); } } return(false); }
public static ArrayMap <bool> DecodeBase64(string name) { string[] nameArray = name.Split('-'); string[] patternTypeArray = nameArray[0] .Split('N')[0] .Replace("X", "") .Split('Y'); var width = int.Parse(patternTypeArray[0]); var height = int.Parse(patternTypeArray[1]); //Debug.Log($"{name} X:{width} Y:{height}"); byte[] array = Convert.FromBase64String(nameArray[1]); BitArray bitArray = new BitArray(Convert.FromBase64String(nameArray[1])); ArrayMap <bool> tMap = new ArrayMap <bool>(width, height); foreach (var pos in tMap.Positions()) { //Debug.Log($"{(pos.Y * tMap.Width) + pos.X}"); tMap[pos.X, pos.Y] = bitArray[(pos.Y * tMap.Width) + pos.X]; } return(tMap); }
public static TimeSpan TimeForLambdaTranslationMap1ParamAccess(int mapWidth, int mapHeight, int iterations) { var s = new Stopwatch(); var map = new ArrayMap <int>(mapWidth, mapHeight); foreach (var pos in map.Positions()) { map[pos] = pos.ToIndex(mapWidth); } var lambdaTranslationMap = new LambdaTranslationMap <int, double>(map, i => i / 100.0); // For caching double val; foreach (var pos in lambdaTranslationMap.Positions()) { val = lambdaTranslationMap[pos]; } s.Start(); for (int i = 0; i < iterations; i++) { foreach (var pos in lambdaTranslationMap.Positions()) { val = lambdaTranslationMap[pos]; } } s.Stop(); return(s.Elapsed); }
static ArrayMap <bool> RandomArray(int seed, int width, int height) { random.Seed = (uint)seed; var result = new ArrayMap <bool>(width, height); foreach (var pos in result.Positions()) { result[pos] = random.NextBoolean(); } return(result); }
private static ISettableMapView <double> TestResMap(int width, int height) { var map = new ArrayMap <double>(width, height); foreach (var pos in map.Positions()) { map[pos] = SingletonRandom.DefaultRNG.NextDouble(); } return(map); }
public void DecodeBase64Test() { ArrayMap <bool> arrayMap1 = ArrayMapHelper.DecodeBase64("X4Y4N000-AAA="); Assert.Equal(4, arrayMap1.Width); Assert.Equal(4, arrayMap1.Height); foreach (var pos in arrayMap1.Positions()) { Assert.False(arrayMap1[pos]); } }
//todo temp for prototype private CombatMap GenerateTerrain() { var terrainMap = new ArrayMap <bool>(MapWidth, MapHeight); QuickGenerators.GenerateRectangleMap(terrainMap); var map = new CombatMap(terrainMap.Width, terrainMap.Height); var biome = FindObjectOfType <TravelManager>().CurrentBiome; var tStore = FindObjectOfType <TerrainStore>(); var tileWeights = tStore.GetTileTypeWeights(biome); foreach (var position in terrainMap.Positions()) { var selection = tileWeights.First().Key; var totalWeight = tileWeights.Values.Sum(); var roll = Random.Range(0, totalWeight); foreach (var tType in tileWeights.OrderByDescending(t => t.Value)) { var weightedValue = tType.Value; if (roll >= weightedValue) { roll -= weightedValue; } else { selection = tType.Key; break; } } Tile tile; if (IsWallTile(selection)) { tile = tStore.GetWallTile(biome, selection, position, MapWidth, MapHeight); } else { tile = TerrainStore.GetFloorTile(biome, selection, position, MapWidth, MapHeight); } map.SetTerrain(tile); } return(map); }
public Map(IGenerator dungeonRandom, int width, int height, Adventure adventure, bool useTestMap = false) { Width = width; Height = height; Adventure = adventure; var wMap = new ArrayMap <bool>(width, height); // creating map here if (useTestMap) { TestMap(wMap); } else { //QuickGenerators.GenerateRandomRoomsMap(wMap, dungeonRandom, 15, 5, 15, 50); QuickGenerators.GenerateCellularAutomataMap(wMap, dungeonRandom); } WalkabilityMap = wMap; ExplorationMap = new ArrayMap <int>(width, height); EntityMap = new ArrayMap <AdventureEntityContainer>(width, height); TileMap = new ArrayMap <Tile>(width, height); Entities = new List <AdventureEntity>(); var resMap = new ArrayMap <bool>(width, height); foreach (var pos in wMap.Positions()) { // build up Entity Map, not necessary and really slow on big maps //EntityMap[i,j] = new AdventureEntityContainer(); if (wMap[pos.X, pos.Y]) { //ExplorationMap[i, j] = 1; _walkableTiles++; resMap[pos.X, pos.Y] = true; TileMap[pos.X, pos.Y] = new StoneTile(this, new Coord(pos.X, pos.Y)); } else { //ExplorationMap[i, j] = -9; resMap[pos.X, pos.Y] = false; TileMap[pos.X, pos.Y] = new StoneWall(this, new Coord(pos.X, pos.Y)); } } FovMap = new FOV(resMap); Locations = CreateMapLocations(wMap, 9); ExpectedFovNum = new int[width, height]; }
public override void _Ready() { var terrain = new ArrayMap <bool>(40, 40); MapHelper.TileMap = this; MapHelper.FogMap = GetParent().GetNode <TileMap>("FogMap"); QuickGenerators.GenerateCellularAutomataMap(terrain); var map = new GoRogue.GameFramework.Map( width: terrain.Width, height: terrain.Height, numberOfEntityLayers: 1, distanceMeasurement: Distance.CHEBYSHEV ); foreach (var pos in terrain.Positions()) { MapHelper.FogMap.SetCell(pos.X, pos.Y, 0); if (terrain[pos]) { SetCell(pos.X, pos.Y, 0); map.SetTerrain(TerrainFactory.Floor(pos)); MapHelper.EmptyTiles.Add(new Vector2(pos.X, pos.Y)); } else // Wall { map.SetTerrain(TerrainFactory.Wall(pos)); SetCell(pos.X, pos.Y, 1); } } var playerScene = GD.Load <PackedScene>("res://entities/Player.tscn"); var player = playerScene.Instance() as Player; map.AddEntity(player); MapHelper.TileMap.AddChild(player); var enemyScene = GD.Load <PackedScene>("res://entities/Enemy.tscn"); foreach (var e in Enumerable.Range(0, 10)) { var enemy = enemyScene.Instance() as Enemy; map.AddEntity(enemy); MapHelper.TileMap.AddChild(enemy); } MapHelper.CurrentMap = map; GD.Print("Number of entities: " + MapHelper.CurrentMap.Entities.Count); GD.Print("Number of children: " + GetChildCount()); }
/// <summary> /// Constructor. Takes a goal map where in all goals are treated as threats to be avoided, /// and a magnitude to use (defaulting to 1.2). /// </summary> /// <param name="baseMap">The underlying goal map to use.</param> /// <param name="magnitude">Magnitude to multiply by during calculation.</param> public FleeMap(GoalMap baseMap, double magnitude = 1.2) { _baseMap = baseMap ?? throw new ArgumentNullException(nameof(baseMap)); Magnitude = magnitude; _goalMap = new ArrayMap <double?>(baseMap.Width, baseMap.Height); _nodes = new ArrayMap <PositionNode>(baseMap.Width, baseMap.Height); foreach (var pos in _nodes.Positions()) { _nodes[pos] = new PositionNode(pos); } _baseMap.Updated += Update; }
public static string EncodeBase64(ArrayMap <bool> tMap, int i = 0) { bool[] boolArray = new bool[tMap.Width * tMap.Height]; foreach (var pos in tMap.Positions()) { boolArray[(pos.Y * tMap.Width) + pos.X] = tMap[pos.X, pos.Y]; } BitArray bitArray = new BitArray(boolArray); var bits = BitArrayToByteArray(bitArray); return($"X{tMap.Width}Y{tMap.Height}N{i.ToString("000")}-{Convert.ToBase64String(bits)}"); }
public List <Coord> GetCoords <T>(ArrayMap <T> map, Coord coord, Func <T, bool> validate) { var coords = new List <Coord>(); foreach (var position in map.Positions()) { if (validate(map[position.X, position.Y]) && (coord.X != position.X || coord.Y != position.Y)) { coords.Add(new Coord(position.X, position.Y)); } } return(coords); }
public void ApplyOverlayTest() { var map = new ArrayMap <bool>(100, 100); QuickGenerators.GenerateCellularAutomataMap(map); var duplicateMap = new ArrayMap <bool>(map.Width, map.Height); duplicateMap.ApplyOverlay(map); foreach (var pos in map.Positions()) { Assert.AreEqual(map[pos], duplicateMap[pos]); } }
public void UnboundedViewportTest() { const int MAP_WIDTH = 100; const int MAP_HEIGHT = 100; var map = new ArrayMap <int>(MAP_WIDTH, MAP_HEIGHT); var unboundedViewport = new UnboundedViewport <int>(map, 1); foreach (var pos in map.Positions()) { Assert.AreEqual(0, unboundedViewport[pos]); } unboundedViewport.ViewArea = unboundedViewport.ViewArea.Translate(5, 5); foreach (var pos in unboundedViewport.Positions()) { if (pos.X < MAP_WIDTH - 5 && pos.Y < MAP_HEIGHT - 5) { Assert.AreEqual(0, unboundedViewport[pos]); } else { Assert.AreEqual(1, unboundedViewport[pos]); } } unboundedViewport.ViewArea = unboundedViewport.ViewArea.WithSize(5, 5); foreach (var pos in unboundedViewport.Positions()) { Assert.AreEqual(0, unboundedViewport[pos]); } unboundedViewport.ViewArea = unboundedViewport.ViewArea.WithPosition(MAP_WIDTH - 1, MAP_HEIGHT - 1); foreach (var pos in unboundedViewport.Positions()) { if (pos.X == 0 && pos.Y == 0) { Assert.AreEqual(0, unboundedViewport[pos]); } else { Assert.AreEqual(1, unboundedViewport[pos]); } } }
private void RemoveLandmassByVoronoiNoise(ArrayMap <bool> rawOverworldMap) { bool remove = false; float remover = 0.0f; foreach (var p in rawOverworldMap.Positions()) { if (rawOverworldMap[p] == false) { remover = voronoiNoiseMap[p.X, p.Y]; remove = true; } if ((remove == true) && (voronoiNoiseMap[p.X, p.Y] == remover) && (rawOverworldMap[p] == true)) { rawOverworldMap[p] = false; } } }
public void GenerateMap() { var tempMap = new ArrayMap <bool>(50, 50); //QuickGenerators.GenerateRectangleMap(tempMap); QuickGenerators.GenerateRandomRoomsMap(tempMap, 20, 5, 12); Map = new Map(50, 50, 1, Distance.CHEBYSHEV); Map.ObjectMoved += OnObjectMoved; foreach (var position in tempMap.Positions()) { if (tempMap[position]) { Map.SetTerrain(new FloorTerrain(position)); } else { Map.SetTerrain(new WallTerrain(position)); } } // instance a player var playerInstance = GD.Load <PackedScene>("res://Characters/Player/Player.tscn").Instance() as Player; GetTree().Root.GetNode("Game").AddChild(playerInstance); playerInstance.Position = Map.WalkabilityView.RandomPosition(true); playerInstance.Moved += OnPlayerMoved; GameController.Instance.Player = playerInstance; AddCharacter(playerInstance); // generate monsters for (var i = 0; i < _numMonsters; ++i) { var skeleman = GD.Load <PackedScene>("res://Characters/Monsters/Skeleman.tscn").Instance() as Monster; GetTree().Root.GetNode("Game").AddChild(skeleman); skeleman.Position = Map.WalkabilityView.RandomPosition(true); AddCharacter(skeleman); Monsters.Add(skeleman); } Map.CalculateFOV(playerInstance.Position, playerInstance.FOVRadius, Radius.DIAMOND); Draw(); }
/// <summary> /// Generates the areas. Floor tiles will be set to true in the provided map, and wall tiles /// will be set to false. /// </summary> /// <param name="map">The map to fill with values when generate is called.</param> /// <param name="rng"> /// The RNG to use to initially fill the map. If null is specified, the default RNG is used. /// </param> /// <param name="fillProbability"> /// Represents the percent chance that a given cell will be a floor cell when the map is /// initially randomly filled. Recommended to be in range [40, 60] (40 is used in the /// roguebasin article). /// </param> /// <param name="totalIterations"> /// Total number of times the cellular automata-based smoothing algorithm is executed. /// Recommended to be in range [2, 10] (7 is used on roguebasin article). /// </param> /// <param name="cutoffBigAreaFill"> /// Total number of times the cellular automata smoothing variation that is more likely to /// result in "breaking up" large areas will be run before switching to the more standard /// nearest neighbors version. Recommended to be in range [2, 7] (4 is used in roguebasin article). /// </param> static public void Generate(ISettableMapView <bool> map, IGenerator rng = null, int fillProbability = 40, int totalIterations = 7, int cutoffBigAreaFill = 4) { if (rng == null) { rng = SingletonRandom.DefaultRNG; } // We must allocate a new one to avoid messing up other map gen features that happened on // the original var tempMap = new ArrayMap <bool>(map.Width, map.Height); tempMap.ApplyOverlay(map); // Sets each cell so as of this point, tempMap is in a clean state randomlyFillCells(tempMap, rng, fillProbability); for (int i = 0; i < totalIterations; i++) { if (i < cutoffBigAreaFill) { cellAutoBigAreaAlgo(tempMap); } else { cellAutoNearestNeighborsAlgo(tempMap); } } // Ensure it's enclosed before we try to connect, so we can't possibly connect a path // that ruins the enclosure. Doing this before connection ensures that filling it can't // kill the path to an area. fillToRectangle(tempMap); // Set rooms to true, but do NOT enforce where walls (false values) are -- this is done // by making sure the blank slate passed in is all false. foreach (var pos in tempMap.Positions()) { if (tempMap[pos]) { map[pos] = true; } } }
public static TestGameMap CreateDungeonMap(int width, int height) { var map = new TestGameMap(width, height); var terrain = new ArrayMap <bool>(width, height); QuickGenerators.GenerateRectangleMap(terrain); foreach (var pos in terrain.Positions()) { if (terrain[pos]) { map.SetTerrain(TerrainFactory.Floor(pos)); } else { map.SetTerrain(TerrainFactory.Wall(pos)); } } return(map); }
public void ApplyTerrainOverlayTranslation() { var grMap = new ArrayMap <bool>(10, 10); QuickGenerators.GenerateRectangleMap(grMap); var map = new Map(grMap.Width, grMap.Height, 1, Distance.CHEBYSHEV); map.ApplyTerrainOverlay(grMap, (pos, b) => b ? new GameObject(pos, 0, null, true, true, true) : new GameObject(pos, 0, null, true, false, false)); // If any value is null this fails due to NullReferenceException: otherwise, we assert the right value got set foreach (var pos in grMap.Positions()) { if (grMap[pos]) { Assert.IsTrue(map.GetTerrain(pos).IsWalkable == true); } else { Assert.IsTrue(map.GetTerrain(pos).IsWalkable == false); } } }
public void ManualGoalMapTest() { var map = new ArrayMap <bool>(MAP_WIDTH, MAP_HEIGHT); RectangleMapGenerator.Generate(map); var stateMap = new ArrayMap <GoalState>(map.Width, map.Height); foreach (var pos in stateMap.Positions()) { stateMap[pos] = map[pos] ? GoalState.Clear : GoalState.Obstacle; } stateMap[MAP_WIDTH / 2, MAP_WIDTH / 2] = GoalState.Goal; stateMap[MAP_WIDTH / 2 + 5, MAP_HEIGHT / 2 + 5] = GoalState.Goal; var goalMap = new GoalMap(stateMap, Distance.EUCLIDEAN); goalMap.Update(); Assert.AreEqual(null, goalMap[0, 0]); Console.Write(goalMap.ToString(5, "0.00")); }
private List <Rectangle> CreateMapLocations(ArrayMap <bool> wMap, int minLocationSize) { var rectangles = new List <Rectangle>(); foreach (var pos in wMap.Positions()) { if (!wMap[pos.X, pos.Y]) { continue; } var width = 2; var height = 2; var rectangle = new Rectangle(pos.X, pos.Y, width, height); Rectangle legitRectangle = rectangle; while (rectangle.Positions().All(p => wMap[p.X, p.Y])) { legitRectangle = rectangle; rectangle = rectangle.ChangeSize(++width, ++height); } if (legitRectangle.Positions().All(p => wMap[p.X, p.Y])) { rectangles.Add(legitRectangle); } } //for (var i = 0; i < wMap.Width; i++) //{ // for (var j = 0; j < wMap.Height; j++) // { // if (!wMap[i, j]) continue; // var width = 2; // var height = 2; // var rectangle = new Rectangle(i, j, width, height); // Rectangle legitRectangle = rectangle; // while (rectangle.Positions().All(p => wMap[p.X, p.Y])) // { // legitRectangle = rectangle; // rectangle = rectangle.ChangeSize(++width, ++height); // } // if (legitRectangle.Positions().All(p => wMap[p.X, p.Y])) // { // rectangles.Add(legitRectangle); // } // } //} var orderedRectangles = rectangles.Where(p => p.Positions().Count() >= minLocationSize).OrderByDescending(p => p.Positions().Count()).ToList(); for (var i = 0; i < orderedRectangles.Count - 1; i++) { for (var j = i + 1; j < orderedRectangles.Count; j++) { if (Rectangle.GetUnion(orderedRectangles[i], orderedRectangles[j]) == orderedRectangles[i] || !Rectangle.GetIntersection(orderedRectangles[i], orderedRectangles[j]).IsEmpty) { orderedRectangles[j] = Rectangle.EMPTY; } } } return(orderedRectangles.Where(p => !p.IsEmpty).Take(20).ToList()); }
private void AssignBiomes(ArrayMap <bool> rawOverworldMap, OverworldTile[] OverWorld) { foreach (var pos in rawOverworldMap.Positions()) { OverworldTile tile = null; int glyph; calculatedBiome = DefineBiomeAt(pos); if (rawOverworldMap[pos]) // land tiles { Color fgd = Color.White; Color bgd = Color.DarkGray; var fgdColdBiome = new Color(53, 79, 0); var bkgColdBiome = new Color(141, 182, 0); var bkgTempBiome = new Color(46, 110, 18); var fgdTempBiome = new Color(00, 68, 00); var bkgWarmBiome = new Color(45, 136, 45); var fgdWarmBiome = new Color(0, 68, 0); switch (calculatedBiome) { case Biome.Cold | Biome.Arid: fgd = fgdColdBiome; //AzureMist bgd = bkgColdBiome; // Apple Green glyph = 44; // ',' break; case Biome.Cold | Biome.SemiArid: fgd = fgdColdBiome; bgd = bkgColdBiome; // Apple Green glyph = 46; // '.' break; case Biome.Cold | Biome.SemiHumid: fgd = fgdColdBiome; bgd = bkgColdBiome; glyph = 15; // '☼' break; case Biome.Cold | Biome.Humid: fgd = fgdColdBiome; bgd = bkgColdBiome; glyph = 42; // '*' break; case Biome.Temperate | Biome.Arid: fgd = new Color(121, 182, 0); bgd = bkgTempBiome; glyph = 15; // '☼' break; case Biome.Temperate | Biome.SemiArid: fgd = fgdTempBiome; bgd = bkgTempBiome; glyph = 6; // '♠' break; case Biome.Temperate | Biome.SemiHumid: fgd = fgdTempBiome; bgd = bkgTempBiome; glyph = 6; // '♠' break; case Biome.Temperate | Biome.Humid: fgd = fgdTempBiome; bgd = bkgTempBiome; glyph = 5; // '♣' break; case Biome.Warm | Biome.Arid: fgd = fgdWarmBiome; bgd = bkgWarmBiome; glyph = 44; // ',' break; case Biome.Warm | Biome.SemiArid: fgd = fgdWarmBiome; bgd = bkgWarmBiome; glyph = 46; // '.' break; case Biome.Warm | Biome.SemiHumid: fgd = fgdWarmBiome; bgd = bkgWarmBiome; glyph = 6; // '♠' break; case Biome.Warm | Biome.Humid: fgd = fgdWarmBiome; bgd = bkgWarmBiome; glyph = 5; // '♣' break; default: glyph = 63; // '?' break; } tile = new OverworldTile($"Land - {glyph}", pos, glyph) { ZoneNoise = voronoiNoiseMap[pos.X, pos.Y], RainNoise = rainNoise[pos.X, pos.Y], Biome = calculatedBiome, Foreground = fgd, Background = bgd, IsWalkable = true, IsTransparent = true }; } else if (rawOverworldMap[pos] == false) // air tiles { glyph = 126; // '~' var bkg = new Color(93, 138, 168); var fgd = Color.Aquamarine; tile = new OverworldTile($"Air - {glyph}", pos, glyph) { ZoneNoise = voronoiNoiseMap[pos.X, pos.Y], RainNoise = rainNoise[pos.X, pos.Y], Biome = calculatedBiome, Foreground = fgd, Background = bkg, IsWalkable = false, IsTransparent = true }; } if (tile != null) { OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)] = tile; //if (voronoiNoiseMap[pos.X, pos.Y] >= (voronoiNoiseMap.Data.Max() - HotSpotLowerLimit)) //{ // if (rainNoise[pos.X, pos.Y] > 0.5) // riverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]); //} bool candidate = rainNoise[pos.X, pos.Y] > MinPersp && (voronoiNoiseMap[pos.X, pos.Y] >= (voronoiNoiseMap.Data.Max() - HotSpotLowerLimit)); switch (tile.Biome) { case Biome.Cold | Biome.SemiHumid: if (candidate) { RiverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]); } break; case Biome.Cold | Biome.Humid: if (candidate) { RiverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]); } break; case Biome.Temperate | Biome.SemiHumid: if (candidate) { RiverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]); } break; case Biome.Temperate | Biome.Humid: if (candidate) { RiverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]); } break; case Biome.Warm | Biome.SemiHumid: if (candidate) { RiverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]); } break; case Biome.Warm | Biome.Humid: if (candidate) { RiverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]); } break; default: break; } //if (tile.Biome == Biome.Humid || tile.Biome == Biome.SemiHumid) //{ // riverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]); //} } else { new Exception($"{tile.ID} is null."); } } }
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); } } } } }