private void UnplacePossibleHallwayToNowhere(Map map, ParenthoodChain parentChain) { ParenthoodChain localChain = new ParenthoodChain(parentChain); ParenthoodElement top = localChain.Pop(); Point seamToFill = Point.Invalid; if (top.Chunk.Type == MapNodeType.Hall) { do { if (top.Chunk.Type == MapNodeType.Hall) { m_placed--; top.Chunk.UnplaceChunkOnMapAtPosition(map, top.UpperLeft); seamToFill = top.Seam; top = localChain.Pop(); } else { if (seamToFill == Point.Invalid) throw new MapGenerationFailureException("Trying to fill in invalid seam"); map.SetTerrainAt(seamToFill, TerrainType.Wall); break; } } while (true); } }
// Returns true if placed, false if we walled off seam private bool PlaceMapNode(MapNode current, MapChunk mapChunk, Map map, Point seam, ParenthoodChain parentChain) { Point placedUpperLeftCorner = mapChunk.PlaceChunkOnMap(map, seam, m_level); if (placedUpperLeftCorner == Point.Invalid) { map.SetTerrainAt(seam, TerrainType.Wall); return false; } else { PossiblyUpdateLargestSmallestPoint(placedUpperLeftCorner, mapChunk); map.SetTerrainAt(seam, TerrainType.Floor); parentChain.Push(mapChunk, placedUpperLeftCorner, seam); WalkNeighbors(current, mapChunk, map, placedUpperLeftCorner, parentChain); parentChain.Pop(); return true; } }
private void GenerateMapFromGraph(MapNode current, Map map, Point seam, ParenthoodChain parentChain) { if (current.Generated) return; current.Generated = true; bool placed = false; switch (current.Type) { case MapNodeType.Entrance: { placed = true; MapChunk entranceChunk = GetRandomChunkFromList(m_entrances); // We need to place entrace so it's at our expected location Point randomCenter = new Point(m_random.getInt(100, 150), m_random.getInt(100, 150)); Point entraceUpperLeftCorner = randomCenter - entranceChunk.PlayerPosition; parentChain.Push(entranceChunk, entraceUpperLeftCorner, Point.Invalid); entranceChunk.PlaceChunkOnMapAtPosition(map, entraceUpperLeftCorner, m_random); PossiblyUpdateLargestSmallestPoint(entraceUpperLeftCorner, entranceChunk); map.AddMapItem(MapObjectFactory.Instance.CreateMapObject("StairsUp", entranceChunk.PlayerPosition + entraceUpperLeftCorner)); if (current.Neighbors.Count != entranceChunk.Seams.Count) throw new InvalidOperationException("Number of neighbors should equal number of seams."); WalkNeighbors(current, entranceChunk, map, entraceUpperLeftCorner, parentChain); parentChain.Pop(); break; } case MapNodeType.Hall: { for (int i = 0; i < 10; i++) { placed = PlaceMapNode(current, GetRandomChunkFromList(m_halls), map, seam, parentChain); if (placed) break; } break; } case MapNodeType.None: { // If we have nothing, see if we have any orphan nodes to try to place if (m_unplacedDueToSpace.Count > 0) { // Grab the first unplaced node, and try again. MapNode treeToGraphOn = m_unplacedDueToSpace.Dequeue(); treeToGraphOn.Generated = false; GenerateMapFromGraph(treeToGraphOn, map, seam, parentChain); } else { map.SetTerrainAt(seam, TerrainType.Wall); if (current.Neighbors.Count != 0) throw new InvalidOperationException("None Node types should only have no neighbors"); } placed = true; break; } case MapNodeType.MainRoom: { placed = PlaceMapNode(current, GetRandomChunkFromList(m_mainRooms), map, seam, parentChain); break; } case MapNodeType.TreasureRoom: { placed = PlaceMapNode(current, GetRandomChunkFromList(m_treasureRooms), map, seam, parentChain); break; } case MapNodeType.SideRoom: { placed = PlaceMapNode(current, GetRandomChunkFromList(m_sideRooms), map, seam, parentChain); break; } case MapNodeType.NoneGivenYet: default: throw new InvalidOperationException("Trying to generate MapNode from invalid node."); } if (!placed) { UnplacePossibleHallwayToNowhere(map, parentChain); m_unplacedDueToSpace.Enqueue(current); } }