summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/Game.fs
diff options
context:
space:
mode:
Diffstat (limited to 'src/LivingVillage.Desktop/Game.fs')
-rw-r--r--src/LivingVillage.Desktop/Game.fs87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop/Game.fs b/src/LivingVillage.Desktop/Game.fs
index 6b52225..862e1de 100644
--- a/src/LivingVillage.Desktop/Game.fs
+++ b/src/LivingVillage.Desktop/Game.fs
@@ -337,6 +337,12 @@ type LivingVillageGame() as this =
let mutable p64PendingName = ""
let mutable p64Pending = false
let mutable p64MoveFrames = 0
+ // P65 证据钩子(职业切片五):货郎真实开局 → 与村民真实闲聊写入既有 World.Rumors →
+ // 真实 Interact 打开对话菜单(拍菜单帧)→ 选「提议交易」询价,拍带中文行情短答的帧。
+ let p65ShotMode = Environment.GetEnvironmentVariable("LV_P65_SHOT") = "1"
+ let mutable p65Step = 0
+ let mutable p65PendingName = ""
+ let mutable p65Pending = false
// P45 证据钩子:LV_P45_SHOT=1 时拍角色 idle / 行走朝下 / 行走朝右 三帧(真实游戏截图)。
let p45ShotMode = Environment.GetEnvironmentVariable("LV_P45_SHOT") = "1"
let mutable p45Step = 0
@@ -1158,6 +1164,75 @@ type LivingVillageGame() as this =
p64PendingName world.Tick world.Avatar.Pos.X world.Avatar.Pos.Y camera.X camera.Y m5View.HomeMode
p64Step <- p64Step + 1
+ /// P65 证据:货郎真实开局 → 闲聊写入既有谣言池 → 真实 Interact 开菜单 → 提议交易询价。
+ member private this.PrepareP65Shot () =
+ let setHour (hour: float) =
+ let tick = M6Presentation.resolveStartTick (Some hour) false
+ world <- { world with Tick = tick; Time = float tick * Sim.dtSeconds }
+ let ask (command: M5Command) =
+ let nextWorld, nextView = M5Interaction.apply command world m5View
+ world <- nextWorld
+ m5View <- nextView
+ let placeAtNpc () =
+ let npc = world.Npcs.[0]
+ world <- { world with Avatar = { world.Avatar with Pos = npc.Pos } }
+ if not p65Pending then
+ match p65Step with
+ | 0 ->
+ setHour 12.0
+ placeAtNpc ()
+ ask M5Command.Interact
+ this.CenterCamera()
+ p65PendingName <- "p65-menu"
+ p65Pending <- true
+ | 1 ->
+ // 真实闲聊一次:把玩家对话写入既有 World.Rumors(最新在前),供询价读取。
+ ask M5Command.Intent1
+ placeAtNpc ()
+ ask M5Command.Interact
+ // 非货郎回归:同世界跑农夫 Interact + Intent3,应仍得旧 dialogue 文案(无 inquiry|)。
+ let farmerView =
+ { M5Interaction.initial with
+ Task = Some(Occupation.stateOf Occupation.Farmer)
+ Seed = m5View.Seed }
+ let farmerWorld, farmerOpen = M5Interaction.apply M5Command.Interact world farmerView
+ let _, farmerAnswered = M5Interaction.apply M5Command.Intent3 farmerWorld farmerOpen
+ printfn "p65-regression status=%s" farmerAnswered.Status
+ // 同一世界两次查询:证明同输入逐字符串一致(禁随机)。
+ let answer1 = Occupation.marketInquiryText (Some Occupation.Peddler) Sim.OfferTrade world
+ let answer2 = Occupation.marketInquiryText (Some Occupation.Peddler) Sim.OfferTrade world
+ printfn
+ "p65-inquiry rumors=%d fresh=%d hit=%b text1=%s text2=%s equal=%b"
+ world.Rumors.Length
+ (Occupation.freshReliableRumors world |> List.length)
+ (Occupation.inquiryRumor world |> Option.isSome)
+ (answer1 |> Option.defaultValue "<none>")
+ (answer2 |> Option.defaultValue "<none>")
+ (answer1 = answer2)
+ p65Step <- p65Step + 1
+ | 2 ->
+ ask M5Command.Intent3
+ p65PendingName <- "p65-answer"
+ p65Pending <- true
+ | _ ->
+ printfn "p65-shot=done"
+ this.Exit()
+
+ /// P65 证据:落盘并打印帧名/面板/状态,供 analyze 核验「货郎 status=inquiry|...」。
+ member private this.CaptureP65Shot () =
+ if p65Pending then
+ p65Pending <- false
+ System.IO.Directory.CreateDirectory recordDirectory |> ignore
+ this.SaveBackBuffer(sprintf "%s/%s.png" recordDirectory p65PendingName)
+ printfn
+ "p65-shot=%s panel=%s avatar=(%.0f,%.0f) status=%s"
+ p65PendingName
+ (M5Interaction.panelName m5View)
+ world.Avatar.Pos.X
+ world.Avatar.Pos.Y
+ m5View.Status
+ p65Step <- p65Step + 1
+
member private this.PrepareP45Shot () =
let baseTick = M6Presentation.resolveStartTick (Some 12.0) false
let setTick (tick: int64) =
@@ -2163,6 +2238,16 @@ type LivingVillageGame() as this =
else this.DispatchMenuInput Confirm
elif menu.Page = Playing then
this.PrepareP64Shot()
+ elif p65ShotMode then
+ if menu.Page = MainMenu then
+ this.DispatchMenuInput Confirm
+ elif menu.Page = OccupationSelect then
+ let targetIndex =
+ MenuState.occupationOptions |> List.findIndex (fun option -> option = Some Occupation.Peddler)
+ if menu.Selected <> targetIndex then this.DispatchMenuInput Down
+ else this.DispatchMenuInput Confirm
+ elif menu.Page = Playing then
+ this.PrepareP65Shot()
elif p45ShotMode then
if menu.Page = MainMenu then
this.DispatchMenuInput Confirm
@@ -2639,6 +2724,8 @@ type LivingVillageGame() as this =
this.CaptureP62Shot()
if p64ShotMode && menu.Page = Playing then
this.CaptureP64Shot()
+ if p65ShotMode && menu.Page = Playing then
+ this.CaptureP65Shot()
if p45ShotMode && menu.Page = Playing then
this.CaptureP45Shot()
if p46ShotMode then