summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/Program.fs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-29 09:18:45 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-29 09:18:45 +0800
commit4aa6fabbb594af1889778ff7f01ae3193dc08b1d (patch)
treef25dea86c382d94bb005239001ef99da25fded37 /src/LivingVillage.Desktop/Program.fs
parenta578791b0dd8ca95fba3af6f3c2f39c816bd7e52 (diff)
downloadliving-village-4aa6fabbb594af1889778ff7f01ae3193dc08b1d.tar.gz
p68: 512×384 整图离线渲染截图证据
- MapSnapshot:MapGen.Result 纯 CPU 渲染为整图 PNG(每瓦片 8px,自包含 IHDR/IDAT/IEND + CRC32 + ZLibStream,无外部图像依赖);调色板覆盖 河流/主路/农田/民居屋顶/小径/桥/树丛 - Program.fs:LV_P68_MAPSHOT=1 钩子用 paramsForSize 512 384 seed=4242 生成并 离线渲染整图后退出(headless,不需图形设备) - P68MapSnapshotTests(3 例,红先):尺寸/PNG 签名、要素像素存在、两次渲染逐字节一致 - scripts/analyze-p68.py:尺寸/调色板像素/无黑白大块/missing_glyph_slots=0/确定性 - Desktop 336/336、Kernel 119/119;digest 953775FA…7F6C ×3 PASS;未动 Kernel/Sim
Diffstat (limited to 'src/LivingVillage.Desktop/Program.fs')
-rw-r--r--src/LivingVillage.Desktop/Program.fs48
1 files changed, 45 insertions, 3 deletions
diff --git a/src/LivingVillage.Desktop/Program.fs b/src/LivingVillage.Desktop/Program.fs
index 0e2adcf..53cc274 100644
--- a/src/LivingVillage.Desktop/Program.fs
+++ b/src/LivingVillage.Desktop/Program.fs
@@ -1,9 +1,51 @@
namespace LivingVillage.Desktop
+open System
+open System.IO
+open System.Security.Cryptography
+
module Program =
+ /// P68 证据钩子:LV_P68_MAPSHOT=1 时离线渲染 512×384 / seed 4242 整图为 PNG 后退出,
+ /// 不启动图形设备(真正 headless)。打印尺寸/瓦片统计/要素统计/确定性供 analyze 核验。
+ let private runMapShot () : int =
+ let map = MapGen.generateWithSize 512 384 (uint64 4242)
+ let scale = MapSnapshot.defaultScale
+ let recordDirectory =
+ match Environment.GetEnvironmentVariable("LV_RECORD_DIR") with
+ | null | "" -> "/tmp/lv-p68-map"
+ | value -> value
+ Directory.CreateDirectory recordDirectory |> ignore
+ let png = MapSnapshot.renderPng map scale
+ let again = MapSnapshot.renderPng (MapGen.generateWithSize 512 384 (uint64 4242)) scale
+ let deterministic = png = again
+ let sha = SHA256.HashData png |> Convert.ToHexString
+ File.WriteAllBytes(Path.Combine(recordDirectory, "p68-map.png"), png)
+ let tiles code = map.Tiles |> Array.filter (fun c -> c = code) |> Array.length
+ let roadTiles =
+ map.MainRoadCenter
+ |> Array.filter (fun y -> y >= 0 && y < map.Height)
+ |> Array.length
+ printfn
+ "p68-map width=%d height=%d scale=%d png=%dx%d bytes=%d"
+ map.Width map.Height scale (map.Width * scale) (map.Height * scale) png.Length
+ printfn
+ "p68-tiles grass=%d water=%d stone=%d peat=%d paddy=%d vegetable=%d"
+ (tiles (int MapGen.GroundTile.Grass)) (tiles (int MapGen.GroundTile.Water))
+ (tiles (int MapGen.GroundTile.Stone)) (tiles (int MapGen.GroundTile.Peat))
+ (tiles (int MapGen.GroundTile.PaddyField)) (tiles (int MapGen.GroundTile.VegetablePlot))
+ printfn
+ "p68-features rivers=%d bridges=%d paths=%d buildings=%d farmhouses=%d groves=%d road_columns=%d"
+ map.Rivers.Length map.Bridges.Length map.Paths.Length map.Buildings.Length
+ map.Farmhouses.Length map.Groves.Length roadTiles
+ printfn "p68-render deterministic=%b sha256=%s" deterministic sha
+ 0
+
[<EntryPoint>]
let main _ =
- use game = new LivingVillageGame()
- game.Run()
- 0
+ if Environment.GetEnvironmentVariable("LV_P68_MAPSHOT") = "1" then
+ runMapShot ()
+ else
+ use game = new LivingVillageGame()
+ game.Run()
+ 0