diff --git a/assets/sprites/_contact_sheet.png b/assets/sprites/_contact_sheet.png deleted file mode 100644 index 8d2ed9e..0000000 Binary files a/assets/sprites/_contact_sheet.png and /dev/null differ diff --git a/assets/sprites/manifest.json b/assets/sprites/manifest.json deleted file mode 100644 index a136922..0000000 --- a/assets/sprites/manifest.json +++ /dev/null @@ -1,175 +0,0 @@ -[ - { - "id": "smile", - "file": "assets/sprites/tarinai_01_smile.png", - "width": 512, - "height": 468 - }, - { - "id": "angry", - "file": "assets/sprites/tarinai_02_angry.png", - "width": 512, - "height": 464 - }, - { - "id": "teary", - "file": "assets/sprites/tarinai_03_teary.png", - "width": 512, - "height": 472 - }, - { - "id": "jito", - "file": "assets/sprites/tarinai_04_jito.png", - "width": 512, - "height": 487 - }, - { - "id": "drool", - "file": "assets/sprites/tarinai_05_drool.png", - "width": 512, - "height": 461 - }, - { - "id": "cry", - "file": "assets/sprites/tarinai_06_cry.png", - "width": 512, - "height": 478 - }, - { - "id": "sleep", - "file": "assets/sprites/tarinai_07_sleep.png", - "width": 511, - "height": 475 - }, - { - "id": "pokan", - "file": "assets/sprites/tarinai_08_pokan.png", - "width": 512, - "height": 469 - }, - { - "id": "stretch", - "file": "assets/sprites/tarinai_09_stretch.png", - "width": 512, - "height": 384 - }, - { - "id": "hurt", - "file": "assets/sprites/tarinai_10_hurt.png", - "width": 512, - "height": 468, - "actionOnly": true - }, - { - "id": "weak", - "file": "assets/sprites/tarinai_11_weak.png", - "width": 512, - "height": 468, - "actionOnly": true - }, - { - "id": "back", - "file": "assets/sprites/tarinai_12_back.png", - "width": 512, - "height": 468, - "actionOnly": true - }, - { - "id": "flee", - "file": "assets/sprites/tarinai_13_flee.png", - "width": 512, - "height": 468, - "actionOnly": true - }, - { - "id": "zunda_eat", - "file": "assets/sprites/tarinai_14_zunda_eat.png", - "width": 512, - "height": 468, - "actionOnly": true - }, - { - "id": "hurt2", - "file": "assets/sprites/tarinai_15_hurt2.png", - "width": 512, - "height": 468, - "actionOnly": true - }, - { - "id": "normal_smirk", - "file": "assets/sprites/tarinai_16_normal_smirk.png", - "width": 512, - "height": 468, - "displayOnly": true - }, - { - "id": "normal_tongue", - "file": "assets/sprites/tarinai_17_normal_tongue.png", - "width": 512, - "height": 468, - "displayOnly": true - }, - { - "id": "fear", - "file": "assets/sprites/tarinai_18_fear.png", - "width": 512, - "height": 468, - "actionOnly": true - }, - { - "id": "flee_fear2", - "file": "assets/sprites/tarinai_19_flee_fear2.png", - "width": 512, - "height": 468, - "actionOnly": true - }, - { - "id": "sleep2", - "file": "assets/sprites/tarinai_20_sleep2.png", - "width": 512, - "height": 468, - "actionOnly": true - }, - { - "id": "normal_happy", - "file": "assets/sprites/tarinai_21_normal_happy.png", - "width": 512, - "height": 468, - "displayOnly": true - }, - { - "id": "fear_blue", - "file": "assets/sprites/tarinai_22_fear_blue.png", - "width": 512, - "height": 468, - "actionOnly": true - }, - { - "id": "fear_cry", - "file": "assets/sprites/tarinai_23_fear_cry.png", - "width": 512, - "height": 468, - "actionOnly": true - }, - { - "id": "stress_dizzy", - "file": "assets/sprites/tarinai_24_stress_dizzy.png", - "width": 512, - "height": 468, - "actionOnly": true - }, - { - "id": "stress_sweat", - "file": "assets/sprites/tarinai_25_stress_sweat.png", - "width": 512, - "height": 468, - "actionOnly": true - }, - { - "id": "intimidate", - "file": "assets/sprites/tarinai_26_intimidate.png", - "width": 512, - "height": 468, - "actionOnly": true - } -] \ No newline at end of file diff --git a/assets/ui/ecology_hp_stress.png b/assets/ui/ecology_hp_stress.png new file mode 100644 index 0000000..b1b0a7d Binary files /dev/null and b/assets/ui/ecology_hp_stress.png differ diff --git a/assets/ui/tool_ball.png b/assets/ui/tool_ball.png new file mode 100644 index 0000000..64e5c55 Binary files /dev/null and b/assets/ui/tool_ball.png differ diff --git a/assets/ui/tool_fight_mochi.png b/assets/ui/tool_fight_mochi.png new file mode 100644 index 0000000..9c54caa Binary files /dev/null and b/assets/ui/tool_fight_mochi.png differ diff --git a/assets/ui/tool_love_mochi.png b/assets/ui/tool_love_mochi.png new file mode 100644 index 0000000..73cf643 Binary files /dev/null and b/assets/ui/tool_love_mochi.png differ diff --git a/assets/ui/tool_nest_box.png b/assets/ui/tool_nest_box.png new file mode 100644 index 0000000..44f5c92 Binary files /dev/null and b/assets/ui/tool_nest_box.png differ diff --git a/assets/ui/tool_pinch.png b/assets/ui/tool_pinch.png new file mode 100644 index 0000000..0ad3cf1 Binary files /dev/null and b/assets/ui/tool_pinch.png differ diff --git a/assets/ui/tool_sleep_drug.png b/assets/ui/tool_sleep_drug.png new file mode 100644 index 0000000..c8d0f5a Binary files /dev/null and b/assets/ui/tool_sleep_drug.png differ diff --git a/assets/ui/tool_water_bowl.png b/assets/ui/tool_water_bowl.png new file mode 100644 index 0000000..d934cfb Binary files /dev/null and b/assets/ui/tool_water_bowl.png differ diff --git a/assets/ui/tool_water_hose.png b/assets/ui/tool_water_hose.png new file mode 100644 index 0000000..31cb91a Binary files /dev/null and b/assets/ui/tool_water_hose.png differ diff --git a/css/styles.css b/css/styles.css index 0cda845..8653502 100644 --- a/css/styles.css +++ b/css/styles.css @@ -554,6 +554,32 @@ meter { accent-color: var(--accent); } + +.selected-card.hidden { display: none; } +.selected-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + margin-bottom: 8px; +} +.selected-head h2 { margin-bottom: 0; } +.selected-close { + width: 28px; + height: 28px; + border: 1px solid rgba(84,68,48,0.16); + border-radius: 999px; + background: rgba(255,255,255,0.76); + color: rgba(76,58,42,0.78); + font-size: 20px; + line-height: 24px; + cursor: pointer; + display: grid; + place-items: center; + padding: 0; +} +.selected-close:hover { background: #fff; } + .selected-info { font-size: 13px; line-height: 1.55; @@ -1068,13 +1094,13 @@ body::before { max-width: min(220px, calc(100vw - 16px)); padding: 7px 9px; border-radius: 10px; - background: rgba(46, 38, 30, 0.20); + background: rgba(46, 38, 30, 0.78); color: #fff8e6; font-family: "Yomogi", "Hiragino Maru Gothic ProN", "Yu Gothic", sans-serif; font-size: 12px; line-height: 1.45; - box-shadow: 0 10px 28px rgba(40, 32, 22, 0.26); - backdrop-filter: blur(2px); + box-shadow: 0 10px 28px rgba(40, 32, 22, 0.18); + backdrop-filter: blur(1px); text-shadow: 0 1px 3px rgba(25, 18, 12, 0.55); pointer-events: none; } @@ -1154,3 +1180,123 @@ body::before { content: ""; background: none; } + +/* Tool UI icons: use in-game styled image assets instead of emoji glyphs. */ +.tool[data-tool="love_mochi"] { --tool-icon: url("../assets/ui/tool_love_mochi.png"); } +.tool[data-tool="fight_mochi"] { --tool-icon: url("../assets/ui/tool_fight_mochi.png"); } +.tool[data-tool="water_bowl"] { --tool-icon: url("../assets/ui/tool_water_bowl.png"); } +.tool[data-tool="sleep_drug"] { --tool-icon: url("../assets/ui/tool_sleep_drug.png"); } +.tool[data-tool="nest_box"] { --tool-icon: url("../assets/ui/tool_nest_box.png"); } +.tool[data-tool="water_hose"] { --tool-icon: url("../assets/ui/tool_water_hose.png"); } +.tool[data-tool="ball"] { --tool-icon: url("../assets/ui/tool_ball.png"); } + +.tool[data-tool="love_mochi"]::before, +.tool[data-tool="fight_mochi"]::before, +.tool[data-tool="water_bowl"]::before, +.tool[data-tool="sleep_drug"]::before, +.tool[data-tool="nest_box"]::before, +.tool[data-tool="water_hose"]::before, +.tool[data-tool="ball"]::before { + content: ""; + position: absolute; + left: 7px; + top: 50%; + width: 30px; + height: 30px; + transform: translateY(-50%); + background: var(--tool-icon) center / contain no-repeat; + opacity: 0.92; + filter: drop-shadow(0 2px 3px rgba(52,40,26,0.12)); + line-height: normal; + text-align: initial; + overflow: visible; +} + +.tool[data-tool="love_mochi"]::after, +.tool[data-tool="fight_mochi"]::after, +.tool[data-tool="water_bowl"]::after, +.tool[data-tool="sleep_drug"]::after, +.tool[data-tool="nest_box"]::after, +.tool[data-tool="water_hose"]::after, +.tool[data-tool="ball"]::after { + content: ""; + position: absolute; + inset: 0; + width: auto; + height: auto; + left: auto; + right: auto; + top: auto; + bottom: auto; + transform: none; + background: var(--tool-icon) right -8px center / 54px 54px no-repeat; + opacity: 0.10; + pointer-events: none; + font-size: initial; + line-height: normal; +} + + +/* 15.2.0: replace legacy poke/pinch PNG icons with emoji glyphs. */ +.tool[data-tool="poke"], +.tool[data-tool="pinch"] { --tool-icon: none; } +.tool[data-tool="poke"]::before, +.tool[data-tool="pinch"]::before { + background: none; + font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif; + font-size: 24px; + line-height: 30px; + text-align: center; + display: block; + opacity: 0.96; +} +.tool[data-tool="poke"]::before { content: "👈"; } +.tool[data-tool="pinch"]::before { content: "🤏"; } +.tool[data-tool="poke"]::after, +.tool[data-tool="pinch"]::after { + background: none; + font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif; + font-size: 46px; + line-height: 54px; + text-align: center; + opacity: 0.10; + right: -6px; + left: auto; + top: 50%; + bottom: auto; + transform: translateY(-50%); + width: 54px; + height: 54px; +} +.tool[data-tool="poke"]::after { content: "👈"; } +.tool[data-tool="pinch"]::after { content: "🤏"; } +.tool[data-tool="poke"] span, +.tool[data-tool="pinch"] span { display: none; } + + +/* 15.3.0: shower uses emoji; nest box and fences use appearance-matched assets/hitboxes. */ +.tool[data-tool="water_hose"] { --tool-icon: none; } +.tool[data-tool="water_hose"]::before { + content: "🚿"; + background: none; + font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif; + font-size: 24px; + line-height: 30px; + text-align: center; + display: block; + opacity: 0.96; +} +.tool[data-tool="water_hose"]::after { + content: "🚿"; + background: none; + font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif; + font-size: 46px; + line-height: 54px; + text-align: center; + opacity: 0.10; + right: -6px; + left: auto; + top: 50%; + bottom: auto; + transform: translateY(-50%); +} diff --git a/docs/prompt.txt b/docs/prompt.txt new file mode 100644 index 0000000..dc86a4a --- /dev/null +++ b/docs/prompt.txt @@ -0,0 +1,485 @@ +You are working on the Tarinai observation game. + +Base input: + +* Start from `tarinai_colony_game_fixed_v6.zip`. +* Modify the project files directly. +* Return a new zip. +* Do not remove existing gameplay features unless explicitly instructed. +* Preserve the existing Japanese UI text style. +* After changes, run syntax checks on all JavaScript files and verify zip integrity. +* Bump the cache-busting version in `index.html` so browsers do not keep loading old JS/CSS. + +Primary goals: +Fix the remaining complexity, behavior mismatch, redundant logic, and fragmented-spec issues identified in the v6 audit. Implement all items below. Do not skip any item. + +--- + +## 1. Family tree update performance + +Current issue: +The family tree update still performs heavy synchronous preprocessing, causing the main game to freeze. + +Implement: + +* Split heavy preprocessing into small chunks. +* Use `requestIdleCallback` when available, with a safe `setTimeout` fallback. +* Avoid doing large graph construction, signature generation, relationship counting, or DOM creation in one blocking pass. +* The game loop must remain responsive while family tree data is prepared. + +Update timing rules: + +* When the family tree panel is hidden: + + * Do not update every 5 seconds. + * Check/update at most once every 30 seconds. +* When the family tree panel is visible: + + * Do not update on a fixed 5-second timer. + * Update only when the family tree is dirty, meaning a relevant change occurred. + * Relevant dirty events include at least: + + * birth + * death + * parent/child relationship creation + * mate/partner relationship creation or change + * name/identity data change that affects the family tree display +* Add or use a clear dirty flag such as `familyTreeDirty`. +* Mark dirty from the source of the change, not by repeatedly recomputing expensive signatures. +* If a background update is already running, do not start another one. +* If a newer dirty event occurs while an update is running, schedule one additional update after the current update completes. + +Expected result: + +* Opening or updating the family tree should not freeze the main simulation. +* Hidden family tree work should be very rare. +* Visible family tree should refresh promptly after actual changes. + +--- + +## 2. Coward personality condition + +Current issue: +The “coward” condition may count total fight results and per-relationship fight results together, causing double counting. + +Implement: + +* The 5% chance to become `臆病` must be based only on total fight wins and total fight losses. +* Do not include per-relationship win/loss counts in this condition. +* Trigger condition: + + * The Tarinai has just taken damage. + * Its total fight losses are greater than its total fight wins. + * Then it has a 5% chance to change personality to `臆病`. +* Avoid changing the personality repeatedly if it is already `臆病`. + +Expected result: + +* The calculation uses only aggregate lifetime fight result counters. +* No double counting. + +--- + +## 3. Disease fight initiation and targeting rules + +Implement the following disease fight rules exactly: + +Fight initiation: + +* Tarinai with `爆発病` can initiate fights. +* Tarinai with `ずんち病` can initiate fights. +* Tarinai with any other disease must not initiate fights. +* Healthy Tarinai may initiate fights according to the existing rules. + +Being targeted / challenged: + +* Tarinai with `ねむり病` must not be targeted for fights. +* Tarinai with any other disease may still be targeted/challenged by another Tarinai. +* This means: + + * `爆発病` and `ずんち病`: can initiate and can be targeted. + * Other non-sleep diseases: cannot initiate, but can be targeted. + * `ねむり病`: cannot initiate and cannot be targeted. + +Apply consistently to: + +* Normal fight selection. +* Forced fight logic. +* Fight-food effects such as `けんか餅`. +* Any helper such as `canStartFight`, `canBeFightTarget`, or equivalent. + +Expected result: + +* Disease rules are not handled by scattered ad-hoc checks. +* Use clear helper functions if they do not already exist. + +--- + +## 4. Collision and external-force unification + +Current issues: + +* Ball speed cap was removed, but some collision detection still uses capped sweep/search distances. +* Very fast balls can still tunnel through objects. +* Explosion knockback and ball knockback can be reduced by normal movement speed caps. +* Knockback, collision damage, explosion impulse, and normal movement are handled inconsistently. + +Implement: + +* Separate normal self-propelled movement from external impulse/knockback. +* External impulses must not be clamped by the normal Tarinai walking speed cap. +* Add or refactor toward helper methods such as: + + * `applyImpulse(entity, vx, vy, options)` + * `applyKnockback(entity, sourceX, sourceY, strength, options)` + * `applyImpactDamage(target, amount, cause)` + * `resolveCircleCircleCollision(...)` + * `resolveCircleRectCollision(...)` +* Exact helper names are flexible, but the behavior must be centralized and not duplicated. + +Unlimited ball speed: + +* Do not reintroduce a ball speed cap. +* Collision detection must handle high-speed balls using swept movement based on actual frame movement distance. +* Remove fixed low `Math.min(...)` collision-search caps that contradict unlimited ball speed. +* Ball vs wall, ball vs fence, ball vs nest box, ball vs ball, and ball vs Tarinai should remain reliable at high speed. + +High-speed ball vs Tarinai: + +* When a sufficiently fast ball hits a Tarinai: + + * Knock the Tarinai away using velocity equal to 1/5 of the ball velocity. + * This knockback must be an external impulse, not normal walking movement. + * Do not let the normal “play with ball” behavior also run for that same impact if it would conflict. + * If the damage from this impact kills the Tarinai, death cause must be `衝突`. + +High-speed Tarinai vs Tarinai: + +* When a sufficiently fast Tarinai hits another Tarinai: + + * The hit Tarinai should also be knocked away. + * Use the attacker’s actual movement/impulse direction and speed. + * If collision damage kills a Tarinai, death cause must be `衝突`. + +Explosion knockback: + +* Make explosion knockback stronger than before. +* Use external impulse, not normal movement velocity. +* Knockback should be partly random. +* Tarinai closer to the blast center should be thrown faster and farther. +* Tarinai farther from the blast center should be thrown less strongly. +* Preserve or improve existing explosion damage behavior. +* If an explosion kills a Tarinai, keep the appropriate explosion-related death cause, not `衝突`. + +Expected result: + +* Normal walking speed remains bounded. +* Knockback from explosions and collisions can exceed walking speed. +* High-speed objects do not frequently tunnel through collisions. +* Collision behavior is handled by shared primitives rather than several unrelated implementations. + +--- + +## 5. Ball-to-ball collision + +Ensure balls collide with each other robustly. + +Requirements: + +* Ball vs ball collision must use circle-circle collision. +* Resolve overlap. +* Exchange or reflect velocity in a physically plausible way. +* Work with high-speed balls, not only overlapping balls. +* Avoid creating infinite acceleration or NaN velocity. +* Do not apply arbitrary maximum speed caps. + +--- + +## 6. Solid obstacle and placement logic unification + +Current issues: +Fence, nest box, and placement preview logic are still partly fragmented. + +Implement: + +* Unify all solid rectangular obstacle collision logic. +* Fence and nest box should use the same obstacle system where possible. +* Rename misleading helpers if needed: + + * For example, functions named only for “fence” but now handling nest boxes too should be renamed or wrapped with neutral names such as `solidObstacle`. +* Ball, Tarinai movement, path blocking, and placement checks should reference the same obstacle data. + +Fence collision: + +* Fence collision bounds must match the visible fence appearance. +* If the visual fence is not the same size as the previous hitbox, update the hitbox to match the visual footprint. +* Avoid separate visual size and collision size unless explicitly documented in one definition table. + +Nest box collision: + +* Preserve the existing 3×3 nest box hitbox rule: + + * If the nest box is divided into a 3×3 grid, the collidable cells are: + + * top-left + * top-center + * top-right + * middle-left + * middle-right + * The middle-center, bottom-left, bottom-center, and bottom-right cells are passable/enterable according to the current nest behavior. +* Ball must bounce off these nest box solid cells. +* Tarinai must not path through these solid cells. + +Placement preview: + +* The preview highlight must use the exact same placement validation as actual placement. +* If the preview is red, clicking must not place the object. +* If the preview is green, clicking should place the object at the previewed position. +* Do not silently clamp or auto-correct an out-of-bounds placement to an in-bounds location. +* If the planned placement would extend outside the field, the highlight must turn red. +* Fix the issue where a fence preview extending outside the field does not turn red. +* The highlighted preview position should show the true placement footprint, not a different corrected footprint. + +Expected result: + +* Placement UI, actual placement, and collision behavior agree. +* No “red but placeable” or “green but placed elsewhere” behavior. + +--- + +## 7. Item/tool definition unification + +Current issues: +Tool names, labels, icons, sizes, placement rules, and descriptions are scattered across multiple files. + +Implement: + +* Create or consolidate a single source of truth for tool/item definitions. +* It should include at least: + + * internal id + * Japanese label + * tooltip text + * UI icon or icon renderer + * game appearance reference where applicable + * placement size / footprint + * whether it is placeable + * whether it is scaleable, if applicable + * collision shape if applicable +* Use this definition in the tool UI, placement preview, placement logic, and logs where appropriate. +* Do not leave conflicting duplicate label/icon/size definitions in separate files unless unavoidable. + +Specific icon requirements: + +* `つつく` must use `👈`. +* `つまむ` must use `🤏`. +* `洗浄` must use the shower emoji `🚿`. +* Remove or stop referencing old PNG icons for `つつく` and `つまむ`. +* Fix the nest box tool UI icon so it matches the actual in-game nest box appearance. +* Ensure every tool that appears in the tool UI has an icon. +* Avoid mojibake/garbled icon rendering. + +Water tool: + +* `水` must remain removed from the tool UI. +* If water still exists as a game object produced by rain or other simulation systems, keep that object behavior. +* Remove leftover UI-only water tool entries, labels, tooltips, and placement handlers unless they are still required by non-UI simulation. + +Expected result: + +* Tool UI no longer has missing icons, old icons, or mismatched nest box visuals. +* Tool data is not scattered unnecessarily. + +--- + +## 8. Observation UI event filtering + +Current issue: +Observation UI hides some events by matching Japanese text strings, which is fragile. + +Implement: + +* Remove from the observation UI: + + * events about poking a ball + * events of the form “X avoided Y” / `○○が××を避けた` +* Prefer event type/category filtering over string matching. +* If event objects do not have a type field, add one at event creation. +* Keep the events available internally if needed, but do not show them in the observation UI. + +Expected result: + +* Future wording changes do not break event filtering. + +--- + +## 9. Death cause normalization + +Ensure these death causes are applied consistently: + +* Death by old age / lifespan: + + * `天寿を全うした` +* Tarinai deleted because it went too far outside the field: + + * `仕様により画面外で削除` +* Death caused by ball collision or Tarinai collision damage: + + * `衝突` +* Explosion death: + + * Keep explosion-related cause. +* Existing disease-related deaths: + + * Preserve current intended disease death causes unless they conflict with the above. + +Implementation: + +* Centralize death cause normalization if possible. +* Avoid scattered caller-side strings that can drift. +* Ensure the family tree, observation UI, and any memorial/death display show the normalized cause. + +--- + +## 10. Out-of-bounds object policy + +Current issue: +Different object types handle out-of-bounds behavior differently. + +Implement a unified out-of-bounds policy: + +* For objects or entities slightly outside the field: + + * Return them to the nearest valid in-field position. +* For objects or entities far outside the field, or with invalid coordinates such as NaN/Infinity: + + * Delete them. +* For Tarinai deleted by this system: + + * Death cause must be `仕様により画面外で削除`. +* For non-living objects: + + * Delete without a death cause. +* Keep wall bounce behavior for balls at normal field boundaries, but still sanitize balls that somehow get far outside or invalid coordinates. + +Expected result: + +* No permanent invisible offscreen objects. +* No NaN entities poisoning the simulation. + +--- + +## 11. Observation relationship highlight + +Current issue: +Relationship highlight during observation can be affected by sprite rotation. + +Implement: + +* Relationship highlights must be drawn in world/screen space independent of the Tarinai sprite rotation. +* Do not draw the highlight inside a rotated sprite transform. +* Ensure highlight position follows the Tarinai but does not rotate with the Tarinai body. + +Expected result: + +* Highlight remains visually stable regardless of sprite rotation. + +--- + +## 12. Nest box behavior preservation + +Preserve and verify previous nest box fixes: + +* Tarinai inside the nest box should be fully transparent in the main field. +* Nest box can contain up to 5 Tarinai. +* Nest box occupant popup should show each individual on a separate line. +* The nest box solid hitbox must follow the 3×3 rule described above. +* Ball should bounce off nest box solid hitbox cells. + +Do not regress these behaviors while refactoring obstacles. + +--- + +## 13. Encyclopedia / ecology page + +Preserve and verify the `たりないの生態` addition: + +* It must include an explanation of health. +* It must include an explanation of stress. +* It must use a Tarinai sprite/image with both the health bar and stress bar visible. +* Do not break existing encyclopedia entries. + +--- + +## 14. Naming and Japanese text preservation + +Preserve previous Japanese terminology changes: + +* `喧嘩傷病` must remain renamed to `きずつき病`. +* `寿命` death text must display as `天寿を全うした`. +* Use the existing tone/style for Japanese labels and descriptions. + +Do not reintroduce removed or old names. + +--- + +## 15. Code quality expectations + +Refactor carefully: + +* Prefer small, well-named helper functions. +* Avoid adding more scattered special cases. +* Avoid duplicating collision math. +* Avoid duplicating item/tool metadata. +* Avoid string-matching for gameplay logic where structured data is possible. +* Preserve save compatibility where possible. +* If save migration is needed, add a safe fallback. + +Add comments only where they clarify non-obvious game rules, especially: + +* disease fight rules +* nest box 3×3 collision cells +* external impulse vs normal movement +* family tree dirty/update scheduling + +--- + +## 16. Validation checklist + +Before returning the zip, verify at minimum: + +Static checks: + +* Run `node --check` on every JavaScript file. +* Ensure there are no `ReferenceError` risks from renamed helpers. +* Ensure old cache version references are updated. + +Manual or scripted behavior checks where practical: + +* Ball vs ball collision works. +* Fast ball hitting Tarinai knocks it by ball velocity / 5. +* Fast collision death cause is `衝突`. +* Explosion throws nearby Tarinai farther than distant Tarinai and is not clamped by walking speed. +* Fence preview turns red when the footprint leaves the field. +* Red placement preview cannot place an object. +* Green placement preview places at the same footprint shown. +* Nest box collision uses the required 3×3 cells. +* Ball bounces off nest box solid cells. +* Family tree hidden update is no more frequent than every 30 seconds. +* Family tree visible update happens when dirty, not every 5 seconds. +* Family tree processing does not freeze the game. +* `臆病` condition uses only total wins/losses. +* `爆発病` and `ずんち病` can initiate fights. +* Other diseases cannot initiate fights. +* `ねむり病` cannot initiate and cannot be targeted. +* Other non-sleep diseases can be targeted. +* Observation UI does not show ball-poke events or avoid events. +* Tool icons are correct: `👈`, `🤏`, `🚿`, and nest box matching in-game appearance. +* `水` is absent from the tool UI. +* Lifespan death cause is `天寿を全うした`. +* Far-outside Tarinai deletion cause is `仕様により画面外で削除`. + +Deliverable: + +* Return a zip named something like `tarinai_colony_game_fixed_v7.zip`. +* Include a concise summary of changed areas and validation results. diff --git a/index.html b/index.html index 65ff9cb..1ca64b0 100644 --- a/index.html +++ b/index.html @@ -3,8 +3,11 @@
+ + +