From dd0907573e13981035a5ff264831edb0534e3496 Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Mon, 21 Sep 2026 02:10:02 +0800 Subject: feat(desktop): LV_AUTOPLAY_SAMPLE 情境演示脚本 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 SampleScript 状态机:进门→内景驻留→出门→走向 NPC →打开对话→发送意图→关闭面板→走开,超时兜底进 SampleComplete。 Game.fs 读取 LV_AUTOPLAY_SAMPLE=1 切换 sample 模式(2x 模拟、 关闭旧 step 倍率、UpdateMenu 常开、独立 UpdatePlaying 分发)。 SampleTests 覆盖首步行走、进门、完整巡游(42/42 通过)。 --- src/LivingVillage.Desktop.Tests/SampleTests.fs | 60 ++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/LivingVillage.Desktop.Tests/SampleTests.fs (limited to 'src/LivingVillage.Desktop.Tests/SampleTests.fs') diff --git a/src/LivingVillage.Desktop.Tests/SampleTests.fs b/src/LivingVillage.Desktop.Tests/SampleTests.fs new file mode 100644 index 0000000..4c833b5 --- /dev/null +++ b/src/LivingVillage.Desktop.Tests/SampleTests.fs @@ -0,0 +1,60 @@ +namespace LivingVillage.Desktop.Tests + +open System +open Microsoft.VisualStudio.TestTools.UnitTesting +open LivingVillage.Kernel +open LivingVillage.Kernel.Sim +open LivingVillage.Desktop +open LivingVillage.Desktop.VillagePresentation + +[] +type SampleTests () = + + let areEqual (expected: 'T) (actual: 'T) = Assert.AreEqual<'T>(expected, actual) + + let freshWorld () = Sim.initialWorldN 42UL Sim.npcCount + + let freshView (world: World) = M5Interaction.refreshPrompt world M5Interaction.initial + + let driveUntil (maxFrames: int) (stop: SampleScript.SampleState -> bool) = + let mutable world = freshWorld () + let mutable view = freshView world + let mutable state = SampleScript.initial + let mutable frames = 0 + while frames < maxFrames && not (stop state) do + let nextWorld, nextView, nextState = SampleScript.runFrame world view state + world <- nextWorld + view <- nextView + state <- nextState + frames <- frames + 1 + world, view, state, frames + + [] + member _.SampleScriptStartsWalkingTowardHomeDoor () = + let spawnWorld = freshWorld () + let movedWorld = + List.fold (fun w _ -> Sim.step { Input = { MoveX = -1.0f; MoveY = 0.0f } } w) spawnWorld [ 1..12 ] + let view = freshView movedWorld + let state, action = SampleScript.step movedWorld view SampleScript.initial + areEqual SampleScript.ApproachDoor state.Stage + match action with + | SampleScript.MoveTo target -> areEqual SampleScript.doorWorldCenter target + | other -> Assert.Fail(sprintf "expected MoveTo toward the door, got %A" other) + + [] + member _.SampleScriptEntersTheHomeThroughTheDoor () = + let _world, view, state, frames = driveUntil 2400 (fun s -> s.Stage = SampleScript.InspectInterior) + Assert.IsTrue( + frames < 2400, + sprintf "home entry never confirmed; stage=%A frames=%d" state.Stage frames) + areEqual (Inside (HomeId 1)) view.HomeMode + + [] + member _.SampleScriptCompletesTheVillageTourWithADialogue () = + let _world, view, state, frames = + driveUntil 22000 (fun s -> s.Stage = SampleScript.SampleComplete) + areEqual SampleScript.SampleComplete state.Stage + Assert.IsFalse(state.TimedOut, sprintf "tour timed out; stage=%A frames=%d" state.Stage frames) + Assert.IsTrue(state.DialogueTarget.IsSome, "no dialogue was opened during the tour") + areEqual Outside view.HomeMode + areEqual WorldPanel view.Panel -- cgit v1.2.3