/// Implementation of the "growing tree" algorithm from here: /// http://www.astrolog.org/labyrnth/algrithm.htm. private void GrowMaze(Vector startPos) { var positions = new Stack <Vector>(); Direction lastDir = null; StartRegion(); Carve(startPos); positions.Push(startPos); while (positions.Any()) { var tile = positions.Last(); // See which adjacent cells are open. var neighbours = Direction.Cardinal .Where(dir => CanCarve(tile, dir)) .ToList(); if (neighbours.Any()) { // Based on how "windy" passages are, try to prefer carving in the // same direction. Direction dir; if (neighbours.Contains(lastDir) && !Randomizer.Chance(windingPercent)) { dir = lastDir; } else { dir = neighbours.PickRandom(); } Carve(tile + dir); Carve(tile + dir * 2); positions.Push(tile + dir * 2); lastDir = dir; } else { // No adjacent uncarved cells. positions.Pop(); // This path has ended. lastDir = null; } } }
internal void Populate() { foreach (var cell in cells) { if (Randomizer.Chance(.1)) { switch (Randomizer.Next(3)) { case 0: cell.Monster = new Orc(); break; default: cell.Monster = new Goblin(); break; } } if (Randomizer.Chance(.2)) { switch (Randomizer.Next(7)) { case 0: case 1: cell.Item = new Sock(); break; case 2: case 3: case 4: cell.Item = new Coin(); break; case 5: cell.Item = new Weapon(); break; case 6: cell.Item = new HealingPotion(); break; } } } }
/// Places rooms ignoring the existing maze corridors. private void AddRooms() { for (var i = 0; i < numRoomTries; i++) { // Pick a random room size. The funny math here does two things: // - It makes sure rooms are odd-sized to line up with maze. // - It avoids creating rooms that are too rectangular: too tall and // narrow or too wide and flat. // TODO: This isn't very flexible or tunable. Do something better here. var size = Randomizer.Next(1, 3 + roomExtraSize) * 2 + 1; var rectangularity = Randomizer.Next(0, 1 + size / 2) * 2; var width = size; var height = size; if (Randomizer.Chance(.5)) { width += rectangularity; } else { height += rectangularity; } var x = Randomizer.Next((Bounds.Width - width) / 2) * 2 + 1; var y = Randomizer.Next((Bounds.Height - height) / 2) * 2 + 1; var room = new Rect(x, y, width, height); if (rooms.Any(r => room.Overlaps(r))) { continue; } rooms.Add(room); StartRegion(); foreach (var pos in room) { Carve(pos); } } }