From 0ea26337830ada438df144b3a51f429f00dc1967 Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Sun, 20 Sep 2026 21:58:31 +0800 Subject: feat(desktop): add deterministic Jiangnan art and Chinese text primitives [Change Nature] This commit adds the Task 3a desktop presentation data slice. [New Capability] - Defines immutable Jiangnan props, water and paving tiles, NPC variants, directions, and two-frame animation metadata. - Provides formal Chinese scene, menu, status, and missing-glyph text layout primitives. [Implementation] - Keeps the new modules pure and deterministic with no GUI, network, or global mutable state. - Adds focused prototype tests, F# compile ordering, and asset/license boundary documentation. [Impact] - Extends desktop presentation APIs without modifying Kernel or Game.fs. - Leaves GUI rendering integration for Task 3b. --- src/LivingVillage.Desktop/ChineseText.fs | 84 ++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/LivingVillage.Desktop/ChineseText.fs (limited to 'src/LivingVillage.Desktop/ChineseText.fs') diff --git a/src/LivingVillage.Desktop/ChineseText.fs b/src/LivingVillage.Desktop/ChineseText.fs new file mode 100644 index 0000000..b0c2fc6 --- /dev/null +++ b/src/LivingVillage.Desktop/ChineseText.fs @@ -0,0 +1,84 @@ +namespace LivingVillage.Desktop + +open System + +module ChineseText = + + type SceneKind = + | VillageScene + | Waterway + | WhiteWallHome + | StoneBridgeScene + | BambooGrove + | VegetableGardenScene + + type DayNightKind = + | DayTime + | NightTime + + type MenuHeadingKind = + | MainMenuHeading + | SettingsHeading + | ControlsHeading + + type StatusHeadingKind = + | StatusHeading + | ReadyStatus + | PausedStatus + + type ChineseCopy = + { SceneTitle: string + Ready: string } + + type TextLayout = + { Lines: string list + MissingGlyphs: char list } + + let sceneLabel scene = + match scene with + | VillageScene -> "江南水乡" + | Waterway -> "水道" + | WhiteWallHome -> "白墙黛瓦民居" + | StoneBridgeScene -> "石桥" + | BambooGrove -> "竹林" + | VegetableGardenScene -> "菜圃" + + let dayNightLabel time = + match time with + | DayTime -> "白天" + | NightTime -> "夜晚" + + let menuHeading heading = + match heading with + | MainMenuHeading -> "主菜单" + | SettingsHeading -> "设置" + | ControlsHeading -> "操作说明" + + let statusHeading status = + match status with + | StatusHeading -> "状态" + | ReadyStatus -> "准备就绪" + | PausedStatus -> "已暂停" + + let copy : ChineseCopy = + { SceneTitle = "江南水乡" + Ready = "准备就绪" } + + let layoutText (maxWidth: int) (supported: Set) (text: string) : TextLayout = + let width = max 1 maxWidth + let normalized, missing = + text + |> Seq.fold + (fun (characters, missingGlyphs) character -> + if Set.contains character supported then + character :: characters, missingGlyphs + else + '□' :: characters, character :: missingGlyphs) + ([], []) + + { Lines = + normalized + |> List.rev + |> List.chunkBySize width + |> List.map (fun line -> new String(Array.ofList line)) + MissingGlyphs = List.rev missing } -- cgit v1.2.3