summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop.Tests/P78NightAmbienceTests.fs
blob: 2a0679851a77966e85c2e886ea8e1fd0b8e8ced6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
namespace LivingVillage.Desktop.Tests

open Microsoft.VisualStudio.TestTools.UnitTesting
open LivingVillage.Desktop

/// P78 夜晚氛围与场景细节回归(纯函数层):
///  * 夜帧水面逐格微光斑:只落在水面/水田、帧号驱动且确定性、昼夜两档(白天恒 0);
///  * 炊烟:生成器世界每户一个烟源、夜帧 alpha/尺寸更大、升腾摇晃有界且确定性;
///  * 桥头灯柱近圈光晕:半径恒为 1 tile(窄光晕),复用既有灯柱瓦片。
[<TestClass>]
type P78NightAmbienceTests () =

    let map = MapGen.generate (MapGen.defaultParams 42UL)

    [<TestMethod>]
    member _.WaterGlintsAreNightOnlyDeterministicAndTwoTier () =
        let glints = SceneDetail.waterGlintTiles map
        Assert.IsTrue(not (List.isEmpty glints), "生成器世界须有水面光斑候选格")
        for (x, y) in glints do
            Assert.IsTrue(SceneDetail.isWaterSurface map x y, sprintf "光斑 (%d,%d) 必须落在水面/水田" x y)
        // 白天恒定关闭(零回归),夜帧两个亮度档。
        for phase in 0 .. SceneDetail.waterGlintPhaseCount - 1 do
            Assert.IsTrue((SceneDetail.waterGlintAlpha 0.0f phase) = 0, "白天光斑必须为 0(零回归)")
        let nightBright = SceneDetail.waterGlintAlpha 1.0f 0
        let nightDim = SceneDetail.waterGlintAlpha 1.0f 1
        Assert.IsTrue(nightBright > 0, "夜帧光斑须可见")
        Assert.IsTrue(nightBright > nightDim && nightDim > 0, "光斑须有两档呼吸层次")
        // 帧号驱动且确定性。
        for tick in [ 0L; 8L; 16L; 32L ] do
            let phase = SceneDetail.waterGlintPhase tick 3 5
            Assert.IsTrue(phase >= 0 && phase < SceneDetail.waterGlintPhaseCount, "相位越界")
            Assert.IsTrue((SceneDetail.waterGlintPhase tick 3 5) = phase, "相位须确定性")
            Assert.IsTrue(abs (SceneDetail.waterGlintOffset tick 3 5) <= 1, "光斑位移须有界 ±1px")
        Assert.IsTrue(
            (SceneDetail.waterGlintPhase 0L 3 5) <> (SceneDetail.waterGlintPhase 8L 3 5)
            || (SceneDetail.waterGlintPhase 8L 3 5) <> (SceneDetail.waterGlintPhase 16L 3 5)
            || (SceneDetail.waterGlintPhase 16L 3 5) <> (SceneDetail.waterGlintPhase 24L 3 5),
            "光斑相位须随帧号变化")

    [<TestMethod>]
    member _.SmokeIsProminentAtNightAndDeterministic () =
        let sources = SceneDetail.smokeSourceTiles map
        let expected = (map.Buildings @ map.Farmhouses) |> List.length
        Assert.IsTrue(not (List.isEmpty sources), "生成器世界须有炊烟源(民居/农舍)")
        Assert.IsTrue(List.length sources <= expected, "去重后炊烟源数不得超过户数")
        let dayAlpha = SceneDetail.smokeAlphaAt 0.0f
        let nightAlpha = SceneDetail.smokeAlphaAt 1.0f
        Assert.IsTrue(dayAlpha > 0, "白天炊烟仍须可辨")
        Assert.IsTrue(nightAlpha > dayAlpha, "夜帧炊烟须更醒目")
        Assert.IsTrue((SceneDetail.smokeCellSize 1.0f) > (SceneDetail.smokeCellSize 0.0f), "夜帧炊烟体量须更大")
        for tick in [ 0L; 24L; 48L ] do
            let frame = SceneDetail.smokeFrame tick
            Assert.IsTrue(frame >= 0 && frame <= 2, "炊烟需三相位")
            let sway, rise = SceneDetail.smokeDrift tick 7
            Assert.IsTrue(abs sway <= 1, "炊烟摇曳须有界 ±1px")
            Assert.IsTrue(rise <= 0 && rise >= -4, "炊烟只向上且位移有界")
            Assert.IsTrue((SceneDetail.smokeDrift tick 7) = (sway, rise), "炊烟位移须确定性")

    [<TestMethod>]
    member _.BridgeHaloIsNarrowAndMatchesLanternTiles () =
        Assert.IsTrue((SceneDetail.bridgeHaloRadiusTiles = 1), "桥头光晕须为窄光晕(1 tile)")
        Assert.IsTrue((SceneDetail.bridgeLanternTiles map) = (VillageArt.bridgeLanternTiles map), "桥头灯柱瓦片须同源")