summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Kernel/Sim.fs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-22 16:16:40 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-22 16:16:40 +0800
commit6c2f180cc7c8315e32d88cbe5d44928d495fe473 (patch)
treeb882d707e1ac1b31c885b19e1f2ce31534448c52 /src/LivingVillage.Kernel/Sim.fs
parent2f915a48837039dc772d7fa25b83b34a707922fd (diff)
downloadliving-village-6c2f180cc7c8315e32d88cbe5d44928d495fe473.tar.gz
feat(kernel): P31 step1 occupation dialogue response bias
- Occupation.biasResponse: deterministic pure remap over Sim.responseFor; no occupation = byte-identical pass-through (all intents x personalities). farmer AskHelp Refused->Helpful; fisher SmallTalk Reserved->Friendly; peddler SmallTalk Reserved->Bargaining; scholar Joke fully overridden to Reserved (documented total-override semantics, opposite of personality). - Sim.responseFor made public (same pure function, reused as the base path). - Sim.chooseDialogueWith: extracted body of chooseDialogue with an injectable respond function; chooseDialogue keeps identity semantics unchanged. - Sim.appendAnnal made public for the upcoming story annal writes. - 9 new kernel tests (92 -> 101); performance digest unchanged.
Diffstat (limited to 'src/LivingVillage.Kernel/Sim.fs')
-rw-r--r--src/LivingVillage.Kernel/Sim.fs19
1 files changed, 15 insertions, 4 deletions
diff --git a/src/LivingVillage.Kernel/Sim.fs b/src/LivingVillage.Kernel/Sim.fs
index 5c4e107..348a60e 100644
--- a/src/LivingVillage.Kernel/Sim.fs
+++ b/src/LivingVillage.Kernel/Sim.fs
@@ -299,7 +299,8 @@ module Sim =
let clamp (v: float32) (lo: float32) (hi: float32) : float32 = if v < lo then lo elif v > hi then hi else v
- let private appendAnnal (entry: AnnalEntry) (world: World) : World =
+ /// P-d 起对调用方公开(剧情线年鉴写入复用同一裁剪口径,语义不变)。
+ let appendAnnal (entry: AnnalEntry) (world: World) : World =
{ world with Annals = (entry :: world.Annals) |> List.truncate maxAnnalEntries }
let hungerDecayPerTick = 0.0012f
@@ -765,7 +766,8 @@ module Sim =
{ Target = target
Options = dialogueOptions })
- let private responseFor (intent: DialogueIntent) (personality: Personality) : DialogueResponse =
+ /// 纯人格回应函数;P-d 起对调用方公开,供 Occupation.biasResponse 复用原口径。
+ let responseFor (intent: DialogueIntent) (personality: Personality) : DialogueResponse =
match intent with
| SmallTalk -> if personality.Extraversion >= 0.5f then Friendly else Reserved
| AskHelp -> if personality.Honesty >= 0.4f then Helpful else Refused
@@ -782,7 +784,12 @@ module Sim =
sprintf "rumor tick=%d source=%A narrator=%A receiver=%A depth=%d"
rumor.Tick rumor.Source rumor.Narrator rumor.Receiver rumor.Depth
- let chooseDialogue (target: NpcId) (intent: DialogueIntent) (world: World) : DialogueResult =
+ let chooseDialogueWith
+ (respond: DialogueIntent -> Personality -> DialogueResponse)
+ (target: NpcId)
+ (intent: DialogueIntent)
+ (world: World)
+ : DialogueResult =
match findNpcIndex target world.Npcs with
| None -> DialogueRejected(DialogueTargetNotFound, world)
| Some targetIndex ->
@@ -794,7 +801,7 @@ module Sim =
elif not (dialogueAvailable targetNpc) then
DialogueRejected(DialogueTargetUnavailable, world)
else
- let response = responseFor intent targetNpc.Mind.Personality
+ let response = respond intent targetNpc.Mind.Personality
let outcome =
{ Tick = world.Tick
Actor = playerId
@@ -842,6 +849,10 @@ module Sim =
withRumorAnnal
DialogueSucceeded(outcome, withDialogueAnnal)
+ /// 既有入口:无职业偏差的人格回应路径(identity,与历史行为逐字节一致)。
+ let chooseDialogue (target: NpcId) (intent: DialogueIntent) (world: World) : DialogueResult =
+ chooseDialogueWith responseFor target intent world
+
let annalText (world: World) : string =
let rows =
world.Annals