diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-29 08:09:12 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-29 08:09:12 +0800 |
| commit | 247d0bc083dffc648f043176eabf9bd4036f19e7 (patch) | |
| tree | 78c11e2f923c7b9322b64dc81ccae86fc5bbceea /src/LivingVillage.Desktop/WorldBootstrap.fs | |
| parent | cf6672ee1d6cf7013472f3bd91e68990f23750e8 (diff) | |
| download | living-village-247d0bc083dffc648f043176eabf9bd4036f19e7.tar.gz | |
p66: 每日任务目标具体化 TargetNpc/TargetTile 定点
- Kernel Occupation:TaskTargets + targetNpcOf/targetTileOf + dailyTaskOfWith/
refreshTodayWith/refreshStateWith(splitmix 同源定点,候选排序消除顺序依赖,禁随机)
- 仅既有 satisfiesCompletion 会读目标的模板定点:帮工→TargetNpc、翻土→TargetTile;
其余 8 模板目标保持 None(不改完成语义)
- Desktop WorldBootstrap:reachableTargets(世界 NPC + 样板菜地瓦片)+
occupationStateForWorld/refreshOccupationTodayWorld;Game 开局/跨日/证据路径切换
- 历史入口 dailyTaskOf/refreshState/occupationStateFor 保留为空候选通配包装(逐字节不变)
- 红先 P66TaskTargetTests(8 例):同 seed 幂等、跨 seed 落在可达集合、候选顺序无关、
历史通配回归、帮工/翻土定点门控完成、跨日重定点、v3 round-trip + v2 基线
- scripts/p66-target-report.fsx + docs/evidence/p66-analysis.txt(PASS)
- Desktop 328/328,Kernel 119/119;digest 953775FA…7F6C ×3 PASS;Sim.fs 未动
Diffstat (limited to 'src/LivingVillage.Desktop/WorldBootstrap.fs')
| -rw-r--r-- | src/LivingVillage.Desktop/WorldBootstrap.fs | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop/WorldBootstrap.fs b/src/LivingVillage.Desktop/WorldBootstrap.fs index e75855f..e0ac037 100644 --- a/src/LivingVillage.Desktop/WorldBootstrap.fs +++ b/src/LivingVillage.Desktop/WorldBootstrap.fs @@ -29,6 +29,45 @@ module WorldBootstrap = let refreshOccupationToday (seed: uint64) (state: Occupation.State) (nowTick: int64) : Occupation.State = Occupation.refreshState seed (Occupation.occupationSeedOf state.Profile.Kind) state.Profile.Kind nowTick state + // ---- P66 任务目标具体化(design §2.4-3)---- + // 可达候选集合完全由世界/样板场景派生;Kernel 只做纯 hash 定点。 + /// 可达 NPC:世界中实际存在的村民 id(顺序稳定)。 + /// 可达瓦片:样板场景的菜地(VegetableGarden)世界瓦片 —— 设计口径「自家地块」, + /// 跨 legacy/riverscape 一致且必在陆地上。 + let reachableTargets (world: World) : Occupation.TaskTargets = + let npcs = world.Npcs |> Array.map (fun npc -> npc.Id) |> Array.toList + let tiles = + VillagePresentation.scene.Elements + |> List.choose (fun element -> + match element.Prop with + | VillagePresentation.VegetableGarden -> + let tile = VillagePresentation.worldTileForSceneTile element.Position + Some(tile.X, tile.Y) + | _ -> None) + { Npcs = npcs; Tiles = tiles } + + /// 新档职业状态(P66):按真实世界的可达候选集合定点当日任务。 + let occupationStateForWorld (seed: uint64) (kind: Occupation.Kind) (nowTick: int64) (world: World) : Occupation.State = + let baseState = Occupation.stateOf kind + { baseState with + Today = + Occupation.dailyTaskOfWith + (reachableTargets world) + seed + (Occupation.occupationSeedOf kind) + (Occupation.dayIndexOf nowTick) + kind } + + /// 跨日刷新(P66):按真实世界的可达候选集合重算跨日当天任务;同日原样保留。 + let refreshOccupationTodayWorld (seed: uint64) (state: Occupation.State) (nowTick: int64) (world: World) : Occupation.State = + Occupation.refreshStateWith + (reachableTargets world) + seed + (Occupation.occupationSeedOf state.Profile.Kind) + state.Profile.Kind + nowTick + state + /// 开局身份年鉴(design §3):带职业建世界后写入一条 `StoryAnnal`「以…为生」, /// 形成个人传记线。Game 与测试共用同一口径。 let appendIdentityAnnal (state: Occupation.State) (world: World) : World = |
