diff --git a/AI_MAP.md b/AI_MAP.md index f801193..02a0d2f 100644 --- a/AI_MAP.md +++ b/AI_MAP.md @@ -6,7 +6,7 @@ Purpose: static Japanese browser simulation/game. Optimize context by reading th - Entrypoint: `index.html` defines the app shell, canvas, dialogs, right panels, and exact script order. - Runtime style: plain browser JS, global IIFEs, exports on `window`, no bundler/module loader. -- Version/cache: `app_manifest.json`, `js/version.js`, and generated `service-worker.js` share `39.15.103`. +- Version/cache: `app_manifest.json`, `js/version.js`, and generated `service-worker.js` share `39.15.164`. - Main loop: `js/main.js` initializes assets/audio/world/UI/save, then drives update/render. - Performance/display settings: `js/perf_profiler.js` owns manual visual settings and profiler buckets; display tiers affect rendering/visuals, not simulation-quality branches. - Update order: `js/system_order.js` calls phase facades from `js/simulation_systems.js`. @@ -59,4 +59,26 @@ Purpose: static Japanese browser simulation/game. Optimize context by reading th - Keep intentional global exports for compatibility with regression checks and browser runtime; remove public facades only after repo-wide caller checks. - Prefer focused edits in the owning subsystem; split modules are intentional compatibility boundaries. - Avoid reintroducing `simulationQualityTier` branches unless a real simulation-quality setting is restored; current quality controls are visual/detail controls. +- `High` display quality may include quality-preserving optimizations, but should not reduce simulation cadence, object limits, or visible fidelity in a noticeable way. +- Save format compatibility with old text saves is not required when intentionally shortening/replacing save hash text; keep current save/load internally consistent instead. - Run `node --check js/*.js` and `python scripts/regression_check.py` for behavior changes. + +## Current Maintenance Notes + +This section records current boundaries only. Version-by-version cleanup history and completed work logs are intentionally omitted. + +### Live Compatibility Surfaces + +- Ordered global-IIFE loading is still part of the app contract; check repo-wide callers before removing bare globals or facade objects. +- Keep public event names with active listeners: `audio:play`, `selection:changed`, `tool:selected`, `world:phase`, `log:entry`, and `tool:placed`. Telemetry-only emit calls should stay removed. +- Save compatibility with old exported text is not required, but the current save/load round-trip must remain internally consistent. +- Tool icon ownership is `TOOL_DEFINITIONS.icon`; UI code converts asset paths for CSS variables. Avoid restoring CSS-local `url(...)` definitions. +- Shared geometry/display/domain helpers should stay in their owning helper modules unless a dedicated namespace migration is being done. + +### Open Architecture Candidates + +- Full namespace migration for behavior/action/needs/tool helpers. This requires rewriting many bare global call sites and updating regression contracts. +- Effect-specific spatial indexing, fuller delta-history storage, and high-speed collision partitioning. These need new indexes or semantics beyond cleanup. +- UI/text-side meaning consolidation, including labels, wrapping/measurement helpers, and duplicated scalar helpers such as `num`, `finiteOr`, `isObject`, and `clonePlain`. +- Further `World.prototype` reduction is possible, but only for helpers proven not to be runtime-facing canvas/UI/tool APIs. + diff --git a/FILES.json b/FILES.json index 376200a..c7645ba 100644 --- a/FILES.json +++ b/FILES.json @@ -1,6 +1,6 @@ { "purpose": "Token-efficient machine-readable routing for tarinai_. Use scripts/ai_inventory.py for exact current file expansion.", - "version": "39.15.103", + "version": "39.15.164", "entrypoints": { "app": "index.html", "runtime": "js/main.js", diff --git a/GAME_FEATURES.md b/GAME_FEATURES.md index 272cfa7..a96d255 100644 --- a/GAME_FEATURES.md +++ b/GAME_FEATURES.md @@ -1,26 +1,3 @@ -## 39.15.136 ツールチップ・統計・病気・空腹調整 -- たりないツールチップは4行固定のまま、横幅を内容に合わせて可変化。 -- コロニー統計に毎日0:00の灰色点線と日付ラベルを表示。 -- 持ち主IDが空、または持ち主が生存個体に存在しないぬいぐるみは削除。 -- きずつき病の個体は日光浴を開始せず、日光浴中に発症した場合も中断する。日光浴回復対象からも除外。 -- 病気中に体力切れ/ストレス過多で死亡した場合、病死として病名を優先記録するよう補強。 -- 空腹度合いの自然上昇幅を通常時・睡眠時ともに3/4倍へ調整。 - -## 39.15.136 水風船・扇風機差分 - -- 水風船の飛沫は雨滴と同じ `Item("water")` 生成経路に統一。専用タイプや専用IDは使わず、短時間だけ速度を持つ水滴として扱う。 -- 水風船の破裂飛沫を増量し、飛距離・初速・飛翔時間を拡大。 -- 水風船は射撃命中、爆竹/爆発病の爆風、げんこつ、火、鋲で破裂する。 -- 扇風機の本体角度と風向きを分離。風向き変更・首振りで変化するのは風範囲/矢印のみ。 -- 扇風機の風が火に当たると、火を単に弱めず、風下へ火種を飛ばして拡散する。 -- たりないが水風船で遊ぶ時の楽しさ・押し出し効果をボール寄りに調整。 - -## 39.15.118 土管ツールチップ・雨滴統一 -- 土管ツールチップは、どの土管にカーソルを合わせても土管内のたりないを一覧表示する。 -- 巣箱・土管に入り透明化済みのたりないは、個体ツールチップを出さない。 -- 土管内の体感温度補正は20℃へ最大±5℃まで寄せる。 -- 水風船破裂時に生成される水滴は、雨で生成される水滴と同じ初期化を使う。 - # tarinai_ Game Features This document describes the playable features of `tarinai_`: what the player sees, what tools do, and how tarinai behave. It is intentionally player/design-facing, not an implementation map. @@ -166,6 +143,11 @@ Tarinai can be pushed by physics objects, carried or affected by ants, dragged b - **Grass ecology**: grass grows, feeds tarinai, comforts them, can become bed material, and has a small chance to reduce fire before burning. - **Dirt and corpses**: zunchi, splats, corpses, and ant corpses affect hygiene, disease, and observation results. - **Day/light conditions**: lighting and sun influence rendering and sunbath behavior. +- **Season temperature**: automatic summer climate is roughly 5℃ hotter than the previous baseline; manual temperature control remains exact to the slider value. + +## Crowded Scene Performance + +Crowded fields are an intended sandbox outcome. Performance work should prefer cached, typed, spatial, dirty, or incremental lookups over lowering object limits. High display quality should preserve visible fidelity and simulation rules while avoiding repeated hidden scans in render, tooltip, family tree, collision, effect, fire, and maintenance paths. ## Disease And Recovery @@ -191,25 +173,6 @@ Recovery depends on the disease or effect. Water, rest, food, medicine, zunda ju ## Save, Reset, And Persistence - The app supports manual save and restore through browser storage. +- Current saves are allowed to use compact/hash-style text. Old save text does not need to remain loadable when the save format is intentionally shortened or replaced, so load failure is acceptable after intentional save-format changes as long as the current save/load path stays internally consistent. - Reset opens field selection and starts a new field state. - Service worker caching allows the static app shell to remain available after load, depending on browser support. - - -## 39.15.117 土管外観・内部温度 - -- 土管の外観を、丸い口と側面が見える斜め上からの視点に変更。 -- 土管内の体感温度を20℃へ近づける内部温度補正を追加。補正幅は最大7℃。 -- 土管ツールチップの内部気温表示にも、土管内補正後の温度を反映。 - -## 39.15.115 水風船の飛散強化・扇風機首振り設定 -- 水風船破裂時に水滴が放射状に飛び、短時間移動してから水たまり状に落ち着く。 -- 配置済み扇風機をクリックすると首振り設定UIを開ける。個別に首振りON/OFF、向き、振り幅、速度を設定可能。 -- 首振り中の扇風機は風の範囲表示と実際の風判定が現在角度に追従する。 - -## 39.15.115 土管 - -- 生活カテゴリに「土管」を追加。丸い口が見える配置アイテムとして表示。 -- たりないが巣箱のように土管の中へ入り、内部の個体は巣箱系ツールチップで確認可能。 -- 土管から出る時は、複数ある場合は別のランダムな土管から出る。 -- 土管内でも眠れるが、寝心地と睡眠優先順位は干草寝床の一段下。 - diff --git a/README.md b/README.md index b85e8c8..b700605 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,6 @@ AI-first entrypoint for a static browser simulation/game. Keep this file small; read deeper docs only when needed. -## v39.15.70 robot cleaner tuning -- Tuned ロボ掃除機 targeting: normal speed is 60, high-speed mode is 120, and speed no longer changes based on the selected cleanup targets. -- The cleaner checks the nearest matching target every 2 seconds, then keeps trying to clean that target between scans. Contact cleanup still removes every matching object it touches. -- The 死骸 target also covers blood traces. When たりない is enabled, nearby Tarinai panic while chased and are cleaned on contact. - ## Read Strategy - Start here for architecture, script order constraints, and where to look next. @@ -18,16 +13,17 @@ AI-first entrypoint for a static browser simulation/game. Keep this file small; ## Runtime Shape -- No bundler; `index.html` loads ordered global-IIFE scripts with `?v=39.15.103`. +- No bundler; `index.html` loads ordered global-IIFE scripts with `?v=39.15.164`. - Mutable runtime lives on `window`; primary entities are `World`, `Tarinai`, items, structures, ants, family graph, weather, and save snapshots. - Update loop: `main.js` creates the world/UI loop; `World.update` delegates to `TarinaiSystemOrder.update`; `system_order.js` runs named phases. - UI loop: pointer/tool/UI intents go through `command_dispatcher.js`; canvas drawing is in render modules; side panels are `ui_*.js`. -- Generated/static app shell: `app_manifest.json`, `service-worker.js`, and `js/version.js` must stay version-aligned. +- Generated/static app shell: `app_manifest.json`, `service-worker.js`, `FILES.json`, and `js/version.js` must stay version-aligned. ## File Routing - `index.html`: DOM shell, CSS/JS load order, panels/dialogs/canvas. - `css/*.css`: base/layout/panel/components/mobile styling. +- `js/domain_ids.js`, `js/item_type_catalog.js`, `js/data.js`, `js/ground_types.js`: stable domain ids, current item-type save catalog, core config, field/ground definitions. - `js/world*.js`: world state, view, update phases, tools, placement, combat, environment, family/social, ants. - `js/tarinai*.js`: creature state, needs, actions, behavior, social life, item effects, update pipeline, rendering. - `js/item*.js`, `js/structures*.js`: item registry/runtime/lifecycle/dynamic behavior/rendering plus structures. @@ -55,33 +51,3 @@ AI-first entrypoint for a static browser simulation/game. Keep this file small; - Syntax: `node --check js/*.js` - Regression: `python scripts/regression_check.py` - Inventory sanity: `powershell -NoProfile -ExecutionPolicy Bypass -File scripts/ai_inventory.ps1 -All` - - -## UI media isolation / scroll repair - -- PC / smartphone UI override rules are separated into `@media (min-width: 981px)` and `@media (max-width: 980px)`. -- PC family tree card is restored below the main game layout, not inside the right menu. -- Smartphone manual scroll no longer uses internal vertical scroll traps for event log / family tree content. -- Auto-scroll does not open collapsed cards. - - -## Event/family/oshibyo UI fixes - -- Event UI hides direct player item placement records while keeping those records in the internal log. -- Collapsed Event UI no longer leaves a large blank area from the log-card min-height. -- Family tree nodes show inherited stats in a 2x2 grid and move the tarinai portrait to the upper-right. -- Oshibyo lodged position is anchored to the left side of the tarinai sprite. - - -## Family polish - -- Family tree generation row spacing is tightened. -- Family tree personality tags also use a 2x2 grid (up to 4 visible tags). -- Sprinkler effective cleaning radius is increased to 3x the previous value and still filters targets by actual distance. - - -## Owned object panic / shoot effect - -- Tarinai panic when their own plushie or simple grass bed is destroyed. -- The selected Tarinai data behavior text explicitly shows the owned-object panic reason. -- Shooting impact effects are larger and remain visible for slightly longer. diff --git a/app_manifest.json b/app_manifest.json index 0d17dce..4d46a30 100644 --- a/app_manifest.json +++ b/app_manifest.json @@ -1,5 +1,5 @@ { - "version": "39.15.136", + "version": "39.15.164", "css": [ "css/base.css", "css/layout.css", @@ -10,6 +10,7 @@ "js": [ "js/version.js", "js/event_bus.js", + "js/domain_ids.js", "js/registry_base.js", "js/disease_registry.js", "js/sound_pack.js", @@ -38,10 +39,12 @@ "js/assets.js", "js/audio.js", "js/perf_profiler.js", + "js/display_helpers.js", "js/render.js", "js/sim_core.js", "js/tarinai_seed_factory.js", "js/structures.js", + "js/item_type_catalog.js", "js/items.js", "js/item_type_initializers.js", "js/item_lifecycle_support.js", diff --git a/css/base.css b/css/base.css index d90a089..e3d7e2b 100644 --- a/css/base.css +++ b/css/base.css @@ -402,35 +402,6 @@ h1 { .tool[data-tool="dwarf_drug"] .tool-sprite-preview, .tool[data-tool="oshibyo"] .tool-sprite-preview { width: 22px; height: 22px; left: 5px; } .tool[data-tool="poke"], .tool[data-tool="water_hose"] { --tool-icon-zoom: 0.92; } -.tool[data-tool="observe"] { --tool-icon: url("../assets/ui/tool_observe.webp"); } -.tool[data-tool="zunchi"] { --tool-icon: url("../assets/ui/tool_zunchi.webp"); } -.tool[data-tool="sweet"] { --tool-icon: url("../assets/ui/tool_sweet.webp"); } -.tool[data-tool="grass"] { --tool-icon: url("../assets/ui/tool_grass.webp"); } -.tool[data-tool="stone"] { --tool-icon: url("../assets/ui/tool_stone.webp"); } -.tool[data-tool="genkotsu"] { --tool-icon: url("../assets/ui/tool_genkotsu.webp"); } -.tool[data-tool="firecracker"] { --tool-icon: url("../assets/ui/tool_firecracker.webp"); } -.tool[data-tool="shoot"] { --tool-icon: url("../assets/ui/tool_shoot.png"); --tool-icon-zoom: 1.48; } -.tool[data-tool="fence_v"] { --tool-icon: url("../assets/ui/tool_fence_v.webp"); } -.tool[data-tool="fence_h"] { --tool-icon: url("../assets/ui/tool_fence_h.webp"); } -.tool[data-tool="bed"] { --tool-icon: url("../assets/ui/tool_bed.webp"); } -.tool[data-tool="love_mochi"] { --tool-icon: url("../assets/ui/tool_love_mochi.webp"); } -.tool[data-tool="fight_mochi"] { --tool-icon: url("../assets/ui/tool_fight_mochi.webp"); } - -.tool[data-tool="signboard"] { --tool-icon: url("../assets/ui/tool_signboard.webp"); } -.tool[data-tool="duplicator"] { --tool-icon: url("../assets/ui/tool_duplicator.webp"); } -.tool[data-tool="pushpin"] { --tool-icon: url("../assets/ui/tool_pushpin.webp"); } -.tool[data-tool="oshibyo"] { --tool-icon: url("../assets/ui/tool_oshibyo.webp"); } - -/* Generated parameter item tool icons. */ -.tool[data-tool="laxative"] { --tool-icon: url("../assets/ui/tool_laxative.webp"); } -.tool[data-tool="protein"] { --tool-icon: url("../assets/ui/tool_protein.webp"); } -.tool[data-tool="niteropu"] { --tool-icon: url("../assets/ui/tool_niteropu.webp"); } -.tool[data-tool="ammo"] { --tool-icon: url("../assets/ui/tool_ammo.webp"); } -.tool[data-tool="mystery_drug"] { --tool-icon: url("../assets/ui/tool_mystery_drug.webp"); } -.tool[data-tool="mercury"] { --tool-icon: url("../assets/ui/tool_mercury.webp"); } -.tool[data-tool="giant_drug"] { --tool-icon: url("../assets/ui/tool_giant_drug.webp"); } -.tool[data-tool="dwarf_drug"] { --tool-icon: url("../assets/ui/tool_dwarf_drug.webp"); } -.tool[data-tool="zunda_juice"] { --tool-icon: url("../assets/ui/tool_zunda_juice.webp"); } .signboard-editor { position: fixed; diff --git a/css/components.css b/css/components.css index f78d734..e6649bd 100644 --- a/css/components.css +++ b/css/components.css @@ -790,16 +790,6 @@ top: 50%; transform: translate(-50%, -50%); } -@media (max-width: 980px) { - .tool-category[data-tool-category="operate"]:not(.collapsed) { top: 58px; } -} - -@media (max-width: 980px) { - body.touch-mobile-ui .tool-tip-popover { - max-width: min(280px, calc(100vw - 24px)); - } -} - /* Collapsed event card must shrink to its header. layout.css gives .log-card a min-height, which left a large blank panel when folded. */ .log-card.collapsed { min-height: 0 !important; height: auto !important; flex: 0 0 auto !important; flex-basis: auto !important; } diff --git a/css/layout.css b/css/layout.css index 9e4dbb5..6515c70 100644 --- a/css/layout.css +++ b/css/layout.css @@ -1,11 +1,6 @@ -/* CSS split file; preserve manifest load order. */ -.tool[data-tool="sleep_drug"] { --tool-icon: url("../assets/ui/tool_sleep_drug.webp"); } -.tool[data-tool="nest_box"] { --tool-icon: url("../assets/ui/tool_nest_box.webp"); } -.tool[data-tool="ant_nest"] { --tool-icon: url("../assets/ui/tool_ant_nest.webp"); } -.tool[data-tool="ball"] { --tool-icon: url("../assets/ui/tool_ball.webp"); --tool-icon-zoom: 1.36; } -.tool[data-tool="delete"] { --tool-icon: url("../assets/ui/tool_delete.webp"); } -.tool[data-tool="new"] { --tool-icon: url("../assets/ui/tool_new.webp"); } -.tool[data-tool="shoot"] { --tool-icon: url("../assets/ui/tool_shoot.png"); --tool-icon-zoom: 1.48; } +/* CSS split file; preserve manifest load order. Tool image paths come from TOOL_DEFINITIONS. */ +.tool[data-tool="ball"] { --tool-icon-zoom: 1.36; } +.tool[data-tool="shoot"] { --tool-icon-zoom: 1.48; } .tool.tool-emoji-icon { --tool-icon: none; } .tool.tool-emoji-icon::before { @@ -302,24 +297,6 @@ meter { .log-observe { border-left-color: rgba(175, 146, 86, 0.62); } .log-event { border-left-color: rgba(132, 120, 210, 0.62); } -@media (max-width: 980px) { - #app { padding: 10px; } - .topbar { align-items: flex-start; flex-direction: column; } - .top-left { align-items: flex-start; flex-direction: column; } - .brand { align-items: center; flex-direction: row; gap: 10px; } - .layout { grid-template-columns: 1fr; } - .panel { max-height: none; overflow: visible; } - #gameCanvas { height: var(--field-mobile-height, 66vh); min-height: var(--field-mobile-min-height, 460px); } - .stage-wrap { min-height: var(--field-mobile-min-height, 460px); } - .field-choice-grid { grid-template-columns: 1fr; } - .reset-preset-choice-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } -} - - - - - - /* Clearer tool category grouping. */ .tool-category[data-tool-category="operate"] { --tool-cat-a: rgba(224,239,255,0.82); --tool-cat-b: rgba(203,226,255,0.74); --tool-cat-line: rgba(82,128,190,0.26); } .tool-category[data-tool-category="food"] { --tool-cat-a: rgba(236,252,219,0.82); --tool-cat-b: rgba(214,244,194,0.74); --tool-cat-line: rgba(96,156,72,0.26); } diff --git a/css/mobile.css b/css/mobile.css index 9fa63f2..ca86dcc 100644 --- a/css/mobile.css +++ b/css/mobile.css @@ -227,7 +227,16 @@ body.touch-mobile-ui.mobile-mode-tool #gameCanvas { cursor: crosshair; } align-items: stretch; gap: 8px; } - .top-left { gap: 8px; } + .top-left { + align-items: flex-start; + flex-direction: column; + gap: 8px; + } + .brand { + align-items: center; + flex-direction: row; + gap: 10px; + } .brand h1, h1 { max-width: 100%; @@ -265,9 +274,16 @@ body.touch-mobile-ui.mobile-mode-tool #gameCanvas { cursor: crosshair; } gap: 10px; overflow: visible; } + .field-choice-grid { grid-template-columns: 1fr; } + .reset-preset-choice-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } + #gameCanvas { + height: var(--field-mobile-height, 66vh); + min-height: var(--field-mobile-min-height, 460px); + } .stage-wrap { position: relative; width: 100%; + min-height: var(--field-mobile-min-height, 460px); overflow: hidden; } .panel { diff --git a/css/panel.css b/css/panel.css index 0dc1763..a964d1c 100644 --- a/css/panel.css +++ b/css/panel.css @@ -137,22 +137,10 @@ body::before { min-width: 0; white-space: nowrap; } -.family-genetic-stats b, -.family-fight-stat b { +.family-genetic-stats b { font-weight: 800; color: rgba(120, 86, 30, 0.92); } -.family-fight-stat { - display: block; - margin-top: 1px; - max-width: 82px; - font-size: 9.7px; - line-height: 1.13; - color: rgba(88, 70, 48, 0.82); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} .lineage-family-tree .tree-node.champion { border-color: rgba(202, 146, 33, 0.58); box-shadow: inset 0 0 0 1px rgba(247, 200, 64, 0.30), 0 3px 8px rgba(120, 78, 12, 0.09); diff --git a/index.html b/index.html index 648018b..2e2ded9 100644 --- a/index.html +++ b/index.html @@ -4,14 +4,14 @@ たりない観察 - - - - - - - - + + + + + + + +
@@ -71,7 +71,7 @@