Make room system generic

This commit is contained in:
Stone_Red
2024-02-04 20:25:30 +01:00
parent 8096f95f04
commit 6734d64e99
9 changed files with 68 additions and 29 deletions
+4 -2
View File
@@ -302,8 +302,6 @@ node_modules/
*.dsp *.dsp
# Visual Studio 6 technical files # Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output # Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts **/*.HTMLClient/GeneratedArtifacts
@@ -396,3 +394,7 @@ FodyWeavers.xsd
# JetBrains Rider # JetBrains Rider
*.sln.iml *.sln.iml
# SQLite
/src/TextLore/games.sqlite-shm
/src/TextLore/games.sqlite-wal
@@ -4,5 +4,5 @@ namespace TextLore.Database;
public class GamesDatabaseContext(DbContextOptions<GamesDatabaseContext> options) : DbContext(options) public class GamesDatabaseContext(DbContextOptions<GamesDatabaseContext> options) : DbContext(options)
{ {
public DbSet<Games.Roguelike.Models.RoomDefinition> RoguelikeRooms { get; set; } public DbSet<Games.Roguelike.Models.RoomDefinition> Rooms { get; set; }
} }
@@ -19,12 +19,12 @@ public class LevelGenerator(DeterministicRandom seed, IQueryable<RoomDefinition>
Level level = new Level(size, seed); Level level = new Level(size, seed);
Queue<Room> generationQueue = new Queue<Room>(); Queue<Room> generationQueue = new Queue<Room>();
RoomDefinition startRoomDefinition = await GetRandomRoomDefinition() ?? throw new InvalidOperationException("No rooms found in the database."); RoomDefinition startRoomDefinition = await GetRandomRoomDefinition(level) ?? throw new InvalidOperationException("No rooms found in the database.");
Position startRoomPosition = new Position(seed.Next(0, size.Width), seed.Next(0, size.Height)); Position startRoomPosition = new Position(seed.Next(0, size.Width), seed.Next(0, size.Height));
Room startRoom = new Room(startRoomPosition, startRoomDefinition); Room startRoom = new Room(startRoomPosition, startRoomDefinition);
level.AddRoom(startRoom); _ = level.AddRoom(startRoom);
generationQueue.Enqueue(startRoom); generationQueue.Enqueue(startRoom);
while (generationQueue.Count > 0) while (generationQueue.Count > 0)
@@ -43,11 +43,11 @@ public class LevelGenerator(DeterministicRandom seed, IQueryable<RoomDefinition>
if (level.IsPositionInBounds(newPosition) && level.GetRoom(newPosition) is null) if (level.IsPositionInBounds(newPosition) && level.GetRoom(newPosition) is null)
{ {
RoomDefinition? newRoomDefinition = await GetRandomRoomDefinition(); RoomDefinition? newRoomDefinition = await GetRandomRoomDefinition(level);
Room newRoom = new Room(newPosition, newRoomDefinition ?? throw new InvalidOperationException("No rooms found in the database.")); Room newRoom = new Room(newPosition, newRoomDefinition ?? throw new InvalidOperationException("No rooms found in the database."));
level.AddRoom(newRoom); _ = level.AddRoom(newRoom);
generationQueue.Enqueue(newRoom); generationQueue.Enqueue(newRoom);
} }
} }
@@ -74,7 +74,7 @@ public class LevelGenerator(DeterministicRandom seed, IQueryable<RoomDefinition>
return level; return level;
} }
private async Task<RoomDefinition?> GetRandomRoomDefinition() private async Task<RoomDefinition?> GetRandomRoomDefinition(Level level)
{ {
RoomDefinition? room = null; RoomDefinition? room = null;
int randomRoomIndex = seed.Next(); int randomRoomIndex = seed.Next();
@@ -87,6 +87,11 @@ public class LevelGenerator(DeterministicRandom seed, IQueryable<RoomDefinition>
{ {
room = await rooms.FirstOrDefaultAsync(x => x.Id == randomRoomIndex); room = await rooms.FirstOrDefaultAsync(x => x.Id == randomRoomIndex);
if (room?.Tag == RoomTag.Unique && level.RoomExists(room))
{
room = null;
}
if (room is not null) if (room is not null)
{ {
break; break;
+19 -2
View File
@@ -22,14 +22,26 @@ public class Level(Size size, DeterministicRandom seed)
return rooms; return rooms;
} }
public void AddRoom(Room room) public bool AddRoom(Room room)
{ {
if (!IsRoomInBounds(room)) if (!IsRoomInBounds(room))
{ {
throw new InvalidOperationException("Room is out of bounds."); return false;
}
if (room.Definition.Tag == RoomTag.Unique && RoomExists(room.Definition))
{
return false;
}
if (room.Definition.Tag == RoomTag.Start && rooms.Values.Any(r => r.Definition.Tag == RoomTag.Start))
{
return false;
} }
rooms[room.Position] = room; rooms[room.Position] = room;
return true;
} }
public bool IsPositionInBounds(Position point) public bool IsPositionInBounds(Position point)
@@ -47,6 +59,11 @@ public class Level(Size size, DeterministicRandom seed)
return rooms.ContainsKey(point); return rooms.ContainsKey(point);
} }
public bool RoomExists(RoomDefinition definition)
{
return rooms.Values.Any(r => r.Definition.Id == definition.Id);
}
public void ClearRoom(Position point) public void ClearRoom(Position point)
{ {
_ = rooms.Remove(point); _ = rooms.Remove(point);
@@ -1,14 +1,22 @@
using System.ComponentModel.DataAnnotations; using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace TextLore.Games.Roguelike.Models; namespace TextLore.Games.Roguelike.Models;
public class RoomDefinition(string name) [PrimaryKey(nameof(Id), nameof(Tag), nameof(Game))]
public class RoomDefinition(int id, RoomTag tag, string game)
{ {
[Key] [Column(Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; } = id;
public int Id { get; private set; }
[Required] [Column(Order = 1)]
public string Name { get; set; } = name; public RoomTag Tag { get; } = tag;
[Column(Order = 2)]
public string Game { get; } = game;
public required string Name { get; set; }
public string Script { get; set; } = string.Empty;
} }
@@ -0,0 +1,9 @@
namespace TextLore.Games.Roguelike.Models;
public enum RoomTag
{
None = 0,
Start = 1,
End = 2,
Unique = 3
}
@@ -37,7 +37,7 @@ public partial class RoguelikePage
{ {
if (firstRender) if (firstRender)
{ {
await console.Execute(new GenerateLevelCommand(DatabaseContext.RoguelikeRooms, NavigationManager, OnLevelGenerated), Seed); await console.Execute(new GenerateLevelCommand(DatabaseContext.Rooms, NavigationManager, OnLevelGenerated), Seed);
} }
} }
} }
+9 -11
View File
@@ -28,17 +28,15 @@ GamesDatabaseContext databaseContext = serviceScope.ServiceProvider.GetRequiredS
if (await databaseContext.Database.EnsureCreatedAsync()) if (await databaseContext.Database.EnsureCreatedAsync())
{ {
databaseContext.RoguelikeRooms.AddRange( databaseContext.Rooms.AddRange(
new TextLore.Games.Roguelike.Models.RoomDefinition("Room 1"), new TextLore.Games.Roguelike.Models.RoomDefinition(1, TextLore.Games.Roguelike.Models.RoomTag.Start, "rogelike") { Name = "Start Room" },
new TextLore.Games.Roguelike.Models.RoomDefinition("Room 2"), new TextLore.Games.Roguelike.Models.RoomDefinition(1, TextLore.Games.Roguelike.Models.RoomTag.Unique, "rogelike") { Name = "Unique Room" },
new TextLore.Games.Roguelike.Models.RoomDefinition("Room 3"), new TextLore.Games.Roguelike.Models.RoomDefinition(2, TextLore.Games.Roguelike.Models.RoomTag.Unique, "rogelike") { Name = "Normal Room 1" },
new TextLore.Games.Roguelike.Models.RoomDefinition("Room 4"), new TextLore.Games.Roguelike.Models.RoomDefinition(3, TextLore.Games.Roguelike.Models.RoomTag.Unique, "rogelike") { Name = "Normal Room 2" },
new TextLore.Games.Roguelike.Models.RoomDefinition("Room 5"), new TextLore.Games.Roguelike.Models.RoomDefinition(4, TextLore.Games.Roguelike.Models.RoomTag.Unique, "rogelike") { Name = "Normal Room 3" },
new TextLore.Games.Roguelike.Models.RoomDefinition("Room 6"), new TextLore.Games.Roguelike.Models.RoomDefinition(5, TextLore.Games.Roguelike.Models.RoomTag.Unique, "rogelike") { Name = "Normal Room 4" },
new TextLore.Games.Roguelike.Models.RoomDefinition("Room 7"), new TextLore.Games.Roguelike.Models.RoomDefinition(6, TextLore.Games.Roguelike.Models.RoomTag.Unique, "rogelike") { Name = "Normal Room 5" },
new TextLore.Games.Roguelike.Models.RoomDefinition("Room 8"), new TextLore.Games.Roguelike.Models.RoomDefinition(1, TextLore.Games.Roguelike.Models.RoomTag.End, "rogelike") { Name = "End Room" }
new TextLore.Games.Roguelike.Models.RoomDefinition("Room 9"),
new TextLore.Games.Roguelike.Models.RoomDefinition("Room 10")
); );
_ = await databaseContext.SaveChangesAsync(); _ = await databaseContext.SaveChangesAsync();
Binary file not shown.