/// <summary> /// Generates a site /// </summary> /// <param name="siteType"></param> /// <param name="biomeType"></param> /// <param name="owner"></param> /// <param name="startPoint"></param> /// <param name="actors"></param> /// <returns></returns> public static MapBlock[,] GenerateSite(SiteData siteData, out Actor[] actors) { MapCoordinate startPoint = null; //First we generate some empty wilderness of the right type MapBlock[,] map = WildernessGenerator.GenerateMap(siteData.Biome, 0, 0, out actors, out startPoint); //Now, clear the tiles from between 5,5 till 25,25 for (int x = 5; x < 26; x++) { for (int y = 5; y < 26; y++) { MapBlock block = map[x, y]; block.RemoveAllItems(); } } ItemFactory.ItemFactory itemFactory = new ItemFactory.ItemFactory(); int waterID = 0; MapItem waterTile = itemFactory.CreateItem(Archetype.TILES, "water", out waterID); //If it's a fishing village, put some water in if (siteData.SiteTypeData.SiteType == SiteType.FISHING_VILLAGE) { for (int x = 0; x < map.GetLength(0); x++) { for (int y = map.GetLength(1) - 10; y < map.GetLength(1); y++) { MapBlock block = map[x, y]; block.RemoveAllItems(); //Set the tile to water block.Tile = itemFactory.CreateItem("tiles", waterID); block.Tile.Coordinate = new MapCoordinate(x, y, 0, MapType.LOCAL); } } } LocalMapGenerator lmg = new LocalMapGenerator(); LocalMapXMLParser parser = new LocalMapXMLParser(); Maplet maplet = parser.ParseMapletFromTag(siteData.SiteTypeData.SiteType.ToString().Replace("_", " ").ToLower(),siteData.Biome); var tileID = DatabaseHandling.GetItemIdFromTag(Archetype.TILES, WildernessGenerator.details[siteData.Biome].BaseTileTag); MapletActorWanderArea[] wanderAreas = null; MapletPatrolPoint[] patrolPoints = null; MapletFootpathNode[] footPath = null; //Now generate the actual map MapBlock[,] siteMap = lmg.GenerateMap(tileID, null, maplet, false, "", siteData.Owners, out actors, out wanderAreas, out patrolPoints, out footPath); //Now lets fuse the maps map = lmg.JoinMaps(map, siteMap, 5, 5); foreach (var actor in actors) { if (actor.CurrentMission == null) { actor.CurrentMission = actor.MissionStack.Count > 0 ? actor.MissionStack.Pop() : null; } if (actor.CurrentMission != null && actor.CurrentMission.GetType() == typeof(WanderMission)) { WanderMission wMiss = actor.CurrentMission as WanderMission; wMiss.WanderPoint.X += 5; wMiss.WanderPoint.Y += 5; wMiss.WanderRectangle = new Rectangle(wMiss.WanderRectangle.X + 5, wMiss.WanderRectangle.Y + 5, wMiss.WanderRectangle.Width, wMiss.WanderRectangle.Height); } } //Fix the patrol points foreach (var point in patrolPoints) { point.Point.X += 5; point.Point.Y += 5; } //Let's fix the patrol points, we need to merge them into PatrolRoutes var patrolRoutes = PatrolRoute.GetPatrolRoutes(patrolPoints); foreach (var area in wanderAreas) { area.WanderRect = new Rectangle(area.WanderRect.X + 5, area.WanderRect.Y + 5, area.WanderRect.Width, area.WanderRect.Height); } //And fix the path nodes foreach (var pn in footPath) { pn.Point.X += 5; pn.Point.Y += 5; } //If the map already has any actors in it, make the characters prone foreach (var actor in actors) { actor.IsProne = true; } //Now generate the pathfinding map PathfinderInterface.Nodes = GeneratePathfindingMap(map); int pathTileID = -1; var dummy = itemFactory.CreateItem(Archetype.TILES, "stone", out pathTileID); //Go through each footpath node. Attempt to connect the node with the other primary nodes foreach (var fp in footPath) { foreach (var primary in footPath.Where(p => p.IsPrimary)) { //Join them up var path = PathfinderInterface.GetPath(fp.Point, primary.Point); if (path != null) { foreach (var coord in path) { MapBlock block = map[coord.X, coord.Y]; //Only do this if the tile isn't wood, or stone if (!block.Tile.InternalName.ToUpper().Contains("STONE") && !block.Tile.InternalName.ToUpper().Contains("WOOD")) { block.Tile = itemFactory.CreateItem("tiles", pathTileID); block.Tile.Coordinate = new MapCoordinate(coord); } } } } } List<Actor> actorList = new List<Actor>(); actorList.AddRange(actors); //And add the actors //Let's generate a number of actors then foreach (ActorProfession profession in Enum.GetValues(typeof(ActorProfession))) { //So do we have any wander areas for them ? var possibleAreas = wanderAreas.Where(wa => wa.Factions.HasFlag(siteData.Owners) && wa.Profession.Equals(profession)); var possibleRoutes = patrolRoutes.Where(pr => pr.Owners.HasFlag(siteData.Owners) && pr.Profession.Equals(profession)); //Any actors? if (siteData.ActorCounts.ContainsKey(profession)) { //Yes, how many int total = siteData.ActorCounts[profession]; var a = ActorGeneration.CreateActors(siteData.Owners, profession, total); foreach(var ac in a) { ac.SiteMember = true; } actorList.AddRange(a); foreach (var actor in a) { //So, where we going to drop them off ? Randomly int tries = 0; for (; ; ) { int randomX = GameState.Random.Next(map.GetLength(0)); int randomY = GameState.Random.Next(map.GetLength(1)); if (map[randomX, randomY].MayContainItems) { //Plop it on there actor.MapCharacter.Coordinate = new MapCoordinate(randomX, randomY, 0, MapType.LOCAL); map[randomX, randomY].ForcePutItemOnBlock(actor.MapCharacter); tries = 0; break; } else { tries++; } if (tries >= 150) { //give up break; } } //Go through each actor, and either tell them to wander in the whole map, or within any possible area which matches //Any possible area avaialble? List<object> possibleMissions = new List<object>(); //I know :( But Using an interface or trying to mangle together an inheritance was worse possibleMissions.AddRange(possibleAreas.Where(pa => pa.MaxAmount > pa.CurrentAmount)); possibleMissions.AddRange(possibleRoutes); var chosenArea = possibleMissions.OrderBy(pa => GameState.Random.Next(100)).FirstOrDefault(); if (chosenArea == null) { //Wander around the whole map actor.CurrentMission = new WanderMission() { LoiterPercentage = 25, WanderPoint = new MapCoordinate(map.GetLength(0) / 2, map.GetLength(1) / 2, 0, MapType.LOCAL), WanderRectangle = new Rectangle(0, 0, map.GetLength(0), map.GetLength(1)) }; } else { //Is this a patrol or a wander ? if (chosenArea.GetType().Equals(typeof(PatrolRoute))) { var patrolDetails = chosenArea as PatrolRoute; PatrolRouteMission pm = new PatrolRouteMission(); pm.PatrolRoute.AddRange(patrolDetails.Route); actor.CurrentMission = pm; } else if (chosenArea.GetType().Equals(typeof(MapletActorWanderArea))) { var wanderDetails = chosenArea as MapletActorWanderArea; //Wander around in that area actor.CurrentMission = new WanderMission() { LoiterPercentage = 25, WanderPoint = new MapCoordinate(wanderDetails.WanderPoint), WanderRectangle = wanderDetails.WanderRect }; wanderDetails.CurrentAmount++; } } } } } actors = actorList.ToArray(); siteData.PatrolRoutes = patrolRoutes.ToList(); siteData.WanderAreas = wanderAreas.ToList(); return map; }
/// <summary> /// Creates and puts a particular room in a particular rectangle /// </summary> /// <param name="roomType"></param> /// <param name="rect"></param> /// <param name="circle">When the room is a Summoning Room, there's the circle</param> private static void PutRoom(MapBlock[,] map, int tileID, int level, DungeonRoomType roomType, Rectangle rect, out SummoningCircle circle) { circle = null; string tagName = roomType.ToString().ToLower().Replace("_", " ") + " room"; LocalMapXMLParser parser = new LocalMapXMLParser(); var maplet = parser.ParseMapletFromTag(tagName); //Change the width and height to match the rectangle we're fitting it in //Leave a rim of 1 maplet.SizeX = rect.Width - 2; maplet.SizeY = rect.Height - 2; LocalMapGenerator lmg = new LocalMapGenerator(); Actor[] actors = null; MapletActorWanderArea[] areas = null; MapletPatrolPoint[] patrolRoutes = null; MapletFootpathNode[] footpathNodes = null; var gennedMap = lmg.GenerateMap(tileID, null, maplet, false, "", OwningFactions.UNDEAD, out actors, out areas, out patrolRoutes, out footpathNodes); //Is this a summoning room? if (roomType == DungeonRoomType.SUMMONING) { //Go through each map block and see if we find a summoning circle for (int x = 0; x < gennedMap.GetLength(0); x++) { for (int y = 0; y < gennedMap.GetLength(1); y++) { var block = gennedMap[x, y]; if (block.GetTopMapItem() != null && block.GetTopMapItem().GetType().Equals(typeof(SummoningCircle))) { circle = block.GetTopMapItem() as SummoningCircle; } } } } if (roomType == DungeonRoomType.COMBAT_PIT) { int docLevel = (int) level/4; docLevel = docLevel < 1 ? 1 : docLevel; docLevel = docLevel > 5 ? 5 : docLevel; //Generate a combat manual - Level [1..5] will be determined by floor of Dungeon Level /4 CombatManual cm = new CombatManual(SpecialAttacksGenerator.GenerateSpecialAttack(docLevel)); //Now place it, somewhere (or at least try 50 times) for(int i=0; i < 50; i++) { MapBlock randomBlock = gennedMap[GameState.Random.Next(gennedMap.GetLength(0)), GameState.Random.Next(gennedMap.GetLength(1))]; if (randomBlock.MayContainItems) { randomBlock.ForcePutItemOnBlock(cm); break; } } } //Do we have any treasure chests? for (int x = 0; x < gennedMap.GetLength(0); x++) { for (int y = 0; y < gennedMap.GetLength(1); y++) { var block = gennedMap[x, y]; if (block.GetTopMapItem() != null && block.GetTopMapItem().GetType().Equals(typeof(TreasureChest))) { TreasureChest chest = block.GetTopMapItem() as TreasureChest; InventoryItemManager iim = new InventoryItemManager(); //Fill em up chest.Contents = iim.FillTreasureChest((InventoryCategory[])Enum.GetValues(typeof(InventoryCategory)), 300 + (50 * level)); } } } //Now fit one into the other lmg.JoinMaps(map, gennedMap, rect.X + 1, rect.Y + 1); }
public static void ParseXML() { LocalMapXMLParser parser = new LocalMapXMLParser(); //Maplet maplet = parser.ParseMaplet(@"Maplets/IronMine.xml"); Actor[] tempy = null; //MapBlock[,] generatedMap = gen.GenerateMap(0, null, maplet, true,"human",DRObjects.Enums.OwningFactions.HUMANS,out tempy); //put in the map ////Generate it LocalMapGenerator gen = new LocalMapGenerator(); SiteData siteData = new SiteData(); siteData.SiteTypeData = SiteDataManager.GetData(SiteType.STABLES); siteData.Biome = GlobalBiome.DENSE_FOREST; siteData.Owners = OwningFactions.HUMANS; //Locate the right actor counts siteData.LoadAppropriateActorCounts(); MapBlock[,] generatedMap = SiteGenerator.GenerateSite(siteData, out tempy); GameState.LocalMap = new LocalMap(50, 50, 1, 0); GameState.LocalMap.Actors = tempy.ToList(); List<MapBlock> collapsedMap = new List<MapBlock>(); foreach (MapBlock block in generatedMap) { collapsedMap.Add(block); } GameState.LocalMap.AddToLocalMap(collapsedMap.ToArray()); MapItem player = new MapItem(); player.Coordinate = new MapCoordinate(10, 5, 0, DRObjects.Enums.MapType.LOCAL); player.Description = "The player character"; player.Graphic = SpriteManager.GetSprite(LocalSpriteName.PLAYERCHAR_MALE); player.InternalName = "Player Char"; player.MayContainItems = false; player.Name = "Player"; MapBlock playerBlock = GameState.LocalMap.GetBlockAtCoordinate(new MapCoordinate(5, 5, 0, DRObjects.Enums.MapType.LOCAL)); playerBlock.PutItemOnBlock(player); GameState.PlayerCharacter = new Actor(); GameState.PlayerCharacter.MapCharacter = player; GameState.PlayerCharacter.IsPlayerCharacter = true; GameState.LocalMap.Actors.Add(GameState.PlayerCharacter); GameState.PlayerCharacter.Attributes = ActorGeneration.GenerateAttributes("human", DRObjects.ActorHandling.CharacterSheet.Enums.ActorProfession.WARRIOR, 10, GameState.PlayerCharacter); GameState.PlayerCharacter.Anatomy = ActorGeneration.GenerateAnatomy("human"); GameState.PlayerCharacter.Attributes.Health = GameState.PlayerCharacter.Anatomy; }
/// <summary> /// Generates a camp /// </summary> /// <returns></returns> public static MapBlock[,] GenerateCamp(int enemies, out MapCoordinate startPoint, out DRObjects.Actor[] enemyArray) { MapBlock[,] map = new MapBlock[MAP_EDGE, MAP_EDGE]; Random random = new Random(); ItemFactory.ItemFactory factory = new ItemFactory.ItemFactory(); int grassTileID = 0; factory.CreateItem(Archetype.TILES, "grass", out grassTileID); //Create a new map which is edge X edge in dimensions and made of grass for (int x = 0; x < MAP_EDGE; x++) { for (int y = 0; y < MAP_EDGE; y++) { MapBlock block = new MapBlock(); map[x, y] = block; block.Tile = factory.CreateItem("tile", grassTileID); block.Tile.Coordinate = new MapCoordinate(x, y, 0, MapType.LOCAL); } } //Now created a wall int pallisadeID = 0; factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall lr", out pallisadeID); //Create a square of pallisade wall int startCoord = (MAP_EDGE - FORTIFICATION_EDGE) / 2; int endCoord = MAP_EDGE - ((MAP_EDGE - FORTIFICATION_EDGE) / 2); for (int x = startCoord + 1; x < endCoord; x++) { MapBlock block = map[x, startCoord]; MapItem item = factory.CreateItem("mundaneitems", pallisadeID); block.ForcePutItemOnBlock(item); block = map[x, endCoord]; item = factory.CreateItem("mundaneitems", pallisadeID); block.ForcePutItemOnBlock(item); } pallisadeID = 0; for (int y = startCoord + 1; y < endCoord; y++) { factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall tb", out pallisadeID); MapBlock block = map[startCoord, y]; MapItem item = factory.CreateItem("mundaneitems", pallisadeID); block.ForcePutItemOnBlock(item); factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall bt", out pallisadeID); block = map[endCoord, y]; item = factory.CreateItem("mundaneitems", pallisadeID); block.ForcePutItemOnBlock(item); } //We need to poke a hole in wall as an entrance //Let's poke one at the top and one at the bottom int center = MAP_EDGE / 2; int rValue = GameState.Random.Next(2); for (int x = -1; x < 2; x++) { if (rValue == 1) { MapBlock block = map[center + x, startCoord]; block.RemoveTopItem(); } else { MapBlock block = map[center + x, endCoord]; block.RemoveTopItem(); } } rValue = GameState.Random.Next(2); for (int y = -1; y < 2; y++) { if (rValue == 1) { MapBlock block = map[startCoord, y + center]; block.RemoveTopItem(); } else { MapBlock block = map[endCoord, y + center]; block.RemoveTopItem(); } } //Now, let's create some maplets in there //There's a single maplet containing the other maplets - let's get it LocalMapXMLParser lm = new LocalMapXMLParser(); Maplet maplet = lm.ParseMapletFromTag("camp"); LocalMapGenerator gen = new LocalMapGenerator(); //TODO: LATER THE OWNER MIGHT NOT BE A BANDIT MapletActorWanderArea[] wanderAreas = null; MapletPatrolPoint[] patrolPoints = null; MapletFootpathNode[] footPath = null; var gennedMap = gen.GenerateMap(grassTileID, null, maplet, false, "", OwningFactions.BANDITS, out enemyArray, out wanderAreas, out patrolPoints,out footPath); gen.JoinMaps(map, gennedMap, startCoord + 1, startCoord + 1); //Let's add some trees and stuff int decorCount = (int)(map.GetLength(1) * 0.50); //Just find as many random points and if it happens to be grass, drop them int itemID = 0; for (int i = 0; i < decorCount; i++) { //Just trees MapItem decorItem = factory.CreateItem(Archetype.MUNDANEITEMS, "tree", out itemID); //Pick a random point MapBlock randomBlock = map[random.Next(map.GetLength(0)), random.Next(map.GetLength(1))]; //Make sure its not inside the camp if (randomBlock.Tile.Coordinate.X >= startCoord && randomBlock.Tile.Coordinate.X <= endCoord && randomBlock.Tile.Coordinate.Y >= startCoord && randomBlock.Tile.Coordinate.Y <= endCoord) { //Not within the camp i--; continue; //try again } if (randomBlock.MayContainItems && randomBlock.Tile.Name == "Grass") { //Yes, can support it randomBlock.ForcePutItemOnBlock(decorItem); } //Otherwise forget all about it } //Now select all the border tiles and put in a "Exit here" border for (int x = 0; x < map.GetLength(0); x++) { MapCoordinate coo = new MapCoordinate(x, 0, 0, MapType.LOCAL); LeaveTownItem lti = new LeaveTownItem(); lti.Coordinate = coo; lti.Description = "path outside the town"; lti.Name = "Leave Town"; lti.Coordinate = coo; map[x, 0].ForcePutItemOnBlock(lti); coo = new MapCoordinate(x, map.GetLength(1) - 1, 0, MapType.LOCAL); lti = new LeaveTownItem(); lti.Coordinate = coo; lti.Description = "path outside the town"; lti.Name = "Leave Town"; lti.Coordinate = coo; map[x, map.GetLength(1) - 1].ForcePutItemOnBlock(lti); } for (int y = 0; y < map.GetLength(1); y++) { MapCoordinate coo = new MapCoordinate(0, y, 0, MapType.LOCAL); LeaveTownItem lti = new LeaveTownItem(); lti.Coordinate = coo; lti.Description = "path outside the town"; lti.Name = "Leave Town"; lti.Coordinate = coo; map[0, y].ForcePutItemOnBlock(lti); coo = new MapCoordinate(map.GetLength(0) - 1, y, 0, MapType.LOCAL); lti = new LeaveTownItem(); lti.Coordinate = coo; lti.Description = "path outside the town"; lti.Name = "Town Borders"; lti.Coordinate = coo; map[map.GetLength(0) - 1, y].ForcePutItemOnBlock(lti); } #region Treasure Room //This is a bit naughty. We need to locate where the tiles become soil MapCoordinate soilStart = null; bool breakOut = false; for (int x = 0; x < map.GetLength(0); x++) { for (int y = 0; y < map.GetLength(1); y++) { if (map[x, y].Tile.Name.ToLower().Equals("soil")) { soilStart = new MapCoordinate(x, y, 0, MapType.LOCAL); breakOut = true; break; } } if (breakOut) { break; } } //Also naughty, we know it's 5x5 #region Inner Wall for (int x = 0; x < 5; x++) { factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall lr", out pallisadeID); MapItem item = factory.CreateItem("mundaneitems", pallisadeID); if (x != 2) //hole in the top { map[soilStart.X + x, soilStart.Y].ForcePutItemOnBlock(item); } factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall lr", out pallisadeID); item = factory.CreateItem("mundaneitems", pallisadeID); map[soilStart.X + x, soilStart.Y + 5].ForcePutItemOnBlock(item); } for (int y = 0; y < 5; y++) { factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall tb", out pallisadeID); MapItem item = factory.CreateItem("mundaneitems", pallisadeID); map[soilStart.X - 1, soilStart.Y + y].ForcePutItemOnBlock(item); factory.CreateItem(Archetype.MUNDANEITEMS, "pallisade wall bt", out pallisadeID); item = factory.CreateItem("mundaneitems", pallisadeID); map[soilStart.X + 5, soilStart.Y + y].ForcePutItemOnBlock(item); } #endregion #endregion #region Patrol Points //Now let's collect the patrol points. We're going to have two possible patrols - one around each of the entrances - and another on the outside corners of the map List<MapCoordinate> outsidePatrol = new List<MapCoordinate>(); outsidePatrol.Add(new MapCoordinate(startCoord - 2, startCoord, 0, MapType.LOCAL)); outsidePatrol.Add(new MapCoordinate(endCoord + 2, startCoord, 0, MapType.LOCAL)); outsidePatrol.Add(new MapCoordinate(endCoord + 2, endCoord, 0, MapType.LOCAL)); outsidePatrol.Add(new MapCoordinate(startCoord - 2, endCoord, 0, MapType.LOCAL)); List<MapCoordinate> insidePatrol = new List<MapCoordinate>(); insidePatrol.Add(new MapCoordinate(center, startCoord + 1, 0, MapType.LOCAL)); insidePatrol.Add(new MapCoordinate(center, endCoord - 1, 0, MapType.LOCAL)); insidePatrol.Add(new MapCoordinate(startCoord + 1, center, 0, MapType.LOCAL)); insidePatrol.Add(new MapCoordinate(endCoord - 1, center, 0, MapType.LOCAL)); //Go through all of those and make sure they're clear of anything that wouldn't let them walk upon them foreach (var coordinate in outsidePatrol) { map[coordinate.X, coordinate.Y].RemoveTopItem(); } foreach (var coordinate in insidePatrol) { map[coordinate.X, coordinate.Y].RemoveTopItem(); } #endregion #region Actors enemyArray = CreateBandits(enemies, outsidePatrol.Select(op => new PatrolPoint() { AcceptableRadius = 2, Coordinate = op }).ToList(), insidePatrol.Select(op => new PatrolPoint() { AcceptableRadius = 2, Coordinate = op }).ToList()); int tries = 0; //Put them on the mappity map for (int i = 0; i < enemyArray.Length; i++) { Actor actor = enemyArray[i]; int randomX = random.Next(map.GetLength(0)); int randomY = random.Next(map.GetLength(1)); if (map[randomX, randomY].MayContainItems) { //Plop it on there actor.MapCharacter.Coordinate = new MapCoordinate(randomX, randomY, 0, MapType.LOCAL); map[randomX, randomY].ForcePutItemOnBlock(actor.MapCharacter); tries = 0; ////If they are wandering, make them wander in the right place //var mission = actor.MissionStack.Peek(); //if (mission.MissionType == ActorMissionType.WANDER) //{ // var wander = mission as WanderMission; // wander.WanderPoint = new MapCoordinate(actor.MapCharacter.Coordinate); // wander.WanderRectangle = new Rectangle(startCoord, startCoord, FORTIFICATION_EDGE, FORTIFICATION_EDGE); //} } else { tries++; i--; } if (tries >= 50) { //give up continue; } } #endregion startPoint = new MapCoordinate(map.GetLength(0) / 2, 0, 0, MapType.LOCAL); return map; }
/// <summary> /// Generates a dungeon having a particular amount of tiers, trap rooms, guard rooms and treasure rooms /// </summary> /// <param name="tiers">How many 'layers' the dungeon contains</param> /// <param name="enemyArray">A list of enemy actors</param> /// <param name="guardRooms">The maximum amount of guardrooms contained in the dungeon</param> /// <param name="maxOwnedPopulation">For each owned room which generates enemies, the maximum amount GENERATED in each room (does not preclude patrols from entering the same room)</param> /// <param name="maxWildPopulation">For each wild room which generates enemies, the maximum amount GENERATED in each room.</param> /// <param name="ownerType">For each owned room, the type of the enemies to create</param> /// <param name="percentageOwned">The percentage of the rooms which are owned as opposed to being wild. Bear in mind that wild rooms can spawn quite a bit of enemies</param> /// <param name="pointsOfInterest">The points of interest (ie guard and treasure rooms for instance) which have been generated. Used for patrols</param> /// <param name="startPoint">The entrance start point</param> /// <param name="utilityRooms">The maximum amount of Utility rooms to generate - these might contain civilian orcs which ignore the maxOwnedPopulation value</param> /// <param name="treasureRooms">The maximum amount of teasure rooms to generate</param> /// <returns></returns> public MapBlock[,] GenerateDungeon(int tiers, int utilityRooms, int guardRooms, int treasureRooms, string ownerType, decimal percentageOwned, int maxWildPopulation, int maxOwnedPopulation, out MapCoordinate startPoint, out DRObjects.Actor[] enemyArray, out List<PointOfInterest> pointsOfInterest) { startPoint = new MapCoordinate(0, 0, 0, MapType.LOCAL); pointsOfInterest = new List<PointOfInterest>(); List<DRObjects.Actor> enemies = new List<DRObjects.Actor>(); List<CitadelRoom> rooms = new List<CitadelRoom>(); int uniqueID = 0; //Start with the root node CitadelRoom root = new CitadelRoom(); root.SquareNumber = (int)Math.Ceiling((double)WIDTH / 2); root.TierNumber = 0; root.UniqueID = uniqueID++; root.Connections.Add(-1); //this is a special id. We'll use it to create a start point rooms.Add(root); int currentTier = 1; int square = (int)Math.Ceiling((double)WIDTH / 2); CitadelRoom focusNode = root; Random random = new Random(DateTime.UtcNow.Millisecond); while (currentTier < tiers) { //Create a new node CitadelRoom newNode = new CitadelRoom(); newNode.SquareNumber = square; newNode.TierNumber = currentTier; newNode.UniqueID = uniqueID++; newNode.CitadelRoomType = CitadelRoomType.EMPTY_ROOM; //connect the focus node to this node focusNode.Connections.Add(newNode.UniqueID); newNode.Connections.Add(focusNode.UniqueID); //change the focus node focusNode = newNode; //aaaand add it to the list rooms.Add(newNode); //Now we decide whether to stay in the same tier - or increase the tier int randomNumber = random.Next(100); int siblings = rooms.Where(r => r.TierNumber.Equals(currentTier)).Count(); int treshold = 0; switch (siblings) { case 1: treshold = PROB_2; break; case 2: treshold = PROB_3; break; case 3: treshold = PROB_4; break; case 4: treshold = PROB_5; break; default: treshold = 0; break; //NEVER } if (randomNumber < treshold) { //then stay in the same place - go either left or right. Can we go in that direction? bool canGoRight = !rooms.Any(r => (r.SquareNumber.Equals(square + 1) && r.TierNumber.Equals(currentTier)) || square + 1 > WIDTH); bool canGoLeft = !rooms.Any(r => (r.SquareNumber.Equals(square - 1) && r.TierNumber.Equals(currentTier)) || square - 1 < 0); if (canGoLeft && canGoRight) { //pick one at random square += random.Next(2) == 1 ? 1 : -1; } else if (canGoLeft) { square -= 1; } else if (canGoRight) { square += 1; } else { //We've done it all currentTier++; } } else { currentTier++; } } //Now that that part is done, lets add some more paths so we turn this into a graph foreach (CitadelRoom room in rooms) { //For each room, check who is a sibling or immediatly under him. There is a 50% chance of forming a link CitadelRoom[] potentialRooms = GetPathableRooms(rooms, room.TierNumber, room.SquareNumber); foreach (CitadelRoom potentialRoom in potentialRooms) { //Is there a connection already? if (!potentialRoom.Connections.Contains(room.UniqueID)) { if (random.Next(2) == 1) { //add a connection room.Connections.Add(potentialRoom.UniqueID); potentialRoom.Connections.Add(room.UniqueID); } } } } //go through the rooms and set some as wild rooms already foreach (var room in rooms) { if (random.Next(100) > percentageOwned) { //Wild room room.CitadelRoomType = CitadelRoomType.WILD_ROOM; } } //Lets assign the rooms based on the maximum amount. //Some rooms have more probability in certain regions. //So lets divide the rooms in 3 //Favoured - x3 //Other - x2 //Unfavoured - x1 int lowerBoundary = rooms.Count / 3; int upperBoundary = 2 * rooms.Count / 3; var orderedUtilities = rooms.Where (o => o.CitadelRoomType == CitadelRoomType.EMPTY_ROOM).OrderByDescending(o => random.Next(100) * (o.UniqueID > upperBoundary ? 1 : o.UniqueID > lowerBoundary ? 2 : 3)).Where(r => r.CitadelRoomType == CitadelRoomType.EMPTY_ROOM ).ToArray().Take(utilityRooms); foreach (var room in orderedUtilities) { room.CitadelRoomType = CitadelRoomType.UTILITY_ROOM; } //Same thing for treasure rooms var orderedTreasure = rooms.Where (o => o.CitadelRoomType == CitadelRoomType.EMPTY_ROOM).OrderByDescending(o => random.Next(100) * (o.UniqueID > upperBoundary ? 3 : o.UniqueID > lowerBoundary ? 2 : 1)).Where(r => r.CitadelRoomType == CitadelRoomType.EMPTY_ROOM ).Take(treasureRooms); foreach (var room in orderedTreasure) { room.CitadelRoomType = CitadelRoomType.TREASURE_ROOM; } //And guard rooms var orderedGuard = rooms.Where (o => o.CitadelRoomType == CitadelRoomType.EMPTY_ROOM).OrderByDescending(o => random.Next(100) * (o.UniqueID > upperBoundary ? 1 : o.UniqueID > lowerBoundary ? 3 : 2)).Where(r => r.CitadelRoomType == CitadelRoomType.EMPTY_ROOM ).Take(guardRooms); foreach (var room in orderedGuard) { room.CitadelRoomType = CitadelRoomType.GUARD_ROOM; } //Now that that part is done, we put them on the actual grid. //We go for a 15x15 room and connect the items in it. //15x15 - with a gap of 7 between them for tunnels int mapWidth = ((WIDTH + 7) * 20); int mapHeight = ((tiers + 7) * 20); //Create new blocks MapBlock[,] map = new MapBlock[mapWidth, mapHeight]; for (int x = 0; x < map.GetLength(0); x++) { for (int y = 0; y < map.GetLength(1); y++) { map[x, y] = new MapBlock() { Tile = new MapItem() { Coordinate = new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL), MayContainItems = false } }; } } LocalMapGenerator gen = new LocalMapGenerator(); LocalMapXMLParser xmlGen = new LocalMapXMLParser(); //Start generating the maps and then stitch them upon the main map foreach (CitadelRoom room in rooms) { MapBlock[,] gennedMap = null; string tag = String.Empty; switch (room.CitadelRoomType) { case CitadelRoomType.EMPTY_ROOM: tag = "Empty Dungeon"; break; case CitadelRoomType.GUARD_ROOM: tag = "Guard Dungeon"; break; case CitadelRoomType.UTILITY_ROOM: tag = "Utility Dungeon"; break; case CitadelRoomType.TREASURE_ROOM: tag = "Treasure Dungeon"; break; case CitadelRoomType.WILD_ROOM: tag = "Empty Dungeon"; break; default: throw new NotImplementedException("Dungeon Room " + room.CitadelRoomType + " not planned for yet."); } //Generate it :) Maplet maplet = xmlGen.ParseMapletFromTag(tag); Actor[] acts = null; MapletActorWanderArea[] wanderAreas = null; MapletPatrolPoint[] patrolPoints = null; MapletFootpathNode[] footPath = null; gennedMap = gen.GenerateMap(25, null, maplet, true, "", OwningFactions.ORCS ,out acts,out wanderAreas,out patrolPoints,out footPath); enemies.AddRange(acts); //Is it a treasure room? if (room.CitadelRoomType == CitadelRoomType.TREASURE_ROOM) { //Generate some loot GenerateLoot(gennedMap, room.TierNumber); } PointOfInterest mapletInterest = null; if (room.CitadelRoomType == CitadelRoomType.GUARD_ROOM || room.CitadelRoomType == CitadelRoomType.TREASURE_ROOM) { //This will be a point of interest. Select a random walkable point in the room and mark the place as such for (int tryAmount = 0; tryAmount < 50; tryAmount++) { //Try for a maximum of 50 times int x = random.Next(gennedMap.GetLength(0)); int y = random.Next(gennedMap.GetLength(1)); if (gennedMap[x, y].Tile.MayContainItems) { //Put this as the point PointOfInterest interest = new PointOfInterest(); interest.Coordinate = new MapCoordinate(x, y, 0, MapType.LOCAL); if (room.CitadelRoomType == CitadelRoomType.GUARD_ROOM) { interest.Type = PointOfInterestType.GUARD_ROOM; } else if (room.CitadelRoomType == CitadelRoomType.TREASURE_ROOM) { interest.Type = PointOfInterestType.TREASURE; } pointsOfInterest.Add(interest); mapletInterest = interest; break; } } } DRObjects.Actor[] roomEnemies = new DRObjects.Actor[] { }; if (room.CitadelRoomType == CitadelRoomType.GUARD_ROOM || room.CitadelRoomType == CitadelRoomType.TREASURE_ROOM) { //Create an amount of enemies - level doesn't matter, we'll regen later gennedMap = gen.GenerateEnemies(gennedMap, random.Next(maxOwnedPopulation), ownerType, out roomEnemies, 10); enemies.AddRange(roomEnemies); } if (room.CitadelRoomType == CitadelRoomType.WILD_ROOM) { //Create an amount of wild enemies - let's get a random type for this room. This will be of level 5. Later we'll have proper wildlife string type = ActorGeneration.GetEnemyType(false); gennedMap = gen.GenerateEnemies(gennedMap, random.Next(maxWildPopulation), type, out roomEnemies, 5); //go through all of room enemies and set them to idle foreach (var enemy in roomEnemies) { enemy.MissionStack.Clear(); enemy.MissionStack.Push(new IdleMission()); } enemies.AddRange(roomEnemies); } //fit her onto the main map int xIncreaser = room.SquareNumber * 20; int yIncreaser = (room.TierNumber * 20) + 3; //Fix the patrol points of any enemies foreach (Actor enemy in roomEnemies.Union(acts)) { if (enemy.MissionStack.Count != 0 && enemy.MissionStack.Peek().MissionType == DRObjects.ActorHandling.ActorMissionType.WANDER) { //Change patrol point MapCoordinate point = (enemy.MissionStack.Peek() as WanderMission).WanderPoint; point.X += xIncreaser; point.Y += yIncreaser; //Change the rectangle x and y too Rectangle rect = (enemy.MissionStack.Peek() as WanderMission).WanderRectangle; rect.X = xIncreaser; rect.Y = yIncreaser; (enemy.MissionStack.Peek() as WanderMission).WanderRectangle = rect; //apparently rectangles are immutable or something } } //Update the point of interest if there is one if (mapletInterest != null) { mapletInterest.Coordinate.X += xIncreaser; mapletInterest.Coordinate.Y += yIncreaser; } for (int x = 0; x < gennedMap.GetLength(0); x++) { for (int y = 0; y < gennedMap.GetLength(1); y++) { map[x + xIncreaser, y + yIncreaser] = gennedMap[x, y]; map[x + xIncreaser, y + yIncreaser].Tile.Coordinate = new MapCoordinate(x + xIncreaser, y + yIncreaser, 0, DRObjects.Enums.MapType.LOCAL); foreach (var item in map[x + xIncreaser, y + yIncreaser].GetItems()) { item.Coordinate = new MapCoordinate(x + xIncreaser, y + yIncreaser, 0, DRObjects.Enums.MapType.LOCAL); } } } //Lets draw the connections - only the ones who's rooms we've drawn yet ItemFactory.ItemFactory factory = new ItemFactory.ItemFactory(); foreach (var connection in room.Connections.Where(c => c < room.UniqueID)) { if (connection == -1) { //Entrance hall! //Create a line of 3 at the bottom and return the coordinates int topEdgeY = yIncreaser; int bottomEdgeXMin = 0 + xIncreaser; int bottomEdgeXMax = gennedMap.GetLength(0) + xIncreaser; //Find the start int xStart = (bottomEdgeXMax - bottomEdgeXMin) / 2 + bottomEdgeXMin; //Set the start point startPoint = new MapCoordinate(xStart + 1, topEdgeY - 2, 0, MapType.LOCAL); //Put the 'leave town' item on it map[startPoint.X, startPoint.Y].ForcePutItemOnBlock(new LeaveTownItem()); int x = xStart; int y = topEdgeY; //go 3 steps down for (int a = 0; a < 3; a++) { for (int x1 = 0; x1 < 3; x1++) { //Draw! map[x + x1, y].Tile = factory.CreateItem("TILES", 25); map[x + x1, y].Tile.Coordinate = new MapCoordinate(x + x1, y, 0, MapType.LOCAL); } y--; //move down } y = topEdgeY; //Walk back do { for (int x1 = 0; x1 < 3; x1++) { //Draw! map[x + x1, y].Tile = factory.CreateItem("TILES", 25); map[x + x1, y].Tile.Coordinate = new MapCoordinate(x + x1, y, 0, MapType.LOCAL); } y++; //move up } while (x >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); //Put the spikes at the entrance int dummy = -1; map[xStart, topEdgeY - 2].ForcePutItemOnBlock(factory.CreateItem(Archetype.MUNDANEITEMS, "spikes", out dummy)); map[xStart + 2, topEdgeY - 2].ForcePutItemOnBlock(factory.CreateItem(Archetype.MUNDANEITEMS, "spikes", out dummy)); continue; } //Identify the room to be connected with var roomToBeConnected = rooms.Where(r => r.UniqueID.Equals(connection)).FirstOrDefault(); //Determine the direction relative to the current room if (roomToBeConnected.SquareNumber > room.SquareNumber) { //RIGHT //Find the rightmost edge of the room and start... somewhere int rightEdgeX = gennedMap.GetLength(0) + xIncreaser; int rightEdgeYMin = 0 + yIncreaser; int rightEdgeYMax = gennedMap.GetLength(1) + yIncreaser; //Pick a start at random int yStart = random.Next(rightEdgeYMax - rightEdgeYMin - 2) + rightEdgeYMin; //Now 'walk' from ystart-ystart+3 until you hit on something which has a block in it int x = rightEdgeX; int y = yStart; while (x < map.GetLength(0) && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems) { for (int y1 = 0; y1 < 3; y1++) { //Draw! map[x, y + y1].Tile = factory.CreateItem("TILES", 25); map[x, y + y1].Tile.Coordinate = new MapCoordinate(x, y + y1, 0, MapType.LOCAL); } x++; //increment x } x = rightEdgeX - 1; //now lets walk backwards too while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems) { for (int y1 = 0; y1 < 3; y1++) { //Draw! map[x, y + y1].Tile = factory.CreateItem("TILES", 25); map[x, y + y1].Tile.Coordinate = new MapCoordinate(x, y + y1, 0, MapType.LOCAL); } x--; //walk back } } else if (roomToBeConnected.SquareNumber < room.SquareNumber) { //LEFT //Find the leftMose edge of the room and start... somewhere int leftEdgeX = xIncreaser; int leftEdgeYMin = 0 + yIncreaser; int leftEdgeYMax = gennedMap.GetLength(1) + yIncreaser; //Pick a start at random int yStart = random.Next(leftEdgeYMax - leftEdgeYMin - 2) + leftEdgeYMin; //Now 'walk' from ystart-ystart+3 until you hit on something which has a block in it int x = leftEdgeX; int y = yStart; do { for (int y1 = 0; y1 < 3; y1++) { //Draw! map[x, y + y1].Tile = factory.CreateItem("TILES", 25); map[x, y + y1].Tile.Coordinate = new MapCoordinate(x, y + y1, 0, MapType.LOCAL); } x--; //decrement x } while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); x = leftEdgeX + 1; //walk backwards do { for (int y1 = 0; y1 < 3; y1++) { //Draw! map[x, y + y1].Tile = factory.CreateItem("TILES", 25); map[x, y + y1].Tile.Coordinate = new MapCoordinate(x, y + y1, 0, MapType.LOCAL); } x++; //walk back } while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); } else if (roomToBeConnected.TierNumber < room.TierNumber) { //BOTTOM //Find the bottommost edge of the room and start... somewhere int bottomEdgeY = yIncreaser; int bottomEdgeXMin = 0 + xIncreaser; int bottomEdgeXMax = gennedMap.GetLength(0) + xIncreaser; //Pick a start at random int xStart = random.Next(bottomEdgeXMax - bottomEdgeXMin - 2) + bottomEdgeXMin; //Now 'walk' from xstart-xstart+3 until you hit on something which has a block in it int x = xStart; int y = bottomEdgeY; do { for (int x1 = 0; x1 < 3; x1++) { //Draw! map[x + x1, y].Tile = factory.CreateItem("TILES", 25); map[x + x1, y].Tile.Coordinate = new MapCoordinate(x + x1, y, 0, MapType.LOCAL); } y--; //decrement y } while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); y = bottomEdgeY + 1; //Walk backwards do { for (int x1 = 0; x1 < 3; x1++) { //Draw! map[x + x1, y].Tile = factory.CreateItem("TILES", 25); map[x + x1, y].Tile.Coordinate = new MapCoordinate(x + x1, y, 0, MapType.LOCAL); } y++; //walk back } while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); } else if (roomToBeConnected.TierNumber > room.TierNumber) { //TOP - Won't ever happen - but sure //Find the topmost edge of the room and start... somewhere int topEdgeY = yIncreaser + gennedMap.GetLength(1); int bottomEdgeXMin = 0 + xIncreaser; int bottomEdgeXMax = gennedMap.GetLength(0) + xIncreaser; //Pick a start at random int xStart = random.Next(bottomEdgeXMax - bottomEdgeXMin - 2) + bottomEdgeXMin; //Now 'walk' from xstart-xstart+3 until you hit on something which has a block in it int x = xStart; int y = topEdgeY; do { bool holed = false; for (int x1 = 0; x1 < 3; x1++) { if (!holed) { //Have a chance of putting in a hole if (random.Next(8) == 0) { holed = true; continue; //don't put in a tile } } //Draw! map[x + x1, y].Tile = factory.CreateItem("TILES", 25); map[x + x1, y].Tile.Coordinate = new MapCoordinate(x + x1, y, 0, MapType.LOCAL); } y++; //move up } while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); //walk back y = topEdgeY + 1; do { for (int x1 = 0; x1 < 3; x1++) { //Draw! map[x + x1, y].Tile = factory.CreateItem("TILES", 25); map[x + x1, y].Tile.Coordinate = new MapCoordinate(x + x1, y, 0, MapType.LOCAL); } y--; //move down } while (x >= 0 && x < map.GetLength(0) && y >= 0 && y < map.GetLength(1) && !map[x, y].Tile.MayContainItems); } } } //We need to fix the enemies to conform to the standards ConformEnemies(enemies); enemyArray = enemies.ToArray(); return map; }
/// <summary> /// Load the location /// </summary> /// <param name="location"></param> /// <param name="forceRegenerate">If set to true, will regenerate the item anyway</param> private void LoadLocation(Location location, bool forceRegenerate = false) { if (LocalMap.MapGenerated(location.UniqueGUID) && !forceRegenerate) { //Reload the map var savedMap = LocalMap.DeserialiseLocalMap(location.UniqueGUID); GameState.LocalMap = new LocalMap(savedMap.localGameMap.GetLength(0), savedMap.localGameMap.GetLength(1), 1, 0); GameState.LocalMap.Location = savedMap.Location; //GameState.LocalMap.Location = location; if (GameState.LocalMap.Location is MapSite && (GameState.LocalMap.Location as MapSite).SiteData.MapRegenerationRequired) { Actor[] newActors = null; //Before we do anything, check that we don't need to regenerate it MapBlock[,] savedMap2D = new MapBlock[savedMap.localGameMap.GetLength(0), savedMap.localGameMap.GetLength(1)]; for (int x = 0; x < savedMap.localGameMap.GetLength(0); x++) { for (int y = 0; y < savedMap.localGameMap.GetLength(1); y++) { savedMap2D[x, y] = savedMap.localGameMap[x, y, 0]; //NB: CHANGE IF WE GO 3D } } var blocks = SiteGenerator.RegenerateSite((GameState.LocalMap.Location as MapSite).SiteData, savedMap2D, savedMap.Actors.ToArray(), out newActors); List<MapBlock> cM = new List<MapBlock>(); foreach (MapBlock block in blocks) { cM.Add(block); } GameState.LocalMap.AddToLocalMap(cM.ToArray()); GameState.LocalMap.Actors = newActors.ToList(); GameState.LocalMap.Tick(); //Tick to remove the dead actors } GameState.LocalMap.Actors = new List<Actor>(); List<MapBlock> collapsedMap = new List<MapBlock>(); foreach (MapBlock block in savedMap.localGameMap) { collapsedMap.Add(block); } GameState.LocalMap.AddToLocalMap(collapsedMap.ToArray()); GameState.LocalMap.PathfindingMap = savedMap.PathfindingMap; GameState.LocalMap.PointsOfInterest = savedMap.PointsOfInterest; GameState.LocalMap.IsUnderground = savedMap.IsUnderground; GameState.LocalMap.Actors = savedMap.Actors; LocalMapGenerator lmg = new LocalMapGenerator(); //Go through the actors foreach (var actor in GameState.LocalMap.Actors) { //Do we have any vendors ? if (actor.VendorDetails != null) { if (Math.Abs((actor.VendorDetails.GenerationTime - GameState.UniverseTime).GetTimeComponent(DRTimeComponent.MONTH)) > 1) { //More than a month old //Regenerate it lmg.UpdateVendorStock(actor); } } } //Find the player character item var playerActor = GameState.LocalMap.Actors.Where(a => a.IsPlayerCharacter).FirstOrDefault(); GameState.PlayerCharacter.MapCharacter.Coordinate = playerActor.MapCharacter.Coordinate; GameState.PlayerCharacter.MapCharacter = playerActor.MapCharacter; //GameState.LocalMap.Location = location; } else { Actor[] actors = null; MapCoordinate startPoint = null; List<PointOfInterest> pointsOfInterest = null; MapBlock[,] gennedMap = null; if (location is BanditCamp) { gennedMap = CampGenerator.GenerateCamp((location as BanditCamp).BanditTotal, out startPoint, out actors); } else if (location is Citadel) { var citadel = location as Citadel; CitadelGenerator gen = new CitadelGenerator(); gennedMap = gen.GenerateDungeon(citadel.TierCount, citadel.TrapRooms, citadel.GuardRooms, citadel.TreasureRoom, citadel.OwnerCreatureType, (decimal)citadel.PercentageOwned, citadel.MaxWildPopulation, citadel.MaxOwnedPopulation, out startPoint, out actors, out pointsOfInterest); } else if (location is MapSite) { var mapSite = location as MapSite; gennedMap = SiteGenerator.GenerateSite(mapSite.SiteData, out actors); startPoint = new MapCoordinate(gennedMap.GetLength(0) / 2, 0, 0, MapType.LOCAL); } else if (location is Settlement) { List<Actor> settlementActors = null; PointOfInterest sp = null; gennedMap = SettlementGenerator.GenerateMap((location as Settlement), out settlementActors, out sp); actors = settlementActors.ToArray(); startPoint = sp.Coordinate; } else if (location is Dungeon) { Dungeon dungeon = null; gennedMap = DungeonGenerator.GenerateDungeonLevel((location as Dungeon).DifficultyLevel, 80, out startPoint, out actors, out dungeon); //Copy the changes, that way we retain the object reference and the guid for serialization (location as Dungeon).Rooms = dungeon.Rooms; (location as Dungeon).SummoningCircles = dungeon.SummoningCircles; } GameState.LocalMap = new LocalMap(gennedMap.GetLength(0), gennedMap.GetLength(1), 1, 0); GameState.LocalMap.Actors = new List<Actor>(); List<MapBlock> collapsedMap = new List<MapBlock>(); foreach (MapBlock block in gennedMap) { collapsedMap.Add(block); } GameState.LocalMap.AddToLocalMap(collapsedMap.ToArray()); GameState.PlayerCharacter.MapCharacter.Coordinate = startPoint; MapBlock playerBlock = GameState.LocalMap.GetBlockAtCoordinate(startPoint); playerBlock.PutItemOnBlock(GameState.PlayerCharacter.MapCharacter); GameState.LocalMap.Actors.AddRange(actors); GameState.LocalMap.Actors.Add(GameState.PlayerCharacter); GameState.LocalMap.PointsOfInterest = pointsOfInterest; GameState.LocalMap.Location = location; GameState.LocalMap.IsUnderground = (location is Dungeon); if (location is Dungeon) //Spawn at least 10 enemies { for (int i = 0; i < 10; i++) { GameState.LocalMap.MinuteChanged(null, null); //Summon! } } } }