Skip to content

Commit 6353498

Browse files
committed
Add Loopy palace style
Based on Reconstructed with some twists: - No regular dead-end rooms (not including item rooms) - Loops pick rooms that are as far away as possible. This is to reduce the likelihood of long dead-end paths that would loop into themselves at the end. (It might still happen if there are very few open rooms.) - No drop rooms This is a small subclass to Reconstructed. I made this instead of having the option to remove drops from all styles, as drops are generally fun in the coordinate palaces.
1 parent b12ddea commit 6353498

6 files changed

Lines changed: 72 additions & 5 deletions

File tree

RandomizerCore/EnumTypes.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,8 @@ public enum PalaceStyle
199199
{
200200
[Description("Vanilla")]
201201
VANILLA,
202-
[Description("Shuffled")]
202+
[Description("Vanilla Shuffle")]
203203
SHUFFLED,
204-
[Description("Reconstructed")]
205-
RECONSTRUCTED,
206204
[Description("Sequential")]
207205
SEQUENTIAL,
208206
[Description("Random Walk")]
@@ -211,6 +209,10 @@ public enum PalaceStyle
211209
VANILLA_WEIGHTED,
212210
[Description("Tower")]
213211
TOWER,
212+
[Description("Reconstructed")]
213+
RECONSTRUCTED,
214+
[Description("Loopy")]
215+
RECONSTRUCTED_LOOPY,
214216
[Description("Chaos"), DefaultWeight(0)]
215217
CHAOS,
216218
[Description("Random"), Metastyle]

RandomizerCore/Sidescroll/Palace.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,31 @@ public bool IsBossRoomAtLeastMinDistance(int minSteps)
185185
return false; // Boss room not found??
186186
}
187187

188+
public static int RoomDistance(Room room1, Room room2)
189+
{
190+
HashSet<Room> reachedRooms = [];
191+
Queue<(Room, int)> roomsToCheck = [];
192+
roomsToCheck.Enqueue((room1, 0));
193+
while (roomsToCheck.Count > 0)
194+
{
195+
var (room, stepsToRoom) = roomsToCheck.Dequeue();
196+
if (room == room2)
197+
{
198+
return stepsToRoom;
199+
}
200+
201+
// This will return false if the room is already added
202+
if (!reachedRooms.Add(room)) { continue; }
203+
204+
int stepsToNextRoom = stepsToRoom + 1;
205+
if (room.Left != null) { roomsToCheck.Enqueue((room.Left, stepsToNextRoom)); }
206+
if (room.Right != null) { roomsToCheck.Enqueue((room.Right, stepsToNextRoom)); }
207+
if (room.Up != null) { roomsToCheck.Enqueue((room.Up, stepsToNextRoom)); }
208+
if (room.Down != null) { roomsToCheck.Enqueue((room.Down, stepsToNextRoom)); }
209+
}
210+
return -1;
211+
}
212+
188213
/// same algorithm as BossRoomMinDistance except for shapes instead of rooms
189214
public static bool BossRoomMinDistanceShape(Dictionary<Coord, RoomExitType> shape, Coord bossRoom, int minSteps)
190215
{

RandomizerCore/Sidescroll/Palaces.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public async Task<List<Palace>> CreatePalaces(Random r, RandomizerProperties pro
7575
PalaceStyle.VANILLA_WEIGHTED => new VanillaWeightedPalaceGenerator(),
7676
PalaceStyle.TOWER => new TowerCoordinatePalaceGenerator(),
7777
PalaceStyle.RECONSTRUCTED => new ReconstructedPalaceGenerator(ct),
78+
PalaceStyle.RECONSTRUCTED_LOOPY => new ReconstructedLoopyPalaceGenerator(ct),
7879
PalaceStyle.CHAOS => new ChaosPalaceGenerator(),
7980
_ => throw new Exception("Unrecognized palace style while generating palaces")
8081
};
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
7+
namespace Z2Randomizer.RandomizerCore.Sidescroll;
8+
9+
public class ReconstructedLoopyPalaceGenerator(CancellationToken ct) : ReconstructedPalaceGenerator(ct)
10+
{
11+
internal override Task<Palace> GeneratePalace(RandomizerProperties props, RoomPool rooms, Random r, int roomCount, int palaceNumber)
12+
{
13+
rooms.RemoveRooms(room => room.HasDrop);
14+
rooms.RemoveRooms(room => !room.IsEntrance && !room.IsBossRoom && !room.HasItem
15+
&& RoomExitTypeExtensions.DEADENDS.Contains(room.CategorizeExits()));
16+
return base.GeneratePalace(props, rooms, r, roomCount, palaceNumber);
17+
}
18+
19+
public override void Consolidate(List<Room> openRooms)
20+
{
21+
Room[] openCopy = new Room[openRooms.Count];
22+
openRooms.CopyTo(openCopy); // shallow copy
23+
foreach (Room r2 in openCopy)
24+
{
25+
var furthestFirst = openRooms.OrderBy(room => -Palace.RoomDistance(r2, room));
26+
foreach (Room r3 in furthestFirst)
27+
{
28+
if (r2 != r3 && openRooms.Contains(r2) && openRooms.Contains(r3))
29+
{
30+
if (AttachToOpen(r2, r3, openRooms))
31+
{
32+
break;
33+
}
34+
}
35+
}
36+
}
37+
}
38+
}

RandomizerCore/Sidescroll/ReconstructedPalaceGenerator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ private void ProcessRoom(Palace palace, Room room, List<Room> openRooms)
307307
}
308308
}
309309

310-
public void Consolidate(List<Room> openRooms)
310+
public virtual void Consolidate(List<Room> openRooms)
311311
{
312312
Room[] openCopy = new Room[openRooms.Count];
313313
openRooms.CopyTo(openCopy);
@@ -330,7 +330,7 @@ public void Consolidate(List<Room> openRooms)
330330
/// <param name="room"></param> The room to be attached
331331
/// <param name="open"></param> The room onto which R is attached
332332
/// <returns>Whether or not the room was actually able to be attached.</returns>
333-
private bool AttachToOpen(Room room, Room open, List<Room> openRooms)
333+
protected bool AttachToOpen(Room room, Room open, List<Room> openRooms)
334334
{
335335
bool placed = false;
336336
//Right from open into r

RandomizerCore/Sidescroll/RoomExitType.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public enum RoomExitType
4141
public static class RoomExitTypeExtensions
4242
{
4343
public static RoomExitType[] ALL = Enum.GetValues(typeof(RoomExitType)).Cast<RoomExitType>().ToArray();
44+
public static RoomExitType[] DEADENDS = [RoomExitType.DEADEND_EXIT_RIGHT, RoomExitType.DEADEND_EXIT_UP, RoomExitType.DEADEND_EXIT_LEFT, RoomExitType.DEADEND_EXIT_DOWN];
4445

4546
public const int LEFT = 0b00010000;
4647
public const int DOWN = 0b00001000;

0 commit comments

Comments
 (0)