diff --git a/.htaccess b/.htaccess
index d579227..36b3f0a 100644
--- a/.htaccess
+++ b/.htaccess
@@ -1,21 +1,21 @@
ExpiresActive On
ExpiresByType text/html "access plus 0 seconds"
- ExpiresByType text/css "access plus 0 seconds"
- ExpiresByType application/javascript "access plus 0 seconds"
- ExpiresByType application/json "access plus 0 seconds"
+ ExpiresByType text/css "access plus 30 days"
+ ExpiresByType application/javascript "access plus 30 days"
+ ExpiresByType application/json "access plus 30 days"
ExpiresByType image/png "access plus 30 days"
ExpiresByType image/webp "access plus 30 days"
ExpiresByType audio/mpeg "access plus 30 days"
ExpiresByType audio/wav "access plus 30 days"
-
- Header set Cache-Control "no-cache, no-store, must-revalidate"
+
+ Header set Cache-Control "no-cache, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "0"
-
+
Header set Cache-Control "public, max-age=2592000"
diff --git a/PATCH_NOTES.md b/PATCH_NOTES.md
index 8c5ba5c..938feeb 100644
--- a/PATCH_NOTES.md
+++ b/PATCH_NOTES.md
@@ -1,3 +1,18 @@
+## 15.9.2 修正
+- 巣箱アイコンとゲーム内描画から、枠内の明色・透過っぽく見える装飾を除去。
+- アリのHPバーを、たりないと同様にダメージ直後だけ表示する方式へ変更。
+- 道具UIに「げんこつ」を追加。添付画像から正義げんこつ部分を切り抜き、上から落下してたりない・アリにダメージと吹っ飛びを与える効果を追加。
+- 初期ロード画面と読み込み進捗バーを追加。JS/CSSをdefer化し、CSS/JSのサーバーキャッシュを有効化して再訪問時の通信量を削減。
+
+
+## 15.9.1 修正
+- 草を地面レイヤーとして扱い、既存の草の上にもオブジェクトを配置できるようにしました。草同士・草と障害物の植え付け制限は維持しています。
+- けんか餅のゲーム内描画から星印を削除し、×印のみ表示するようにしました。
+- ダメージ後に出る「こわい…」吹き出しを削除しました。
+- 家系図に「更新」トグルを追加しました。デフォルトはOFFで、ONの間だけ家系図を描画・更新します。
+- 死亡した個体のライブIDを再利用しないようにし、友達・敵対関係が別個体へ引き継がれて見える問題を防止しました。死亡時の一時ターゲット参照も掃除します。
+- たりないデータUIをカテゴリ別の折り畳み表示に変更しました。
+
# Patch Notes
## Encoding cleanup
diff --git a/README.md b/README.md
index a55624e..69725d1 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Read only these first: `README.md`, `docs/AI_CONTEXT.md`, `docs/code_map.md`. Th
## Core simulation
- Entities: `Tarinai` agents with hunger, sleep/energy, loneliness, stress, health, age, personality, family links, relationships, diseases, favorite flag, target/need AI, transient animation timers.
-- World: bounded field with weather, time, lighting, temperature, spatial-grid queries, items, effects, logs, archive/family data, persistence, placement and collision rules.
+- World: bounded field with weather, time, lighting, temperature, spatial-grid queries, items, effects, logs, archive/family data, placement and collision rules.
- Observation loop: agents autonomously seek food/water/sleep/social targets, react to zunchi, tools, rain, cold, crowding, relationships, disease, damage, conflict, reproduction, and player input.
- Records: observation log and family tree store births, deaths, parentage, cause-of-death labels, favorite state, and key state changes.
@@ -50,7 +50,7 @@ js/sim_core.js Names, personalities, relationships, effects, spatial grid.
js/health.js Damage memory, death-cause normalization, damage application.
js/items.js Item state, lifecycle, drawing, grass/zunchi/ball/firecracker logic.
js/tarinai.js Agent state, AI, disease state, eating, conflict, reproduction, draw.
-js/world.js World update, placement, weather, logs, save/load, global interactions.
+js/world.js World update, placement, weather, logs, global interactions.
js/ui.js Input, tool selection, dialogs, observation panel.
js/ui_charts.js Population/statistics charts.
js/ui_family.js Family/archive UI and cause-of-death display.
@@ -69,7 +69,7 @@ docs/code_map.md Symbol-to-file lookup table.
## v15 notes
- Colony chart tab `events` was removed. `environment` now reports security, hygiene, and happiness.
-- Selected Tarinai UI includes per-individual records derived from matching observation log entries.
+- Selected Tarinai UI includes per-individual records attached by structured observation events.
- Observation highlights selected relatives and major social relations: parent, child, friend, enemy.
- Explosions impart velocity to nearby zunchi items; cursor contact reduces stress and emits dense heart effects.
diff --git a/assets/objects/genkotsu.png b/assets/objects/genkotsu.png
new file mode 100644
index 0000000..8160368
Binary files /dev/null and b/assets/objects/genkotsu.png differ
diff --git a/assets/ui/tool_genkotsu.png b/assets/ui/tool_genkotsu.png
new file mode 100644
index 0000000..8160368
Binary files /dev/null and b/assets/ui/tool_genkotsu.png differ
diff --git a/assets/ui/tool_nest_box.png b/assets/ui/tool_nest_box.png
index c681d19..4f60156 100644
Binary files a/assets/ui/tool_nest_box.png and b/assets/ui/tool_nest_box.png differ
diff --git a/css/styles.css b/css/styles.css
index 2b87d0d..c41a5e0 100644
--- a/css/styles.css
+++ b/css/styles.css
@@ -1,4 +1,3 @@
-@import url("https://fonts.googleapis.com/css2?family=Yomogi&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Zen+Maru+Gothic:wght@400;500;700&family=M+PLUS+Rounded+1c:wght@400;500;700&family=Yomogi&display=swap");
:root {
@@ -36,6 +35,64 @@ button {
color: inherit;
}
+.loading-screen {
+ position: fixed;
+ inset: 0;
+ z-index: 9999;
+ display: grid;
+ place-items: center;
+ padding: 24px;
+ background:
+ radial-gradient(circle at 50% 30%, rgba(164, 225, 104, 0.22), transparent 32%),
+ linear-gradient(180deg, rgba(239, 248, 255, 0.98), rgba(247, 245, 236, 0.98));
+ transition: opacity 180ms ease, visibility 180ms ease;
+}
+.loading-screen.hidden {
+ opacity: 0;
+ visibility: hidden;
+ pointer-events: none;
+}
+.loading-panel {
+ width: min(420px, 92vw);
+ padding: 24px 22px;
+ border-radius: 24px;
+ border: 1px solid rgba(84, 68, 48, 0.16);
+ background: rgba(255, 252, 246, 0.92);
+ box-shadow: 0 18px 48px rgba(64, 48, 32, 0.16);
+ text-align: center;
+}
+.loading-title {
+ font-weight: 700;
+ font-size: 18px;
+ letter-spacing: 0.04em;
+ margin-bottom: 8px;
+}
+.loading-text {
+ color: var(--muted);
+ font-size: 13px;
+ line-height: 1.55;
+ min-height: 1.55em;
+}
+.loading-bar {
+ height: 12px;
+ margin: 18px 0 8px;
+ border-radius: 999px;
+ overflow: hidden;
+ background: rgba(90, 70, 48, 0.12);
+}
+.loading-bar-fill {
+ width: 0%;
+ height: 100%;
+ border-radius: inherit;
+ background: linear-gradient(90deg, #9ce84b, #f0d35b);
+ transition: width 160ms ease;
+}
+.loading-percent {
+ color: var(--muted);
+ font-size: 12px;
+ font-variant-numeric: tabular-nums;
+}
+
#app {
width: min(1480px, 100vw);
margin: 0 auto;
@@ -191,23 +248,6 @@ h1 {
justify-content: flex-end;
gap: 8px;
}
-.save-text-dialog-panel {
- width: min(760px, calc(100vw - 30px));
-}
-.save-text-area {
- width: 100%;
- min-height: 180px;
- margin-top: 10px;
- padding: 10px;
- border-radius: 12px;
- border: 1px solid var(--line);
- background: rgba(255,255,255,0.82);
- color: var(--ink);
- font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
- resize: vertical;
- word-break: break-all;
-}
-.save-text-actions { flex-wrap: wrap; }
.archive-reset-dialog-panel {
width: min(420px, 100%);
}
@@ -349,32 +389,18 @@ h1 {
.tool[data-tool="sweet"] { --tool-icon: url("../assets/ui/tool_sweet.png"); }
.tool[data-tool="grass"] { --tool-icon: url("../assets/ui/tool_grass.png"); }
.tool[data-tool="stone"] { --tool-icon: url("../assets/ui/tool_stone.png"); }
+.tool[data-tool="genkotsu"] { --tool-icon: url("../assets/ui/tool_genkotsu.png"); }
.tool[data-tool="firecracker"] { --tool-icon: url("../assets/ui/tool_firecracker.png"); }
.tool[data-tool="fence_v"] { --tool-icon: url("../assets/ui/tool_fence_v.png"); }
.tool[data-tool="fence_h"] { --tool-icon: url("../assets/ui/tool_fence_h.png"); }
.tool[data-tool="bed"] { --tool-icon: url("../assets/ui/tool_bed.png"); }
-.tool[data-tool="ball"] { --tool-icon: none; }
-.tool[data-tool="ball"]::before {
- content: "\26bd ";
- background: none;
- font-size: 24px;
- line-height: 1;
- filter: drop-shadow(0 2px 3px rgba(52,40,26,0.12));
-}
-.tool[data-tool="ball"]::after {
- content: "\26bd ";
- background: none;
- font-size: 48px;
- line-height: 1;
- opacity: 0.10;
- right: -6px;
- left: auto;
- top: 50%;
- bottom: auto;
- transform: translateY(-50%);
- width: 54px;
- height: 54px;
-}
+.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="ant_nest"] { --tool-icon: url("../assets/ui/tool_ant_nest.png"); }
+.tool[data-tool="ball"] { --tool-icon: url("../assets/ui/tool_ball.png"); }
.tool[data-tool="poke"] { --tool-icon: none; }
.tool[data-tool="poke"]::before {
content: "\1F448";
@@ -420,39 +446,19 @@ h1 {
width: 54px;
height: 54px;
}
-.tool[data-tool="love_mochi"] { --tool-icon: none; }
-.tool[data-tool="love_mochi"]::before {
- content: "\1F495";
+.tool[data-tool="water_hose"] { --tool-icon: none; }
+.tool[data-tool="water_hose"]::before {
+ content: "\1F6BF";
background: none;
+ font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
font-size: 24px;
line-height: 1;
filter: drop-shadow(0 2px 3px rgba(52,40,26,0.12));
}
-.tool[data-tool="love_mochi"]::after {
- content: "\1F495";
- background: none;
- font-size: 46px;
- line-height: 1;
- opacity: 0.10;
- right: -6px;
- left: auto;
- top: 50%;
- bottom: auto;
- transform: translateY(-50%);
- width: 54px;
- height: 54px;
-}
-.tool[data-tool="fight_mochi"] { --tool-icon: none; }
-.tool[data-tool="fight_mochi"]::before {
- content: "\1F4A2";
- background: none;
- font-size: 24px;
- line-height: 1;
- filter: drop-shadow(0 2px 3px rgba(52,40,26,0.12));
-}
-.tool[data-tool="fight_mochi"]::after {
- content: "\1F4A2";
+.tool[data-tool="water_hose"]::after {
+ content: "\1F6BF";
background: none;
+ font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
font-size: 46px;
line-height: 1;
opacity: 0.10;
@@ -506,6 +512,36 @@ h1 {
.tool-category.collapsed .tool-category-toggle::before { content: "\25b8 "; }
.tool-category-body { padding: 8px; }
.tool-category.collapsed .tool-category-body { display: none; }
+
+.selected-data-groups {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ margin-top: 8px;
+}
+.selected-category {
+ border: 1px solid rgba(84,68,48,0.10);
+ border-radius: 14px;
+ background: rgba(255,255,255,0.30);
+ overflow: hidden;
+}
+.selected-category-toggle {
+ width: 100%;
+ border: 0;
+ border-bottom: 1px solid rgba(84,68,48,0.08);
+ background: rgba(255,252,244,0.66);
+ padding: 8px 10px;
+ text-align: left;
+ cursor: pointer;
+ font-weight: 700;
+ font-size: 12px;
+ color: var(--ink);
+}
+.selected-category-toggle::before { content: "\25be "; display: inline-block; width: 16px; color: var(--muted); }
+.selected-category.collapsed .selected-category-toggle::before { content: "\25b8 "; }
+.selected-category-body { padding: 7px 9px; }
+.selected-category.collapsed .selected-category-body { display: none; }
+.selected-category-body .info-row:last-child { border-bottom: 0; }
.tool-size-badge {
position: absolute;
right: 7px;
@@ -993,6 +1029,20 @@ body::before {
z-index: 1;
isolation: isolate;
}
+
+.lineage-actions {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ flex-wrap: wrap;
+ justify-content: flex-end;
+}
+.btn.active {
+ background: #efffde;
+ border-color: rgba(103,178,44,0.46);
+ font-weight: 700;
+}
+
.lineage-render-status {
position: sticky;
top: 0;
@@ -1106,38 +1156,6 @@ body::before {
}
-.tool[data-tool="water_bowl"] { --tool-icon: none; }
-.tool[data-tool="water_bowl"]::before {
- content: "\1F963";
- font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
- font-size: 23px;
- display: grid;
- place-items: center;
-}
-.tool[data-tool="sleep_drug"] { --tool-icon: none; }
-.tool[data-tool="sleep_drug"]::before {
- content: "\1F48A";
- font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
- font-size: 23px;
- display: grid;
- place-items: center;
-}
-.tool[data-tool="nest_box"] { --tool-icon: none; }
-.tool[data-tool="nest_box"]::before {
- content: "\1FABA";
- font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
- font-size: 23px;
- display: grid;
- place-items: center;
-}
-.tool[data-tool="water_hose"] { --tool-icon: none; }
-.tool[data-tool="water_hose"]::before {
- content: "\1F6BF";
- font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
- font-size: 23px;
- display: grid;
- place-items: center;
-}
.tool[data-tip] { position: relative; }
.tool-tip-popover {
position: fixed;
@@ -1210,149 +1228,6 @@ body::before {
font-weight: 600;
}
-.tool[data-tool="water_bowl"]::before,
-.tool[data-tool="sleep_drug"]::before,
-.tool[data-tool="nest_box"]::before,
-.tool[data-tool="water_hose"]::before {
- position: absolute;
- left: 7px;
- top: 50%;
- width: 30px;
- height: 30px;
- transform: translateY(-50%);
- background: none;
- line-height: 30px;
- text-align: center;
- overflow: hidden;
-}
-.tool[data-tool="water_bowl"]::after,
-.tool[data-tool="sleep_drug"]::after,
-.tool[data-tool="nest_box"]::after,
-.tool[data-tool="water_hose"]::after {
- 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: "\1F448"; }
-.tool[data-tool="pinch"]::before { content: "\1F90F"; }
-.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: "\1F448"; }
-.tool[data-tool="pinch"]::after { content: "\1F90F"; }
-.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: "\1F6BF";
- 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: "\1F6BF";
- 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%);
-}
-
.relation-list-row {
align-items: start;
}
@@ -1416,32 +1291,3 @@ body::before {
opacity: 0.72;
flex: 0 0 auto;
}
-.tool[data-tool="ant_nest"] { --tool-icon: url("../assets/ui/tool_ant_nest.png"); }
-.tool[data-tool="ant_nest"]::before {
- content: "";
- background: var(--tool-icon) center / contain no-repeat;
-}
-.tool[data-tool="ant_nest"]::after {
- content: "";
- background: var(--tool-icon) right -8px center / 54px 54px no-repeat;
-}
-
-/* v15.7.2: object-faithful tool icons for ball and nest box. */
-.tool[data-tool="ball"] { --tool-icon: url("../assets/ui/tool_ball.png"); }
-.tool[data-tool="ball"]::before,
-.tool[data-tool="ball"]::after {
- content: "";
- background: var(--tool-icon) center / contain no-repeat;
- font-size: 0;
-}
-.tool[data-tool="ball"]::after {
- background-position: right -8px center;
- background-size: 54px 54px;
- opacity: 0.10;
-}
-.tool[data-tool="nest_box"] { --tool-icon: url("../assets/ui/tool_nest_box.png"); }
-.tool[data-tool="nest_box"]::after {
- content: "";
- background: var(--tool-icon) right -8px center / 54px 54px no-repeat;
- opacity: 0.10;
-}
diff --git a/docs/AI_CONTEXT.md b/docs/AI_CONTEXT.md
index 593a0dc..53984ed 100644
--- a/docs/AI_CONTEXT.md
+++ b/docs/AI_CONTEXT.md
@@ -5,9 +5,9 @@ Purpose: dense orientation for code-editing agents. Browser-only simulation; no
Load order from `index.html`: `data -> math -> assets -> audio -> render -> sim_core -> items -> health -> tarinai -> world -> text_catalog -> ui -> ui_charts -> ui_family -> main`.
Primary objects:
-- `World` (`js/world.js`): owns field size, time/weather, tarinai array, items, effects, logs, archive, save/load, placement, collision, interaction dispatch.
+- `World` (`js/world.js`): owns field size, time/weather, tarinai array, items, effects, logs, archive, placement, collision, interaction dispatch.
- `Tarinai` (`js/tarinai.js`): agent state and AI. Use helper files for shared rules; avoid making this file larger.
-- `Item` (`js/items.js`): item state, draw, lifecycle, serialization.
+- `Item` (`js/items.js`): item state, draw, lifecycle.
- `HEALTH` (`js/health.js`): damage memory, major-damage window, death-cause classification, damage application.
- `TEXT_CATALOG` (`js/text_catalog.js`): Japanese tooltips and ecology cards. Keep Japanese escaped.
diff --git a/docs/code_map.md b/docs/code_map.md
index 6a4bd87..5ae1a80 100644
--- a/docs/code_map.md
+++ b/docs/code_map.md
@@ -15,7 +15,7 @@ Use this as the first lookup table before opening large files.
| Item creation/lifecycle/draw | `js/items.js` / `class Item` |
| Cleaning, rain, placement | `js/world.js` / placement/update interaction helpers |
| Fence collision | `js/world.js` / `resolveFenceCollision` |
-| Logs/archive/save | `js/world.js` |
+| Logs/archive | `js/world.js` |
| Main renderer | `js/render.js` / `render` helpers |
| Agent drawing | `js/tarinai.js` / `draw` |
| Input/tools/dialogs | `js/ui.js` |
diff --git a/docs/prompt.txt b/docs/prompt.txt
index dc90944..c54aa78 100644
--- a/docs/prompt.txt
+++ b/docs/prompt.txt
@@ -1,265 +1,910 @@
-You are modifying an existing JavaScript browser game project.
+You are working on the latest Tarinai observation game build.
-Implement a personality system for the \u201ctarinai\u201d creatures. Keep the implementation conservative and debuggable. Do not add extra systems beyond the specification below.
+Base input:
-## Goal
+* Start from `tarinai_colony_game_ant_nest_v5_fixed(1).zip`.
+* The extracted project folder may be named `tarinai_colony_game_personality_fixed`.
+* Modify the project files directly.
+* Return a new zip named something like `tarinai_colony_game_ant_nest_v6_fixed.zip`.
+* Preserve the current Japanese UI tone and naming style.
+* After changes, run syntax checks on all JavaScript files and verify zip integrity.
+* Bump all cache-busting versions in `index.html` consistently so browsers do not keep loading old JS/CSS.
-Add four continuous personality parameters to each tarinai:
+Important context:
+
+* This latest build already includes the four-axis personality system.
+* This latest build already includes the ant nest feature.
+* Do not revert either of those systems.
+* Do not reintroduce the old legacy named personality system.
+* Do not preserve old save compatibility.
+* Old local save data is irrelevant.
+
+Important intentional behaviors to preserve:
+
+* The family tree reset feature is intentional. It exists so the player can delete an extremely large/heavy family tree. Do not remove it.
+* The family tree reset may clear family tree data/cache and related heavy relationship graph data according to the current intended behavior. Do not “fix” it as a bug.
+* Item placement drop-impact damage is intentional. Do not remove it.
+* Keep item placement drop damage behavior as-is unless it directly causes a runtime error.
+* Grass planting checks may remain mostly as-is.
+* Tool-size inheritance may remain as-is.
+* Screen resizing may reset the field. Do not add complicated resize preservation logic.
+
+---
+
+# 1. Completely remove save/load functionality
+
+Remove the save/load feature entirely.
+
+Requirements:
+
+* Remove manual save buttons, load buttons, autosave controls, import/export controls, or any equivalent UI if present.
+* Remove localStorage save/load usage.
+* Remove autosave timers.
+* Remove save key constants such as `tarinai-colony-save-*`.
+* Remove save migration logic.
+* Remove backward compatibility code for old saves.
+* Remove serialization/deserialization code that exists only for save/load.
+* Remove comments and fallback code related to old save formats.
+* Do not preserve compatibility with previous versions.
+* Do not add new save/load functionality.
+* Do not remove normal image/audio asset loading functions. Only remove game-state save/load.
+
+Current-code hints:
+
+* `CONFIG.saveKey` still exists and should be removed.
+* `serialize()` / `load(data)` style world-state code still exists and should be removed if it is only used for save/load.
+* CSS classes for old save text dialogs should be removed if unused.
+* Legacy personality stubs that exist only for old-save compatibility should be removed if they are not used by the current four-axis personality system.
+
+Expected result:
+
+* The game starts fresh.
+* No save/load UI is visible.
+* No old localStorage data is read.
+* No migration or compatibility logic remains.
+
+---
+
+# 2. Living Tarinai internal IDs
+
+Introduce or refactor to a living-only internal ID system for Tarinai.
+
+Important:
+
+* The existing code uses `id` widely for Tarinai identity, family tree, ants, relationships, and logs.
+* Do not blindly make historical family-tree identity reusable if that would corrupt the family tree.
+* The requested reusable ID is the active living individual ID.
+* If persistent historical/family-tree identity is still needed, introduce a separate internal snapshot/archive key such as `familyKey` or `archiveKey`.
+* Do not display either ID in the UI.
+
+Requirements:
+
+* Every living Tarinai must have an internal living ID.
+* The living ID must not be displayed.
+* Use the living ID internally for:
+
+ * observation event ownership
+ * relationship highlights
+ * fight participants
+ * damage attribution where needed
+ * current ant targeting/dragging
+ * current selection state
+ * avoiding name-based ambiguity
+* Do not use display name text as an internal identifier.
+* Death must completely remove/release the living ID from the active living registry.
+* Released living IDs may be reused by later Tarinai.
+* Reusing a living ID must not attach new Tarinai events to an old dead Tarinai’s logs, observation history, family tree entry, or ant target.
+* Any historical display that survives death must store a display snapshot separately:
+
+ * name snapshot
+ * sprite/type snapshot
+ * death cause
+ * family links if needed
+ * any required personality display snapshot
+* Ants that target or drag a Tarinai must not accidentally switch to a new Tarinai after a released living ID is reused. Use direct object references, validation tokens, or live ID plus generation token if necessary.
+
+Expected result:
+
+* Living Tarinai are internally identifiable without relying on names.
+* Dead Tarinai living IDs are released and reusable.
+* Historical displays remain stable.
+* ID reuse does not corrupt logs, family tree, relationships, selection, or ant behavior.
+
+---
+
+# 3. Four-axis personality compatibility
+
+The latest build uses four continuous personality axes:
* aggression
* openness
* sociability
* neuroticism
-Each parameter ranges from `-1.0` to `+1.0`.
+Do not reintroduce legacy named personality as a main data model.
-Personality should affect behavior only when the value crosses clear thresholds. Small changes should be recorded internally, but observation logs should only be written when a threshold is crossed.
+Coward/timid behavior:
-## Personality axes
+* Do not set a legacy `currentPersonality = "臆病"` style value.
+* Do not add a separate cowardice parameter.
+* `臆病` should remain a derived tag/state based on the four-axis personality model.
+* The existing intended derivation is high neuroticism plus low aggression.
+* When a Tarinai takes damage and its total fight losses are greater than its total fight wins:
-### aggression
+ * with 5% chance, shift its current personality slightly toward cowardly behavior,
+ * for example increase neuroticism and decrease aggression,
+ * use only total fight wins/losses,
+ * do not include per-relationship win/loss counts,
+ * do not double count.
+* If this behavior is already implemented correctly, keep it and only clean up naming/comments so it does not imply a legacy named-personality route.
-Range:
+Expected result:
-* low side: calm
-* high side: irritable
+* The four-axis personality system remains intact.
+* `臆病` remains a derived display/behavior tag, not a separate old personality.
+* The damage/loss condition uses only aggregate lifetime fight result counters.
-Behavior:
+---
-* High aggression makes the tarinai more likely to threaten others, start fights, or retaliate.
-* Low aggression makes the tarinai less likely to start fights.
+# 4. Observation logs, event ownership, filtering, and statistics
-Changes:
+Current issues:
-* Winning fights should slightly increase aggression.
-* Losing fights should slightly decrease aggression.
+* Observation logs may still be assigned by checking whether event text includes a Tarinai’s name.
+* Hidden observation events may still count in event statistics.
+* `つつく` / poke may still be classified as fight by text inference.
-### openness
+Implement:
-Range:
+* Observation events must store structured participant references.
+* Use living Tarinai IDs while participants are alive.
+* Also store display-name snapshots so old logs remain correct after death or ID reuse.
+* Do not assign observation events by `text.includes(name)` or similar name substring matching.
+* Event objects should have structured fields such as:
-* low side: conservative
-* high side: playful
+ * `type`
+ * `actorLiveId`
+ * `targetLiveId`
+ * `participantLiveIds`
+ * `participantSnapshots`
+ * `hiddenFromObservation`
+ * `countInStats`
+* Exact field names are flexible, but the data must be structured.
+* Hidden observation events must not be counted in statistics.
+* Do not merely hide them from the UI while still incrementing counters.
+* Events hidden from observation UI should either not be logged as visible observation events or should be marked with `countInStats: false`.
-Behavior:
+Remove from the observation UI and statistics:
-* High openness makes the tarinai more likely to wander farther, investigate new objects, and play with toys such as balls.
-* Low openness makes the tarinai prefer familiar or nearby areas.
+* events about poking a ball
+* events of the form “X avoided Y” / `○○が××を避けた`
+* events that merely indicate selecting a Tarinai for observation, such as `○○を選択した。`
-Changes:
+Important classification rule:
-* Being petted by the cursor should slightly increase openness.
+* `つつく` / poke is not a fight.
+* Do not classify poke events as `fight`.
+* If there is an `inferLogKind()` or equivalent text-based classifier, fix or replace it so poke does not become fight.
+* Prefer structured event types over Japanese text matching.
-### sociability
+Log display formatting:
-Range:
+* Remove name-substring based log decoration where practical.
+* Render participant names from structured event snapshots.
+* If a participant has died and its living ID was released, use the display-name snapshot stored in the event.
+* Do not allow reused living IDs to rewrite old log display names.
-* low side: loner
-* high side: social
+Expected result:
-Behavior:
+* Observation logs attach to the correct individuals.
+* Hidden events are not shown and not counted.
+* Poke is not treated as fight.
+* Similar Tarinai names no longer corrupt logs.
-* High sociability makes the tarinai more likely to approach other tarinai, especially parents, children, friends, or the cursor.
-* High sociability also makes the tarinai more likely to react when a parent, child, or friend is fighting nearby.
-* Low sociability makes the tarinai prefer being alone.
+---
-Changes:
+# 5. Family tree update performance and scheduling
-* Spending time near parents, children, or friends should slightly increase sociability.
+The latest build already has some idle/chunked family tree rendering. Preserve it and finish the scheduling/consistency work.
-### neuroticism
+Requirements:
-Range:
+* Keep heavy preprocessing split 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.
-* low side: insensitive / unfazed
-* high side: delicate / sensitive
+Update timing rules:
-Behavior:
+* When the family tree panel is hidden or offscreen:
-* High neuroticism makes the tarinai gain more stress from unpleasant stimuli such as corpses, poop, nearby fights, or overcrowding.
-* Low neuroticism makes the tarinai less affected by such stimuli.
+ * Do not update every 5 seconds.
+ * Check/update at most once every 30 seconds.
+* When the family tree panel is visible:
-Changes:
+ * 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:
-* Touching poop or corpses should still increase stress immediately.
-* However, repeated exposure should slightly reduce neuroticism over time, representing habituation.
-* This means tarinai can become less sensitive to unpleasant stimuli after repeated exposure.
+ * birth
+ * death
+ * parent/child relationship creation
+ * mate/partner relationship creation or change
+ * name/identity data change that affects the family tree display
+ * family tree reset
+* 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.
+* If the family tree reset button is used, cancel stale pending render tokens/timers so old async work cannot reinsert deleted tree HTML afterward.
-Important:
+Important preservation rule:
-* Do not treat \u201ccowardice\u201d as a direct low-aggression state.
-* If a cowardly tag is needed, derive it as a compound state from high neuroticism and low aggression.
-* Do not implement a separate cowardice parameter.
+* Do not remove the family tree reset feature.
+* It is intentional and may clear family tree data/cache and current heavy relationship graph data.
+* Only fix reset-related runtime errors or stale async render problems.
-## Birth personality and current personality
+Expected result:
-Each tarinai should have two personality objects:
+* Opening or updating the family tree should not freeze the main simulation.
+* Hidden family tree work should be rare.
+* Visible family tree should refresh promptly after actual changes.
+* Reset remains available and does not allow stale async renders to restore old content.
-```js
-birthPersonality
-currentPersonality
-```
+---
-Rules:
+# 6. Disease fight initiation and targeting rules
-* `birthPersonality` is created at birth and normally does not change.
-* `currentPersonality` starts equal to `birthPersonality`.
-* Experience modifies only `currentPersonality`.
-* The tarinai data UI should show both birth personality and current personality.
+Implement the following disease fight rules exactly.
-## Inheritance
+Fight initiation:
-When a child is born:
+* 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.
-```text
-child birth personality =
- average of the parents' current personality
- + random variation between -0.2 and +0.2 for each parameter
-```
+Being targeted / challenged:
-Clamp each resulting value to `-1.0` through `+1.0`.
+* Tarinai with `ねむり病` must not be targeted for fights.
+* Tarinai with any other disease may still be targeted/challenged by another Tarinai.
+* This means:
-Then:
+ * `爆発病` and `ずんち病`: can initiate and can be targeted.
+ * `きずつき病` and other non-sleep diseases: cannot initiate, but can be targeted.
+ * `ねむり病`: cannot initiate and cannot be targeted.
-```js
-child.currentPersonality = child.birthPersonality
-```
+Apply consistently to:
-The child should pass its changed current personality to future descendants, not only its original birth personality.
+* Normal fight selection.
+* Forced fight logic.
+* Intimidation logic if it can lead to fights.
+* Fight-food effects such as `けんか餅`.
+* Any helper such as `canStartFight`, `canBeFightTarget`, or equivalent.
-## Thresholds and personality tags
+Expected result:
-Use two threshold levels:
+* Disease rules are handled by clear helper functions.
+* No scattered ad-hoc disease checks disagree.
-```text
--1.0 to -0.75: strong low-side trait
--0.75 to -0.5: slight low-side trait
--0.5 to +0.5: neutral, no visible personality tag
-+0.5 to +0.75: slight high-side trait
-+0.75 to +1.0: strong high-side trait
-```
+---
-Display tags:
+# 7. Collision and external-force unification
-* Slight traits should be displayed as \u201cslightly X\u201d.
-* Strong traits should be displayed as \u201cX\u201d.
-* Neutral values should not create a visible tag.
+The latest build already has `applyImpulse()` and some collision refactoring. Preserve and finish the design.
-Example:
+Requirements:
-* aggression `+0.62` -> \u201cslightly irritable\u201d
-* aggression `+0.83` -> \u201cirritable\u201d
-* sociability `-0.58` -> \u201cslightly loner\u201d
-* sociability `-0.82` -> \u201cloner\u201d
-* openness `+0.20` -> no tag
+* Normal self-propelled movement and external impulse/knockback must remain separate.
+* External impulses must not be clamped by the normal Tarinai walking speed cap.
+* If helper functions already exist, reuse and tighten them instead of adding duplicates.
+* Useful helpers may include:
-Behavior activation:
+ * `applyImpulse(entity, vx, vy, options)`
+ * `applyKnockback(entity, sourceX, sourceY, strength, options)`
+ * `applyImpactDamage(target, amount, cause)`
+ * `resolveCircleCircleCollision(...)`
+ * `resolveCircleRectCollision(...)`
-* Slight traits affect relevant behavior with a 50% chance when choosing a behavior.
-* Strong traits affect relevant behavior with a 100% chance when choosing a behavior.
-* Do not check this every frame. Apply it only during behavior selection or when evaluating a relevant event.
+Unlimited ball speed:
-## Daily personality change limit
+* 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.
-Add a daily change cap so personality values cannot change too quickly.
+High-speed ball vs Tarinai:
-Recommended limits:
+* When a sufficiently fast ball hits a Tarinai:
-```text
-Per parameter:
- maximum increase per day: +0.08
- maximum decrease per day: -0.08
+ * 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 normal “play with ball” behavior also run for that same dangerous impact if it would conflict.
+ * If the damage from this impact kills the Tarinai, death cause must be `衝突`.
-Across all parameters:
- maximum total absolute personality change per day: 0.20
-```
+High-speed Tarinai vs Tarinai:
-If a change would exceed the daily limit, reduce or ignore the excess change.
+* When a sufficiently fast Tarinai hits another Tarinai:
-Reset these daily counters at the start of each new in-game day.
+ * The hit Tarinai should be knocked away.
+ * Use the attacker’s actual movement/impulse direction and speed.
+ * If collision damage kills a Tarinai, death cause must be `衝突`.
-## Observation log rules
+Explosion knockback:
-Write personality change entries to the observation log only when a threshold is crossed.
+* Keep explosion knockback strong.
+* 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 `衝突`.
-Log when:
+Ant interaction preservation:
-* a value crosses `+0.5`
-* a value crosses `+0.75`
-* a value crosses `-0.5`
-* a value crosses `-0.75`
-* a value returns from a visible trait range back into neutral
+* Preserve existing ant damage handling from firecracker explosions and dropped-object impacts.
+* Do not break worker ants, queen ants, ant corpses, or ant nest reproduction behavior while refactoring forces.
-Do not log every small personality change.
+Expected result:
-Example log messages:
+* 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 scattered custom math.
-```text
-\u201cMochi\u201d has become slightly irritable after winning fights.
-\u201cMimi\u201d has become playful after spending time with toys.
-\u201cNoko\u201d has become less sensitive after repeated contact with corpses.
-\u201cTari\u201d no longer seems especially social.
-```
+---
-Use the existing observation log system if one exists.
+# 8. Ball-to-ball collision
-## Tarinai data UI
+Ensure balls collide with each other robustly.
-Update the tarinai data UI to show personality information clearly.
+Requirements:
-It should include:
+* 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 infinite acceleration or NaN velocity.
+* Do not apply arbitrary maximum speed caps.
-1. Birth personality
-2. Current personality
-3. Visible personality tags derived from current personality
+If this is already implemented, verify it and remove any remaining contradictory caps or stale-grid issues.
-Example structure:
+---
-```text
-Personality Tags:
-slightly irritable / social
+# 9. Item falling speed
-Birth Personality:
-Aggression: -0.12
-Openness: +0.31
-Sociability: +0.48
-Neuroticism: +0.66
+Current issue:
+Item falling motion can look like it changes speed unnaturally.
-Current Personality:
-Aggression: +0.57
-Openness: +0.34
-Sociability: +0.76
-Neuroticism: +0.22
-```
+Implement:
-Keep the UI compact. Do not create a large new panel unless necessary.
+* Make the visible item falling motion constant speed.
+* Replace nonlinear visual curves such as `Math.pow(dropT, ...)` with linear progress unless a specific item intentionally has a special animation.
+* The item should fall at a stable fixed speed from its start height to the ground.
+* Keep the existing item placement drop-impact damage behavior.
+* Do not remove drop-impact damage.
+* Do not make harmless-looking items non-damaging merely because they look harmless. Current placement drop-impact behavior is intentional.
-## Implementation constraints
+Expected result:
-* Keep the code simple and localized.
-* Reuse existing behavior, logging, and UI systems where possible.
-* Avoid adding unrelated features.
-* Avoid adding complex new simulation systems.
-* Preserve existing save data as much as possible.
-* If old save data lacks personality fields, initialize them safely.
-* Clamp all personality values to `-1.0` through `+1.0`.
-* Add helper functions where useful, such as:
+* Falling items move at a visually consistent constant speed.
+* Existing drop impact behavior remains.
- * `ensurePersonality(tarinai)`
- * `adjustPersonality(tarinai, key, delta, reason)`
- * `getPersonalityTraitTags(tarinai)`
- * `getTraitStrength(value)`
- * `shouldApplyPersonalityBehavior(tarinai, key, direction)`
+---
-## Validation
+# 10. Solid obstacle and placement logic unification
-After implementation:
+Current issues:
+Fence, nest box, water dish, grass, and placement preview logic are partly fragmented.
-* Run syntax checks for all JavaScript files.
-* Verify that old tarinai without personality data do not crash the game.
-* Verify that personality values are clamped.
-* Verify that daily limits work.
-* Verify that threshold crossing creates observation logs.
-* Verify that minor personality changes do not spam logs.
-* Verify that tarinai data UI shows birth personality, current personality, and visible tags.
-* Verify that children inherit from parents' current personality with \u00b10.2 random variation.
+Implement:
+
+* Unify placement validation for the object types where overlap matters.
+* Overlap is important for:
+
+ * grass
+ * fence
+ * nest box
+ * water dish
+* For other items, overlap does not need to be strict unless an existing rule already requires it.
+* Do not over-engineer overlap rules for stones, balls, food items, firecrackers, poop, ant nests, ant corpses, or similar objects.
+
+Solid obstacles:
+
+* 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 movement, 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 any case 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.
+
+Grass placement:
+
+* Keep the existing grass planting spot search/check behavior unless it directly conflicts with the unified placement preview/actual placement contract.
+* Do not spend time expanding grass checks to every object type.
+
+Screen resize:
+
+* Do not implement special preservation behavior for screen resizing.
+* Screen size change is allowed to reset the field.
+* Do not add complicated coordinate scaling or migration logic for resize.
+
+Expected result:
+
+* Placement UI, actual placement, and collision behavior agree.
+* No “red but placeable” or “green but placed elsewhere” behavior.
+* Grass, fence, nest box, and water dish avoid important overlap.
+* Other item overlap can remain permissive.
+
+---
+
+# 11. Spatial query scratch arrays
+
+Current issue:
+`nearbyItems()` and `nearbyTarinai()` may share the same mutable scratch array. Nested spatial queries can overwrite an outer loop’s result.
+
+Implement:
+
+* `nearbyItems()` and `nearbyTarinai()` must not share the same mutable scratch array.
+* Nested spatial queries must not overwrite an outer loop’s result.
+* Use separate scratch arrays, return fresh arrays, or explicitly copy results where nested queries are possible.
+* Verify:
+
+ * item interaction loops
+ * bed/nest occupancy checks
+ * best bed search
+ * ball interactions
+ * Tarinai interaction loops
+ * ant prey search if it uses nearby queries
+
+Expected result:
+
+* Spatial queries are safe even when nested.
+* Loops over nearby entities do not mutate unexpectedly.
+
+---
+
+# 12. Spatial rebuild/update phase
+
+Current issue:
+The spatial grid may be rebuilt before entities move, so later collision and interaction passes can use stale positions.
+
+Implement:
+
+* Ensure spatial grid data is not stale during collision and interaction passes.
+* Prefer phase separation:
+
+ * update items
+ * update ants if their movement affects targeting/collision
+ * update Tarinai movement
+ * rebuild spatial grid
+ * resolve cross-entity interactions/collisions
+* If full phase separation is too invasive, at minimum rebuild the spatial grid after Tarinai movement and before any interaction/collision logic that relies on it.
+* Avoid relying on grid data from before entities moved.
+
+Expected result:
+
+* Nearby queries use current positions.
+* Collision and interaction behavior is more stable.
+
+---
+
+# 13. Duplicate weather log
+
+Current issue:
+Weather changes may create duplicate identical log entries in some builds.
+
+Implement:
+
+* Verify `updateWeather()`.
+* A weather change must create only one weather log entry.
+* Do not log the same weather text twice.
+* Preserve the actual weather behavior.
+
+Expected result:
+
+* One weather change produces one visible log entry.
+
+---
+
+# 14. Tool/item definition and CSS icon cleanup
+
+The latest build already has a `TOOL_DEFINITIONS`-style structure. Finish consolidating and remove conflicts.
+
+Requirements:
+
+* Use a single current source of truth for tool/item definitions where practical.
+* 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 scalable
+ * collision shape if applicable
+ * simulation-only status 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 `つまむ`.
+* If `洗浄` has both an emoji and a PNG icon, ensure the displayed tool UI follows the current requested shower emoji specification.
+* Fix the nest box tool UI icon so it matches the actual in-game nest box appearance.
+* Preserve the ant nest tool icon and ensure it remains visible.
+* Ensure every tool that appears in the tool UI has an icon.
+* Avoid mojibake/garbled icon rendering.
+* CSS icon definitions must be unified to the current specification.
+* Remove old CSS generations and conflicting icon overrides.
+* Do not rely on CSS order to accidentally choose the correct icon.
+
+Water tool:
+
+* `水` must remain removed from the tool UI.
+* If water still exists as a simulation object produced by rain or other systems, keep that object behavior.
+* `水の皿` remains a valid tool/item.
+* Keep `water` as simulation-only if needed.
+* Remove leftover UI-only water tool entries, labels, tooltips, and placement handlers unless required by non-UI simulation.
+
+Static tool buttons:
+
+* If `index.html` still hardcodes tool buttons, ensure it does not conflict with `TOOL_DEFINITIONS`.
+* Prefer generating or validating tool metadata from the definition table if practical.
+* At minimum, make sure static buttons and definition data agree.
+
+Expected result:
+
+* Tool UI no longer has missing icons, old icons, or mismatched nest box visuals.
+* Current icon definitions are clean and non-duplicated.
+* Ant nest remains integrated.
+
+---
+
+# 15. 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 observation UI, family tree, memorial/death display, and any other death display show the normalized cause.
+* Since save/load is removed, do not implement migration for old death-cause strings.
+
+Expected result:
+
+* Death cause strings are consistent.
+* Collision deaths do not appear as generic accidents.
+* Lifespan deaths show `天寿を全うした`.
+
+---
+
+# 16. Out-of-bounds object policy
+
+Implement or verify 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 `仕様により画面外で削除`.
+ * Release its living ID so it may be reused.
+* 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.
+* Ant workers/queens should not remain permanently invisible offscreen. If they go far out or become invalid, delete or safely return them according to the least disruptive current ant behavior.
+* Do not add resize-specific preservation logic; field reset on screen size change is acceptable.
+
+Expected result:
+
+* No permanent invisible offscreen objects or actors.
+* No NaN entities poison the simulation.
+* Far-outside Tarinai deletion has the correct death cause.
+
+---
+
+# 17. Observation relationship highlight
+
+Current issue:
+Relationship highlight during observation can be affected by sprite rotation in some builds.
+
+Implement or verify:
+
+* Relationship highlights must be drawn in world/screen space independent of 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.
+* Use living IDs or stable current object references for relationship lookup where appropriate, not name matching.
+* Include the latest intended relationship types:
+
+ * parents
+ * children
+ * enemies
+ * friends, using the current friendship threshold
+
+Expected result:
+
+* Highlight remains visually stable regardless of sprite rotation.
+* Highlight targets the correct individuals.
+
+---
+
+# 18. 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.
+* Living Tarinai IDs must not break nest box occupancy.
+* Since save/load is removed, do not add save compatibility for nest box IDs.
+
+Expected result:
+
+* Nest box behavior remains stable after obstacle and ID refactoring.
+
+---
+
+# 19. Ant nest behavior preservation
+
+Preserve the current ant nest feature.
+
+Do not regress:
+
+* `ant_nest` remains placeable.
+* Each ant nest starts with the intended worker count.
+* Worker ants spawn from their home nest.
+* Worker ants search for Tarinai and drag them back to the nest.
+* Multiple workers dragging the same Tarinai increase carrying speed.
+* Dragged Tarinai can struggle and kill workers.
+* Dead workers become edible `ant_corpse` items.
+* Damaged workers keep their HP when returning to and leaving the nest.
+* A full nest can spawn a queen.
+* A queen can create a new ant nest in an open spot.
+* Queen spawning remains limited according to the current intended daily rule.
+* Ant health does not recover.
+* Ant sprites and Irasutoya credit remain.
+
+ID-related requirements:
+
+* Ants must not use display names to target Tarinai.
+* Ant target references must not break after living ID reuse.
+* If a target Tarinai dies, is deleted, or its living ID is released, worker ants should safely abandon or retarget according to current behavior.
+* Removing save/load must not remove active runtime ant behavior.
+
+Expected result:
+
+* Ant nest behavior remains intact after ID, save/load, and spatial refactoring.
+
+---
+
+# 20. 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.
+* Keep the latest shortened ecology cards and HP/stress meter placement note if present.
+* Do not break existing encyclopedia entries.
+* Preserve the Irasutoya credit entry added for ant assets.
+
+---
+
+# 21. Naming and Japanese text preservation
+
+Preserve previous Japanese terminology changes:
+
+* `喧嘩傷病` must remain renamed to `きずつき病`.
+* Lifespan death text must display as `天寿を全うした`.
+* Friend relation label should remain `友達` if that is the current intended label.
+* Use the existing tone/style for Japanese labels and descriptions.
+* Do not reintroduce removed or old names.
+
+---
+
+# 22. Remove obsolete or dead code where safe
+
+Clean up old or dead specifications, but do not remove active gameplay.
+
+Remove or simplify where safe:
+
+* old save/load compatibility code
+* old save migration code
+* old CSS icon generations
+* obsolete tool icon definitions
+* UI-only `water` tool leftovers
+* unused save-only item serialization fields
+* comments describing removed old-save behavior
+* old code paths for removed tools such as UI `水`
+* old legacy named-personality compatibility stubs if they exist only for old saves
+* old `food`, `mirror`, `cardboard`, or similar legacy remnants only if they are truly unreachable and not part of current gameplay
+
+Keep:
+
+* Current rain/simulation water behavior if it exists.
+* Current grass planting behavior.
+* Current tool-size inheritance behavior.
+* Current field reset behavior on screen resize.
+* Family tree reset feature.
+* Item placement drop-impact damage.
+* Four-axis personality system.
+* Ant nest feature.
+
+---
+
+# 23. Input cleanup
+
+If practical without destabilizing gameplay, clean up mouse/touch input handling.
+
+Requirements:
+
+* Consider converting canvas input to `PointerEvent` handling.
+* Keep behavior equivalent on desktop.
+* Ensure dragging, pinching, hosing, placing, panning, and clicking remain stable.
+* Do not make this a large risky rewrite if the existing input system is stable.
+* This is lower priority than save/load removal, IDs, logging, collision, family tree performance, spatial safety, and item falling speed.
+
+Expected result:
+
+* Input behavior remains stable.
+* Touch and pointer handling do not regress.
+
+---
+
+# 24. 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.
+* Do not add save compatibility or migration code.
+* Do not over-engineer screen-resize preservation.
+* Keep intentional odd behaviors when explicitly listed above.
+
+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
+* reusable living Tarinai IDs
+* hidden observation events not counting in statistics
+* four-axis personality compatibility
+* constant item falling speed
+* intentional family tree reset behavior
+* intentional item placement drop-impact damage
+* ant target safety with reusable living IDs
+
+---
+
+# 25. 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 all cache version references are updated consistently.
+* Ensure save/load functions and UI are removed.
+* Ensure no localStorage game-state save/load code remains.
+* Ensure old save migration and old-save compatibility comments are removed.
+
+Manual or scripted behavior checks where practical:
+
+* The game starts fresh without reading old saves.
+* No save/load UI is visible.
+* Living Tarinai have internal living IDs.
+* Living IDs are not displayed.
+* Dead Tarinai living IDs are released and can be reused without corrupting active references.
+* Historical family tree/log display snapshots remain stable after death and ID reuse.
+* Ant targeting does not break when Tarinai die or living IDs are released.
+* Observation events attach by structured IDs/snapshots, not by name substring.
+* Hidden observation events do not appear and do not count in statistics.
+* `つつく` is not classified as fight.
+* Selecting a Tarinai for observation is not counted as a gameplay event/stat.
+* 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.
+* Falling items use visually constant falling speed.
+* Existing item placement drop-impact damage still exists.
+* 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.
+* Grass, fence, nest box, and water dish respect important overlap checks.
+* Other item overlap remains permissive unless already constrained.
+* Nest box collision uses the required 3×3 cells.
+* Ball bounces off nest box solid cells.
+* Spatial query results are safe from nested-query overwrites.
+* Spatial grid is not stale during interaction/collision passes.
+* A weather change creates only one log entry.
+* Family tree hidden/offscreen 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.
+* Family tree reset feature still exists and can clear heavy family tree data/cache.
+* Family tree reset does not allow stale async renders to restore old tree content.
+* Four-axis personality UI still works.
+* Legacy named personality is not reintroduced.
+* Damage plus total losses greater than total wins can shift personality toward derived `臆病` behavior without creating a legacy personality field.
+* `爆発病` 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: `👈`, `🤏`, `🚿`, nest box matching in-game appearance, and ant nest visible.
+* CSS icon definitions are unified to current specs.
+* `水` is absent from the tool UI.
+* `水の皿` remains available.
+* Simulation-only rain water still works if present.
+* Lifespan death cause is `天寿を全うした`.
+* Far-outside Tarinai deletion cause is `仕様により画面外で削除`.
+* Ant nest behavior still works.
+* Screen resize may reset the field; no special preservation behavior is required.
+
+Deliverable:
+
+* Return a zip named something like `tarinai_colony_game_ant_nest_v6_fixed.zip`.
+* Include a concise summary of changed areas and validation results.
diff --git a/index.html b/index.html
index 9e55382..c95f7b3 100644
--- a/index.html
+++ b/index.html
@@ -3,13 +3,20 @@