summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Kernel/Occupation.fs
Commit message (Collapse)AuthorAgeFilesLines
* p66: 每日任务目标具体化 TargetNpc/TargetTile 定点Somhairle H. Marisol6 days1-9/+65
| | | | | | | | | | | | | | - 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 未动
* p65: 职业切片五 货郎打听行情读 World.Rumors(中文行情短答 ↵Somhairle H. Marisol6 days1-0/+61
| | | | | | | | | | | | | + 稿证据) - Kernel Occupation 新增 freshReliableRumors/inquiryRumor/marketInquiryText(纯判定+文案, 对齐 Sim.latestRumorFor 新鲜度/可信度口径,全序命中规则,禁随机;不改 Sim.fs) - Desktop chooseIntent:货郎 OfferTrade 读对话前谣言池,Status=inquiry|<短答>;statusLabel 透出 - 真字补 17 字(东头西北巷口盐巴米布茶柴涨两文落些)并重出 atlas(340 字/384x528) - 红先 P65RumorInquiryTests(6 例):命中/幂等/陈旧·微弱·空池/仅货郎/非货郎回归逐字节/ save v2 头不变+v3 round-trip/穷举组合无缺字 - LV_P65_SHOT 钩子 + scripts/analyze-p65.py + docs/evidence/p65-*(PASS) - Desktop 320/320,Kernel 119/119;digest 953775FA…7F6C ×3 PASS
* p55: ↵Somhairle H. Marisol6 days1-5/+83
| | | | 当日任务经济闭环——设计口径物品报酬入账(夜捕鱼×2/送粮食物×1, 其余不发) + 连续完成天数(streak 跨日保留/漏完成清零) + v3 streak 尾段与 save(None) 兼容 + LV_P55_SHOT 证据
* p51: 职业系统实现首切片——开局钱/体力/背包侧车 + ↵Somhairle H. Marisol6 days1-2/+13
| | | | 当日任务/跨日刷新 + StartNewGameWith 读回(design §2.4-1)
* feat(kernel,desktop): P31 step3 story annals + identity entry + glyph atlasSomhairle H. Marisol12 days1-14/+22
| | | | | | | | | | | | | | | | | | - 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.
* feat(kernel): P31 step2 story stage state machineSomhairle H. Marisol12 days1-0/+103
| | | | | | | | | | | | | | | - Occupation.Story: three-segment arc per occupation (accept task -> visit households -> conclude), driven one stage per player dialogue with day gates derived from the same splitmix pattern as the daily task pool (start day = hash(seed ^ storySeed, day 0) mod 3 + 2, range [2,4]). - relationMeanToPlayer: decayed valence mean over acquainted NPCs only (same decay formula as Sim.relationMatrix); no acquaintances = 0. - Three endings (warm/plain/distant) chosen by deterministic thresholds (>=0.3 / >=0.0 / <0); ending text is fixed at the concluding dialogue. - onDialogue returns (state, summary text option) for the caller to write into the yearbook; StoryStage itself is unchanged (0..3) and already roundtrips through the existing v3 occupation segment. - 14 new kernel tests (101 -> 115); performance digest unchanged.
* feat(kernel): P31 step1 occupation dialogue response biasSomhairle H. Marisol12 days1-0/+31
| | | | | | | | | | | | | - 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.
* feat(occupation): P15 补齐货郎/书生各 2 条每日任务模板 + ↵Somhairle H. Marisol13 days1-6/+55
| | | | | | | | | | | | | | 既有事件通道信号桥(Kernel 纯函数 TDD) - TaskTemplateId 扩出 BuyGoods(收货)/Resell(转卖)/ObserveNotes(观察记事)/ReasonDebate(论理), taskPoolOf 货郎=[收货,转卖]、书生=[观察记事,论理],四职业池均非空。 - TaskSignal 增 Purchased(玩家买入)/Observed(观察),satisfiesCompletion 给出四模板完成判定; 新增 occupationSeedOf/refreshToday(跨日才重生成,同日含 Done/Failed 终态保留)。 - signalOfInteraction/advanceTask:仅 playerId 发起的 DialogueEvent/TradeEvent 产生信号, NPC 互动不派任务;Offered 须先 acceptTask,终态不可复活。WorldSave 模板 token 双向同步。 - 测试 83 全绿(新增 6:池非空、货郎书生逐日池内确定、模板中文名、完成信号正负、 事件桥含玩家买/卖与 NPC 忽略、既有 DialogueEvent→accept→Done 全链路、refreshToday 逐日)。 - 不动 Sim.step 数值路径;旧档 v3 模板 token 仅新增合法值,未知模板仍拒绝。
* feat(occupation): P12 ↵Somhairle H. Marisol13 days1-0/+21
| | | | 报价偏置纯函数——货郎买卖±3.00%/书生解读±1.00%,4位定点基点,默认无职业=旧行为(TDD 6例)
* feat(occupation): P11 存档 v3 today-task 尾段(annals 后追加)+ ↵Somhairle H. Marisol13 days1-9/+11
| | | | | | 双向兼容 Occupation.State 增 Today: DailyTask option(State 声明移至 DailyTask 之后;TaskToken 保留为 v3 前缀占位扩展位)。WorldSave:saveWith 有任务时在 annals 之后追加尾段 task-today|<template>|<state>|<offered>|<due>|npc-none/some|tile-none/some;无任务/无职业不追加(默认 None = 旧行为,v2 逐字节不变)。load 重构为内部 parse 返回 (World, Occupation.State option):尾段可选——旧 v3(P10 版式无尾段)新 reader 读出 Today=None;v1/v2 无任务;尾段后多余 token 或未知模板 token 拒绝(不吞档)。loadFromFileWith 顺手修正:不再经 stateOf 重置,前缀 task/stage 与 Today 全量保真。5 例测试:尾段位置(marker 在 annal 之后)+ 全字段 round-trip + 重存逐字节一致、无任务 v3 旧版式、v1/v2 无尾段 + 未知模板拒绝、尾段后垃圾拒绝、字节级双跑一致。
* feat(occupation): P11 每日任务生成纯函数 + TaskState ↵Somhairle H. Marisol13 days1-0/+118
| | | | | | 状态机(Kernel 侧) Occupation.fs 增补:TaskState(Offered|Active|Done|Failed)、TaskTemplateId 首期池=农夫3(送粮/帮工/翻土)+渔夫3(夜捕/卖渔/询价)、DailyTask 记录(设计 §2/§3)。生成 = taskHash(seed ^ occupationSeed, dayIndex) mod |pool|,与 Rng.fs splitmix 同源(禁 System.Random),输出只依赖三元组;taskHash 以 5 个 splitmix 已知向量钉死。完成判定 = satisfiesCompletion 纯谓词,信号 TaskSignal(Dialogued/Traded/ArrivedAt/NightAtWater) 全部来自既有事件通道(DialogueEvent/TradeEvent/到达瓦片/夜+水边),TargetNpc/TargetTile None=通配;acceptTask/applySignal/expireAt 状态机纯函数,Sim.step 数值路径零改动。货郎/书生空池 → dailyTaskOf = None。13 例测试:splitmix 向量、池约束、逐日确定性、窗口=整日、中文名、状态机转移、六模板正负完成信号、终态不可复活、逾期判负。
* feat(occupation): 职业系统第一片 — Kernel 结构 / bootstrap 注入 ↵Somhairle H. Marisol13 days1-0/+53
/ 存档 v3 Occupation.fs(Kind/Profile/State + 农夫/渔夫/货郎/书生 中文名常量,按设计 §1 表给初始 Money/Energy/Inventory);ItemKind 扩出 Fish/Spice/Scroll(basePrice 分支补齐,Food 10.0f 数值路径不变 → 无职业 digest 不动);WorldBootstrap.initialWorldWithOccupation 默认 None = 旧行为(Money/Energy 覆盖,库存字段先留数据侧、物理挂接留交易单——取舍见 design §2-C 反对加字段);WorldSave: v3 头仅在有职业时写入(保存 saveToFileWith / loadFromFileWith,v1/v2/v3 无职业类型默认,token 顺序 version|w|h|kind|task|story|…),默认路径 save 输出逐字节等同现行 v2;P10 测试 5 例(§1 表值、v3 round-trip、v1/v2 不吞档、双 seed 逐字节、中文名);Kernel.Tests 引用 Desktop 以驱动 WorldBootstrap(取舍:不做测试专用 shim)。TaskToken/StoryStage 为 v3 占位(任务系统后续单实现)。