From e46f1ddda07fc9c3d2617663ed28a3d1391c198b Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Mon, 28 Sep 2026 20:58:24 +0800 Subject: p47: 整改 — 倒影改暖色垂直光柱(gap-skip穿桥面落水面,最长≥3格)+近景接入倒影+近景屋顶受光/背光双档luma MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../P47SceneDetailTests.fs | 28 +++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'src/LivingVillage.Desktop.Tests/P47SceneDetailTests.fs') diff --git a/src/LivingVillage.Desktop.Tests/P47SceneDetailTests.fs b/src/LivingVillage.Desktop.Tests/P47SceneDetailTests.fs index 4ff0a66..ac8bf80 100644 --- a/src/LivingVillage.Desktop.Tests/P47SceneDetailTests.fs +++ b/src/LivingVillage.Desktop.Tests/P47SceneDetailTests.fs @@ -20,7 +20,7 @@ type P47SceneDetailTests () = assertInt 4 (snd SceneDetail.shadowOffsetPx) "shadow dy" // alpha strictly decreases with distance and never goes negative. let alphas = [ for d in 1 .. 6 -> SceneDetail.reflectionAlphaAt d ] - Assert.IsTrue(alphas |> List.forall (fun a -> a >= 0), "reflection alpha must be >= 0") + Assert.IsTrue(alphas |> List.forall (fun a -> a >= 96), "reflection alpha must stay legible (>= 96)") Assert.IsTrue(alphas.[0] > alphas.[1] && alphas.[1] > alphas.[2], "alpha must decrease with distance") // wobble is exactly the 3-phase water ramp mapped to -1/0/+1 and is deterministic. for tick in [ 0L; 32L; 64L; 96L ] do @@ -40,14 +40,26 @@ type P47SceneDetailTests () = Assert.IsTrue(not (List.isEmpty sources), "the generator map must have bank light sources") let streaks = SceneDetail.reflectionStreaks map Assert.IsTrue(not (List.isEmpty streaks), "there must be at least one reflection streak") - for (x, y, alpha) in streaks do - Assert.IsTrue(SceneDetail.isWater map x y, sprintf "reflection (%d,%d) must sit on water" x y) - Assert.IsTrue(alpha > 0, "reflection alpha must be positive") - // every streak sits directly below its source within reflectionRange. + for (x, y, alpha, _) in streaks do + Assert.IsTrue(SceneDetail.isWaterSurface map x y, sprintf "reflection (%d,%d) must sit on a reflective surface" x y) + Assert.IsTrue(alpha >= 96, "reflection alpha must stay legible (>= 96)") + // every streak sits in the same column as a source, within stream range + bridge/own-structure gap. let sourceSet = sources |> Set.ofList - for (x, y, _) in streaks do - Assert.IsTrue([ 1 .. SceneDetail.reflectionRange ] |> List.exists (fun d -> Set.contains (x, y - d) sourceSet), - sprintf "reflection (%d,%d) must be under a source" x y) + for (x, y, _, _) in streaks do + Assert.IsTrue( + [ 1 .. SceneDetail.reflectionRange + SceneDetail.reflectionGap ] + |> List.exists (fun d -> Set.contains (x, y - d) sourceSet), + sprintf "reflection (%d,%d) must be in the column below a source" x y) + // each light source keeps its kind so the renderer can tint per kind. + for (_, _, kind) in SceneDetail.lightSources map do + Assert.IsTrue(kind = SceneDetail.BridgeLantern || kind = SceneDetail.RoadLantern || kind = SceneDetail.RedLantern, + "light source kind must be one of the three known kinds") + // at least one source must produce a full >= 3 tile vertical reflection (leader acceptance). + let longest = + SceneDetail.lightSources map + |> List.map (fun (x, y, _) -> SceneDetail.reflectionLength map x y) + |> List.fold max 0 + Assert.IsTrue(longest >= 3, sprintf "the longest reflection must span >= 3 tiles, got %d" longest) [] member _.BankReedsAndFloatersAreDenseAndDeterministic () = -- cgit v1.2.3