blob: de5698ac6f13ea71d23cb6c9636bbf5a33307d37 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
# 维护说明
结论先行:主分支保持 0 警告 0 错误 + Desktop 69/69、Kernel 50/50 全绿;性能基线
final_digest 固定 953775FAEB2FDDE97289491AA260BD8D390C571E48A7A13AD2CB6FB7124F7F6C。
本文记录模块职责、不变量与逐字可复制的验收命令。
## 模块职责
- `src/LivingVillage.Kernel/`:纯确定性模拟(需求/关系/谣言/年鉴/交易),无渲染依赖。
- `Sim.fs`:世界结构、`Sim.step` 主推进、对话/交易/谣言决策、地图边界
`configureBounds`(默认 64×48,可到 512×384)。
- `WorldSave.fs`:存档序列化。V2 头携带地图宽高,V1 旧档读入自动回退 64×48。
- `Personality.fs / Interaction.fs(fsm) / M6*.fs`:NPC 行为状态机与里程碑数据。
- `src/LivingVillage.Desktop/`:MonoGame 渲染与交互层。
- `VillageArt.fs`:图集加载与世界/人物/室内绘制;CC0 覆盖层(LV_ASSET_PACK=cc0)。
- `Interaction.fs`:M5 视图与情境解析(FloatingPrompt / panelLines / 情境提示)。
- `M6Presentation.fs`:昼夜光照纯函数(lightingBlend)与渲染档(Blend/LanternGlow)。
- `TitleScreen.fs / Game.fs`:标题布局与主循环;LV Autos(sample / flow / record / map tour)。
- `ProceduralMap.fs`:512×384 确定性地形(splitmix 随机游走河道 + 三倍频值噪声 + 泊松布点)。
- `SampleScript.fs`:自动演示脚本(靠近→提示→交互→关闭→离开全流程)。
- `src/LivingVillage.Headless/`:headless 入口 + PerformanceProbe(digest、基跑)。
- `scripts/make-jiangnan-art.py / make-cc0-art.py`:原创与 CC0 素材确定性生成。
- `third_party/`:Kenney Tiny Farm、Puny Characters(均 CC0 1.0,来源与 sha256 在 PROVENANCE.md)。
## 模拟状态不变量(验收依据)
1. **数组快照**:`Sim.world.Npcs` 数组与 `InteractionResolver.resolve` / `refreshPrompt` 的
调用之间必须保持恒定——选择/提示路径从不 mutation(PrototypeTests 快照回归)。
2. **确定性 RNG**:世界推进只随 `World.Rng`(splitmix)与 `(seed)` 派生,禁止墙钟与
`System.Random`。昼夜/波纹/入场/动画帧全是 `tick → 值` 纯函数。
3. **存档 v1/v2**:`WorldSave` v2 头携带 `width height`,V1 读入回退默认。`worldDigest`
对版本头与边界 token 不敏感(剥头后重构 V1 常量语义再 SHA256),摘要只绑定模拟状态。
4. **地图 512×384 大世界**:`ProceduralMap.generate` 同 seed 两次生成逐字节一致;
村核矩形(24..38 × 16..34)由生成器不变式保证可通行。
## 性能基线命令
```bash
dotnet src/LivingVillage.Headless/bin/Release/net8.0/LivingVillage.Headless.dll --performance-baseline
```
- 口径:seed=42,npc=4,warmup=120,measure=6000,repetitions=3(见首行 `performance_config`)。
- 门槛:`final_digest=953775FAEB2FDDE97289491AA260BD8D390C571E48A7A13AD2CB6FB7124F7F6C` 三次一致 + `performance_determinism=PASS`。
- digest 变化处理:先比对 `WorldSave.save world` 全文文本(版本头变化不构成失败即 digest 规范化后等价);
再查 Sim.step 数值路径是否被改动(不允许)。历史归属见 `artifacts/perf-independent/*/README.md`。
## 已验证命令
```bash
# 完整重建(0 警告 0 错误)
dotnet clean LivingVillage.sln 2>&1 | tail -n1
rm -rf src/*/bin src/*/obj
dotnet restore LivingVillage.sln
dotnet build LivingVillage.sln -c Release 2>&1 | tail -n3
# 全量测试
dotnet test src/LivingVillage.Desktop.Tests -c Release --no-build
dotnet test src/LivingVillage.Kernel.Tests -c Release --no-build
# 素材再生成(确定性,输出 byte-identical)
python3 scripts/make-jiangnan-art.py && python3 scripts/make-cc0-art.py
# Xvfb 录屏取证(沿用既有 pN harness 外参即可;harness 不入库)
pkill -f "Xvfb :99"; Xvfb :99 -screen 0 1280x720x24 & sleep 2
ffmpeg -y -f x11grab -video_size 1280x720 -framerate 10 -i :99 -pix_fmt yuv420p out.mp4
LV_AUTOPLAY_SAMPLE=1 LV_AUTOPLAY_DAYLIGHT=1 LV_AUTOPLAY_RECORD=1 \
dotnet src/LivingVillage.Desktop/bin/Release/net8.0/LivingVillage.Desktop.dll
```
## 取证快照位置(近期)
- `/tmp/lv-p2-ui/`、`/tmp/lv-p3-fixes/`(标题/键位/P5 提示与修)
- `/tmp/lv-p6-art/`(昼夜光照/四帧行走/标题入场)
- `/tmp/lv-p7-map/`(512×384 大世界巡游帧 + 夜灯对照)
- `/tmp/lv-p8-cc0/`(CC0 同 seed 对照帧)
- `artifacts/perf-independent/<TS>/`(digest 3 联测回读)
|