public FilledRegion Apply(FillData data) { List <Region> spawnAreas = new List <Region>(); //Get data. Generation.BeingFilled = data.BeingFilled; int numb = Generation.NumbPlateaus; int width = Generation.PlateauWidth; int space = Generation.SpaceBetweenPlateaus; int border = Generation.Border; //Plateau location data. int height = (int)Math.Round((PlateauRelativeHeight * data.BeingFilled.Height), 0); if (height >= data.BeingFilled.Height) { height = data.BeingFilled.Height - 1; } int top = data.BeingFilled.Bottom - height; //Add the plateaus. Region r; for (int i = 0; i < numb; ++i) { r = new Region(data.BeingFilled.Left + border + (i * (space + width)), top, width - 1, data.BeingFilled.Bottom - top); data.FillRegion(true, r); spawnAreas.Add(new Region(new Location(r.Left, data.BeingFilled.Top), r.TopRight.Above)); } //Make room for any holes that the plateaus covered. foreach (Location l in data.HolesAlongPerimeter()) { //The hole is covered if it is just under the region and the space right above it is covered. if (data.BeingFilled.Touches(l.Above, true, true, false) && data.GetMapAt(l.Above)) { //Make a litle tunnel under the plateau. int[] plateauSides = PlateauSides(l.X, numb, width, space, border, data.BeingFilled.Left, data.BeingFilled.Right); Region cleared = new Region(plateauSides[0], data.BeingFilled.Bottom, width - 1, 0); data.FillRegion(false, cleared); } } return(new SteppedHallwayRegion(data.BeingFilled, spawnAreas)); }
public FilledRegion Apply(FillData data) { bool horizontal = data.BeingFilled.Width > data.BeingFilled.Height; bool vertical = data.BeingFilled.Height > data.BeingFilled.Width; //Put a thin line through the middle. if (horizontal) { data.FillRegion(true, new Region(data.BeingFilled.Left + 1, data.BeingFilled.CenterY, data.BeingFilled.Width - 2, 0, true)); } else if (vertical) { data.FillRegion(true, new Region(data.BeingFilled.CenterX, data.BeingFilled.Top + 1, 0, data.BeingFilled.Height - 2, true)); } return(new LineRegion(data.BeingFilled)); }
public FilledRegion Apply(FillData data) { //Fill the square. data.FillRegion(true, new Region(data.BeingFilled.TopLeft.Right.Below, data.BeingFilled.BottomRight.Left.Above)); //Create the lines. Region horz = new Region(data.BeingFilled.LeftMid.Right, data.BeingFilled.Center.Left); Region horz2 = new Region(data.BeingFilled.Center.Right, data.BeingFilled.RightMid.Left); Region vert = new Region(data.BeingFilled.TopMid.Below, data.BeingFilled.Center.Above); Region vert2 = new Region(data.BeingFilled.Center.Below, data.BeingFilled.BottomMid.Above); data.FillRegion(false, horz); data.FillRegion(false, horz2); data.FillRegion(false, vert); data.FillRegion(false, vert2); Region center = new Region(data.BeingFilled.Center, data.BeingFilled.Center); data.Holes.Add(center.Center); data.FillRegion(false, center); return(new CarvedPlusRegion(data.BeingFilled)); }
public void IterateFillPattern() { //Already done? if (iterateFillPatternsRegionCount >= Regions.Count) { return; } //Run an iteration. FilledRegion temp; Region r = Regions[iterateFillPatternsRegionCount]; iterateFillPatternsRegionCount++; //Pick a random applicable pattern (assuming one exists) and apply it. FillPattern p = Settings.MostSuitable(r); if (p != null) { //Clear the space, and apply the pattern. FillData.BeingFilled = r; FillData.FillRegion(false, r); temp = p.Apply(FillData); //If the filled region is blank, replace it with a BlankRegion. bool blank = true; for (int i = temp.Covering.Left; i <= temp.Covering.Right; ++i) { for (int j = temp.Covering.Top; j <= temp.Covering.Bottom; ++j) { if (FillData.GetMapAt(new Location(i, j))) { blank = false; break; } } if (!blank) { break; } } if (blank) { temp = new BlankRegion(temp.Covering); } //Now add it. FilledRegions.Add(temp); Region r2; //Make sure the spawn points are all valid. foreach (Spawns s in FilledRegions[FilledRegions.Count - 1].PotentialSpawns.Keys) { for (int i = 0; i < FilledRegions[FilledRegions.Count - 1].PotentialSpawns[s].Count; ++i) { r2 = FilledRegions[FilledRegions.Count - 1].PotentialSpawns[s][i]; if (r2.Width < 0 || r2.Height < 0) { FilledRegions[FilledRegions.Count - 1].PotentialSpawns[s].RemoveAt(i--); } } } } //If no regions fit, add a "NoRegion". else { FilledRegions.Add(new NoRegion(r)); } }
public FilledRegion Apply(FillData data) { //The spawning areas. List <Region> spawningAreas = new List <Region>(); //Get/set some data. Region area = data.BeingFilled; PlateauGeneration.BeingFilled = data.BeingFilled; //If the corridor is going to be vertical, flip the width and height. if (area.Height > area.Width) { PlateauGeneration.BeingFilled = new Region(area.Y, area.X, area.Height, area.Width); } int numb = PlateauGeneration.NumbPlateaus; int plateauSize = PlateauGeneration.PlateauWidth; int space = PlateauGeneration.SpaceBetweenPlateaus; int border = PlateauGeneration.Border; //Plateau size data. //"maxSize" is the largest allowable hurdle height. int maxSize = PlateauGeneration.BeingFilled.Height - 1; if (area.Height > area.Width) { //Vertical. //Add the plateaus. int hurdleWidth, plateauExtent; for (int i = 0; i < numb; ++i) { //Get a width within the given random variation. hurdleWidth = (int)Math.Round((area.Width + 1) * (HurdleAverageSpaceScale + ((2 * HurdleHeightVariance * (float)GeneratorSettings.R.NextDouble()) - HurdleHeightVariance)), 0); //Keep it constrained. if (hurdleWidth > maxSize) { hurdleWidth = maxSize; } if (hurdleWidth < 1) { hurdleWidth = 1; } //Get the width of the plateau given the size of a hurdle. plateauExtent = area.Width + 1 - hurdleWidth; plateauExtent /= 2; //Fill in the plateaus. data.FillRegion(true, new Region(area.Left, area.Top + border + (i * (space + plateauSize)), plateauExtent - 1, plateauSize - 1)); if ((2 * plateauExtent) + hurdleWidth >= area.Width + 1) { data.FillRegion(true, new Region(area.Right - plateauExtent + 1, area.Top + border + (i * (space + plateauSize)), plateauExtent - 1, plateauSize - 1)); } else { data.FillRegion(true, new Region(area.Right - plateauExtent, area.Top + border + (i * (space + plateauSize)), plateauExtent, plateauSize - 1)); } } //Make room for any holes that the plateaus covered. foreach (Location l in data.HolesAlongPerimeter()) { //The hole is covered if it is just left/right of the region and the space just right/left of it (respectively) is filled. if ((area.Touches(l.Left, true, true, false) && data.GetMapAt(l.Left)) || (area.Touches(l.Right, true, true, false) && data.GetMapAt(l.Right))) { //Make a little tunnel under the plateau. int[] plateauSides = SteppedHallwayPattern.PlateauSides(l.Y, numb, plateauSize, space, border, area.Top, area.Bottom); Region cleared; if (l.X - 1 == area.Right) { cleared = new Region(data.BeingFilled.Right, plateauSides[0], 0, plateauSize - 1); } else { cleared = new Region(data.BeingFilled.Left, plateauSides[0], 0, plateauSize - 1); } data.FillRegion(false, cleared); } } } else { //Horizontal. //Add the plateaus. int hurdleHeight, plateauHeight; for (int i = 0; i < numb; ++i) { //Get a height within the given random variation. hurdleHeight = (int)Math.Round((area.Height + 1) * (HurdleAverageSpaceScale + ((2 * HurdleHeightVariance * (float)GeneratorSettings.R.NextDouble()) - HurdleHeightVariance)), 0); //Keep it constrained. if (hurdleHeight > maxSize) { hurdleHeight = maxSize; } if (hurdleHeight < 1) { hurdleHeight = 1; } //Get the height of the plateau given the size of a hurdle. plateauHeight = area.Height + 1 - hurdleHeight; plateauHeight /= 2; //Fill in the plateaus. data.FillRegion(true, new Region(area.Left + border + (i * (space + plateauSize)), area.Top, plateauSize - 1, plateauHeight - 1)); if ((2 * plateauHeight) + hurdleHeight >= area.Height + 1) { data.FillRegion(true, new Region(area.Left + border + (i * (space + plateauSize)), area.Bottom - plateauHeight + 1, plateauSize - 1, plateauHeight - 1)); spawningAreas.Add(new Region(area.Left + border + (i * (space + plateauSize)), area.Top + plateauHeight, plateauSize - 1, data.BeingFilled.Height - plateauHeight - plateauHeight - 2)); } else { data.FillRegion(true, new Region(area.Left + border + (i * (space + plateauSize)), area.Bottom - plateauHeight, plateauSize - 1, plateauHeight)); spawningAreas.Add(new Region(area.Left + border + (i * (space + plateauSize)), area.Top + plateauHeight, plateauSize - 1, data.BeingFilled.Height - plateauHeight - plateauHeight - 1)); } } } //Make room for any holes that the plateaus covered. foreach (Location l in data.HolesAlongPerimeter()) { //Horizontal. if (area.Height < area.Width) { //The hole is covered if it is just below/above the region and the space above/below it (respectively) is filled. if ((area.Touches(l.Above, true, true, false) && data.GetMapAt(l.Above)) || (area.Touches(l.Below, true, true, false) && data.GetMapAt(l.Below))) { //Make a little tunnel under the plateau. int[] plateauSides = SteppedHallwayPattern.PlateauSides(l.X, numb, plateauSize, space, border, area.Left, area.Right); Region cleared; if (l.Y - 1 == area.Bottom) { cleared = new Region(plateauSides[0], data.BeingFilled.Bottom, plateauSize - 1, 0); } else { cleared = new Region(plateauSides[0], data.BeingFilled.Top, plateauSize - 1, 0); } data.FillRegion(false, cleared); } } //Vertical. else if ((area.Touches(l.Left, true, true, false) && data.GetMapAt(l.Left)) || (area.Touches(l.Right, true, true, false) && data.GetMapAt(l.Right))) { //Make a little tunnel under the plateau. int[] plateauSides = SteppedHallwayPattern.PlateauSides(l.Y, numb, plateauSize, space, border, area.Top, area.Bottom); Region cleared; if (l.X - 1 == area.Right) { cleared = new Region(data.BeingFilled.Right, plateauSides[0], 0, plateauSize - 1); } else { cleared = new Region(data.BeingFilled.Left, plateauSides[0], 0, plateauSize - 1); } data.FillRegion(false, cleared); } } //Return the new regions. return(new ThickHurdleRegion(data.BeingFilled, spawningAreas)); }
private void FillTunnels() { //Go through all nodes and make tunnels, // with special edge tunnels around the perimeter (if the level wraps around). Location lastNodePos = (Settings.TunnelLength + MaxRoomSize) * (Settings.NumberOfNodes - new Location(1, 1)); Location topLeft, nextTopLeft; Region beingCleared; foreach (PositionalNode n in NodeStates.Keys)//Graph.AllNodes(new PositionalNode(new float[2] { 1.0f, 1.0f }, 0))) { //Fill in the tunnel to the right and down from this cell. //Down. if (n.Coordinate[1] < lastNodePos.Y) { topLeft = new Location(VerticalTunnelX((int)n.Coordinate[0]), NodeAreas[n].Bottom); if (NodeStates[n] == NodeState.Room) { topLeft = topLeft.Below; } nextTopLeft = NodeAreas[new PositionalNode(new float[2] { n.Coordinate[0], n.Coordinate[1] + MaxRoomSize.Y + Settings.TunnelLength.Y }, 0)].TopLeft; beingCleared = new Region(topLeft, new Location(topLeft.X + Settings.TunnelThickness.Y - 1, nextTopLeft.Y - 1)); FillData.FillRegion(false, beingCleared); Regions.Add(beingCleared); for (int x = beingCleared.Left; x <= beingCleared.Right; ++x) { Holes.Add(new Location(x, beingCleared.Top)); Holes.Add(new Location(x, beingCleared.Bottom)); } } //Right. if (n.Coordinate[0] < lastNodePos.X) { topLeft = new Location(NodeAreas[n].Right, HorizontalTunnelY((int)n.Coordinate[1])).Right; nextTopLeft = NodeAreas[new PositionalNode(new float[2] { n.Coordinate[0] + MaxRoomSize.X + Settings.TunnelLength.X, n.Coordinate[1] }, 0)].TopLeft; beingCleared = new Region(topLeft, new Location(nextTopLeft.X - 1, topLeft.Y + Settings.TunnelThickness.X - 1)); FillData.FillRegion(false, beingCleared); Regions.Add(beingCleared); for (int y = beingCleared.Top; y <= beingCleared.Bottom; ++y) { Holes.Add(new Location(beingCleared.Left, y)); Holes.Add(new Location(beingCleared.Right, y)); } } //Border cases. //Left border. if (Settings.WrapAroundX && n.Coordinate[0] == 1.0f) { topLeft = new Location(0, HorizontalTunnelY((int)n.Coordinate[1])); nextTopLeft = NodeAreas[n].TopLeft.Left; beingCleared = new Region(topLeft, new Location(nextTopLeft.X, topLeft.Y + Settings.TunnelThickness.X - 1)); FillData.FillRegion(false, beingCleared); Regions.Add(beingCleared); for (int y = beingCleared.Top; y <= beingCleared.Bottom; ++y) { Holes.Add(new Location(beingCleared.Right, y)); } } //Top border. if (Settings.WrapAroundY && n.Coordinate[1] == 1.0f) { topLeft = new Location(VerticalTunnelX((int)n.Coordinate[0]), 0); nextTopLeft = NodeAreas[n].TopLeft.Above; beingCleared = new Region(topLeft, new Location(topLeft.X + Settings.TunnelThickness.Y - 1, nextTopLeft.Y)); FillData.FillRegion(false, beingCleared); Regions.Add(beingCleared); for (int x = beingCleared.Left; x <= beingCleared.Right; ++x) { Holes.Add(new Location(x, beingCleared.Bottom)); } } //Right border. if (Settings.WrapAroundX && n.Coordinate[0] == lastNodePos.X + 1) { topLeft = new Location(NodeAreas[n].Right, HorizontalTunnelY((int)n.Coordinate[1])).Right; beingCleared = new Region(topLeft, new Location(Map.GetLength(0) - 1, topLeft.Y + Settings.TunnelThickness.X - 1)); FillData.FillRegion(false, beingCleared); Regions.Add(beingCleared); for (int y = beingCleared.Top; y <= beingCleared.Bottom; ++y) { Holes.Add(new Location(beingCleared.Left, y)); } } //Bottom border. if (Settings.WrapAroundY && n.Coordinate[1] == lastNodePos.Y + 1) { topLeft = new Location(VerticalTunnelX((int)n.Coordinate[0]), NodeAreas[n].Bottom).Below; beingCleared = new Region(topLeft, new Location(topLeft.X + Settings.TunnelThickness.Y - 1, Map.GetLength(1) - 1)); FillData.FillRegion(false, beingCleared); Regions.Add(beingCleared); for (int x = beingCleared.Left; x <= beingCleared.Right; ++x) { Holes.Add(new Location(x, beingCleared.Top)); } } } }
public void IterateBase() { if (DoneBaseGen) { return; } count += 1; PositionalNode current = baseGenIterateCounter.Current; //Make either a room or a tunnel junction at the given spot. if (GeneratorSettings.R.NextDouble() < Settings.PercentRooms) { //Room. Location size = new Location(Settings.RoomDimensions.X + (int)Settings.RoomXVariance.Random(), Settings.RoomDimensions.Y + (int)Settings.RoomYVariance.Random()); size = new Location(System.Math.Max(size.X, Settings.TunnelThickness.X), System.Math.Max(size.Y, Settings.TunnelThickness.Y)); Region room = new Region((int)current.Coordinate[0], (int)current.Coordinate[1], size.X - 1, size.Y - 1); if (!room.SubRegionOf(new Region(0, 0, Map.GetLength(0), Map.GetLength(1)))) { DoneBaseGen = !baseGenIterateCounter.MoveNext(); NodeStates.Remove(current); return; } //Move the room to the center. Location offset = new Location((int)Math.Round((MaxRoomSize.X - room.Width - 1) / 2.0f, 0), (int)Math.Round((MaxRoomSize.Y - room.Height - 1) / 2.0f, 0)); room = new Region(room.TopLeft + offset, room.BottomRight + offset); //Clear the room area. Regions.Add(room); FillData.FillRegion(false, room); //Add the room data. NodeStates[current] = NodeState.Room; NodeAreas.Add(current, room); } else { //Tunnel junction. Location size = MaxRoomSize; Region space = new Region((int)current.Coordinate[0], (int)current.Coordinate[1], size.X - 1, size.Y - 1); space = new Region(space.Left + Settings.JunctionOffset.X, space.Top + Settings.JunctionOffset.Y, Settings.TunnelThickness.Y - 1, Settings.TunnelThickness.X - 1); if (!space.SubRegionOf(new Region(0, 0, Map.GetLength(0), Map.GetLength(1)))) { DoneBaseGen = !baseGenIterateCounter.MoveNext(); NodeStates.Remove(current); return; } Regions.Add(space); FillData.FillRegion(false, space); //Add the room data. NodeStates[current] = NodeState.TunnelJunction; NodeAreas.Add(current, space); } //Prepare for the next iteration. DoneBaseGen = !baseGenIterateCounter.MoveNext(); }
public FilledRegion Apply(FillData data) { //Start on either the relative top or bottom of the corridor. bool top = MathF.R.NextDouble() > 0.5; //Set up the plateau properties. bool horizontal = data.BeingFilled.Width > data.BeingFilled.Height; if (horizontal) { Generation.BeingFilled = data.BeingFilled; } else { Generation.BeingFilled = new Region(data.BeingFilled.Y, data.BeingFilled.X, data.BeingFilled.Height, data.BeingFilled.Width); } int spaceBetween = Generation.SpaceBetweenPlateaus; int border = Generation.Border; int plateauWidth = Generation.PlateauWidth; int numbPlateaus = Generation.NumbPlateaus; //Fill the area. Also keep track of the free space above/below plateaus. List <Region> freeAreas = new List <Region>(); for (int i = 0; i < numbPlateaus; ++i) { if (top) { if (horizontal) { data.FillRegion(true, new Region(data.BeingFilled.Left + border + (i * (spaceBetween + plateauWidth)), data.BeingFilled.Top, plateauWidth - 1, data.BeingFilled.Height - 1)); freeAreas.Add(new Region(data.BeingFilled.Left + border + (i * (spaceBetween + plateauWidth)), data.BeingFilled.Bottom, plateauWidth - 1, 0)); } else { data.FillRegion(true, new Region(data.BeingFilled.Left, data.BeingFilled.Top + border + (i * (spaceBetween + plateauWidth)), data.BeingFilled.Width - 1, plateauWidth - 1)); freeAreas.Add(new Region(data.BeingFilled.Left + 1, data.BeingFilled.Top + border + (i * (spaceBetween + plateauWidth)) - 1, data.BeingFilled.Width - 2, 0)); } } else { if (horizontal) { data.FillRegion(true, new Region(data.BeingFilled.Left + border + (i * (spaceBetween + plateauWidth)), data.BeingFilled.Top + 1, plateauWidth - 1, data.BeingFilled.Height - 1)); freeAreas.Add(new Region(data.BeingFilled.Left + border + (i * (spaceBetween + plateauWidth)), data.BeingFilled.Top, plateauWidth - 1, 0)); } else { data.FillRegion(true, new Region(data.BeingFilled.Left + 1, data.BeingFilled.Top + border + (i * (spaceBetween + plateauWidth)), data.BeingFilled.Width - 1, plateauWidth - 1)); freeAreas.Add(new Region(data.BeingFilled.Left + 1, data.BeingFilled.Top + border + (i * (spaceBetween + plateauWidth)) - 1, data.BeingFilled.Width - 2, 0)); } } top = !top; } Region area = data.BeingFilled; //Make room for any holes that the plateaus covered. //TODO: Instead of clearing out the bottom, just clear that column of plateau. Possibly also do this for other plateau patterns? foreach (Location l in data.HolesAlongPerimeter()) { //Horizontal. if (area.Height < area.Width) { //The hole is covered if it is just below/above the region and the space above/below it (respectively) is filled. if ((area.Touches(l.Above, true, true, false) && data.GetMapAt(l.Above)) || (area.Touches(l.Below, true, true, false) && data.GetMapAt(l.Below))) { //Make a little tunnel under the plateau. int[] plateauSides = SteppedHallwayPattern.PlateauSides(l.X, numbPlateaus, plateauWidth, spaceBetween, border, area.Left, area.Right); Region cleared; if (l.Y - 1 == area.Bottom) { cleared = new Region(plateauSides[0], data.BeingFilled.Bottom, plateauWidth - 1, 0); } else { cleared = new Region(plateauSides[0], data.BeingFilled.Top, plateauWidth - 1, 0); } data.FillRegion(false, cleared); } } //Vertical else if ((area.Touches(l.Left, true, true, false) && data.GetMapAt(l.Left)) || (area.Touches(l.Right, true, true, false) && data.GetMapAt(l.Right))) { //Make a little tunnel under the plateau. int[] plateauSides = SteppedHallwayPattern.PlateauSides(l.Y, numbPlateaus, plateauWidth, spaceBetween, border, area.Top, area.Bottom); Region cleared; if (l.X - 1 == area.Right) { cleared = new Region(data.BeingFilled.Right, plateauSides[0], 0, plateauWidth - 1); } else { cleared = new Region(data.BeingFilled.Left, plateauSides[0], 0, plateauWidth - 1); } data.FillRegion(false, cleared); } } if (horizontal) { return(new ZipperRegion(data.BeingFilled, freeAreas)); } else { return(new ZipperRegion(data.BeingFilled, new List <Region>())); } }
public FilledRegion Apply(FillData data) { Region clearArea = new Region(data.BeingFilled.Center.Left.Above, data.BeingFilled.Center.Right.Below); //Fill the inner ring. //Move from each corner of the X to the center. Location counter; Location center = data.BeingFilled.Center; bool moveHorizontally; bool horizontalBias = data.BeingFilled.Width > data.BeingFilled.Height; //Fill in the center. data.FillRegion(true, new Region(clearArea.TopLeft.Above.Left, clearArea.BottomRight.Below.Right)); for (int i = 0; i < 4; ++i) { //Get the point to start from. switch (i) { case 0: counter = data.BeingFilled.TopLeft.Right.Below; data.SetMapAt(counter, false); break; case 1: counter = data.BeingFilled.TopRight.Left.Below; data.SetMapAt(counter, false); break; case 2: counter = data.BeingFilled.BottomLeft.Right.Above; data.SetMapAt(counter, false); break; case 3: counter = data.BeingFilled.BottomRight.Left.Above; data.SetMapAt(counter, false); break; default: throw new InvalidOperationException(); } //Clear a path to the center. while (!clearArea.Touches(counter, true, true, true)) { //Get which direction to move in. float relativeDistX = Math.Abs(counter.X - center.X) / (float)data.BeingFilled.Width; float relativeDistY = Math.Abs(counter.Y - center.Y) / (float)data.BeingFilled.Height; if (relativeDistX > relativeDistY) { moveHorizontally = true; } else if (relativeDistX < relativeDistY) { moveHorizontally = false; } else { moveHorizontally = horizontalBias; } //Move that direction, add the region, and fill part of the X after moving. if (moveHorizontally) { int amount = Math.Sign(center.X - counter.X); counter.X += amount; data.SetMapAt(counter, false); data.SetMapAt(new Location(counter.X + amount, counter.Y), true); if (counter.Y > 1 && counter.Y < data.BeingFilled.Bottom - 1) { data.SetMapAt(new Location(counter.X, counter.Y + Math.Sign(counter.Y - center.Y)), true); } } else { int amount = Math.Sign(center.Y - counter.Y); counter.Y += amount; data.SetMapAt(counter, false); data.SetMapAt(new Location(counter.X, counter.Y + amount), true); if (counter.X > 1 && counter.X < data.BeingFilled.Right - 1) { data.SetMapAt(new Location(counter.X + Math.Sign(counter.X - center.X), counter.Y), true); } } } //Keep the center clear. data.FillRegion(false, clearArea); } //Just to be safe, clear the perimeter at the end. data.FillPerimeter(false, data.BeingFilled); return(new XRegion(data.BeingFilled, data.Map)); }