summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop.Tests
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-21 08:16:10 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-21 08:16:10 +0800
commitf64045ca6245ed853f4d8ac1bcce6f4fe13068ce (patch)
tree8f637a981c7099aa6216c1bdebb0921c3b9b513d /src/LivingVillage.Desktop.Tests
parentdd0907573e13981035a5ff264831edb0534e3496 (diff)
downloadliving-village-f64045ca6245ed853f4d8ac1bcce6f4fe13068ce.tar.gz
feat(desktop): 固化样例世界与昼光呈现
[变更性质] - this commit adds a deterministic desktop bootstrap for the playable sample world. [新增功能] - this commit places the avatar away from the home doorway and separates villagers from scene footprints. - this commit provides a warm high-contrast daylight tint and exits autoplay after SampleComplete. [实现方案] - this commit isolates desktop spawn policy in WorldBootstrap and routes game startup and sample tests through it. - this commit adds regression coverage for spawn positions, spacing, determinism, and daylight tint. [影响范围] - this commit affects the Desktop application and Desktop tests only. - this commit preserves Kernel behavior and does not include unrelated worktree changes.
Diffstat (limited to 'src/LivingVillage.Desktop.Tests')
-rw-r--r--src/LivingVillage.Desktop.Tests/DesktopTests.fs53
-rw-r--r--src/LivingVillage.Desktop.Tests/SampleTests.fs2
2 files changed, 54 insertions, 1 deletions
diff --git a/src/LivingVillage.Desktop.Tests/DesktopTests.fs b/src/LivingVillage.Desktop.Tests/DesktopTests.fs
index 1c175ce..20cbbe9 100644
--- a/src/LivingVillage.Desktop.Tests/DesktopTests.fs
+++ b/src/LivingVillage.Desktop.Tests/DesktopTests.fs
@@ -4,6 +4,7 @@ open Microsoft.VisualStudio.TestTools.UnitTesting
open LivingVillage.Kernel
open LivingVillage.Kernel.Sim
open LivingVillage.Desktop
+open LivingVillage.Desktop.VillagePresentation
module private Harness =
@@ -71,3 +72,55 @@ type DesktopTests () =
Assert.AreEqual<M6DayNight>(Night, night.Mode)
Assert.AreNotEqual(day.Background, night.Background)
Assert.AreNotEqual(day.WorldTint, night.WorldTint)
+
+ [<TestMethod>]
+ member _.DesktopBootstrapMovesAvatarOffTheHomeDoorAndSeparatesVillagers () =
+ let world = WorldBootstrap.initialWorld 42UL Sim.npcCount
+ let avatarPixel : PixelPosition =
+ { X = world.Avatar.Pos.X
+ Y = world.Avatar.Pos.Y }
+ let avatarTile =
+ sceneTileFromPixel avatarPixel
+ let home = scene.Homes |> List.head
+ let renderPlan = VillageArt.sampleRenderPlan ()
+ let blockedTiles =
+ (renderPlan.Grounds |> List.map (fun (tile, _) -> VillageArt.worldTile renderPlan tile))
+ @ (renderPlan.Props |> List.map (fun prop -> VillageArt.worldTile renderPlan prop.Position))
+ |> List.map (fun tile -> tile.X, tile.Y)
+ |> Set.ofList
+ let sceneTileOf (position: Vec2) : TilePosition =
+ sceneTileFromPixel
+ { X = position.X
+ Y = position.Y }
+ let distanceSquared (first: Vec2) (second: Vec2) : float32 =
+ let dx = second.X - first.X
+ let dy = second.Y - first.Y
+ dx * dx + dy * dy
+ let npcTiles = world.Npcs |> Array.map (fun npc -> sceneTileOf npc.Pos)
+
+ Assert.AreEqual<int>(6, avatarTile.X)
+ Assert.AreEqual<int>(7, avatarTile.Y)
+ Assert.IsFalse(isNearHomeDoor avatarTile home, "The avatar must start beyond the doorway interaction radius.")
+ Assert.IsTrue(
+ npcTiles |> Array.forall (fun tile -> not (Set.contains (tile.X, tile.Y) blockedTiles)),
+ "A villager must not spawn on the house, water, bridge, or garden footprint.")
+ Assert.IsTrue(
+ world.Npcs
+ |> Array.forall (fun npc -> distanceSquared world.Avatar.Pos npc.Pos >= 96.0f * 96.0f),
+ "Villagers must not overlap the avatar spawn.")
+
+ for first in 0 .. world.Npcs.Length - 2 do
+ for second in first + 1 .. world.Npcs.Length - 1 do
+ Assert.IsTrue(
+ distanceSquared world.Npcs.[first].Pos world.Npcs.[second].Pos >= 96.0f * 96.0f,
+ sprintf "villagers %d and %d are too close" first second)
+
+ let repeated = WorldBootstrap.initialWorld 42UL Sim.npcCount
+ Assert.AreEqual<World>(world, repeated)
+
+ [<TestMethod>]
+ member _.DaylightUsesAWarmHighContrastWorldTint () =
+ let day = M6Presentation.profileAtTick (6L * Sim.ticksPerDay / 24L)
+
+ Assert.IsTrue(day.WorldTint.R > day.WorldTint.G)
+ Assert.IsTrue(day.WorldTint.G > day.WorldTint.B)
diff --git a/src/LivingVillage.Desktop.Tests/SampleTests.fs b/src/LivingVillage.Desktop.Tests/SampleTests.fs
index 4c833b5..ae81b64 100644
--- a/src/LivingVillage.Desktop.Tests/SampleTests.fs
+++ b/src/LivingVillage.Desktop.Tests/SampleTests.fs
@@ -12,7 +12,7 @@ type SampleTests () =
let areEqual (expected: 'T) (actual: 'T) = Assert.AreEqual<'T>(expected, actual)
- let freshWorld () = Sim.initialWorldN 42UL Sim.npcCount
+ let freshWorld () = WorldBootstrap.initialWorld 42UL Sim.npcCount
let freshView (world: World) = M5Interaction.refreshPrompt world M5Interaction.initial