diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-22 16:33:03 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-22 16:33:03 +0800 |
| commit | 9821b54ff2a77539898b62471d79dc4685b59cad (patch) | |
| tree | ffd5fb63883dd05b80fca5729af74be41df3a04d /src/LivingVillage.Kernel | |
| parent | 0539bba17c260f6a4b51d3cefddac0ff448c19bc (diff) | |
| download | living-village-9821b54ff2a77539898b62471d79dc4685b59cad.tar.gz | |
feat(kernel,desktop): P31 step3 story annals + identity entry + glyph atlas
- Sim.AnnalKind gains StoryAnnal (summary lives in the existing Summary
field); WorldSave v3 serializes it with the new 'story' token. v1/v2
saves never contain the token and stay byte-identical; v3 save -> load
-> save roundtrips byte-for-byte (tested).
- Occupation.Story.identitySummaryOf: plain chronicle-style identity line
written to the yearbook at game start (design section 3), e.g. yi-da-yu-wei-sheng.
- Desktop: story summaries render in the chronicle panel; StartNewGame
appends the identity annal; chooseIntent now routes responses through
Occupation.biasResponse and advances the storyline (one stage per
player dialogue) with the summary appended as a StoryAnnal.
- M5View gains Seed (world seed source for the story start-day hash).
- Chinese copy synced into requiredUiLabels; cjk-glyphs.txt +
CjkGlyphAtlas.characterTable extended 238 -> 307 glyphs (384x480),
atlas regenerated with the deterministic script.
- 4 new kernel tests (115 -> 119); performance digest unchanged.
Diffstat (limited to 'src/LivingVillage.Kernel')
| -rw-r--r-- | src/LivingVillage.Kernel/Occupation.fs | 36 | ||||
| -rw-r--r-- | src/LivingVillage.Kernel/Sim.fs | 2 | ||||
| -rw-r--r-- | src/LivingVillage.Kernel/WorldSave.fs | 2 |
3 files changed, 26 insertions, 14 deletions
diff --git a/src/LivingVillage.Kernel/Occupation.fs b/src/LivingVillage.Kernel/Occupation.fs index 00cd2e9..c207395 100644 --- a/src/LivingVillage.Kernel/Occupation.fs +++ b/src/LivingVillage.Kernel/Occupation.fs @@ -343,18 +343,26 @@ module Occupation = let endingTextOf (kind: Kind) (ending: Ending) : string = match kind, ending with - | Farmer, Warm -> "雨水与年成有了结果:乡邻都说雨水匀,今年差不了。" - | Farmer, Plain -> "雨水与年成有了结果:雨水尚可,年成将就,照旧耕作。" - | Farmer, Distant -> "雨水与年成有了结果:问不出准信,年成只能看天。" - | Fisher, Warm -> "水位与收成有了结果:乡邻说得真切,水位稳了,收成坏不了。" - | Fisher, Plain -> "水位与收成有了结果:众说平常,水位尚可,收成将就。" - | Fisher, Distant -> "水位与收成有了结果:问了几家都淡淡的,水情还得自己看。" - | Peddler, Warm -> "新货的路子有了结果:乡邻热心指路,新货不愁卖。" - | Peddler, Plain -> "新货的路子有了结果:说法平常,先小量试卖。" - | Peddler, Distant -> "新货的路子有了结果:各家都淡淡的,路子还得自己闯。" - | Scholar, Warm -> "庙前的争论有了结果:各说各理,事有分晓。" - | Scholar, Plain -> "庙前的争论有了结果:众说纷纭,暂无定论。" - | Scholar, Distant -> "庙前的争论有了结果:无人理会,先记在册上。" + | Farmer, Warm -> "雨水与年成有了结果:乡邻都说雨水匀,今年差不了" + | Farmer, Plain -> "雨水与年成有了结果:雨水尚可,年成将就,照旧耕作" + | Farmer, Distant -> "雨水与年成有了结果:问不出准信,年成只能看天" + | Fisher, Warm -> "水位与收成有了结果:乡邻说得真切,水位稳了,收成坏不了" + | Fisher, Plain -> "水位与收成有了结果:众说平常,水位尚可,收成将就" + | Fisher, Distant -> "水位与收成有了结果:问了几家都淡淡的,水情还得自己看" + | Peddler, Warm -> "新货的路子有了结果:乡邻热心指路,新货不愁卖" + | Peddler, Plain -> "新货的路子有了结果:说法平常,先小量试卖" + | Peddler, Distant -> "新货的路子有了结果:各家都淡淡的,路子还得自己闯" + | Scholar, Warm -> "庙前的争论有了结果:各说各理,事有分晓" + | Scholar, Plain -> "庙前的争论有了结果:众说纷纭,暂无定论" + | Scholar, Distant -> "庙前的争论有了结果:无人理会,先记在册上" + + /// §3 身份条目:开局写入年鉴(如「以打渔为生」),不带主语、沿年鉴短句风格。 + let identitySummaryOf (kind: Kind) : string = + match kind with + | Farmer -> "以耕田为生" + | Fisher -> "以打渔为生" + | Peddler -> "以贩货为生" + | Scholar -> "以读书为生" /// 用一次玩家对话推进剧情线:同输入两次结果一致。 /// 返回(新状态, 应写入年鉴的摘要文本 option);无门控命中时原样返回。 @@ -366,10 +374,10 @@ module Occupation = match state.StoryStage with | 0 when day >= startDay -> { state with StoryStage = 1 }, - Some (sprintf "接了件事:%s,得去村里多问问。" (lineNameOf kind)) + Some (sprintf "接了件事:%s,得去村里多问问" (lineNameOf kind)) | 1 when day >= startDay + 1L -> { state with StoryStage = 2 }, - Some "走访了几户人家,改日再问。" + Some "走访了几户人家,改日再问" | 2 when day >= startDay + 2L -> let ending = endingOf (relationMeanToPlayer world) { state with StoryStage = 3 }, diff --git a/src/LivingVillage.Kernel/Sim.fs b/src/LivingVillage.Kernel/Sim.fs index 348a60e..0ead9d5 100644 --- a/src/LivingVillage.Kernel/Sim.fs +++ b/src/LivingVillage.Kernel/Sim.fs @@ -153,6 +153,8 @@ module Sim = | DialogueAnnal of DialogueOutcome | RumorAnnal of RumorEvent | TradeAnnal of InteractionEvent + /// P-d 剧情线/身份条目:文案直接落在 Summary(存档 token "story",仅带职业的 v3 存档产生)。 + | StoryAnnal type AnnalEntry = { Tick: int64 diff --git a/src/LivingVillage.Kernel/WorldSave.fs b/src/LivingVillage.Kernel/WorldSave.fs index b3bdfa9..7f724a3 100644 --- a/src/LivingVillage.Kernel/WorldSave.fs +++ b/src/LivingVillage.Kernel/WorldSave.fs @@ -390,12 +390,14 @@ module WorldSave = | TradeAnnal event -> add tokens "trade" writeInteraction tokens event + | StoryAnnal -> add tokens "story" let private readAnnalKind (reader: TokenReader) label = match reader.Take(label) with | "dialogue" -> DialogueAnnal(readDialogueOutcome reader (label + ".outcome")) | "rumor" -> RumorAnnal(readRumor reader (label + ".rumor")) | "trade" -> TradeAnnal(readInteraction reader (label + ".event")) + | "story" -> StoryAnnal | _ -> invalid (sprintf "invalid %s" label) let private writeAnnal tokens (value: AnnalEntry) = |
