From 80f6b11ec70c72ad84af4a1dc48c66fe8ef33965 Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Thu, 1 Oct 2026 14:47:23 +0200 Subject: [PATCH] feat: player sight radius configuration and update related logic --- BlazorRogue.Tests/ConfigurationTests.cs | 1 + Data/game-config.json | 1 + Entities/Configuration.cs | 20 ++++++++++++++++++++ Pages/GamePage.razor | 10 ++++++---- World/Generation/FenceGalleryMapGenerator.cs | 2 +- World/Map.cs | 3 +-- 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/BlazorRogue.Tests/ConfigurationTests.cs b/BlazorRogue.Tests/ConfigurationTests.cs index 351a0c5..e8e40b6 100644 --- a/BlazorRogue.Tests/ConfigurationTests.cs +++ b/BlazorRogue.Tests/ConfigurationTests.cs @@ -411,6 +411,7 @@ public void ParseLoadsGameConfigDefaults() var configuration = ParseConfiguration(); Assert.Equal(0, configuration.StartingLevelNumber); + Assert.Equal(12, configuration.PlayerSightRadius); Assert.False(configuration.DebugMode); Assert.Equal(-1002, configuration.DebugLevelNumber); } diff --git a/Data/game-config.json b/Data/game-config.json index 031e51a..1873e7d 100644 --- a/Data/game-config.json +++ b/Data/game-config.json @@ -1,5 +1,6 @@ { "starting_level": 0, + "player_sight_radius": 12, "debug_mode": false, "debug_level": -1002 } diff --git a/Entities/Configuration.cs b/Entities/Configuration.cs index 8164ec1..32ec81b 100644 --- a/Entities/Configuration.cs +++ b/Entities/Configuration.cs @@ -124,6 +124,16 @@ public LiquidType LiquidTypeById(string id) => /// public int StartingLevelNumber { get; private set; } = DefaultStartingLevelNumber; + /// Player sight radius when game-config.json doesn't say otherwise. + internal const int DefaultPlayerSightRadius = 6; + + /// + /// How many tiles the player can see (and wake monsters) around themselves, from + /// Data/game-config.json's player_sight_radius. Defaults to + /// ; must be positive. + /// + public int PlayerSightRadius { get; private set; } = DefaultPlayerSightRadius; + /// /// Initial value for (verbose combat rolls in the message log), /// from Data/game-config.json's debug_mode. Defaults to false; toggle it @@ -361,6 +371,16 @@ void ParseGameConfig(JsonDocumentOptions options) { StartingLevelNumber = RequireNonNullInt(startingLevelElement, "starting_level"); } + if (root.TryGetProperty("player_sight_radius", out var sightRadiusElement)) + { + PlayerSightRadius = RequireNonNullInt(sightRadiusElement, "player_sight_radius"); + if (PlayerSightRadius < 1) + { + throw new InvalidOperationException( + $"game-config.json 'player_sight_radius' must be positive, but is {PlayerSightRadius}." + ); + } + } if (root.TryGetProperty("debug_mode", out var debugModeElement)) { DebugMode = debugModeElement.GetBoolean(); diff --git a/Pages/GamePage.razor b/Pages/GamePage.razor index 25bc3c4..1145cca 100644 --- a/Pages/GamePage.razor +++ b/Pages/GamePage.razor @@ -624,8 +624,9 @@ else windowYOffset = Math.Clamp(optimalYOffset, 0, game.Map.Height - windowHeight); // optional: keep move buffer proportional after resize - windowMoveBufferX = Math.Min(Map.PlayerSightRadius + 1, Math.Max(1, windowWidth / 3)); - windowMoveBufferY = Math.Min(Map.PlayerSightRadius + 1, Math.Max(1, windowHeight / 3)); + int sightRadius = game.Configuration.PlayerSightRadius; + windowMoveBufferX = Math.Min(sightRadius + 1, Math.Max(1, windowWidth / 3)); + windowMoveBufferY = Math.Min(sightRadius + 1, Math.Max(1, windowHeight / 3)); } private async Task ToggleRenderMode() @@ -850,8 +851,9 @@ else // guarded on `session is null` so neither is dereferenced before that. Game game = null!; - int windowMoveBufferX = Map.PlayerSightRadius + 1; - int windowMoveBufferY = Map.PlayerSightRadius + 1; + // Placeholders until FitMapToViewportAsync derives them from the configured sight radius. + int windowMoveBufferX = BlazorRogue.Entities.Configuration.DefaultPlayerSightRadius + 1; + int windowMoveBufferY = BlazorRogue.Entities.Configuration.DefaultPlayerSightRadius + 1; int windowWidth = 25; int windowHeight = 20; diff --git a/World/Generation/FenceGalleryMapGenerator.cs b/World/Generation/FenceGalleryMapGenerator.cs index 60e5585..82d3be6 100644 --- a/World/Generation/FenceGalleryMapGenerator.cs +++ b/World/Generation/FenceGalleryMapGenerator.cs @@ -151,7 +151,7 @@ protected override Tuple CreateLayout() // twice) for a fresh goblin and try approaching more directly. _ = AddMonsterAt(enclosureX0 + 2, enclosureY0 + 1, configuration.MonsterTypes["goblin"]); - // Sight radius is only Map.PlayerSightRadius (6) - too small to see the whole gallery from + // Sight radius is only game-config.json's player_sight_radius - may be too small to see the whole gallery from // one spot regardless, but this puts the swatch row mostly in view on arrival, with the // enclosure a short walk south. return Tuple.Create(8, 6); diff --git a/World/Map.cs b/World/Map.cs index 3e7ea2b..4d9c9a5 100644 --- a/World/Map.cs +++ b/World/Map.cs @@ -22,8 +22,7 @@ class Map // Set via AddPlayer() shortly after Map construction (DungeonGenerator always calls it before // the map is used); null! avoids forcing nullable-checks on every consumer of this property. public Moveable Player { get; private set; } = null!; - public const int PlayerSightRadius = 6; - public const int PlayerSightRadiusSquared = PlayerSightRadius * PlayerSightRadius; + public int PlayerSightRadius => Game.Configuration.PlayerSightRadius; public List DebugInfo = [];