From 874911821f904270cc35ae3fe919a84f05c9f1fe Mon Sep 17 00:00:00 2001 From: 33333-33333 Date: Sat, 20 Jun 2026 20:29:44 +0900 Subject: [PATCH] fixed issueeessss --- PATCH_NOTES.md | 35 ++ README.md | 7 +- assets/sprites/tarinai_22_stress_blue.png | Bin 108346 -> 0 bytes assets/sprites/tarinai_23_stress_cry.png | Bin 111962 -> 0 bytes assets/ui/tool_pinch.png | Bin 1381 -> 0 bytes assets/ui/tool_poke.png | Bin 2391 -> 0 bytes css/styles.css | 162 +++++- docs/prompt.txt | 574 +++++++--------------- index.html | 74 +-- js/data.js | 63 ++- js/health.js | 17 +- js/items.js | 53 +- js/render.js | 53 +- js/sim_core.js | 193 +++++++- js/tarinai.js | 471 +++++++++++++----- js/text_catalog.js | 116 ++--- js/ui.js | 179 ++++++- js/ui_charts.js | 5 +- js/ui_family.js | 383 ++++++++++++--- js/world.js | 465 ++++++++++++++---- 20 files changed, 1950 insertions(+), 900 deletions(-) create mode 100644 PATCH_NOTES.md delete mode 100644 assets/sprites/tarinai_22_stress_blue.png delete mode 100644 assets/sprites/tarinai_23_stress_cry.png delete mode 100644 assets/ui/tool_pinch.png delete mode 100644 assets/ui/tool_poke.png diff --git a/PATCH_NOTES.md b/PATCH_NOTES.md new file mode 100644 index 0000000..8582fe4 --- /dev/null +++ b/PATCH_NOTES.md @@ -0,0 +1,35 @@ +# Patch Notes + +## Encoding cleanup +- Normalized `index.html` back to UTF-8. +- Replaced mojibake strings with the intended labels. +- Escaped Japanese text in source files to avoid encoding-dependent corruption. + +## Personality specification fixes +- Personality tags and data UI now use Japanese labels from the four-axis personality model. +- Threshold-crossing personality logs are now generated in Japanese and only when visible trait bands change. +- Daily personality caps now track increase and decrease separately per parameter. +- Current personality effects are neutral inside the -0.5 to +0.5 band. +- Direct conversion to the legacy timid personality after damage was removed; cowardly behavior is derived from high neuroticism plus low aggression. +- Corpse/splat contact now increases stress and slowly reduces neuroticism through habituation. + +## Follow-up fixes +- Fixed CSS emoji escapes for tool UI icons. CSS now uses code-point escapes such as `\\1F448` instead of invalid surrogate escapes. +- Hid the detailed four-axis personality rows from the compact tarinai data UI. +- Restored `bestBedFor()` fallback so tarinai can choose hay beds when no usable nest box is available. +- Damage now wakes sleeping tarinai and forces tarinai hidden inside a nest box to leave the box. +- Added a short minimum stay window after entering a nest box to avoid immediate exit loops. +- Renamed the friend relation label from `\\u4ef2\\u826f\\u3057` to `\\u53cb\\u9054` in UI text and related logs. + + +## Personality cleanup v3 +- Current live friend count now changes sociability drift. Family/friend proximity raises sociability more when the tarinai has more current friends, while a lonely tarinai with no current friends can slowly lose sociability. +- Removed the legacy named personality route from constructor, serialization, child inheritance, selected data UI, selected-card overlay, and family-tree titles. The game now uses only birthPersonality/currentPersonality four-axis data. +- Kept empty legacy stubs only for old-save compatibility so older saves cannot revive the pre-four-axis personality model. + +## Follow-up fixes v4 +- Restored compact personality information in the tarinai data panel: visible tags, birth personality, and current personality. +- Moved the focused-tarinai highlight outside the sprite rotation transform so the ring and label stay upright. +- Shortened ecology cards and added the HP/stress meter placement note: upper meter is HP, lower meter is stress. +- Raised the friendship threshold to 16 affinity and reused the same threshold for friend count, friend behavior, friend UI, and observe highlights. +- Observe mode now highlights friends of the selected tarinai as well as parents, children, and enemies. diff --git a/README.md b/README.md index e64b3d1..a55624e 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Read only these first: `README.md`, `docs/AI_CONTEXT.md`, `docs/code_map.md`. Th ## Important mechanics -- Personality affects fear, fighting, social pull, sleep priority, zunda preference, playfulness; children inherit one parent's personality. +- Personality uses four axes: aggression, openness, sociability, and neuroticism. Children inherit from the parents' current four-axis personality average with variation. - Relationships track affinity/fear/fight outcomes and influence approach, avoidance, intimidation, conflict, co-parent behavior, and UI summaries. - Death causes are normalized by `js/health.js`: fight, hunger, disease, stress overload, over-poking, firecracker, accident, lifespan. Major damage within 10 seconds can become ` de suyaku` in UI text (`...\u3067\u8870\u5f31`). - Water-curable diseases force high-priority water seeking. Zunda-curable diseases force high-priority zunda seeking. @@ -72,3 +72,8 @@ docs/code_map.md Symbol-to-file lookup table. - Selected Tarinai UI includes per-individual records derived from matching observation log entries. - 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. + +## v4 \u8ffd\u52a0\u4fee\u6b63 +- \u5de3\u7bb1\u5165\u9000\u5ba4\u3092\u5c02\u7528\u72b6\u614b\u5316\u3057\u3001\u900f\u660e\u5316\u30fb\u5f53\u305f\u308a\u5224\u5b9a\u6d88\u6ec5\u30fb\u500b\u4f53\u6570\u53cd\u6620\u30fb\u9000\u51fa\u5fa9\u5e30\u3092\u5b89\u5b9a\u5316\u3002 +- \u7761\u7720\u6642\u306e\u512a\u5148\u9806\u4f4d\u3092\u300c\u5de3\u7bb1 \u2192 \u5e72\u3057\u8349\u30d9\u30c3\u30c9 \u2192 \u305d\u306e\u5834\u300d\u306b\u5909\u66f4\u3002 +- \u305f\u308a\u306a\u3044\u30c7\u30fc\u30bfUI\u306e\u53cb\u9054/\u6575\u5bfe\u3092\u5168\u4ef6\u30c1\u30c3\u30d7\u8868\u793a\u306b\u3057\u3001\u30af\u30ea\u30c3\u30af\u3067\u500b\u4f53\u3078\u79fb\u52d5\u3067\u304d\u308b\u3088\u3046\u306b\u5909\u66f4\u3002 diff --git a/assets/sprites/tarinai_22_stress_blue.png b/assets/sprites/tarinai_22_stress_blue.png deleted file mode 100644 index b1f3b404151da3f1db221e2878bb8df2e598cb66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108346 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

Q%Ki$GQ5b^j_)e? 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 diff --git a/assets/sprites/tarinai_23_stress_cry.png b/assets/sprites/tarinai_23_stress_cry.png deleted file mode 100644 index 320a2b1f836abd489a0466d3cb519d413b581f6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111962 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�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 diff --git a/assets/ui/tool_pinch.png b/assets/ui/tool_pinch.png deleted file mode 100644 index 0ad3cf1a5e0a941e3e2c2957438fac1784f27daf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1381 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 JPDHLkV1gJlZn6LX diff --git a/css/styles.css b/css/styles.css index 8653502..74c557e 100644 --- a/css/styles.css +++ b/css/styles.css @@ -156,6 +156,8 @@ h1 { .field-dialog.hidden { display: none; } .field-dialog-panel { width: min(440px, 100%); + max-height: calc(100vh - 36px); + overflow: auto; border-radius: 16px; padding: 16px; background: rgba(255, 252, 245, 0.96); @@ -220,6 +222,9 @@ h1 { .ecology-dialog-panel { width: min(760px, 100%); + max-height: calc(100vh - 36px); + overflow-y: auto; + overscroll-behavior: contain; } .ecology-grid { display: grid; @@ -228,17 +233,17 @@ h1 { } .ecology-card { display: grid; - grid-template-columns: 84px minmax(0, 1fr); + grid-template-columns: 72px minmax(0, 1fr); gap: 10px; align-items: center; - padding: 12px; + padding: 10px; border-radius: 14px; background: linear-gradient(180deg, rgba(255,255,255,0.88), rgba(243,237,225,0.76)); border: 1px solid rgba(84,68,48,0.12); } .ecology-card img { - width: 84px; - height: 84px; + width: 72px; + height: 72px; object-fit: contain; filter: drop-shadow(0 8px 18px rgba(56, 44, 32, 0.10)); } @@ -251,7 +256,7 @@ h1 { margin: 0; color: var(--muted); font-size: 12px; - line-height: 1.55; + line-height: 1.40; } .toast { @@ -338,11 +343,10 @@ h1 { opacity: 0.10; pointer-events: none; } -.tool span { min-width: 16px; text-align: center; color: rgba(72,58,43,0.64); font-size: 10px; } +.tool > span:not(.tool-size-badge) { display: none; } .tool[data-tool="observe"] { --tool-icon: url("../assets/ui/tool_observe.png"); } .tool[data-tool="zunchi"] { --tool-icon: url("../assets/ui/tool_zunchi.png"); } .tool[data-tool="sweet"] { --tool-icon: url("../assets/ui/tool_sweet.png"); } -.tool[data-tool="water"] { --tool-icon: url("../assets/ui/tool_water.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="firecracker"] { --tool-icon: url("../assets/ui/tool_firecracker.png"); } @@ -373,14 +377,14 @@ h1 { } .tool[data-tool="poke"] { --tool-icon: none; } .tool[data-tool="poke"]::before { - content: "\1f448 "; + content: "\1F448"; background: none; font-size: 25px; line-height: 1; filter: drop-shadow(0 2px 3px rgba(52,40,26,0.12)); } .tool[data-tool="poke"]::after { - content: "\1f448 "; + content: "\1F448"; background: none; font-size: 48px; line-height: 1; @@ -396,14 +400,14 @@ h1 { .tool[data-tool="pinch"] { --tool-icon: none; } .tool[data-tool="pinch"]::before { - content: "\1f90f "; + content: "\1F90F"; background: none; font-size: 25px; line-height: 1; filter: drop-shadow(0 2px 3px rgba(52,40,26,0.12)); } .tool[data-tool="pinch"]::after { - content: "\1f90f "; + content: "\1F90F"; background: none; font-size: 48px; line-height: 1; @@ -418,14 +422,14 @@ h1 { } .tool[data-tool="love_mochi"] { --tool-icon: none; } .tool[data-tool="love_mochi"]::before { - content: "\1f495 "; + content: "\1F495"; background: none; 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 "; + content: "\1F495"; background: none; font-size: 46px; line-height: 1; @@ -440,14 +444,14 @@ h1 { } .tool[data-tool="fight_mochi"] { --tool-icon: none; } .tool[data-tool="fight_mochi"]::before { - content: "\1f4a2 "; + 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 "; + content: "\1F4A2"; background: none; font-size: 46px; line-height: 1; @@ -472,7 +476,7 @@ h1 { .hint { color: var(--muted); font-size: 12px; - line-height: 1.55; + line-height: 1.40; margin: 10px 0 0; } @@ -582,11 +586,36 @@ meter { .selected-info { font-size: 13px; - line-height: 1.55; + line-height: 1.40; } .selected-info.empty { color: var(--muted); } + +.selected-name-editor { + margin: 0 0 8px; +} +.selected-name-input { + width: 100%; + box-sizing: border-box; + border: 1px solid rgba(103,178,44,0.34); + border-radius: 13px; + background: rgba(246,252,238,0.96); + color: var(--ink); + font-size: 18px; + font-weight: 700; + line-height: 1.25; + padding: 8px 10px; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.82); +} +.selected-name-input:focus { + outline: 2px solid rgba(103,178,44,0.24); + border-color: rgba(103,178,44,0.62); + background: #fff; +} +.selected-effects { + margin: 2px 0 6px; +} .badge { display: inline-block; font-size: 11px; @@ -605,6 +634,29 @@ meter { padding: 5px 0; } .info-row span:first-child { color: var(--muted); } +.personality-values strong { + display: flex; + flex-wrap: wrap; + justify-content: flex-end; + gap: 2px 8px; + max-width: 68%; + text-align: right; +} +.personality-values strong span { + color: var(--ink); + white-space: nowrap; +} +.personality-tag { + display: inline-block; + border-radius: 999px; + padding: 2px 7px; + background: rgba(103,178,44,0.10); + border: 1px solid rgba(103,178,44,0.22); +} +.personality-tag.neutral { + background: rgba(120,110,90,0.08); + border-color: rgba(120,110,90,0.16); +} .log-card { min-height: 260px; flex: 0 0 auto; display: flex; flex-direction: column; } .log { @@ -1250,8 +1302,8 @@ body::before { display: block; opacity: 0.96; } -.tool[data-tool="poke"]::before { content: "👈"; } -.tool[data-tool="pinch"]::before { content: "🤏"; } +.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; @@ -1268,8 +1320,8 @@ body::before { width: 54px; height: 54px; } -.tool[data-tool="poke"]::after { content: "👈"; } -.tool[data-tool="pinch"]::after { content: "🤏"; } +.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; } @@ -1277,7 +1329,7 @@ body::before { /* 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: "🚿"; + content: "\1F6BF"; background: none; font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif; font-size: 24px; @@ -1287,7 +1339,7 @@ body::before { opacity: 0.96; } .tool[data-tool="water_hose"]::after { - content: "🚿"; + content: "\1F6BF"; background: none; font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif; font-size: 46px; @@ -1300,3 +1352,67 @@ body::before { bottom: auto; transform: translateY(-50%); } + +.relation-list-row { + align-items: start; +} +.relation-list-row > strong { + min-width: 0; + width: 100%; + justify-content: flex-end; +} +.relation-chip-list { + display: flex; + flex-wrap: wrap; + justify-content: flex-end; + gap: 5px; + max-width: 100%; +} +.relation-chip { + display: inline-flex; + align-items: center; + gap: 4px; + max-width: 138px; + min-width: 0; + border: 1px solid rgba(104, 150, 84, 0.24); + border-radius: 999px; + background: rgba(250, 255, 242, 0.88); + color: #4d6140; + padding: 2px 6px 2px 2px; + font: inherit; + font-size: 11px; + line-height: 1.2; + cursor: pointer; + box-shadow: 0 1px 0 rgba(255,255,255,0.74); +} +.relation-chip.enemy { + border-color: rgba(178, 92, 74, 0.28); + background: rgba(255, 246, 240, 0.92); + color: #754739; +} +.relation-chip:hover, +.relation-chip:focus-visible { + transform: translateY(-1px); + background: rgba(255,255,255,0.98); + outline: 2px solid rgba(118, 186, 72, 0.18); +} +.relation-chip.enemy:hover, +.relation-chip.enemy:focus-visible { + outline-color: rgba(190, 92, 72, 0.18); +} +.relation-chip .relation-face { + width: 22px; + height: 22px; +} +.relation-chip-name { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + min-width: 0; +} +.relation-chip em { + font-style: normal; + font-size: 10px; + opacity: 0.72; + flex: 0 0 auto; +} diff --git a/docs/prompt.txt b/docs/prompt.txt index dc86a4a..dc90944 100644 --- a/docs/prompt.txt +++ b/docs/prompt.txt @@ -1,485 +1,265 @@ -You are working on the Tarinai observation game. +You are modifying an existing JavaScript browser game project. -Base input: +Implement a personality system for the \u201ctarinai\u201d creatures. Keep the implementation conservative and debuggable. Do not add extra systems beyond the specification below. -* 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. +## Goal -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. +Add four continuous personality parameters to each tarinai: ---- +* aggression +* openness +* sociability +* neuroticism -## 1. Family tree update performance +Each parameter ranges from `-1.0` to `+1.0`. -Current issue: -The family tree update still performs heavy synchronous preprocessing, causing the main game to freeze. +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. -Implement: +## Personality axes -* 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. +### aggression -Update timing rules: +Range: -* When the family tree panel is hidden: +* low side: calm +* high side: irritable - * Do not update every 5 seconds. - * Check/update at most once every 30 seconds. -* When the family tree panel is visible: +Behavior: - * 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: +* High aggression makes the tarinai more likely to threaten others, start fights, or retaliate. +* Low aggression makes the tarinai less likely to start fights. - * 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. +Changes: -Expected result: +* Winning fights should slightly increase aggression. +* Losing fights should slightly decrease aggression. -* 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. +### openness ---- +Range: -## 2. Coward personality condition +* low side: conservative +* high side: playful -Current issue: -The “coward” condition may count total fight results and per-relationship fight results together, causing double counting. +Behavior: -Implement: +* 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. -* 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: +Changes: - * 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 `臆病`. +* Being petted by the cursor should slightly increase openness. -Expected result: +### sociability -* The calculation uses only aggregate lifetime fight result counters. -* No double counting. +Range: ---- +* low side: loner +* high side: social -## 3. Disease fight initiation and targeting rules +Behavior: -Implement the following disease fight rules exactly: +* 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. -Fight initiation: +Changes: -* 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. +* Spending time near parents, children, or friends should slightly increase sociability. -Being targeted / challenged: +### neuroticism -* Tarinai with `ねむり病` must not be targeted for fights. -* Tarinai with any other disease may still be targeted/challenged by another Tarinai. -* This means: +Range: - * `爆発病` and `ずんち病`: can initiate and can be targeted. - * Other non-sleep diseases: cannot initiate, but can be targeted. - * `ねむり病`: cannot initiate and cannot be targeted. +* low side: insensitive / unfazed +* high side: delicate / sensitive -Apply consistently to: +Behavior: -* Normal fight selection. -* Forced fight logic. -* Fight-food effects such as `けんか餅`. -* Any helper such as `canStartFight`, `canBeFightTarget`, or equivalent. +* 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. -Expected result: +Changes: -* Disease rules are not handled by scattered ad-hoc checks. -* Use clear helper functions if they do not already exist. +* 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. ---- +Important: -## 4. Collision and external-force unification +* 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. -Current issues: +## Birth personality and current personality -* 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. +Each tarinai should have two personality objects: -Implement: +```js +birthPersonality +currentPersonality +``` -* 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: +Rules: - * `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. +* `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. -Unlimited ball speed: +## Inheritance -* 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. +When a child is born: -High-speed ball vs Tarinai: +```text +child birth personality = + average of the parents' current personality + + random variation between -0.2 and +0.2 for each parameter +``` -* When a sufficiently fast ball hits a Tarinai: +Clamp each resulting value to `-1.0` through `+1.0`. - * 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 `衝突`. +Then: -High-speed Tarinai vs Tarinai: +```js +child.currentPersonality = child.birthPersonality +``` -* When a sufficiently fast Tarinai hits another Tarinai: +The child should pass its changed current personality to future descendants, not only its original birth personality. - * 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 `衝突`. +## Thresholds and personality tags -Explosion knockback: +Use two threshold levels: -* 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 `衝突`. +```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 +``` -Expected result: +Display tags: -* 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. +* 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. ---- +Example: -## 5. Ball-to-ball collision +* 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 -Ensure balls collide with each other robustly. +Behavior activation: -Requirements: +* 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. -* 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. +## Daily personality change limit ---- +Add a daily change cap so personality values cannot change too quickly. -## 6. Solid obstacle and placement logic unification +Recommended limits: -Current issues: -Fence, nest box, and placement preview logic are still partly fragmented. +```text +Per parameter: + maximum increase per day: +0.08 + maximum decrease per day: -0.08 -Implement: +Across all parameters: + maximum total absolute personality change per day: 0.20 +``` -* Unify all solid rectangular obstacle collision logic. -* Fence and nest box should use the same obstacle system where possible. -* Rename misleading helpers if needed: +If a change would exceed the daily limit, reduce or ignore the excess change. - * 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. +Reset these daily counters at the start of each new in-game day. -Fence collision: +## Observation log rules -* 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. +Write personality change entries to the observation log only when a threshold is crossed. -Nest box collision: +Log when: -* Preserve the existing 3×3 nest box hitbox rule: +* 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 - * If the nest box is divided into a 3×3 grid, the collidable cells are: +Do not log every small personality change. - * 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. +Example log messages: -Placement preview: +```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. +``` -* 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. +Use the existing observation log system if one exists. -Expected result: +## Tarinai data UI -* Placement UI, actual placement, and collision behavior agree. -* No “red but placeable” or “green but placed elsewhere” behavior. +Update the tarinai data UI to show personality information clearly. ---- +It should include: -## 7. Item/tool definition unification +1. Birth personality +2. Current personality +3. Visible personality tags derived from current personality -Current issues: -Tool names, labels, icons, sizes, placement rules, and descriptions are scattered across multiple files. +Example structure: -Implement: +```text +Personality Tags: +slightly irritable / social -* Create or consolidate a single source of truth for tool/item definitions. -* It should include at least: +Birth Personality: +Aggression: -0.12 +Openness: +0.31 +Sociability: +0.48 +Neuroticism: +0.66 - * 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. +Current Personality: +Aggression: +0.57 +Openness: +0.34 +Sociability: +0.76 +Neuroticism: +0.22 +``` -Specific icon requirements: +Keep the UI compact. Do not create a large new panel unless necessary. -* `つつく` 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. +## Implementation constraints -Water tool: +* 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: -* `水` 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. + * `ensurePersonality(tarinai)` + * `adjustPersonality(tarinai, key, delta, reason)` + * `getPersonalityTraitTags(tarinai)` + * `getTraitStrength(value)` + * `shouldApplyPersonalityBehavior(tarinai, key, direction)` -Expected result: +## Validation -* Tool UI no longer has missing icons, old icons, or mismatched nest box visuals. -* Tool data is not scattered unnecessarily. +After implementation: ---- - -## 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. +* 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. diff --git a/index.html b/index.html index 1ca64b0..1a7885d 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@ たりない観察 - +

@@ -37,7 +37,7 @@
@@ -165,20 +165,20 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/js/data.js b/js/data.js index b681204..6c4fe60 100644 --- a/js/data.js +++ b/js/data.js @@ -33,6 +33,68 @@ const DECOR_ASSETS = [ { id: "zunchi", path: "assets/objects/zunchi.png" }, { id: "zunchi_02", path: "assets/objects/zunchi_02.png" }, ]; + +const TOOL_DEFINITIONS = Object.freeze({ + observe: { id: "observe", label: "\u89b3\u5bdf", placeable: false, scalable: false, icon: "assets/ui/tool_observe.png", tooltip: "\u500b\u4f53\u3092\u9078\u629e\u3057\u3001\u72b6\u614b\u30fb\u6027\u683c\u30fb\u75c5\u6c17\u30fb\u304a\u6c17\u306b\u5165\u308a\u3092\u78ba\u8a8d\u3059\u308b\u3002" }, + delete: { id: "delete", label: "\u524a\u9664", placeable: false, scalable: false, icon: "assets/ui/tool_delete.png", tooltip: "\u7f6e\u3044\u305f\u9053\u5177\u3084\u6c5a\u308c\u3092\u6d88\u3059\u3002" }, + poke: { id: "poke", label: "\u3064\u3064\u304f", placeable: false, scalable: false, iconText: "\u{1F448}", tooltip: "\u305f\u308a\u306a\u3044\u3092\u3064\u3064\u304f\u3002\u30dc\u30fc\u30eb\u3082\u3064\u3064\u3044\u3066\u8ee2\u304c\u305b\u308b\u3002" }, + pinch: { id: "pinch", label: "\u3064\u307e\u3080", placeable: false, scalable: false, iconText: "\u{1F90F}", tooltip: "\u305f\u308a\u306a\u3044\u3084\u7269\u3092\u3064\u307e\u3093\u3067\u79fb\u52d5\u3055\u305b\u308b\u3002" }, + new: { id: "new", label: "\u8ffd\u52a0", placeable: false, scalable: false, icon: "assets/ui/tool_new.png", tooltip: "\u753b\u9762\u5916\u304b\u3089\u65b0\u3057\u3044\u305f\u308a\u306a\u3044\u3092\u547c\u3076\u3002" }, + water_hose: { id: "water_hose", label: "\u6d17\u6d44", placeable: false, scalable: false, iconText: "\u{1F6BF}", icon: "assets/ui/tool_water_hose.png", tooltip: "\u30c9\u30e9\u30c3\u30b0\u3067\u6c5a\u308c\u3092\u304d\u308c\u3044\u306b\u3059\u308b\u3002" }, + zunchi: { id: "zunchi", itemType: "zunchi", label: "\u305a\u3093\u3061", placeable: true, scalable: true, radius: 14, amount: 240, icon: "assets/ui/tool_zunchi.png", tooltip: "\u305f\u308a\u306a\u3044\u306e\u305a\u3093\u3061\u3002\u75c5\u6c17\u3084\u8349\u306e\u80a5\u6599\u306b\u95a2\u308f\u308b\u3002" }, + sweet: { id: "sweet", itemType: "sweet", label: "\u305a\u3093\u3060\u9905", placeable: true, scalable: true, radius: 13, amount: 62, icon: "assets/ui/tool_sweet.png", tooltip: "\u305f\u308a\u306a\u3044\u306e\u5927\u597d\u7269\u3002\u4e00\u90e8\u306e\u75c5\u6c17\u3092\u6cbb\u305b\u308b\u3002" }, + love_mochi: { id: "love_mochi", itemType: "love_mochi", label: "\u3078\u3053\u9905", placeable: true, scalable: true, radius: 13, amount: 62, icon: "assets/ui/tool_love_mochi.png", tooltip: "\u98df\u5f8c\u3057\u3070\u3089\u304f\u7e41\u6b96\u884c\u52d5\u304c\u8d77\u304d\u3084\u3059\u304f\u306a\u308b\u3002" }, + fight_mochi: { id: "fight_mochi", itemType: "fight_mochi", label: "\u3051\u3093\u304b\u9905", placeable: true, scalable: true, radius: 13, amount: 62, icon: "assets/ui/tool_fight_mochi.png", tooltip: "\u98df\u5f8c\u3057\u3070\u3089\u304f\u3051\u3093\u304b\u304c\u8d77\u304d\u3084\u3059\u304f\u306a\u308b\u3002" }, + water_bowl: { id: "water_bowl", itemType: "water_bowl", label: "\u6c34\u306e\u76bf", placeable: true, scalable: false, radius: 20, amount: 999, icon: "assets/ui/tool_water_bowl.png", tooltip: "\u885b\u751f\u7684\u306a\u6c34\u304c\u5165\u3063\u305f\u76bf\u3002\u4e00\u90e8\u306e\u75c5\u6c17\u3092\u6cbb\u305b\u308b\u3002" }, + sleep_drug: { id: "sleep_drug", itemType: "sleep_drug", label: "\u306d\u3080\u308a\u85ac", placeable: true, scalable: true, radius: 13, amount: 58, icon: "assets/ui/tool_sleep_drug.png", tooltip: "\u98df\u3079\u308b\u3068\u306d\u3080\u308a\u75c5\u306b\u306a\u308b\u3002\u30c0\u30e1\u30fc\u30b8\u3067\u5b8c\u6cbb\u3059\u308b\u3002" }, + grass: { id: "grass", itemType: "grass", label: "\u8349", placeable: true, scalable: true, radius: 17, amount: 120, icon: "assets/ui/tool_grass.png", tooltip: "\u98df\u3079\u7269\u3002\u305f\u308a\u306a\u3044\u304c\u5b89\u5fc3\u3059\u308b\u3002" }, + stone: { id: "stone", itemType: "stone", label: "\u77f3", placeable: true, scalable: true, radius: 20, amount: 999, icon: "assets/ui/tool_stone.png", tooltip: "\u91cd\u3044\u77f3\u3002\u843d\u3068\u3059\u3068\u5371\u306a\u3044\u3002" }, + bed: { id: "bed", itemType: "bed", label: "\u5e72\u8349\u5bdd\u5e8a", placeable: true, scalable: false, radius: 37, amount: 999, icon: "assets/ui/tool_bed.png", tooltip: "\u8fd1\u304f\u3067\u7720\u308b\u3002\u4f53\u529b\u304c\u56de\u5fa9\u3059\u308b\u3002" }, + nest_box: { id: "nest_box", itemType: "nest_box", label: "\u5de3\u7bb1", placeable: true, scalable: false, radius: 42, amount: 999, icon: "assets/ui/tool_nest_box.png", collisionShape: "nest_box_3x3", tooltip: "\u3044\u308b\u3060\u3051\u3067\u30b9\u30c8\u30ec\u30b9\u4f4e\u6e1b\u3002\u7720\u308b\u3068\u7761\u7720\u306e\u8cea\u304c\u4e0a\u304c\u308b\u3002" }, + ball: { id: "ball", itemType: "ball", label: "\u30dc\u30fc\u30eb", placeable: true, scalable: false, radius: 18, amount: 999, icon: "assets/ui/tool_ball.png", collisionShape: "circle", tooltip: "\u305f\u308a\u306a\u3044\u304c\u904a\u3076\u305f\u3081\u306e\u304a\u3082\u3061\u3083\u3002" }, + firecracker: { id: "firecracker", itemType: "firecracker", label: "\u7206\u7af9", placeable: true, scalable: true, radius: 15, amount: 999, icon: "assets/ui/tool_firecracker.png", tooltip: "\u7206\u767a\u3092\u8d77\u3053\u3059\u3002" }, + fence_v: { id: "fence_v", itemType: "fence_v", label: "\u7e26\u306e\u67f5", placeable: true, scalable: true, radius: 42, amount: 999, icon: "assets/ui/tool_fence_v.png", collisionShape: "rect", tooltip: "\u305f\u308a\u306a\u3044\u3092\u901a\u305b\u3093\u307c\u3059\u308b\u3002" }, + fence_h: { id: "fence_h", itemType: "fence_h", label: "\u6a2a\u306e\u67f5", placeable: true, scalable: true, radius: 42, amount: 999, icon: "assets/ui/tool_fence_h.png", collisionShape: "rect", tooltip: "\u305f\u308a\u306a\u3044\u3092\u901a\u305b\u3093\u307c\u3059\u308b\u3002" }, + water: { id: "water", itemType: "water", label: "\u6c34", placeable: false, scalable: false, radius: 12, amount: 64, simulationOnly: true }, + trace: { id: "trace", itemType: "trace", label: "\u8db3\u8de1", placeable: false, scalable: false, radius: 16, amount: 220, simulationOnly: true }, + splat: { id: "splat", itemType: "splat", label: "\u3057\u3076\u304d", placeable: false, scalable: false, radius: 26, amount: 260, simulationOnly: true }, + food: { id: "food", itemType: "food", label: "\u98df\u3079\u7269", placeable: false, scalable: false, radius: 14, amount: 85, simulationOnly: true }, +}); + +function toolDefinition(id = "") { + return TOOL_DEFINITIONS[id] || null; +} + +function toolLabel(id = "") { + const def = toolDefinition(id); + return def?.label || id || ""; +} + +function toolItemType(id = "") { + const def = toolDefinition(id); + return def?.placeable ? (def.itemType || def.id) : null; +} + +function itemDefinition(type = "") { + return Object.values(TOOL_DEFINITIONS).find(def => (def.itemType || def.id) === type) || null; +} + +function itemRadiusFor(type = "", fallback = 12) { + return itemDefinition(type)?.radius ?? fallback; +} + +function itemAmountFor(type = "", fallback = 80) { + return itemDefinition(type)?.amount ?? fallback; +} + +function scalableToolIds() { + return Object.values(TOOL_DEFINITIONS).filter(def => def.scalable).map(def => def.id); +} + +function toolTipsFromDefinitions() { + return Object.fromEntries(Object.entries(TOOL_DEFINITIONS).filter(([, def]) => def.tooltip).map(([id, def]) => [id, def.tooltip])); +} + const ALPHA_BOUNDS = { smile: { x: 18, y: 18, w: 476, h: 432, imageW: 512, imageH: 468 }, angry: { x: 16, y: 16, w: 480, h: 432, imageW: 512, imageH: 464 }, @@ -106,4 +168,3 @@ const LIGHTING_TUNING = { goldenOverlayAlpha: 0.045, bloomWashAlpha: 0.040, }; - diff --git a/js/health.js b/js/health.js index 7c74473..1e3f7a9 100644 --- a/js/health.js +++ b/js/health.js @@ -10,12 +10,12 @@ const HEALTH = (() => { poke: "\u3064\u3064\u304b\u308c\u3059\u304e\u305f", firecracker: "\u7206\u7af9", accident: "\u4e8b\u6545", - collision: "衝突", - outOfBounds: "仕様により画面外で削除", - lifespan: "天寿を全うした", + collision: "\u885d\u7a81", + outOfBounds: "\u4ed5\u69d8\u306b\u3088\u308a\u753b\u9762\u5916\u3067\u524a\u9664", + lifespan: "\u5929\u5bff\u3092\u5168\u3046\u3057\u305f", sleepDisease: "\u306d\u3080\u308a\u75c5", explosionDisease: "\u7206\u767a\u75c5", - fightDisease: "きずつき病", + fightDisease: "\u304d\u305a\u3064\u304d\u75c5", zunchiDisease: "\u305a\u3093\u3061\u75c5", }); const DISEASE_RE = /([^\u3001\u3002\s]+\u75c5)/; @@ -26,12 +26,12 @@ const HEALTH = (() => { if (text.includes(WEAKENED_SUFFIX)) return text.replace(/\u3067\u8870\u5f31.*$/, ""); if (/\u55a7\u5629|fight|headbutt/.test(text)) return CAUSES.fight; if (/\u7206\u7af9|firecracker|explosion/.test(text)) return CAUSES.firecracker; - if (/仕様により画面外で削除|画面外で削除|out.*bounds|offscreen/.test(text)) return CAUSES.outOfBounds; - if (/衝突|collision/.test(text)) return CAUSES.collision; + if (/\u4ed5\u69d8\u306b\u3088\u308a\u753b\u9762\u5916\u3067\u524a\u9664|\u753b\u9762\u5916\u3067\u524a\u9664|out.*bounds|offscreen/.test(text)) return CAUSES.outOfBounds; + if (/\u885d\u7a81|collision/.test(text)) return CAUSES.collision; if (/\u3064\u3064\u304b\u308c|\u3064\u3064\u304d|poke/.test(text)) return CAUSES.poke; if (/\u306d\u3080\u308a\u75c5|sleep.*disease/.test(text)) return CAUSES.sleepDisease; if (/\u7206\u767a\u75c5|explosion.*disease/.test(text)) return CAUSES.explosionDisease; - if (/\u3051\u3093\u304b\u75c5|喧嘩傷病|きずつき病|fight.*disease/.test(text)) return CAUSES.fightDisease; + if (/\u3051\u3093\u304b\u75c5|\u304d\u305a\u3064\u304d\u75c5|fight.*disease/.test(text)) return CAUSES.fightDisease; if (/\u305a\u3093\u3061\u75c5|zunchi_sick|zunchi.*\u75c5/.test(text)) return CAUSES.zunchiDisease; if (/\u75c5/.test(text)) { const disease = text.match(DISEASE_RE); @@ -40,7 +40,7 @@ const HEALTH = (() => { if (/\u98e2|\u7a7a\u8179|\u98df\u3079\u7269|hunger/.test(text)) return CAUSES.hunger; if (/\u30b9\u30c8\u30ec\u30b9|stress/.test(text)) return CAUSES.stress; if (/\u30dc\u30fc\u30eb|\u843d\u3061|\u843d\u4e0b|\u77f3|\u9053\u5177|\u4e8b\u6545|\u5f53\u305f|ball|drop|stone|accident/.test(text)) return CAUSES.accident; - if (/\u5bff\u547d|天寿を全うした/.test(text)) return CAUSES.lifespan; + if (/\u5bff\u547d|\u5929\u5bff/.test(text)) return CAUSES.lifespan; return ""; } @@ -121,6 +121,7 @@ const HEALTH = (() => { cause = rememberDamage(t, actualLoss, reason); if (cause === CAUSES.fight || /\u55a7\u5629|fight/.test(String(reason || ""))) t.recordBleedExposure(); if (t.sleepDisease) t.recoverSleepDisease("\u30c0\u30e1\u30fc\u30b8\u3067\u306d\u3080\u308a\u75c5\u304c\u6cbb\u3063\u305f"); + if (t.wakeFromDamage) t.wakeFromDamage(cause || reason); if (t.maybeBecomeTimidAfterDamage) t.maybeBecomeTimidAfterDamage(cause || reason); t.showHpBar(); } diff --git a/js/items.js b/js/items.js index 094f29d..0e78cf4 100644 --- a/js/items.js +++ b/js/items.js @@ -1,18 +1,23 @@ -// tarinai_colony_game build 15.4.0: ball collisions, fence hitboxes, and archive throttling +// tarinai_colony_game build 15.6.2: food servings, nest box access, and editable tarinai data "use strict"; +const FOOD_SERVING_TYPES = new Set(["food", "sweet", "love_mochi", "fight_mochi", "sleep_drug"]); +const FOOD_SERVINGS_BY_SIZE = { small: 1, medium: 5, large: 15 }; +function foodServingsForSize(size = "medium") { + return FOOD_SERVINGS_BY_SIZE[size] || FOOD_SERVINGS_BY_SIZE.medium; +} +function isServingFoodType(type = "") { + return FOOD_SERVING_TYPES.has(type); +} + class Item { constructor(type, x, y) { this.id = crypto.randomUUID ? crypto.randomUUID() : `${Date.now()}-${Math.random()}`; this.type = type; this.x = x; this.y = y; - this.r = { - food: 14, sweet: 13, love_mochi: 13, fight_mochi: 13, sleep_drug: 13, water: 12, water_bowl: 20, grass: 17, stone: 20, bed: 37, nest_box: 42, ball: 18, firecracker: 15, fence_v: 42, fence_h: 42, trace: 16, splat: 26, zunchi: 14 - }[type] || 12; - this.amount = { - food: 85, sweet: 62, love_mochi: 62, fight_mochi: 62, sleep_drug: 58, water: 64, water_bowl: 999, grass: 120, stone: 999, bed: 999, nest_box: 999, ball: 999, firecracker: 999, fence_v: 999, fence_h: 999, trace: 220, splat: 260, zunchi: 240 - }[type] || 80; + this.r = itemRadiusFor(type, 12); + this.amount = itemAmountFor(type, 80); this.age = 0; this.seed = Math.random() * 1000; this.dropTimer = 0; @@ -57,6 +62,13 @@ class Item { this.fuseTimer = 5; this.fuseMax = 5; } + if (isServingFoodType(type)) { + this.toolSize = "medium"; + this.foodServingScale = 1; + this.foodServingsMax = foodServingsForSize(this.toolSize); + this.foodServingsRemaining = this.foodServingsMax; + this.amount = this.foodServingsRemaining; + } } update(dt, worldRef = world) { this.age += dt; @@ -69,7 +81,7 @@ class Item { } } if (this.type === "water") this.amount -= dt * 0.9; - if (["sweet", "love_mochi", "fight_mochi", "sleep_drug"].includes(this.type)) this.amount -= dt * 0.12; + if (["sweet", "love_mochi", "fight_mochi", "sleep_drug"].includes(this.type) && !Number.isFinite(this.foodServingsRemaining)) this.amount -= dt * 0.12; if (this.type === "trace") this.amount -= dt * 1.35; if (this.type === "splat") this.amount -= dt * 1.05; if (this.type === "firecracker") { @@ -445,7 +457,7 @@ class Item { type: this.type, x: this.x, y: this.y, amount: this.amount, age: this.age, seed: this.seed, stage: this.stage, stageTimer: this.stageTimer, fertility: this.fertility, freshness: this.freshness, growth: this.growth, health: this.health, seedTimer: this.seedTimer, eatenAmount: this.eatenAmount, fertilityBoost: this.fertilityBoost, lifeSpan: this.lifeSpan, wither: this.wither, - comfort: this.comfort, wear: this.wear, crawlOpen: this.crawlOpen, zunchiVariant: this.zunchiVariant, toolSize: this.toolSize, blastScale: this.blastScale, fuseTimer: this.fuseTimer, fuseMax: this.fuseMax, dropTimer: this.dropTimer, dropMax: this.dropMax, + comfort: this.comfort, wear: this.wear, crawlOpen: this.crawlOpen, zunchiVariant: this.zunchiVariant, toolSize: this.toolSize, foodServingScale: this.foodServingScale, foodServingsMax: this.foodServingsMax, foodServingsRemaining: this.foodServingsRemaining, blastScale: this.blastScale, fuseTimer: this.fuseTimer, fuseMax: this.fuseMax, dropTimer: this.dropTimer, dropMax: this.dropMax, vx: this.vx, vy: this.vy, prevX: this.prevX, prevY: this.prevY, spin: this.spin, spinVelocity: this.spinVelocity, lastKickedAt: this.lastKickedAt, lastKickerId: this.lastKickerId, lastPokedAt: this.lastPokedAt, pokeCombo: this.pokeCombo, lastPokeAngle: this.lastPokeAngle @@ -459,12 +471,8 @@ class Item { it.type = type; it.x = o.x; it.y = o.y; - it.r = { - food: 14, sweet: 13, love_mochi: 13, fight_mochi: 13, sleep_drug: 13, water: 12, water_bowl: 20, grass: 17, stone: 20, bed: 37, nest_box: 42, ball: 18, firecracker: 15, fence_v: 42, fence_h: 42, trace: 16, splat: 26, zunchi: 14 - }[type] || 12; - it.amount = o.amount ?? ({ - food: 85, sweet: 62, love_mochi: 62, fight_mochi: 62, sleep_drug: 58, water: 64, water_bowl: 999, grass: 120, stone: 999, bed: 999, nest_box: 999, ball: 999, firecracker: 999, fence_v: 999, fence_h: 999, trace: 220, splat: 260, zunchi: 240 - }[type] || 80); + it.r = itemRadiusFor(type, 12); + it.amount = o.amount ?? itemAmountFor(type, 80); it.age = o.age || 0; it.seed = o.seed || Math.random() * 1000; it.dropTimer = 0; @@ -534,6 +542,17 @@ class Item { it.lastPokeAngle = o.lastPokeAngle ?? it.lastPokeAngle ?? rand(0, Math.PI * 2); it.zunchiVariant = o.zunchiVariant || it.zunchiVariant || "zunchi"; it.toolSize = o.toolSize || it.toolSize || "medium"; + it.foodServingScale = o.foodServingScale || it.foodServingScale || ({ small: 0.68, medium: 1.0, large: 1.48 }[it.toolSize] || 1); + if (isServingFoodType(it.type)) { + const servingMax = foodServingsForSize(it.toolSize); + it.foodServingsMax = Number.isFinite(o.foodServingsMax) ? o.foodServingsMax : servingMax; + if (Number.isFinite(o.foodServingsRemaining)) { + it.foodServingsRemaining = clamp(o.foodServingsRemaining, 0, it.foodServingsMax); + } else { + it.foodServingsRemaining = Math.max(1, Math.min(it.foodServingsMax, Math.ceil(it.foodServingsMax * clamp((o.amount ?? it.amount) / 70, 0.05, 1)))); + } + it.amount = it.foodServingsRemaining; + } it.blastScale = o.blastScale || it.blastScale || 1; it.fuseTimer = o.fuseTimer ?? it.fuseTimer; it.fuseMax = o.fuseMax ?? it.fuseMax; @@ -548,7 +567,8 @@ class Item { const warm = lightState.warmth; const styleNight = lightState.light < 0.42; const styleWarm = !styleNight && (lightState.goldenStrength > 0.22 || warm > 0.55); - const visibleAlpha = clamp(this.amount / 40, 0.24, 1); + const servingRatio = isServingFoodType(this.type) ? ((this.foodServingsRemaining ?? this.amount) / Math.max(1, this.foodServingsMax || foodServingsForSize(this.toolSize || "medium"))) : null; + const visibleAlpha = isServingFoodType(this.type) ? clamp(servingRatio ?? 1, 0.24, 1) : clamp(this.amount / 40, 0.24, 1); const dropT = this.dropMax > 0 ? clamp(this.dropTimer / this.dropMax, 0, 1) : 0; const dropY = dropT > 0 ? -170 * Math.pow(dropT, 0.42) : 0; const shadow = projectedShadowParams(lightState, Math.max(0.4, this.r / 18)); @@ -869,4 +889,3 @@ class Item { ctx.restore(); } } - diff --git a/js/render.js b/js/render.js index 4270e76..1b59734 100644 --- a/js/render.js +++ b/js/render.js @@ -124,51 +124,30 @@ function drawItemGlow(ctx, item, lighting, visibleAlpha = 1) { return; } -const PLACEABLE_TOOL_TYPES = Object.freeze({ - zunchi: "zunchi", sweet: "sweet", love_mochi: "love_mochi", fight_mochi: "fight_mochi", sleep_drug: "sleep_drug", water: "water", water_bowl: "water_bowl", grass: "grass", - stone: "stone", bed: "bed", nest_box: "nest_box", ball: "ball", firecracker: "firecracker", fence_v: "fence_v", fence_h: "fence_h", -}); - function placementPreviewFor(world) { const p = world?.pointer; - const type = PLACEABLE_TOOL_TYPES[world?.tool || ""]; + const type = toolItemType(world?.tool || ""); if (!p?.inside || !type) return null; const pad = CONFIG.worldPadding || 30; - let x = clamp(p.x, pad, world.w - pad); - let y = clamp(p.y, pad, world.h - pad); - const r = { - food: 14, sweet: 13, love_mochi: 13, fight_mochi: 13, sleep_drug: 13, water: 12, water_bowl: 20, grass: 17, stone: 20, bed: 37, nest_box: 42, ball: 18, firecracker: 15, fence_v: 42, fence_h: 42, zunchi: 14 - }[type] || 12; + let x = p.x; + let y = p.y; + const r = itemRadiusFor(type, 12); const rectOutside = (rect) => Boolean(rect && (rect.left < pad || rect.top < pad || rect.right > world.w - pad || rect.bottom > world.h - pad)); const circleOutside = (cx, cy, radius) => cx - radius < pad || cy - radius < pad || cx + radius > world.w - pad || cy + radius > world.h - pad; let blocked = false; - if (type === "grass" && world.findGrassPlantingSpot) { - const spot = world.findGrassPlantingSpot(x, y, { allowOriginal: true, minRadius: 22, maxRadius: 128, attempts: 16 }); - if (!spot) return { type, x, y, r, blocked: true }; - x = spot.x; - y = spot.y; - blocked = circleOutside(x, y, Math.max(14, r * 1.55)); - } + let tmp = { type, x, y, r, dead: false }; if ((type === "fence_v" || type === "fence_h") && world.fenceRect) { - const raw = { type, x, y, r }; - const rawRect = world.fenceRect(raw); - blocked = rectOutside(rawRect); - const tmp = { type, x, y, r }; - const rect = world.fenceRect(tmp); - if (rect) { - const dx = Math.max(pad - rect.left, 0) - Math.max(rect.right - (world.w - pad), 0); - const dy = Math.max(pad - rect.top, 0) - Math.max(rect.bottom - (world.h - pad), 0); - tmp.x += dx; - tmp.y += dy; - return { type, x: tmp.x, y: tmp.y, r, rect: world.fenceRect(tmp), blocked: blocked || world.fencePlacementBlocked?.(raw) || world.fencePlacementBlocked?.(tmp) }; - } + const rawRect = world.fenceRect(tmp); + return { type, x, y, r, rect: rawRect, blocked: rectOutside(rawRect) || world.placementBlocked?.(tmp) || world.fencePlacementBlocked?.(tmp) }; } if (type === "nest_box" && world.nestBoxBaseRect) { - const tmp = { type, x, y, r, dead: false }; const rect = world.nestBoxBaseRect(tmp); - return { type, x, y, r, rect, blocked: rectOutside(rect) }; + return { type, x, y, r, rect, blocked: rectOutside(rect) || world.placementBlocked?.(tmp) }; } - if (!blocked) blocked = circleOutside(x, y, Math.max(14, r * (type === "bed" ? 1.55 : 1.25))); + if (type === "grass") { + blocked = !world.grassSpotOpen?.(x, y, { avoidTarinai: true }) || circleOutside(x, y, Math.max(14, r * 1.55)); + } + if (!blocked) blocked = circleOutside(x, y, Math.max(14, r * (type === "bed" ? 1.55 : 1.25))) || world.placementBlocked?.(tmp); return { type, x, y, r, blocked }; } @@ -773,7 +752,8 @@ function drawNestBoxTooltip(ctx, world) { const info = world.pointerNestBoxInfo?.(); if (!info) return; const box = info.box; - const title = "\u5de3\u7bb1"; + const capacity = info.capacity || world.nestBoxCapacity?.(box) || 5; + const title = `\u5de3\u7bb1 (${info.occupants.length}/${capacity})\u5339`; const lines = info.occupants.length ? [title, ...info.occupants.map(t => t.name)] : [title, "\u4e2d\u306b\u306f\u8ab0\u3082\u3044\u306a\u3044"]; @@ -823,10 +803,9 @@ function drawSelectedCard(ctx, world, lighting) { const child = t.juvenile && t.parentToFollow?.() ? " / \u5b50" : ""; const zHint = t.digest > 4.9 ? " / \u305a\u3093\u3061" : ""; ctx.fillText(`${stateLabel(t.state)}${child}${zHint}`, x + 10, y + 35); - const personality = t.personalityLabel ? t.personalityLabel() : (t.personality || "\u4e0d\u660e"); - ctx.fillText(`\u6027\u683c ${personality}`, x + 10, y + 52); const genLabel = (t.displayGeneration && t.displayGeneration()) ? ` \u4e16\u4ee3 ${t.generation}` : ""; - ctx.fillText(`\u6c17\u5206 ${fmt(t.mood)}${genLabel} \u4f53\u529b ${fmt(t.energy)}`, x + 10, y + 68); + ctx.fillText(`\u6c17\u5206 ${fmt(t.mood)}${genLabel} \u4f53\u529b ${fmt(t.energy)}`, x + 10, y + 52); + ctx.fillText(`\u30b9\u30c8\u30ec\u30b9 ${fmt(t.stress)} \u7a7a\u8179 ${fmt(t.hunger)}`, x + 10, y + 68); ctx.restore(); } diff --git a/js/sim_core.js b/js/sim_core.js index 89706e0..43fb3bb 100644 --- a/js/sim_core.js +++ b/js/sim_core.js @@ -64,19 +64,189 @@ function stableUnit(seed, salt = "") { return ((h >>> 0) % 100000) / 100000; } -const PERSONALITIES = { - timid: { label: "\u81c6\u75c5", desc: "\u9003\u3052\u3084\u3059\u304f\u3001\u55a7\u5629\u3092\u907f\u3051\u308b", fear: 1.42, fight: 0.48, social: 0.96, relation: 1.04, sleep: 1.00, zunda: 1.00, play: 0.78 }, - glutton: { label: "\u98df\u3044\u3057\u3093\u574a", desc: "\u305a\u3093\u3060\u9905\u3092\u512a\u5148\u3057\u3084\u3059\u3044", fear: 0.92, fight: 0.82, social: 1.00, relation: 1.00, sleep: 0.95, zunda: 1.42, play: 0.84 }, - sleepy: { label: "\u7720\u305f\u304c\u308a", desc: "\u65e9\u3081\u306b\u5bdd\u5e8a\u3078\u5411\u304b\u3046", fear: 0.96, fight: 0.72, social: 0.92, relation: 0.96, sleep: 1.34, zunda: 0.92, play: 0.68 }, - lonely: { label: "\u5bc2\u3057\u304c\u308a", desc: "\u4ed6\u306e\u305f\u308a\u306a\u3044\u3078\u5bc4\u308a\u3084\u3059\u3044", fear: 1.02, fight: 0.70, social: 1.34, relation: 1.38, sleep: 0.96, zunda: 1.00, play: 1.08 }, - irritable: { label: "\u6012\u308a\u3063\u307d\u3044", desc: "\u55a7\u5629\u304c\u8d77\u304d\u3084\u3059\u3044", fear: 0.82, fight: 1.82, social: 0.78, relation: 0.78, sleep: 0.90, zunda: 0.94, play: 0.82 }, - playful: { label: "\u904a\u3073\u597d\u304d", desc: "\u30dc\u30fc\u30eb\u3084\u52d5\u304f\u3082\u306e\u306b\u5f15\u304d\u5bc4\u305b\u3089\u308c\u3084\u3059\u3044", fear: 0.92, fight: 0.74, social: 1.10, relation: 1.04, sleep: 0.94, zunda: 0.96, play: 1.72 }, - calm: { label: "\u30de\u30a4\u30da\u30fc\u30b9", desc: "\u53cd\u5fdc\u304c\u7a4f\u3084\u304b\u3067\u5b89\u5b9a\u3057\u3084\u3059\u3044", fear: 0.82, fight: 0.58, social: 1.02, relation: 1.08, sleep: 1.02, zunda: 0.94, play: 0.86 }, -}; -const PERSONALITY_IDS = Object.keys(PERSONALITIES); +// Legacy named personalities were removed. Keep these stubs only so old save data +// and old UI fallback references cannot revive the pre-four-axis personality model. +const PERSONALITIES = Object.freeze({}); +const PERSONALITY_IDS = []; function personalityForSeed(seed) { - return stableChoice(seed, "personality", PERSONALITY_IDS) || "calm"; + return ""; +} + +const PERSONALITY_KEYS = ["aggression", "openness", "sociability", "neuroticism"]; +const PERSONALITY_DAILY_LIMIT = { perAxis: 0.08, total: 0.20 }; +const FRIEND_AFFINITY_THRESHOLD = 16; +const PERSONALITY_LABELS = { + aggression: { label: "\u653b\u6483\u6027", low: "\u304a\u3060\u3084\u304b", high: "\u6012\u308a\u3063\u307d\u3044" }, + openness: { label: "\u958b\u653e\u6027", low: "\u4fdd\u5b88\u7684", high: "\u904a\u3073\u597d\u304d" }, + sociability: { label: "\u793e\u4ea4\u6027", low: "\u4e00\u4eba\u597d\u304d", high: "\u4ef2\u9593\u597d\u304d" }, + neuroticism: { label: "\u795e\u7d4c\u8cea\u6027", low: "\u7121\u9813\u7740", high: "\u7e4a\u7d30" }, +}; + +function clampPersonalityValue(value) { + return clamp(Number(value) || 0, -1, 1); +} + +function normalizePersonality(source = null) { + const out = {}; + for (const key of PERSONALITY_KEYS) out[key] = clampPersonalityValue(source?.[key]); + return out; +} + +function randomBirthPersonality(seed = "") { + const out = {}; + for (const key of PERSONALITY_KEYS) out[key] = clampPersonalityValue(stableUnit(seed, `personality-${key}`) * 1.2 - 0.6); + return out; +} + +function personalityFromParents(a, b) { + const pa = ensurePersonality(a).currentPersonality; + const pb = ensurePersonality(b).currentPersonality; + const out = {}; + for (const key of PERSONALITY_KEYS) out[key] = clampPersonalityValue(((pa[key] || 0) + (pb[key] || 0)) / 2 + rand(-0.2, 0.2)); + return out; +} + +function getTraitStrength(value) { + const v = clampPersonalityValue(value); + if (v >= 0.75) return { direction: 1, strength: "strong" }; + if (v >= 0.5) return { direction: 1, strength: "slight" }; + if (v <= -0.75) return { direction: -1, strength: "strong" }; + if (v <= -0.5) return { direction: -1, strength: "slight" }; + return { direction: 0, strength: "neutral" }; +} + +function personalityBand(value) { + const t = getTraitStrength(value); + return t.direction === 0 ? "neutral" : `${t.direction > 0 ? "high" : "low"}-${t.strength}`; +} + +function personalityEffectValue(value) { + const trait = getTraitStrength(value); + if (!trait.direction) return 0; + return trait.direction * (trait.strength === "strong" ? 1 : 0.5); +} + +function personalityReasonText(reason = "") { + const key = String(reason || "").replace(/[.\u3002]+$/g, "").trim(); + const map = { + "after winning fights": "\u55a7\u5629\u306b\u52dd\u3063\u305f\u5f71\u97ff\u3067", + "after losing fights": "\u55a7\u5629\u306b\u8ca0\u3051\u305f\u5f71\u97ff\u3067", + "after being petted": "\u64ab\u3067\u3089\u308c\u305f\u5f71\u97ff\u3067", + "after staying near family": "\u89aa\u5b50\u306e\u8fd1\u304f\u3067\u904e\u3054\u3057\u305f\u5f71\u97ff\u3067", + "after staying near friends": "\u53cb\u9054\u306e\u8fd1\u304f\u3067\u904e\u3054\u3057\u305f\u5f71\u97ff\u3067", + "after having no friends": "\u53cb\u9054\u304c\u3044\u306a\u3044\u6642\u9593\u304c\u7d9a\u3044\u305f\u5f71\u97ff\u3067", + "after repeated contact with poop": "\u305a\u3093\u3061\u306b\u6163\u308c\u305f\u5f71\u97ff\u3067", + "after repeated contact with corpses": "\u6b7b\u9ab8\u306b\u6163\u308c\u305f\u5f71\u97ff\u3067", + "after being hurt": "\u75db\u307f\u3092\u899a\u3048\u305f\u5f71\u97ff\u3067", + }; + return map[key] || key; +} + +function personalityBecomeText(label = "") { + const text = String(label || ""); + if (text === "\u6012\u308a\u3063\u307d\u3044") return "\u6012\u308a\u3063\u307d\u304f"; + return text; +} + +function personalityAppearanceText(label = "") { + const text = String(label || ""); + if (text === "\u6012\u308a\u3063\u307d\u3044") return "\u6012\u308a\u3063\u307d\u3044\u69d8\u5b50"; + return `${text}\u306a\u69d8\u5b50`; +} + +function getPersonalityTraitTags(tarinai) { + const p = ensurePersonality(tarinai).currentPersonality; + const tags = []; + for (const key of PERSONALITY_KEYS) { + const trait = getTraitStrength(p[key]); + if (!trait.direction) continue; + const label = PERSONALITY_LABELS[key]?.[trait.direction > 0 ? "high" : "low"] || key; + tags.push(trait.strength === "slight" ? `\u5c11\u3057${label}` : label); + } + const cowardly = (p.neuroticism || 0) >= 0.75 && (p.aggression || 0) <= -0.5; + if (cowardly && !tags.includes("\u81c6\u75c5")) tags.push("\u81c6\u75c5"); + return tags; +} + +function personalityDailyState(tarinai) { + const day = tarinai?.world?.day || 1; + const state = tarinai.personalityDaily || {}; + if (state.day !== day) { + tarinai.personalityDaily = { day, total: 0, byKey: {} }; + return tarinai.personalityDaily; + } + state.byKey = state.byKey || {}; + for (const key of Object.keys(state.byKey)) { + const v = state.byKey[key]; + if (typeof v === "number") state.byKey[key] = { up: Math.max(0, v), down: Math.max(0, -v) }; + else state.byKey[key] = { up: Math.max(0, Number(v?.up) || 0), down: Math.max(0, Number(v?.down) || 0) }; + } + state.total = Math.max(0, Number(state.total) || 0); + tarinai.personalityDaily = state; + return state; +} + +function ensurePersonality(tarinai) { + if (!tarinai) return { birthPersonality: normalizePersonality(), currentPersonality: normalizePersonality() }; + if (!tarinai.birthPersonality) tarinai.birthPersonality = randomBirthPersonality(tarinai.id || Math.random()); + tarinai.birthPersonality = normalizePersonality(tarinai.birthPersonality); + tarinai.currentPersonality = normalizePersonality(tarinai.currentPersonality || tarinai.birthPersonality); + personalityDailyState(tarinai); + return { birthPersonality: tarinai.birthPersonality, currentPersonality: tarinai.currentPersonality }; +} + +function personalityThresholdLogText(tarinai, key, value, reason = "", previousBand = "") { + const trait = getTraitStrength(value); + const name = tarinai?.name || "\u305f\u308a\u306a\u3044"; + if (!trait.direction) { + const oldSide = String(previousBand).startsWith("low") ? "low" : "high"; + const oldLabel = PERSONALITY_LABELS[key]?.[oldSide] || key; + return `\u300c${name}\u300d\u306f${personalityAppearanceText(oldLabel)}\u304c\u76ee\u7acb\u305f\u306a\u304f\u306a\u3063\u305f\u3002`; + } + const label = PERSONALITY_LABELS[key]?.[trait.direction > 0 ? "high" : "low"] || key; + const visible = trait.strength === "slight" ? `\u5c11\u3057${personalityBecomeText(label)}` : personalityBecomeText(label); + const prefix = personalityReasonText(reason); + return `\u300c${name}\u300d\u306f${prefix ? `${prefix}\u3001` : ""}${visible}\u306a\u3063\u305f\u3002`; +} + +function adjustPersonality(tarinai, key, delta, reason = "") { + if (!tarinai || !PERSONALITY_KEYS.includes(key)) return 0; + ensurePersonality(tarinai); + const requested = Number(delta) || 0; + if (!requested) return 0; + const state = personalityDailyState(tarinai); + const dir = Math.sign(requested); + const used = state.byKey[key] || { up: 0, down: 0 }; + const dirKey = dir > 0 ? "up" : "down"; + const keyRoom = Math.max(0, PERSONALITY_DAILY_LIMIT.perAxis - (used[dirKey] || 0)); + const totalRoom = Math.max(0, PERSONALITY_DAILY_LIMIT.total - (state.total || 0)); + const allowed = Math.min(Math.abs(requested), keyRoom, totalRoom); + if (allowed <= 0) return 0; + const before = tarinai.currentPersonality[key] || 0; + const beforeBand = personalityBand(before); + const applied = dir * allowed; + const after = clampPersonalityValue(before + applied); + const actual = after - before; + if (!actual) return 0; + tarinai.currentPersonality[key] = after; + state.byKey[key] = used; + used[actual > 0 ? "up" : "down"] = (used[actual > 0 ? "up" : "down"] || 0) + Math.abs(actual); + state.total = (state.total || 0) + Math.abs(actual); + const afterBand = personalityBand(after); + if (beforeBand !== afterBand) { + const text = personalityThresholdLogText(tarinai, key, after, reason, beforeBand); + tarinai.world?.log?.(text, "observe"); + tarinai.addRecord?.(text, "observe"); + } + return actual; +} + +function shouldApplyPersonalityBehavior(tarinai, key, direction = 1) { + const p = ensurePersonality(tarinai).currentPersonality; + const trait = getTraitStrength(p[key]); + if (trait.direction !== Math.sign(direction || 1)) return false; + return trait.strength === "strong" || Math.random() < 0.5; } function relationDefaults() { @@ -321,4 +491,3 @@ function drawHeartShape(ctx, x, y, size, opts = {}) { ctx.stroke(); ctx.restore(); } - diff --git a/js/tarinai.js b/js/tarinai.js index 84b6eb1..3cfdd80 100644 --- a/js/tarinai.js +++ b/js/tarinai.js @@ -19,19 +19,23 @@ class Tarinai { this.world = world; this.id = opts.id || (crypto.randomUUID ? crypto.randomUUID() : `${Date.now()}-${Math.random()}`); this.name = opts.name || makeName(world); - this.personality = opts.personality || personalityForSeed(this.id); + // Legacy string personality is intentionally ignored. The game now uses only the four-axis personality model. + this.personality = ""; this.type = opts.type || baseSpriteId(); const typeMeta = SPRITES.find(s => s.id === this.type); if (typeMeta?.actionOnly || typeMeta?.displayOnly) this.type = baseSpriteId(); + this.birthPersonality = normalizePersonality(opts.birthPersonality || opts.personalityBirth); + if (!opts.birthPersonality && !opts.personalityBirth) this.birthPersonality = randomBirthPersonality(this.id); + this.currentPersonality = normalizePersonality(opts.currentPersonality || opts.personalityCurrent || this.birthPersonality); + this.personalityDaily = opts.personalityDaily && typeof opts.personalityDaily === "object" ? JSON.parse(JSON.stringify(opts.personalityDaily)) : null; + ensurePersonality(this); this.trait = makeTrait(this.type); - const pdef = PERSONALITIES[this.personality] || PERSONALITIES.calm; - this.trait.social *= pdef.social ?? 1; - this.trait.stress /= pdef.fear ?? 1; - this.trait.sleep *= pdef.sleep ?? 1; this.x = opts.x ?? rand(100, world.w - 100); this.y = opts.y ?? rand(100, world.h - 100); this.vx = opts.vx ?? rand(-12, 12); this.vy = opts.vy ?? rand(-12, 12); + this.impulseVx = opts.impulseVx ?? 0; + this.impulseVy = opts.impulseVy ?? 0; this.scale = opts.scale ?? rand(0.22, 0.33); this.radius = 56 * this.scale; this.age = opts.age ?? rand(0, 20); @@ -109,6 +113,11 @@ class Tarinai { this.fightDiseaseCooldown = opts.fightDiseaseCooldown ?? 0; this.lastBleedAt = opts.lastBleedAt ?? -999; this.favorite = Boolean(opts.favorite); + this.insideNestBoxId = opts.insideNestBoxId || null; + this.nestFade = opts.nestFade ?? (this.insideNestBoxId ? 1 : 0); + this.nestBoxEnteredAt = opts.nestBoxEnteredAt ?? (this.insideNestBoxId ? (world?.time || 0) : -Infinity); + this.nestBoxStayUntil = opts.nestBoxStayUntil ?? (this.insideNestBoxId ? ((world?.time || 0) + 10) : -Infinity); + this.focusPulseTimer = opts.focusPulseTimer ?? 0; if (this.isZunchiSlave) this.name = "\u305a\u3093\u3061\u3069\u308c\u3044"; this.tempComfort = opts.tempComfort ?? 0.62; this.tempTimer = opts.tempTimer ?? stableUnit(this.id, "temp-start") * 0.55; @@ -167,7 +176,7 @@ class Tarinai { birthRitualRole: this.birthRitualRole, birthRitualLeader: this.birthRitualLeader, pokeFlashTimer: this.pokeFlashTimer, zunchiStain: this.zunchiStain, zunchiStainSeed: this.zunchiStainSeed, totalFightLosses: this.totalFightLosses, totalFightWins: this.totalFightWins, isZunchiSlave: this.isZunchiSlave, formerName: this.formerName, loveMochiTimer: this.loveMochiTimer, fightMochiTimer: this.fightMochiTimer, - sleepDisease: this.sleepDisease, sleepDiseaseCooldown: this.sleepDiseaseCooldown, explosionDisease: this.explosionDisease, explosionDiseaseTimer: this.explosionDiseaseTimer, fightDisease: this.fightDisease, fightDiseaseCooldown: this.fightDiseaseCooldown, lastBleedAt: this.lastBleedAt, favorite: this.favorite, insideNestBoxId: this.insideNestBoxId || null, nestFade: this.nestFade || 0, sleepDiseaseAnchorX: this.sleepDiseaseAnchorX, sleepDiseaseAnchorY: this.sleepDiseaseAnchorY, records: this.records ? this.records.slice(0, 42) : [], + sleepDisease: this.sleepDisease, sleepDiseaseCooldown: this.sleepDiseaseCooldown, explosionDisease: this.explosionDisease, explosionDiseaseTimer: this.explosionDiseaseTimer, fightDisease: this.fightDisease, fightDiseaseCooldown: this.fightDiseaseCooldown, lastBleedAt: this.lastBleedAt, favorite: this.favorite, insideNestBoxId: this.insideNestBoxId || null, nestFade: this.nestFade || 0, nestBoxEnteredAt: this.nestBoxEnteredAt, nestBoxStayUntil: this.nestBoxStayUntil, focusPulseTimer: this.focusPulseTimer || 0, sleepDiseaseAnchorX: this.sleepDiseaseAnchorX, sleepDiseaseAnchorY: this.sleepDiseaseAnchorY, records: this.records ? this.records.slice(0, 42) : [], zunchiDisease: this.zunchiDisease, zunchiDiseaseSeverity: this.zunchiDiseaseSeverity, zunchiDiseaseCooldown: this.zunchiDiseaseCooldown, tempComfort: this.tempComfort, tempTimer: this.tempTimer, parents: this.parents, parentNames: this.parentNames, children: this.children, birthTime: this.birthTime, @@ -176,7 +185,8 @@ class Tarinai { nextHeadbutt: this.nextHeadbutt, digest: this.digest, poopCount: this.poopCount, stretchTimer: this.stretchTimer, grassEatTimer: this.grassEatTimer, hurtTimer: this.hurtTimer, defeatedTimer: this.defeatedTimer, defeatedById: this.defeatedById, fightWinnerId: this.fightWinnerId, - relationships: this.relationships, personality: this.personality, fallTimer: this.fallTimer, fallMax: this.fallMax, fallDir: this.fallDir, + relationships: this.relationships, fallTimer: this.fallTimer, fallMax: this.fallMax, fallDir: this.fallDir, + birthPersonality: normalizePersonality(this.birthPersonality), currentPersonality: normalizePersonality(this.currentPersonality), personalityDaily: this.personalityDaily || null, blastSpinTimer: this.blastSpinTimer, blastSpinMax: this.blastSpinMax, postBirthPeaceTimer: this.postBirthPeaceTimer, lastMealColor: this.lastMealColor, aiTimer: this.aiTimer, envTimer: this.envTimer, nextCursorHeartAt: this.nextCursorHeartAt, cursorPetting: this.cursorPetting, entryTimer: this.entryTimer || 0, @@ -225,9 +235,9 @@ class Tarinai { } - addRecord(text, kind = "note") { + addRecord(text, kind = "note", options = {}) { if (!text) return; - if (this.world?.shouldHideFromObservationRecords?.(text)) return; + if (options.hiddenFromObservation) return; if (!Array.isArray(this.records)) this.records = []; const entry = { time: this.world?.time || 0, text: String(text), kind: kind || "note" }; const head = this.records[0]; @@ -237,13 +247,33 @@ class Tarinai { } personalityProfile() { - return PERSONALITIES[this.personality] || PERSONALITIES.calm; + const base = { label: "\u4e2d\u7acb", fear: 1, fight: 1, social: 1, relation: 1, sleep: 1, zunda: 1, play: 1 }; + const p = ensurePersonality(this).currentPersonality; + const e = { + neuroticism: personalityEffectValue(p.neuroticism), + aggression: personalityEffectValue(p.aggression), + sociability: personalityEffectValue(p.sociability), + openness: personalityEffectValue(p.openness), + }; + return { + ...base, + fear: clamp((base.fear || 1) * (1 + e.neuroticism * 0.38), 0.55, 1.85), + fight: clamp((base.fight || 1) * (1 + e.aggression * 0.55), 0.35, 2.35), + social: clamp((base.social || 1) * (1 + e.sociability * 0.24), 0.62, 1.52), + relation: clamp((base.relation || 1) * (1 + e.sociability * 0.24), 0.62, 1.60), + play: clamp((base.play || 1) * (1 + e.openness * 0.45), 0.45, 2.10), + }; } personalityLabel() { - return this.personalityProfile().label || this.personality || "\u4e0d\u660e"; + const tags = getPersonalityTraitTags(this); + return tags.length ? tags.join(" / ") : "\u4e2d\u7acb"; } + personalityTags() { return getPersonalityTraitTags(this); } + adjustPersonality(key, delta, reason = "") { return adjustPersonality(this, key, delta, reason); } + shouldApplyPersonalityBehavior(key, direction = 1) { return shouldApplyPersonalityBehavior(this, key, direction); } + fightWinCount() { return this.totalFightWins || 0; } @@ -253,17 +283,17 @@ class Tarinai { } maybeBecomeTimidAfterDamage(cause = "") { - if (this.dead || this.personality === "timid") return false; + if (this.dead) return false; const losses = this.totalFightLosses || 0; const wins = this.totalFightWins || 0; if (losses <= wins) return false; if (Math.random() >= 0.05) return false; - this.personality = "timid"; + const changedA = this.adjustPersonality?.("neuroticism", 0.025, "after being hurt") || 0; + const changedB = this.adjustPersonality?.("aggression", -0.015, "after being hurt") || 0; this.fearTimer = Math.max(this.fearTimer || 0, 1.2); this.stress = clamp((this.stress || 0) + 5, 0, 130); - this.world?.spawnBubble?.(this.x, this.y - this.radius * 1.35, "こわい…", "rgba(90,80,120,0.78)"); - this.addRecord?.(`${this.name}は痛みで臆病になった。`, "health"); - return true; + this.world?.spawnBubble?.(this.x, this.y - this.radius * 1.35, "\u3053\u308f\u3044\u2026", "rgba(90,80,120,0.78)"); + return Boolean(changedA || changedB); } relationTo(id) { @@ -285,7 +315,7 @@ class Tarinai { strongestRelation(kind = "friend") { let bestId = null; - let bestScore = kind === "fear" ? 5 : 8; + let bestScore = kind === "fear" ? 5 : FRIEND_AFFINITY_THRESHOLD; for (const [id, rel] of Object.entries(this.relationships || {})) { const score = kind === "fear" ? (rel.fear || 0) : (rel.affinity || 0); if (score > bestScore) { bestId = id; bestScore = score; } @@ -299,7 +329,23 @@ class Tarinai { return { friend, fear }; } - bestFriendLive(minScore = 10, maxDist = Infinity) { + currentFriendCount(minScore = FRIEND_AFFINITY_THRESHOLD, liveOnly = true) { + let count = 0; + const liveIds = liveOnly ? new Set((this.world?.tarinai || []).filter(o => o && !o.dead && o !== this).map(o => o.id)) : null; + for (const [id, rel] of Object.entries(this.relationships || {})) { + if ((rel.affinity || 0) <= minScore) continue; + if (liveIds && !liveIds.has(id)) continue; + count += 1; + } + return count; + } + + sociabilityFriendScale() { + const friends = this.currentFriendCount ? this.currentFriendCount(FRIEND_AFFINITY_THRESHOLD, true) : 0; + return clamp(0.82 + Math.min(6, friends) * 0.16, 0.82, 1.78); + } + + bestFriendLive(minScore = FRIEND_AFFINITY_THRESHOLD, maxDist = Infinity) { let best = null, bestScore = minScore; for (const [id, rel] of Object.entries(this.relationships || {})) { const score = rel.affinity || 0; @@ -369,6 +415,24 @@ class Tarinai { normalizeDeathReason(reason = "", opts = {}) { return HEALTH.normalizeDeathReason(this, reason, opts); } damage(amount, reason = "") { return HEALTH.applyDamage(this, amount, reason); } + wakeFromDamage(reason = "") { + if (this.dead) return false; + const wasSleeping = this.state === "sleep" || this.sleeping || this.insideNestBoxId; + if (!wasSleeping) return false; + const box = this.nestBoxById ? this.nestBoxById(this.insideNestBoxId) : null; + this.sleeping = false; + this.state = "panic"; + this.target = null; + this.thought = "\u30c0\u30e1\u30fc\u30b8\u3067\u76ee\u304c\u899a\u3081\u305f"; + this.fearTimer = Math.max(this.fearTimer || 0, 0.85); + this.hurtTimer = Math.max(this.hurtTimer || 0, 1.2); + this.nestBoxStayUntil = -Infinity; + if (this.insideNestBoxId) this.leaveNestBox(box); + this.vx += rand(-34, 34); + this.vy += rand(-26, 8); + return true; + } + recoverHealth(amount) { if (this.dead) return; this.energy = clamp(this.energy + Math.max(0, amount || 0), 0, 100); @@ -406,7 +470,7 @@ class Tarinai { } targetIgnoresFence(target = this.target) { - return Boolean(target?.type === "sweet" || this.state === "panic" || this.state === "fight" || this.state === "intimidate" || this.state === "birth_ritual" || this.state === "cursor_enemy"); + return Boolean(target?.type === "sweet" || target?.type === "nest_box" || (target?.type === "bed" && (this.state === "seek_bed" || this.state === "sleep")) || this.state === "panic" || this.state === "fight" || this.state === "intimidate" || this.state === "birth_ritual" || this.state === "cursor_enemy"); } shouldAvoidTarget(target) { @@ -647,9 +711,9 @@ class Tarinai { this.fightDisease = true; this.fightDiseaseCooldown = 18; this.fearTimer = Math.max(this.fearTimer || 0, 0.35); - this.thought = "きずつき病\u3067\u5f53\u3066\u3082\u306a\u304f\u5f77\u5fa8\u3063\u3066\u3044\u308b"; + this.thought = "\u304d\u305a\u3064\u304d\u75c5\u3067\u5f53\u3066\u3082\u306a\u304f\u5f77\u5fa8\u3063\u3066\u3044\u308b"; this.world?.spawnBubble?.(this.x, this.y - this.radius * 1.20, "?", "rgba(150,78,44,0.80)"); - this.world?.log?.(`${this.name}\u306fきずつき病\u3092\u767a\u75c7\u3057\u305f\u3002`, "fight"); + this.world?.log?.(`${this.name}\u306f\u304d\u305a\u3064\u304d\u75c5\u3092\u767a\u75c7\u3057\u305f\u3002`, "fight"); return true; } @@ -657,10 +721,10 @@ class Tarinai { if (!this.fightDisease) return false; this.fightDisease = false; this.fightDiseaseCooldown = 20; - this.thought = reason || "きずつき病\u304c\u6cbb\u3063\u305f"; + this.thought = reason || "\u304d\u305a\u3064\u304d\u75c5\u304c\u6cbb\u3063\u305f"; this.stress = clamp(this.stress - 12, 0, 130); this.world?.spawnBubble?.(this.x, this.y - this.radius * 1.18, "\u306f\u3046", "rgba(82,126,88,0.76)"); - this.world?.log?.(`${this.name}\u306eきずつき病\u304c\u6cbb\u3063\u305f\u3002`, "fight"); + this.world?.log?.(`${this.name}\u306e\u304d\u305a\u3064\u304d\u75c5\u304c\u6cbb\u3063\u305f\u3002`, "fight"); return true; } @@ -684,34 +748,112 @@ class Tarinai { return true; } - updateNestBoxPresence(dt = 0) { - const previous = this.insideNestBoxId || null; - let box = null; - if (previous) box = this.world?.items?.find?.(it => it && !it.dead && it.id === previous && it.type === "nest_box") || null; - if (!box && this.target && !this.target.dead && this.target.type === "nest_box") box = this.target; - if (!box) { - this.insideNestBoxId = null; - this.nestFade = clamp((this.nestFade || 0) - dt * 1.8, 0, 1); - return null; - } - const d = distXY(this.x, this.y, box.x, box.y); - const occupants = this.world?.nestBoxOccupants ? this.world.nestBoxOccupants(box, Infinity) : []; + nestBoxById(id) { + if (!id) return null; + return this.world?.items?.find?.(it => it && !it.dead && it.id === id && it.type === "nest_box") || null; + } + + isInsideNestBox() { + return Boolean(this.insideNestBoxId); + } + + wantsNestBox(box = null) { + if (!box || box.dead || box.type !== "nest_box") return false; + if (this.insideNestBoxId === box.id && (this.world?.time || 0) < (this.nestBoxStayUntil || -Infinity)) return true; + if (!(this.state === "sleep" || this.state === "seek_bed")) return false; + return this.target === box || this.insideNestBoxId === box.id; + } + + enterNestBox(box, dt = 0.016) { + if (!box || box.dead || box.type !== "nest_box" || this.dead) return false; const capacity = this.world?.nestBoxCapacity ? this.world.nestBoxCapacity(box) : 5; - const occupantIndex = occupants.indexOf(this); - const hasRoom = occupantIndex >= 0 ? occupantIndex < capacity : occupants.length < capacity; - const canEnter = hasRoom && (this.state === "sleep" || this.state === "seek_bed") && d <= Math.max(18, box.r * 0.58); - if (canEnter) { - this.insideNestBoxId = box.id; - this.nestFade = clamp((this.nestFade || 0) + dt * 2.4, 0, 1); - const pull = clamp(dt * 4.2, 0, 1); - this.x = lerp(this.x, box.x, pull); - this.y = lerp(this.y, box.y, pull); - this.vx *= Math.pow(0.45, dt * 60); - this.vy *= Math.pow(0.45, dt * 60); - return box; + const occupants = this.world?.nestBoxOccupants ? this.world.nestBoxOccupants(box, Infinity) : []; + const alreadyInside = this.insideNestBoxId === box.id; + if (!alreadyInside && occupants.length >= capacity) return false; + if (!alreadyInside) { + this.nestBoxEnteredAt = this.world?.time || 0; + this.nestBoxStayUntil = Math.max(this.nestBoxStayUntil || -Infinity, (this.world?.time || 0) + 14); + } + this.insideNestBoxId = box.id; + this.target = box; + if (this.state === "seek_bed") this.state = "sleep"; + if (this.state === "sleep") this.sleeping = true; + const inner = this.world?.nestBoxInnerPoint ? this.world.nestBoxInnerPoint(box, this) : { x: box.x, y: box.y }; + const pull = clamp(dt * (alreadyInside ? 10.0 : 13.5), 0, 1); + this.x = lerp(this.x, inner.x, pull); + this.y = lerp(this.y, inner.y, pull); + if (this.nestFade >= 0.88 || distXY(this.x, this.y, inner.x, inner.y) < 3.5) { + this.x = inner.x; + this.y = inner.y; + } + this.nestFade = clamp((this.nestFade || 0) + dt * 5.8, 0, 1); + this.vx = 0; + this.vy = 0; + this.impulseVx = 0; + this.impulseVy = 0; + return true; + } + + leaveNestBox(box = null) { + const b = box || this.nestBoxById(this.insideNestBoxId); + if (b && this.world?.nestBoxEntryPoint) { + const entry = this.world.nestBoxExitPoint ? this.world.nestBoxExitPoint(b, this) : this.world.nestBoxEntryPoint(b); + this.x = clamp(entry.x, CONFIG.worldPadding, this.world.w - CONFIG.worldPadding); + this.y = clamp(entry.y, CONFIG.worldPadding, this.world.h - CONFIG.worldPadding); + this.vx = rand(-8, 8); + this.vy = rand(6, 18); } this.insideNestBoxId = null; - this.nestFade = clamp((this.nestFade || 0) - dt * 1.8, 0, 1); + this.nestFade = 0; + this.nestBoxEnteredAt = -Infinity; + this.nestBoxStayUntil = -Infinity; + return true; + } + + updateNestBoxPresence(dt = 0) { + const currentBox = this.nestBoxById(this.insideNestBoxId); + const targetBox = this.target && !this.target.dead && this.target.type === "nest_box" ? this.target : null; + const box = currentBox || targetBox; + if (!box) { + this.insideNestBoxId = null; + this.nestFade = clamp((this.nestFade || 0) - dt * 3.0, 0, 1); + return null; + } + + if (currentBox && !this.wantsNestBox(currentBox)) { + this.leaveNestBox(currentBox); + return null; + } + + if (currentBox) { + if ((this.world?.time || 0) < (this.nestBoxStayUntil || -Infinity)) { + this.state = "sleep"; + this.sleeping = true; + this.target = currentBox; + } + this.enterNestBox(currentBox, dt); + return currentBox; + } + + if (!this.wantsNestBox(targetBox)) { + this.nestFade = clamp((this.nestFade || 0) - dt * 3.0, 0, 1); + return null; + } + + const entry = this.world?.nestBoxEntryPoint ? this.world.nestBoxEntryPoint(targetBox) : { x: targetBox.x, y: targetBox.y }; + const base = this.world?.nestBoxBaseRect ? this.world.nestBoxBaseRect(targetBox) : null; + const r = targetBox.r || 42; + const entryD = distXY(this.x, this.y, entry.x, entry.y); + const centerD = distXY(this.x, this.y, targetBox.x, targetBox.y); + const inDoorColumn = base && this.x >= base.left + r * 0.18 && this.x <= base.right - r * 0.18 && this.y >= base.top + r * 0.06 && this.y <= base.bottom + r * 0.48; + const captureRange = Math.max(118, r * 2.05, this.radius + 82); + const nearEnough = entryD <= captureRange || centerD <= Math.max(104, r * 1.90) || inDoorColumn; + if (nearEnough) { + this.enterNestBox(targetBox, dt || 0.016); + return targetBox; + } + + this.nestFade = clamp((this.nestFade || 0) - dt * 3.0, 0, 1); return null; } @@ -756,7 +898,7 @@ class Tarinai { if (this.recoverZunchiDisease("\u81ea\u7136\u306b\u305a\u3093\u3061\u75c5\u304c\u6cbb\u307e\u3063\u305f")) this.world?.log?.(`${this.name}\u306e\u305a\u3093\u3061\u75c5\u304c\u81ea\u7136\u306b\u6cbb\u3063\u305f\u3002`, "accident"); } if (this.fightDisease && Math.random() < dt * 0.00070 * (this.energy > 58 ? 1.4 : 1.0)) { - this.recoverFightDisease("\u81ea\u7136\u306bきずつき病\u304c\u6cbb\u3063\u305f"); + this.recoverFightDisease("\u81ea\u7136\u306b\u304d\u305a\u3064\u304d\u75c5\u304c\u6cbb\u3063\u305f"); } if (this.fightDisease) { this.stress = clamp(this.stress + dt * 0.16, 0, 130); @@ -849,7 +991,7 @@ class Tarinai { if (["fight", "panic", "cursor_enemy", "hurt", "defeated", "fight_sick"].includes(this.state)) return false; if ((this.fearTimer || 0) > 0.18 || (this.intimidatedTimer || 0) > 0.04 || (this.intimidateTimer || 0) > 0.04) return false; if (this.mood < 46 || this.stress > 64) return false; - return this.affection > 12 || this.mood > 58 || this.goodMode === "smile" || ["lonely", "calm", "playful", "teary", "cry"].includes(this.personality); + return this.affection > 12 || this.mood > 58 || this.goodMode === "smile" || this.shouldApplyPersonalityBehavior("sociability", 1); } applyCursorContactCare(dt) { @@ -861,6 +1003,7 @@ class Tarinai { const p = clamp(1 - d / touch, 0, 1); const relief = dt * (1.35 + 2.65 * p); this.stress = clamp((this.stress || 0) - relief, 0, 130); + this.adjustPersonality("openness", dt * 0.006 * (0.4 + p), "after being petted."); this.moodLiftTimer = Math.max(this.moodLiftTimer || 0, 0.5); this.cursorPetting = clamp((this.cursorPetting || 0) + dt * (1.0 + p * 2.4), 0, 1.75); this.goodMode = "smile"; @@ -914,6 +1057,7 @@ class Tarinai { } } this.pokeFlashTimer = Math.max(0, this.pokeFlashTimer - dt); + this.focusPulseTimer = Math.max(0, (this.focusPulseTimer || 0) - dt); this.cursorPetting = Math.max(0, this.cursorPetting - dt * 1.2); if (this.freezeSleepDiseaseMotion(dt)) { this.checkLife(dt); @@ -1035,9 +1179,16 @@ class Tarinai { if (parent && dist(this, parent) < 96) { this.stress = clamp(this.stress - dt * 0.42, 0, 130); this.loneliness = clamp(this.loneliness - dt * 0.32, 0, 110); + this.adjustPersonality("sociability", dt * 0.004 * this.sociabilityFriendScale(), "after staying near family."); + } + const friend = this.bestFriendLive ? this.bestFriendLive(FRIEND_AFFINITY_THRESHOLD, 92) : null; + const friendCount = this.currentFriendCount ? this.currentFriendCount(FRIEND_AFFINITY_THRESHOLD, true) : 0; + if (friend) { + this.stress = clamp(this.stress - dt * 0.36, 0, 130); + this.adjustPersonality("sociability", dt * 0.004 * this.sociabilityFriendScale(), "after staying near friends."); + } else if (friendCount <= 0 && this.loneliness > 72 && this.age > 8) { + this.adjustPersonality("sociability", -dt * 0.0018, "after having no friends."); } - const friend = this.bestFriendLive ? this.bestFriendLive(12, 92) : null; - if (friend) this.stress = clamp(this.stress - dt * 0.36, 0, 130); let grassComfort = 0; for (const it of this.world.nearbyItems(this.x, this.y, 105)) { if (it.type !== "grass" || it.dead) continue; @@ -1054,7 +1205,7 @@ class Tarinai { if (grassComfort > 0) { this.stress = clamp(this.stress - dt * Math.min(0.32, grassComfort * 0.08), 0, 130); if (this.state === "panic") this.fearTimer = Math.max(0, this.fearTimer - dt * Math.min(0.22, grassComfort * 0.06)); - if (this.need === "\u9759\u3051\u3055" || this.personality === "timid") this.affection += dt * Math.min(0.06, grassComfort * 0.012); + if (this.need === "\u9759\u3051\u3055" || this.shouldApplyPersonalityBehavior("neuroticism", 1)) this.affection += dt * Math.min(0.06, grassComfort * 0.012); } } @@ -1080,10 +1231,44 @@ class Tarinai { return target?.type === "nest_box" ? "\u5de3\u7bb1" : "\u5e72\u8349\u5bdd\u5e8a"; } + isServingFoodItem(it) { + return Boolean(it && typeof isServingFoodType === "function" && isServingFoodType(it.type)); + } + + foodItemHasServingLeft(it) { + if (!it || it.dead) return false; + if (!this.isServingFoodItem(it)) return (it.amount || 0) > 1.2; + this.ensureFoodServings(it); + return (it.foodServingsRemaining || 0) > 0; + } + + ensureFoodServings(it) { + if (!this.isServingFoodItem(it)) return; + const max = typeof foodServingsForSize === "function" ? foodServingsForSize(it.toolSize || "medium") : 5; + if (!Number.isFinite(it.foodServingsMax) || it.foodServingsMax <= 0) it.foodServingsMax = max; + if (!Number.isFinite(it.foodServingsRemaining)) { + const original = { food: 85, sweet: 62, love_mochi: 62, fight_mochi: 62, sleep_drug: 58 }[it.type] || 62; + const ratio = clamp((it.amount ?? original) / original, 0.05, 1); + it.foodServingsRemaining = Math.max(1, Math.ceil(it.foodServingsMax * ratio)); + } + it.foodServingsRemaining = clamp(it.foodServingsRemaining, 0, it.foodServingsMax); + it.amount = it.foodServingsRemaining; + } + + consumeFoodServing(it, nutrition) { + this.ensureFoodServings(it); + if (!this.isServingFoodItem(it) || (it.foodServingsRemaining || 0) <= 0) return 0; + it.foodServingsRemaining = Math.max(0, (it.foodServingsRemaining || 0) - 1); + it.amount = it.foodServingsRemaining; + return nutrition; + } + sleepSpotFor(bed) { if (!bed) return { x: this.x, y: this.y }; if (bed.type === "nest_box") { - return { x: clamp(bed.x, CONFIG.worldPadding, this.world.w - CONFIG.worldPadding), y: clamp(bed.y, CONFIG.worldPadding, this.world.h - CONFIG.worldPadding) }; + if (this.insideNestBoxId === bed.id && this.world?.nestBoxInnerPoint) return this.world.nestBoxInnerPoint(bed, this); + if (this.world?.nestBoxEntryPoint) return this.world.nestBoxEntryPoint(bed); + return { x: clamp(bed.x, CONFIG.worldPadding, this.world.w - CONFIG.worldPadding), y: clamp(bed.y + (bed.r || 42) * 0.24, CONFIG.worldPadding, this.world.h - CONFIG.worldPadding) }; } const angle = stableUnit(this.id, `bed-angle-${bed.id || bed.seed || "bed"}`) * Math.PI * 2; const baseRing = bed.r * 0.52; @@ -1128,6 +1313,7 @@ class Tarinai { const d = dist(this, z); const push = clamp(1 - d / 90, 0, 1); this.stress = clamp(this.stress + push * dt * 1.2 * this.personalityProfile().fear, 0, 130); + if (push > 0.2) this.adjustPersonality("neuroticism", -dt * push * 0.0035, "after repeated contact with poop."); this.vx += (this.x - z.x) / Math.max(d, 1) * push * dt * 40; this.vy += (this.y - z.y) / Math.max(d, 1) * push * dt * 40; } @@ -1182,12 +1368,12 @@ class Tarinai { this.fightWinnerId = null; } - const friendNearby = this.bestFriendLive ? this.bestFriendLive(12, 170) : null; + const friendNearby = this.bestFriendLive ? this.bestFriendLive(FRIEND_AFFINITY_THRESHOLD, 170) : null; if (friendNearby && friendNearby.state === "panic" && friendNearby.target) { this.state = "panic"; this.target = this.panicDestination(friendNearby.target); this.fearTimer = Math.max(this.fearTimer, 0.32); - this.thought = "\u4ef2\u826f\u3057\u3068\u4e00\u7dd2\u306b\u9003\u3052\u3066\u3044\u308b"; + this.thought = "\u53cb\u9054\u3068\u4e00\u7dd2\u306b\u9003\u3052\u3066\u3044\u308b"; return; } @@ -1245,11 +1431,11 @@ class Tarinai { if (this.hasZundaCurableDisease?.() && this.fightTimer <= 0.04 && this.birthRitualTimer <= 0.04 && this.defeatedTimer <= 0.04) { const cureFood = this.world.nearest(this, ["sweet"], 700); - if (cureFood && cureFood.amount > 1.2 && !this.shouldAvoidTarget(cureFood)) { + if (cureFood && this.foodItemHasServingLeft(cureFood) && !this.shouldAvoidTarget(cureFood)) { this.state = "seek_food"; this.target = cureFood; this.foodReactTimer = Math.max(this.foodReactTimer, 0.42); - this.thought = this.fightDisease ? "きずつき病\u3067\u305a\u3093\u3060\u9905\u3092\u63a2\u3057\u3066\u3044\u308b" : "\u7206\u767a\u75c5\u3067\u305a\u3093\u3060\u9905\u3092\u63a2\u3057\u3066\u3044\u308b"; + this.thought = this.fightDisease ? "\u304d\u305a\u3064\u304d\u75c5\u3067\u305a\u3093\u3060\u9905\u3092\u63a2\u3057\u3066\u3044\u308b" : "\u7206\u767a\u75c5\u3067\u305a\u3093\u3060\u9905\u3092\u63a2\u3057\u3066\u3044\u308b"; return; } } @@ -1257,14 +1443,14 @@ class Tarinai { if (this.fightDisease && this.fightTimer <= 0.04 && this.birthRitualTimer <= 0.04 && this.defeatedTimer <= 0.04) { this.state = "fight_sick"; this.target = null; - this.thought = "きずつき病\u3067\u5f53\u3066\u3082\u306a\u304f\u5f77\u5fa8\u3063\u3066\u3044\u308b"; + this.thought = "\u304d\u305a\u3064\u304d\u75c5\u3067\u5f53\u3066\u3082\u306a\u304f\u5f77\u5fa8\u3063\u3066\u3044\u308b"; if (Math.random() < dt * 0.45) this.wanderAngle += rand(-3.4, 3.4); return; } if (!this.isZunchiSlave) { const specialMochi = this.world.nearest(this, ["love_mochi", "fight_mochi", "sleep_drug"], wasSleeping ? 520 : 390); - if (specialMochi && specialMochi.amount > 1.2 && this.hunger > 10 && !this.shouldAvoidTarget(specialMochi)) { + if (specialMochi && this.foodItemHasServingLeft(specialMochi) && this.hunger > 10 && !this.shouldAvoidTarget(specialMochi)) { this.state = "seek_food"; this.target = specialMochi; this.foodReactTimer = Math.max(this.foodReactTimer, 0.34); @@ -1286,7 +1472,7 @@ class Tarinai { const zunda = this.world.nearest(this, ["sweet"], zundaRange); const zundaHungry = this.hunger > Math.max(7, 18 - 10 * (this.personalityProfile().zunda - 1)); const zundaReward = this.affection > 8 && this.hunger > 7; - if (zunda && zunda.amount > 1.2 && ((wasSleeping && this.hunger > 7) || zundaHungry || zundaReward)) { + if (zunda && this.foodItemHasServingLeft(zunda) && ((wasSleeping && this.hunger > 7) || zundaHungry || zundaReward)) { this.state = "seek_food"; this.target = zunda; this.foodReactTimer = Math.max(this.foodReactTimer, 0.36); @@ -1306,7 +1492,7 @@ class Tarinai { if (keepSleeping || (personalSleep && this.energy < 90 + 8 * sleepBias) || this.energy < 28 + 8 * sleepBias) { let bed = this.isSleepFurniture(previousTarget) ? previousTarget : null; if (!bed && friendNearby && this.isSleepFurniture(friendNearby.target) && (friendNearby.state === "sleep" || friendNearby.state === "seek_bed")) bed = friendNearby.target; - if (!bed && !wasSleeping) bed = this.world.bestBedFor(this, 360); + if (!bed) bed = this.world.bestBedFor(this, wasSleeping ? 480 : 420); if (bed && !wasSleeping && this.energy > 18) { const spot = this.sleepSpotFor(bed); if (distXY(this.x, this.y, spot.x, spot.y) > this.radius + 10) { @@ -1323,7 +1509,7 @@ class Tarinai { this.nextSleepBubbleAt = this.world.time + 4.5; this.world.spawnBubble(this.x, this.y - this.radius * 1.18, "Zzz...", "rgba(65,70,92,0.72)"); } - this.thought = bed ? "\u30d9\u30c3\u30c9\u306e\u8fd1\u304f\u3067\u7720\u3063\u3066\u3044\u308b" : "\u7720\u3063\u3066\u3044\u308b"; + this.thought = bed ? (bed.type === "nest_box" ? "\u5de3\u7bb1\u306e\u4e2d\u3067\u7720\u3063\u3066\u3044\u308b" : "\u30d9\u30c3\u30c9\u306e\u8fd1\u304f\u3067\u7720\u3063\u3066\u3044\u308b") : "\u7720\u3063\u3066\u3044\u308b"; return; } @@ -1355,19 +1541,21 @@ class Tarinai { } const playTrait = this.personalityProfile().play ?? 1; - const ballRange = this.personality === "playful" ? 540 : 240 + 60 * playTrait; + const openPlay = this.shouldApplyPersonalityBehavior("openness", 1); + const closedPlay = this.shouldApplyPersonalityBehavior("openness", -1); + const ballRange = openPlay ? 540 : (closedPlay ? 170 : 240 + 60 * playTrait); const ball = this.world.nearest(this, ["ball"], ballRange); if (ball && this.energy > 26 && this.hunger < 98 && !this.shouldAvoidTarget(ball)) { const ballSpeed = Math.hypot(ball.vx || 0, ball.vy || 0); const chasers = this.world.countBallChasers ? this.world.countBallChasers(ball, this) : 0; - const baseChance = this.personality === "playful" ? 0.74 : 0.08; + const baseChance = openPlay ? 0.74 : (closedPlay ? 0.025 : 0.08); const movingBonus = clamp(ballSpeed / 120, 0, 0.42); const socialBonus = this.loneliness > 48 ? 0.10 : 0; - if (chasers < 5 && (this.personality === "playful" || ballSpeed > 7 || Math.random() < baseChance * playTrait + movingBonus + socialBonus)) { + if (chasers < 5 && (openPlay || ballSpeed > 7 || Math.random() < baseChance * playTrait + movingBonus + socialBonus)) { this.state = "play_ball"; this.target = ball; this.goodMode = "smile"; - this.thought = this.personality === "playful" ? "\u30dc\u30fc\u30eb\u306b\u5f15\u304d\u5bc4\u305b\u3089\u308c\u3066\u3044\u308b" : "\u8ee2\u304c\u308b\u3082\u306e\u304c\u6c17\u306b\u306a\u3063\u3066\u3044\u308b"; + this.thought = openPlay ? "\u30dc\u30fc\u30eb\u306b\u5f15\u304d\u5bc4\u305b\u3089\u308c\u3066\u3044\u308b" : "\u8ee2\u304c\u308b\u3082\u306e\u304c\u6c17\u306b\u306a\u3063\u3066\u3044\u308b"; return; } } @@ -1388,7 +1576,7 @@ class Tarinai { this.state = "seek_food"; this.target = friendNearby.target; this.foodReactTimer = Math.max(this.foodReactTimer, 0.24); - this.thought = "\u4ef2\u826f\u3057\u3068\u4e00\u7dd2\u306b\u98df\u3079\u306b\u884c\u304f"; + this.thought = "\u53cb\u9054\u3068\u4e00\u7dd2\u306b\u98df\u3079\u306b\u884c\u304f"; return; } @@ -1404,8 +1592,10 @@ class Tarinai { } } - if (this.loneliness > 63 - (this.personality === "lonely" ? 16 : 0)) { - const other = this.world.nearestOther(this, 300); + const socialSeek = this.shouldApplyPersonalityBehavior("sociability", 1); + const lonerSeek = this.shouldApplyPersonalityBehavior("sociability", -1); + if (this.loneliness > 63 - (socialSeek ? 16 : 0) + (lonerSeek ? 10 : 0)) { + const other = this.world.nearestOther(this, socialSeek ? 390 : (lonerSeek ? 190 : 300)); if (other) { this.state = "seek_friend"; this.target = other; @@ -1446,14 +1636,13 @@ class Tarinai { const d = dist(this, it); if (d > this.radius + it.r + 12) continue; - if (((it.type === "sweet" && canSweetBite) || (it.type === "food" && canBite)) && it.amount > 1.2) { - const eating = Math.min(it.amount, it.type === "sweet" ? 7.2 : 8.5); + if (((it.type === "sweet" && canSweetBite) || (it.type === "food" && canBite)) && this.foodItemHasServingLeft(it)) { + const eating = this.consumeFoodServing(it, it.type === "sweet" ? 7.2 : 8.5); if (eating > 0) { this.state = "eat"; this.target = it; this.vx *= Math.pow(0.25, dt * 60); this.vy *= Math.pow(0.25, dt * 60); - it.amount -= eating; this.hunger -= eating * (it.type === "sweet" ? 0.75 : 0.95); this.recoverHealth(eating * (it.type === "sweet" ? 0.28 : 0.46)); this.affection += it.type === "sweet" ? eating * 0.03 : eating * 0.012; @@ -1461,7 +1650,7 @@ class Tarinai { this.stress = clamp(this.stress - eating * 0.42, 0, 130); this.fearTimer = Math.max(0, this.fearTimer - eating * 0.035); if (this.explosionDisease) this.recoverExplosionDisease("\u305a\u3093\u3060\u9905\u3067\u7206\u767a\u75c5\u304c\u6cbb\u3063\u305f"); - if (this.fightDisease) this.recoverFightDisease("\u305a\u3093\u3060\u9905\u3067きずつき病\u304c\u6cbb\u3063\u305f"); + if (this.fightDisease) this.recoverFightDisease("\u305a\u3093\u3060\u9905\u3067\u304d\u305a\u3064\u304d\u75c5\u304c\u6cbb\u3063\u305f"); } this.eatTimer = Math.max(this.eatTimer, 0.32); this.eatCooldown = it.type === "sweet" ? rand(0.34, 0.62) : rand(0.44, 0.78); @@ -1482,13 +1671,13 @@ class Tarinai { } } - if (canSweetBite && (it.type === "love_mochi" || it.type === "fight_mochi" || it.type === "sleep_drug") && it.amount > 1.2) { - const eating = Math.min(it.amount, 6.8); + if (canSweetBite && (it.type === "love_mochi" || it.type === "fight_mochi" || it.type === "sleep_drug") && this.foodItemHasServingLeft(it)) { + const eating = this.consumeFoodServing(it, 6.8); + if (eating <= 0) continue; this.state = "eat"; this.target = it; this.vx *= Math.pow(0.25, dt * 60); this.vy *= Math.pow(0.25, dt * 60); - it.amount -= eating; this.hunger -= eating * 0.82; this.recoverHealth(eating * 0.24); this.affection += eating * 0.04; @@ -1497,12 +1686,20 @@ class Tarinai { this.loveMochiTimer = Math.max(this.loveMochiTimer || 0, 42 + rand(4, 12)); this.bubble("\u2661", 2.4, "rgba(190,82,132,0.78)"); this.lastMealColor = "#ff7bab"; - } else { + } else if (it.type === "fight_mochi") { this.stress = clamp(this.stress + eating * 0.22, 0, 130); this.fearTimer = Math.max(this.fearTimer || 0, 0.32); this.fightMochiTimer = Math.max(this.fightMochiTimer || 0, 52 + rand(10, 18)); this.bubble("!", 2.0, "rgba(180,86,52,0.80)"); this.lastMealColor = "#e07c43"; + } else { + this.stress = clamp(this.stress - eating * 0.10, 0, 130); + this.energy = clamp(this.energy - eating * 0.20, 0, 100); + this.fearTimer = Math.max(0, (this.fearTimer || 0) - 0.18); + this.fightMochiTimer = Math.max(0, (this.fightMochiTimer || 0) - 2.5); + this.bubble("Zzz...", 2.3, "rgba(104,84,168,0.78)"); + this.lastMealColor = "#b89cff"; + if (!this.sleepDisease && Math.random() < Math.min(0.98, 0.35 + eating * 0.075)) this.infectSleepDisease(it); } this.eatTimer = Math.max(this.eatTimer, 0.30); this.eatCooldown = rand(0.38, 0.68); @@ -1521,7 +1718,8 @@ class Tarinai { } if (canBite && it.type === "grass") { - const bite = Math.min(it.amount, rand(4.2, 7.2)); + const servingScale = Number.isFinite(it.foodServingScale) ? it.foodServingScale : (it.toolSize === "large" ? 1.18 : (it.toolSize === "small" ? 0.82 : 1)); + const bite = Math.min(it.amount, rand(4.2, 7.2) * servingScale); this.state = "eat"; this.target = it; this.grassEatTimer = Math.max(this.grassEatTimer, 0.22); @@ -1548,10 +1746,14 @@ class Tarinai { if (it.type === "zunchi") { const touch = clamp(1 - d / (this.radius + it.r + 12), 0, 1); - if (!this.isZunchiSlave) this.stress = clamp(this.stress + touch * dt * 3.4, 0, 130); + if (!this.isZunchiSlave) { + this.stress = clamp(this.stress + touch * dt * 3.4 * this.personalityProfile().fear, 0, 130); + if (touch > 0.08) this.adjustPersonality("neuroticism", -dt * touch * 0.0045, "after repeated contact with poop."); + } this.zunchiStain = clamp((this.zunchiStain || 0) + touch * dt * (this.isZunchiSlave ? 5.2 : 9.5), 0, 100); if (canZunchiBite) { - const bite = Math.min(it.amount, this.isZunchiSlave ? rand(4.8, 7.4) : rand(3.4, 5.8)); + const servingScale = Number.isFinite(it.foodServingScale) ? it.foodServingScale : (it.toolSize === "large" ? 1.18 : (it.toolSize === "small" ? 0.82 : 1)); + const bite = Math.min(it.amount, (this.isZunchiSlave ? rand(4.8, 7.4) : rand(3.4, 5.8)) * servingScale); this.state = "eat"; this.target = it; this.vx *= Math.pow(0.18, dt * 60); @@ -1559,7 +1761,8 @@ class Tarinai { it.amount -= bite; this.hunger -= bite * (this.isZunchiSlave ? 0.66 : 0.18); this.recoverHealth(bite * (this.isZunchiSlave ? 0.10 : 0.02)); - this.stress = clamp(this.stress + bite * (this.isZunchiSlave ? 0.06 : 0.52), 0, 130); + this.stress = clamp(this.stress + bite * (this.isZunchiSlave ? 0.06 : 0.52) * this.personalityProfile().fear, 0, 130); + if (!this.isZunchiSlave) this.adjustPersonality("neuroticism", -bite * 0.0015, "after repeated contact with poop."); this.zunchiStain = clamp((this.zunchiStain || 0) + bite * (this.isZunchiSlave ? 0.75 : 1.75), 0, 100); this.lastMealColor = "#6b8d3f"; this.eatTimer = Math.max(this.eatTimer, 0.24); @@ -1604,7 +1807,7 @@ class Tarinai { if (it.type === "ball") { const touch = clamp(1 - d / (this.radius + it.r + 12), 0, 1); - if (this.state === "play_ball" || this.target === it || this.personality === "playful") { + if (this.state === "play_ball" || this.target === it || this.shouldApplyPersonalityBehavior("openness", 1)) { this.goodMode = "smile"; this.stress = clamp(this.stress - dt * (0.9 + touch * 1.8), 0, 130); this.loneliness = clamp(this.loneliness - dt * (0.4 + touch), 0, 110); @@ -1612,9 +1815,17 @@ class Tarinai { } } + if (it.type === "splat") { + const touch = clamp(1 - d / (this.radius + it.r + 16), 0, 1); + if (touch > 0) { + this.stress = clamp(this.stress + touch * dt * 2.8 * this.personalityProfile().fear, 0, 130); + if (touch > 0.06) this.adjustPersonality("neuroticism", -dt * touch * 0.0042, "after repeated contact with corpses"); + } + } + if (it.type === "trace") { this.loneliness -= dt * 0.25; - this.stress += dt * 0.06; + this.stress += dt * 0.06 * this.personalityProfile().fear; } } this.hunger = clamp(this.hunger, 0, 115); @@ -1663,12 +1874,12 @@ class Tarinai { this.loneliness -= dt * 1.65 * this.trait.social; this.affection += dt * 0.28 * this.trait.social; this.adjustRelation(o, dt * 0.18 * pdef.relation * (rel.fear > 10 ? 0.35 : 1), -dt * 0.018, "nearby"); - if ((rel.affinity || 0) > 10) { + if ((rel.affinity || 0) >= FRIEND_AFFINITY_THRESHOLD) { this.stress = clamp(this.stress - dt * 0.62 * this.trait.social, 0, 130); this.affection = clamp(this.affection + dt * 0.18, 0, 80); if (this.world.relationNotice(this.id, o.id, "friend-calm", 55)) this.world.log(`${this.name}\u306f${o.name}\u3068\u3044\u308b\u3068\u5c11\u3057\u843d\u3061\u7740\u304f\u3002`, "relation"); } - if ((rel.affinity || 0) > 8 && this.world.relationNotice(this.id, o.id, "friend", 32)) { + if ((rel.affinity || 0) >= FRIEND_AFFINITY_THRESHOLD && this.world.relationNotice(this.id, o.id, "friend", 32)) { this.world.log(`${this.name}\u306f\u3088\u304f${o.name}\u306e\u8fd1\u304f\u306b\u3044\u308b\u3002`, "relation"); } if (this.type === "angry") this.stress += dt * 0.08; @@ -1711,10 +1922,14 @@ class Tarinai { const relB = o.relationTo(this.id); const battleDrug = this.hasFightMochiEffect() || o.hasFightMochiEffect(); const loveDrug = this.hasLoveMochiEffect() || o.hasLoveMochiEffect(); - const fightRisk = (this.mood < 55 || o.mood < 55 || this.stress > 46 || o.stress > 46 || this.type === "angry" || o.type === "angry" || closeCount > 3 || this.personality === "irritable" || o.personality === "irritable" || battleDrug || o.isZunchiSlave || this.isZunchiSlave); + const aggressiveThis = this.shouldApplyPersonalityBehavior("aggression", 1); + const aggressiveOther = o.shouldApplyPersonalityBehavior?.("aggression", 1); + const calmThis = this.shouldApplyPersonalityBehavior("aggression", -1); + const calmOther = o.shouldApplyPersonalityBehavior?.("aggression", -1); + const fightRisk = (this.mood < 55 || o.mood < 55 || this.stress > 46 || o.stress > 46 || this.type === "angry" || o.type === "angry" || closeCount > 3 || aggressiveThis || aggressiveOther || battleDrug || o.isZunchiSlave || this.isZunchiSlave); const fearBrake = battleDrug ? clamp(1 - ((relA.fear || 0) + (relB.fear || 0)) / 220, 0.74, 1.15) : clamp(1 - ((relA.fear || 0) + (relB.fear || 0)) / 120, 0.34, 1); const friendBrake = battleDrug ? clamp(1 - Math.max(relA.affinity || 0, relB.affinity || 0) / 180, 0.72, 1.12) : clamp(1 - Math.max(relA.affinity || 0, relB.affinity || 0) / 90, 0.48, 1); - const personalityRisk = this.personalityProfile().fight * o.personalityProfile().fight; + const personalityRisk = this.personalityProfile().fight * o.personalityProfile().fight * (calmThis ? 0.62 : 1) * (calmOther ? 0.62 : 1); const conflictBias = (battleDrug ? 2.9 : 1) * (o.isZunchiSlave ? 2.2 : 1) * (this.isZunchiSlave ? 1.15 : 1); const birthPeace = (this.postBirthPeaceTimer || 0) > 0 || (o.postBirthPeaceTimer || 0) > 0; const familyFightBlocked = this.world.areParentChild ? this.world.areParentChild(this, o) : false; @@ -1723,7 +1938,7 @@ class Tarinai { this.world.startConflict(this, o); } - if (!this.isZunchiSlave && !o.isZunchiSlave && d < (loveDrug ? 44 : 36) && this.reproductionTimer <= 0 && o.reproductionTimer <= 0 && this.fightTimer <= 0 && o.fightTimer <= 0) { + if (!this.isZunchiSlave && !o.isZunchiSlave && !this.sleepDisease && !o.sleepDisease && !this.fightDisease && !o.fightDisease && d < (loveDrug ? 44 : 36) && this.reproductionTimer <= 0 && o.reproductionTimer <= 0 && this.fightTimer <= 0 && o.fightTimer <= 0) { const enough = loveDrug ? (this.hunger < 90 && o.hunger < 92 && this.energy > 18 && o.energy > 18) : (this.hunger < 55 && o.hunger < 60 && this.energy > 44 && o.energy > 44); const lonelyBond = loveDrug ? (this.loneliness > 4 || o.loneliness > 4 || this.affection > 0 || o.affection > 0) : (this.loneliness > 24 || o.loneliness > 24); if (enough && lonelyBond && Math.random() < dt * (loveDrug ? 0.72 : 0.25)) { @@ -1733,7 +1948,7 @@ class Tarinai { } if (closeCount > 8) { - this.stress += dt * 0.9; + this.stress += dt * 0.9 * this.personalityProfile().fear; this.energy -= dt * 0.25; this.fearTimer = Math.max(this.fearTimer, 0.18); } @@ -1755,6 +1970,12 @@ class Tarinai { this.energy = clamp(this.energy + dt * (this.target ? 1.8 + bedComfort * 1.35 : 2.1), 0, 100); this.stress = clamp(this.stress + dt * (crowdedSleep ? 0.18 * Math.max(1, bedCrowd - 5) : -0.12 * bedComfort), 0, 130); this.hunger = clamp(this.hunger + dt * 0.018, 0, 115); + if (this.target && !this.target.dead && this.target.type === "nest_box") { + this.updateNestBoxPresence(dt); + this.vx = 0; + this.vy = 0; + return; + } if (this.target && !this.target.dead && this.isSleepFurniture(this.target)) { const spot = this.sleepSpotFor(this.target); const dx = spot.x - this.x; @@ -1828,9 +2049,13 @@ class Tarinai { const bedDx = this.target.x - this.x; const bedDy = this.target.y - this.y; const bedDist = Math.hypot(bedDx, bedDy); - if (d <= Math.max(this.radius + 8, 26) || bedDist <= Math.max(this.target.r * 0.58, 20)) { + const reachedSleepFurniture = this.target.type === "nest_box" + ? (this.insideNestBoxId === this.target.id || d <= Math.max(this.radius + 34, this.target.r * 1.08) || bedDist <= Math.max(this.target.r * 1.05, 62)) + : (d <= Math.max(this.radius + 8, 26) || bedDist <= Math.max(this.target.r * 0.58, 20)); + if (reachedSleepFurniture) { this.state = "sleep"; this.sleeping = true; + if (this.target.type === "nest_box") this.enterNestBox(this.target, dt); return; } } @@ -1890,8 +2115,13 @@ class Tarinai { this.vy = this.vy / v * maxV; } - this.x += this.vx * dt; - this.y += this.vy * dt; + const impulseVx = Number.isFinite(this.impulseVx) ? this.impulseVx : 0; + const impulseVy = Number.isFinite(this.impulseVy) ? this.impulseVy : 0; + this.x += (this.vx + impulseVx) * dt; + this.y += (this.vy + impulseVy) * dt; + const impulseDrag = Math.pow(0.58, dt * 3.2); + this.impulseVx = Math.abs(impulseVx) < 0.35 ? 0 : impulseVx * impulseDrag; + this.impulseVy = Math.abs(impulseVy) < 0.35 ? 0 : impulseVy * impulseDrag; if (this.entryTimer > 0) { this.entryTimer = Math.max(0, this.entryTimer - dt); @@ -1914,7 +2144,7 @@ class Tarinai { reason = this.dominantDeathCause("", { lowHealth: true }) || "\u4e8b\u6545"; } else if (this.hunger >= 108) reason = "\u98e2\u9913"; - else if (this.age >= this.lifeSpan) reason = "天寿を全うした"; + else if (this.age >= this.lifeSpan) reason = "\u5929\u5bff\u3092\u5168\u3046\u3057\u305f"; else if (this.stress >= 124) { reason = this.dominantDeathCause("\u30b9\u30c8\u30ec\u30b9\u904e\u591a", { stressDeath: true }) || "\u30b9\u30c8\u30ec\u30b9\u904e\u591a"; } @@ -2032,7 +2262,7 @@ class Tarinai { const style = { parent: { color: "rgba(86,142,232,0.86)", label: "\u89aa" }, child: { color: "rgba(93,170,92,0.88)", label: "\u5b50" }, - friend: { color: "rgba(240,91,135,0.90)", label: "\u4ef2\u826f\u3057" }, + friend: { color: "rgba(240,91,135,0.90)", label: "\u53cb\u9054" }, enemy: { color: "rgba(214,82,66,0.90)", label: "\u6575\u5bfe" }, }[observeKind] || { color: "rgba(255,250,220,0.78)", label: "" }; ctx.save(); @@ -2070,27 +2300,40 @@ class Tarinai { ctx.restore(); } - - ctx.rotate(angle); - ctx.globalAlpha *= nestHideAlpha; - if (insideCardboard) ctx.globalAlpha *= 0.58; - - if (this.world.selected === this) { ctx.save(); - ctx.globalAlpha = 0.85; - ctx.strokeStyle = "rgba(165, 220, 98, 0.92)"; - ctx.lineWidth = 2; + const pulse = 0.5 + 0.5 * Math.sin(this.world.time * 7.5); + const jumpPulse = clamp(this.focusPulseTimer || 0, 0, 1); + ctx.globalAlpha = (0.82 + pulse * 0.12) * nestHideAlpha; + ctx.shadowColor = "rgba(124, 210, 76, 0.92)"; + ctx.shadowBlur = 14 + 18 * Math.max(pulse, jumpPulse); + ctx.strokeStyle = "rgba(112, 198, 70, 0.98)"; + ctx.lineWidth = 4.2 + jumpPulse * 2.0; ctx.beginPath(); - ctx.ellipse(0, drawH * 0.14, drawW * 0.62, drawH * 0.48, 0, 0, Math.PI * 2); + ctx.ellipse(0, drawH * 0.14, drawW * (0.74 + jumpPulse * 0.10), drawH * (0.56 + jumpPulse * 0.08), 0, 0, Math.PI * 2); ctx.stroke(); - ctx.setLineDash([5, 4]); - ctx.lineWidth = 1.2; - ctx.strokeStyle = "rgba(255,255,255,0.86)"; + ctx.shadowBlur = 0; + ctx.setLineDash([9, 5]); + ctx.lineWidth = 2.0; + ctx.strokeStyle = "rgba(255,255,255,0.96)"; ctx.beginPath(); - ctx.ellipse(0, drawH * 0.14, drawW * 0.72, drawH * 0.56, 0, 0, Math.PI * 2); + ctx.ellipse(0, drawH * 0.14, drawW * 0.88, drawH * 0.68, 0, 0, Math.PI * 2); ctx.stroke(); ctx.setLineDash([]); + ctx.fillStyle = "rgba(255,252,232,0.94)"; + ctx.strokeStyle = "rgba(112,198,70,0.88)"; + ctx.lineWidth = 2; + const focusLabel = "\u6ce8\u76ee"; + ctx.font = `${Math.max(11, this.radius * 0.54)}px Yomogi, ui-rounded, sans-serif`; + const lw = ctx.measureText(focusLabel).width + 18; + const ly = -drawH * 0.64; + tarinaiRoundRectPath(ctx, -lw / 2, ly - 11, lw, 22, 11); + ctx.fill(); + ctx.stroke(); + ctx.fillStyle = "rgba(72,126,42,0.96)"; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.fillText(focusLabel, 0, ly); ctx.restore(); } else if ((this.world.performanceLevel ? this.world.performanceLevel() : 0) < 2 && this.world.pointer?.inside && distXY(this.x, this.y, this.world.pointer.x, this.world.pointer.y) < this.radius * 2.0) { ctx.save(); @@ -2103,6 +2346,11 @@ class Tarinai { ctx.restore(); } + ctx.rotate(angle); + ctx.globalAlpha *= nestHideAlpha; + if (insideCardboard) ctx.globalAlpha *= 0.58; + + if (this.eatTimer > 0.02) { ctx.save(); ctx.globalAlpha = 0.46 * (this.eatTimer / 0.32); @@ -2235,16 +2483,17 @@ class Tarinai { }; if (stressActive) { const pct = clamp((this.stress || 0) / 130, 0, 1); - drawMeter(baseY - (hpActive ? 11 : 0), pct, pct > 0.72 ? "rgba(178,74,110,0.92)" : "rgba(212,126,84,0.90)", clamp((this.stressBarTimer || 0) / 0.7, 0.35, 1)); + drawMeter(baseY, pct, pct > 0.72 ? "rgba(178,74,110,0.92)" : "rgba(212,126,84,0.90)", clamp((this.stressBarTimer || 0) / 0.7, 0.35, 1)); } if (hpActive) { const pct = clamp(this.energy / 100, 0, 1); - drawMeter(baseY, pct, pct > 0.45 ? "rgba(118,190,80,0.88)" : (pct > 0.20 ? "rgba(232,172,68,0.90)" : "rgba(218,82,70,0.92)"), clamp((this.hpBarTimer || 0) / 0.7, 0.35, 1)); + drawMeter(baseY - (stressActive ? 11 : 0), pct, pct > 0.45 ? "rgba(118,190,80,0.88)" : (pct > 0.20 ? "rgba(232,172,68,0.90)" : "rgba(218,82,70,0.92)"), clamp((this.hpBarTimer || 0) / 0.7, 0.35, 1)); } } } contains(x, y) { + if (this.insideNestBoxId || (this.nestFade || 0) >= 0.92) return false; const hit = this.world.screenSizeToWorld ? this.world.screenSizeToWorld(this.radius * 1.9) : this.radius * 1.9; return distXY(this.x, this.y, x, y) < hit; } diff --git a/js/text_catalog.js b/js/text_catalog.js index 1fb771b..7e58f38 100644 --- a/js/text_catalog.js +++ b/js/text_catalog.js @@ -1,76 +1,54 @@ "use strict"; const TEXT_CATALOG = { - toolTips: { - observe: "\u500b\u4f53\u3092\u9078\u629e\u3057\u3001\u72b6\u614b\u30fb\u6027\u683c\u30fb\u75c5\u6c17\u30fb\u304a\u6c17\u306b\u5165\u308a\u3092\u78ba\u8a8d\u3059\u308b\u3002", - delete: "\u7f6e\u3044\u305f\u9053\u5177\u3084\u6c5a\u308c\u3092\u6d88\u3059\u3002", - poke: "たりないをつつく。", - pinch: "たりないや物を移動させる。", - new: "\u753b\u9762\u5916\u304b\u3089\u65b0\u3057\u3044\u305f\u308a\u306a\u3044\u3092\u547c\u3076\u3002", - zunchi: "たりないのうんち。病気を生み出すかも。", - sweet: "たりないの大好物。一部の病気を治せる。", - love_mochi: "\u98df\u5f8c\u3057\u3070\u3089\u304f\u7e41\u6b96\u884c\u52d5\u304c\u8d77\u304d\u3084\u3059\u304f\u306a\u308b\u3002", - fight_mochi: "食後しばらくの間けんかが起きやすくなる。", - water: "\u98f2\u3080\u3068\u6c17\u5206\u56de\u5fa9\u3002\u305a\u3093\u3061\u75c5\u3068\u7206\u767a\u75c5\u3092\u6cbb\u3059\u3002", - water_bowl: "衛生的な水が入った皿。一部の病気を治せる。", - sleep_drug: "\u98df\u3079\u308b\u3068\u306d\u3080\u308a\u75c5\u306b\u306a\u308b\u3002\u30c0\u30e1\u30fc\u30b8\u3067\u5b8c\u6cbb\u3059\u308b\u3002", - grass: "食べ物。たりないが安心する。", - stone: "あぶない。", - bed: "\u8fd1\u304f\u3067\u7720\u308b\u3002\u4f53\u529b\u304c\u56de\u5fa9\u3059\u308b\u3002", - nest_box: "\u3044\u308b\u3060\u3051\u3067\u30b9\u30c8\u30ec\u30b9\u4f4e\u6e1b\u3002\u7720\u308b\u3068\u7761\u7720\u306e\u8cea\u304c\u4e0a\u304c\u308b\u3002", - water_hose: "ドラッグで汚れをきれいにする。", - ball: "たりないが遊ぶたのしいおもちゃ。", - firecracker: "爆発を起こす。", - fence_v: "たりないを通せんぼする。", - fence_h: "たりないを通せんぼする。" - }, + toolTips: toolTipsFromDefinitions(), ecologyCards: [ - { - "title": "\u305f\u308a\u306a\u3044\u3068\u306f", - "image": "assets/sprites/tarinai_01_smile.png", - "text": "\u5ead\u3067\u52dd\u624b\u306b\u66ae\u3089\u3059\u5c0f\u3055\u306a\u751f\u304d\u7269\u3002\u304a\u306a\u304b\u3001\u7720\u6c17\u3001\u6c17\u5206\u3001\u30b9\u30c8\u30ec\u30b9\u3001\u4f53\u529b\u3067\u884c\u52d5\u304c\u5909\u308f\u308b\u3002" - }, - { - "title": "体力とストレス", - "image": "assets/ui/ecology_hp_stress.png", - "text": "体力はけがや衝突、爆発、空腹などで減り、0になると死亡する。ストレスは恐怖、混雑、汚れ、けんかなどで増え、高すぎると行動が乱れたり命に関わる。体力バーとストレスバーは、状態が変化した直後や観察時に表示される。" - }, - { - "title": "\u66ae\u3089\u3057\u3068\u6b32\u6c42", - "image": "assets/sprites/tarinai_05_drool.png", - "text": "\u98df\u3079\u7269\u3001\u6c34\u3001\u5bdd\u5e8a\u3001\u5de3\u7bb1\u3001\u4ef2\u9593\u3092\u63a2\u3057\u3066\u52d5\u304f\u3002\u96e8\u3084\u6c17\u6e29\u3001\u8349\u3001\u6c5a\u308c\u3001\u9053\u5177\u3082\u65e5\u3005\u306e\u72b6\u614b\u306b\u5f71\u97ff\u3059\u308b\u3002" - }, - { - "title": "\u6027\u683c\u3068\u500b\u6027", - "image": "assets/sprites/tarinai_21_normal_happy.png", - "text": "\u81c6\u75c5\u3001\u98df\u3044\u3057\u3093\u574a\u3001\u7720\u305f\u304c\u308a\u3001\u5bc2\u3057\u304c\u308a\u306a\u3069\u306e\u6027\u683c\u304c\u3042\u308b\u3002\u6027\u683c\u306f\u6050\u6016\u3001\u55a7\u5629\u3001\u7761\u7720\u3001\u4ef2\u9593\u3078\u306e\u5bc4\u308a\u65b9\u306b\u73fe\u308c\u308b\u3002" - }, - { - "title": "\u5bb6\u65cf\u3068\u95a2\u4fc2", - "image": "assets/sprites/tarinai_27_birth_ritual.png", - "text": "\u89aa\u5b50\u3001\u5171\u540c\u89aa\u3001\u4ef2\u826f\u3057\u3001\u82e6\u624b\u3001\u6050\u6016\u3092\u8a18\u9332\u3059\u308b\u3002\u5b50\u306f\u89aa\u306e\u7247\u65b9\u306e\u6027\u683c\u3092\u7d99\u304e\u3001\u5bb6\u7cfb\u56f3\u306b\u4e16\u4ee3\u304c\u6b8b\u308b\u3002" - }, - { - "title": "\u75c5\u6c17\u3068\u6cbb\u7642", - "image": "assets/sprites/tarinai_24_stress_dizzy.png", - "text": "\u305a\u3093\u3061\u75c5\u3001\u306d\u3080\u308a\u75c5\u3001\u7206\u767a\u75c5\u3001きずつき病\u304c\u3042\u308b\u3002\u6c34\u3067\u6cbb\u308b\u75c5\u6c17\u306e\u500b\u4f53\u306f\u6c34\u3092\u3001\u305a\u3093\u3060\u9905\u3067\u6cbb\u308b\u75c5\u6c17\u306e\u500b\u4f53\u306f\u305a\u3093\u3060\u9905\u3092\u512a\u5148\u3059\u308b\u3002" - }, - { - "title": "\u55a7\u5629\u3068\u4e8b\u6545", - "image": "assets/sprites/tarinai_26_intimidate.png", - "text": "\u5a01\u5687\u3001\u6d41\u8840\u3001\u7206\u7af9\u3001\u30dc\u30fc\u30eb\u3001\u843d\u4e0b\u7269\u3067\u50b7\u3064\u304f\u3002\u6b7b\u56e0\u306f\u55a7\u5629\u3001\u98e2\u9913\u3001\u75c5\u6c17\u3001\u30b9\u30c8\u30ec\u30b9\u904e\u591a\u3001\u7206\u7af9\u3001\u4e8b\u6545\u306a\u3069\u306b\u5206\u304b\u308c\u308b\u3002" - }, - { - "title": "\u9053\u5177\u3068\u4ecb\u5165", - "image": "assets/sprites/tarinai_18_fear.png", - "text": "\u3064\u3064\u304f\u3001\u3064\u307e\u3080\u3001\u9905\u3001\u6c34\u3001\u6d17\u6d44\u3001\u5de3\u7bb1\u3001\u67f5\u3001\u7206\u7af9\u306a\u3069\u3067\u74b0\u5883\u3092\u4f5c\u308b\u3002\u9053\u5177\u306f\u52a9\u3051\u306b\u3082\u5371\u967a\u306b\u3082\u306a\u308b\u3002" - }, - { - "title": "\u89b3\u5bdf\u306e\u65b9\u6cd5", - "image": "assets/sprites/tarinai_11_weak.png", - "text": "\u305f\u308a\u306a\u3044\u9054\u306e\u72b6\u6cc1\u3092\u89b3\u5bdf\u30c4\u30fc\u30eb\u3001\u661f\u30de\u30fc\u30af\u3001\u89b3\u5bdf\u30ed\u30b0\u3001\u5bb6\u7cfb\u56f3\u3001\u6b7b\u56e0\u7b49\u304b\u3089\u77e5\u308b\u3053\u3068\u304c\u51fa\u6765\u308b\u3002" - } - ] + { + title: "\u305f\u308a\u306a\u3044\u3068\u306f", + image: "assets/sprites/tarinai_01_smile.png", + text: "\u5ead\u3067\u66ae\u3089\u3059\u5c0f\u3055\u306a\u751f\u304d\u7269\u3002\u7a7a\u8179\u3001\u7720\u6c17\u3001\u6c17\u5206\u3001\u30b9\u30c8\u30ec\u30b9\u3001\u4f53\u529b\u3067\u884c\u52d5\u304c\u5909\u308f\u308b\u3002", + }, + { + title: "\u4f53\u529b\u3068\u30b9\u30c8\u30ec\u30b9", + image: "assets/ui/ecology_hp_stress.png", + text: "\u30d0\u30fc\u306f\u4e0a\u304c\u4f53\u529b\u3001\u4e0b\u304c\u30b9\u30c8\u30ec\u30b9\u3002\u4f53\u529b\u306f\u3051\u304c\u3084\u4e8b\u6545\u3067\u6e1b\u308a\u30010\u3067\u6b7b\u4ea1\u3002\u30b9\u30c8\u30ec\u30b9\u306f\u6050\u6016\u3001\u6df7\u96d1\u3001\u6c5a\u308c\u3001\u3051\u3093\u304b\u3067\u5897\u3048\u3001\u9ad8\u3044\u3068\u884c\u52d5\u304c\u4e71\u308c\u308b\u3002", + }, + { + title: "\u66ae\u3089\u3057\u3068\u6b32\u6c42", + image: "assets/sprites/tarinai_05_drool.png", + text: "\u98df\u3079\u7269\u3001\u6c34\u3001\u5bdd\u5e8a\u3001\u5de3\u7bb1\u3001\u4ef2\u9593\u3092\u63a2\u3057\u3066\u52d5\u304f\u3002\u96e8\u3001\u6c17\u6e29\u3001\u8349\u3001\u6c5a\u308c\u3001\u9053\u5177\u3082\u72b6\u614b\u306b\u5f71\u97ff\u3059\u308b\u3002", + }, + { + title: "\u6027\u683c\u3068\u500b\u6027", + image: "assets/sprites/tarinai_21_normal_happy.png", + text: "\u653b\u6483\u6027\u3001\u958b\u653e\u6027\u3001\u793e\u4ea4\u6027\u3001\u795e\u7d4c\u8cea\u6027\u304c\u7d4c\u9a13\u3067\u5c11\u3057\u305a\u3064\u5909\u308f\u308b\u3002\u95be\u5024\u3092\u8d85\u3048\u308b\u3068\u6027\u683c\u30bf\u30b0\u3068\u884c\u52d5\u5dee\u306b\u51fa\u308b\u3002", + }, + { + title: "\u5bb6\u65cf\u3068\u95a2\u4fc2", + image: "assets/sprites/tarinai_27_birth_ritual.png", + text: "\u89aa\u5b50\u3001\u5171\u540c\u89aa\u3001\u53cb\u9054\u3001\u6575\u5bfe\u3001\u6050\u6016\u3092\u8a18\u9332\u3059\u308b\u3002\u5b50\u306f\u89aa\u306e\u73fe\u5728\u6027\u683c\u3092\u53d7\u3051\u7d99\u304e\u3001\u5bb6\u7cfb\u56f3\u306b\u4e16\u4ee3\u304c\u6b8b\u308b\u3002", + }, + { + title: "\u75c5\u6c17\u3068\u6cbb\u7642", + image: "assets/sprites/tarinai_24_stress_dizzy.png", + text: "\u305a\u3093\u3061\u75c5\u3001\u306d\u3080\u308a\u75c5\u3001\u7206\u767a\u75c5\u3001\u304d\u305a\u3064\u304d\u75c5\u304c\u3042\u308b\u3002\u75c5\u6c17\u3054\u3068\u306b\u6c34\u3084\u305a\u3093\u3060\u9905\u306a\u3069\u3092\u6c42\u3081\u308b\u3002", + }, + { + title: "\u3051\u3093\u304b\u3068\u4e8b\u6545", + image: "assets/sprites/tarinai_26_intimidate.png", + text: "\u5a01\u5687\u3001\u6d41\u8840\u3001\u7206\u7af9\u3001\u30dc\u30fc\u30eb\u3001\u843d\u4e0b\u7269\u3067\u50b7\u3064\u304f\u3002\u6b7b\u56e0\u306f\u3051\u3093\u304b\u3001\u98e2\u9913\u3001\u75c5\u6c17\u3001\u4e8b\u6545\u306a\u3069\u306b\u5206\u304b\u308c\u308b\u3002", + }, + { + title: "\u9053\u5177\u3068\u4ecb\u5165", + image: "assets/sprites/tarinai_18_fear.png", + text: "\u3064\u3064\u304f\u3001\u3064\u307e\u3080\u3001\u9905\u3001\u6c34\u3001\u6d17\u6d44\u3001\u5de3\u7bb1\u3001\u67f5\u3001\u7206\u7af9\u306a\u3069\u3067\u74b0\u5883\u3092\u4f5c\u308b\u3002\u52a9\u3051\u306b\u3082\u5371\u967a\u306b\u3082\u306a\u308b\u3002", + }, + { + title: "\u89b3\u5bdf\u306e\u65b9\u6cd5", + image: "assets/sprites/tarinai_11_weak.png", + text: "\u89b3\u5bdf\u30c4\u30fc\u30eb\u3001\u661f\u30de\u30fc\u30af\u3001\u89b3\u5bdf\u30ed\u30b0\u3001\u5bb6\u7cfb\u56f3\u3001\u6b7b\u56e0\u7d71\u8a08\u304b\u3089\u500b\u4f53\u306e\u5909\u5316\u3092\u8ffd\u3048\u308b\u3002", + }, + ], }; window.TEXT_CATALOG = TEXT_CATALOG; diff --git a/js/ui.js b/js/ui.js index abaa975..c172696 100644 --- a/js/ui.js +++ b/js/ui.js @@ -136,6 +136,100 @@ function relationIconHtml(id) { return ``; } +function relationEntries(t, kind = "friend") { + const rows = []; + const liveIds = new Set((world?.tarinai || []).filter(o => o && !o.dead && o !== t).map(o => o.id)); + for (const [id, rel] of Object.entries(t?.relationships || {})) { + if (!liveIds.has(id)) continue; + const score = kind === "enemy" ? (rel.fear || 0) : (rel.affinity || 0); + const threshold = kind === "enemy" ? 0.5 : FRIEND_AFFINITY_THRESHOLD; + if (score <= threshold) continue; + rows.push({ id, score, name: relationDisplayName(world, id) }); + } + rows.sort((a, b) => b.score - a.score || a.name.localeCompare(b.name, "ja")); + return rows; +} + +function relationListHtml(t, kind = "friend") { + const rows = relationEntries(t, kind); + if (!rows.length) return "\u306a\u3057"; + const sign = kind === "friend" ? "+" : ""; + return `
${rows.map(r => ` + `).join("")}
`; +} + +function focusTarinaiById(id) { + const t = world?.tarinai?.find(o => o && !o.dead && o.id === id); + if (!t) { showToast("\u305d\u306e\u500b\u4f53\u306f\u3082\u3046\u9078\u629e\u3067\u304d\u307e\u305b\u3093\u3002"); return false; } + world.selected = t; + t.focusPulseTimer = Math.max(t.focusPulseTimer || 0, 1.25); + selectTool("observe"); + if (Number.isFinite(t.x) && Number.isFinite(t.y)) { + world.cameraX = t.x - (world.visibleWorldW ? world.visibleWorldW() : (world.viewportW || world.w)) / 2; + world.cameraY = t.y - (world.visibleWorldH ? world.visibleWorldH() : (world.viewportH || world.h)) / 2; + world.clampCamera?.(); + } + uiCache.selectedSnapshot = ""; + renderSelected(); + renderStats(); + render?.(); + showToast(`\u300c${t.name}\u300d\u3078\u79fb\u52d5\u3057\u307e\u3057\u305f\u3002`); + return true; +} + +function quoteNameInRecordText(text, name) { + const raw = String(text || ""); + const n = String(name || "").trim(); + if (!n) return raw; + const parts = raw.split(n); + if (parts.length <= 1) return raw; + let out = ""; + for (let i = 0; i < parts.length - 1; i++) { + const before = parts[i].slice(-1); + const after = parts[i + 1].charAt(0); + out += parts[i] + ((before === "\u300c" && after === "\u300d") ? n : `\u300c${n}\u300d`); + } + return out + parts[parts.length - 1]; +} + +function renameSelectedTarinai(rawName) { + const t = world.selected; + if (!t || t.dead || !world.tarinai.includes(t)) return false; + const next = String(rawName || "").replace(/\s+/g, " ").trim().slice(0, 18); + if (!next) { + uiCache.selectedSnapshot = ""; + renderSelected(); + return false; + } + if (next === t.name) return false; + const oldName = t.name; + t.name = next; + if (t.isZunchiSlave) t.formerName = next; + world.recordFamily?.(t); + world.markFamilyTreeDirty?.("rename"); + uiCache.archiveFamilyVersion = null; + uiCache.selectedSnapshot = ""; + renderSelected(); + renderArchive?.(); + render?.(); + showToast(`\u300c${oldName}\u300d\u3092\u300c${next}\u300d\u306b\u6539\u540d\u3057\u307e\u3057\u305f\u3002`); + return true; +} + +function personalityValueText(value) { + const n = clamp(Number(value) || 0, -1, 1); + return `${n >= 0 ? "+" : ""}${n.toFixed(2)}`; +} + +function personalityRowsHtml(personality = {}) { + const p = normalizePersonality(personality); + return PERSONALITY_KEYS.map(key => `${escapeHtml(PERSONALITY_LABELS[key]?.label || key)}: ${personalityValueText(p[key])}`).join(""); +} + function renderSelected() { const t = world.selected; if (!t || t.dead || !world.tarinai.includes(t)) { @@ -150,17 +244,28 @@ function renderSelected() { ui.selectedCard?.classList.remove("hidden"); uiCache.selectedEmpty = false; + const activeNameInput = document.activeElement?.matches?.("[data-selected-name]") && document.activeElement?.dataset?.selectedId === t.id; + if (activeNameInput) return; const rel = t.relationSummary ? t.relationSummary() : {}; const fightRecord = relationFightRecord(t); + const generationDisplay = t.displayGeneration ? t.displayGeneration() : ((t.hasPaired || t.parents?.length || t.children?.length) ? t.generation : ""); + ensurePersonality(t); + const personalityTags = t.personalityTags ? t.personalityTags() : getPersonalityTraitTags(t); + const personalitySnapshot = [ + ...PERSONALITY_KEYS.map(key => personalityValueText(t.birthPersonality?.[key])), + ...PERSONALITY_KEYS.map(key => personalityValueText(t.currentPersonality?.[key])), + personalityTags.join(",") + ].join(","); const snapshot = [ - t.id, t.type, t.name, (t.displayGeneration ? t.displayGeneration() : ((t.hasPaired || t.parents?.length || t.children?.length) ? t.generation : "")), t.state, t.personality, t.thought, targetLabel(t.target), + t.id, t.type, t.name, generationDisplay, t.state, t.thought, targetLabel(t.target), fmt(t.age), fmt(t.lifeSpan), fmt(t.hunger), fmt(t.loneliness), fmt(t.energy), fmt(t.stress), fmt(t.mood), t.parentNames?.join("+") || "", t.children?.length || 0, fmt(t.lack), - rel.friend?.id || "", rel.friend?.score || 0, rel.friend?.id ? tarinaiSpritePathForId(rel.friend.id) : "", rel.fear?.id || "", rel.fear?.score || 0, rel.fear?.id ? tarinaiSpritePathForId(rel.fear.id) : "", fightRecord, + relationEntries(t, "friend").map(r => `${r.id}:${fmt(r.score)}:${r.name}`).join(","), relationEntries(t, "enemy").map(r => `${r.id}:${fmt(r.score)}:${r.name}`).join(","), fightRecord, t.isZunchiSlave ? 1 : 0, fmt(t.totalFightLosses || 0), fmt(t.loveMochiTimer || 0), fmt(t.fightMochiTimer || 0), t.zunchiDisease ? 1 : 0, fmt(t.zunchiDiseaseSeverity || 0), fmt(t.zunchiStain || 0), t.sleepDisease ? 1 : 0, t.explosionDisease ? 1 : 0, fmt(t.explosionDiseaseTimer || 0), t.fightDisease ? 1 : 0, t.favorite ? 1 : 0, + personalitySnapshot, (t.records || []).slice(0, 6).map(r => `${Math.round(r.time || 0)}:${r.kind || ""}:${r.text || ""}`).join("~") ].join("|"); if (uiCache.selectedSnapshot === snapshot) return; @@ -168,21 +273,36 @@ function renderSelected() { ui.selectedInfo.className = "selected-info"; const effectBadges = []; - effectBadges.push(`\u6027\u683c ${escapeHtml(t.personalityLabel ? t.personalityLabel() : t.personality || "\u4e0d\u660e")}`); if (t.isZunchiSlave) effectBadges.push(`\u305a\u3093\u3061\u3069\u308c\u3044`); if (t.favorite) effectBadges.push(`\u2605`); if (t.zunchiDisease) effectBadges.push(`\u305a\u3093\u3061\u75c5 ${fmt((t.zunchiDiseaseSeverity || 0) * 100)}`); if (t.sleepDisease) effectBadges.push(`\u306d\u3080\u308a\u75c5`); if (t.explosionDisease) effectBadges.push(`\u7206\u767a\u75c5 ${fmt(t.explosionDiseaseTimer || 0)}`); - if (t.fightDisease) effectBadges.push(`きずつき病`); + if (t.fightDisease) effectBadges.push(`\u304d\u305a\u3064\u304d\u75c5`); if ((t.loveMochiTimer || 0) > 0.1) effectBadges.push(`\u3078\u3053\u9905 ${fmt(t.loveMochiTimer)}`); if ((t.fightMochiTimer || 0) > 0.1) effectBadges.push(`\u3051\u3093\u304b\u9905 ${fmt(t.fightMochiTimer)}`); - const recordHtml = (t.records || []).slice(0, 8).map(r => `
  • ${escapeHtml(world.clockString ? world.clockStringFromTime ? world.clockStringFromTime(r.time || 0) : formatRecordTime(r.time || 0) : formatRecordTime(r.time || 0))}${escapeHtml(r.text || "")}
  • `).join("") || `
  • -\u8a18\u9332\u306a\u3057
  • `; + const personalityTagHtml = personalityTags.length + ? personalityTags.map(tag => `${escapeHtml(tag)}`).join("") + : `\u4e2d\u7acb`; + const personalityHtml = ` +
    \u6027\u683c\u30bf\u30b0${personalityTagHtml}
    +
    \u8a95\u751f\u6642\u6027\u683c${personalityRowsHtml(t.birthPersonality)}
    +
    \u73fe\u5728\u6027\u683c${personalityRowsHtml(t.currentPersonality)}
    + `; + const recordHtml = (t.records || []).slice(0, 8).map(r => { + const timeText = world.clockString ? (world.clockStringFromTime ? world.clockStringFromTime(r.time || 0) : formatRecordTime(r.time || 0)) : formatRecordTime(r.time || 0); + const recordText = quoteNameInRecordText(r.text || "", t.name); + return `
  • ${escapeHtml(timeText)}${escapeHtml(recordText)}
  • `; + }).join("") || `
  • -\u8a18\u9332\u306a\u3057
  • `; ui.selectedInfo.innerHTML = ` -
    ${escapeHtml(t.label())}${escapeHtml(t.name)}${(t.displayGeneration ? t.displayGeneration() : ((t.hasPaired || t.parents?.length || t.children?.length) ? t.generation : null)) ? `\u4e16\u4ee3 ${t.generation}` : ""}${effectBadges.join("")}
    -
    \u6027\u683c${escapeHtml(t.personalityLabel ? t.personalityLabel() : t.personality || "\u4e0d\u660e")}
    +
    + +
    + ${effectBadges.length ? `
    ${effectBadges.join("")}
    ` : ""} +
    \u4e16\u4ee3${escapeHtml(generationDisplay || "\u4e0d\u660e")}
    \u72b6\u614b${escapeHtml(stateLabel(t.state))}
    \u7406\u7531${escapeHtml(reasonLabel(t))}
    + ${personalityHtml}
    \u5bfe\u8c61${escapeHtml(targetLabel(t.target))}
    \u5e74\u9f62${fmt(t.age)} / ${fmt(t.lifeSpan)}
    \u7a7a\u8179${fmt(t.hunger)}
    @@ -191,8 +311,8 @@ function renderSelected() {
    \u30b9\u30c8\u30ec\u30b9${fmt(t.stress)}
    \u305a\u3093\u3061\u6c5a\u308c${fmt(t.zunchiStain || 0)}
    \u6c17\u5206${fmt(t.mood)}
    -
    \u4ef2\u826f\u3057${rel.friend ? `${relationIconHtml(rel.friend.id)}${escapeHtml(`${rel.friend.name} +${fmt(rel.friend.score)}`)}` : "\u306a\u3057"}
    -
    \u907f\u3051\u308b\u76f8\u624b${rel.fear ? `${relationIconHtml(rel.fear.id)}${escapeHtml(`${rel.fear.name} ${fmt(rel.fear.score)}`)}` : "\u306a\u3057"}
    +
    \u53cb\u9054${relationListHtml(t, "friend")}
    +
    \u6575\u5bfe${relationListHtml(t, "enemy")}
    \u55a7\u5629\u8a18\u61b6${escapeHtml(fightRecord)}
    \u7d2f\u8a08\u6557\u5317${t.totalFightLosses || 0}
    \u89aa${escapeHtml(t.parentNames?.length ? t.parentNames.join(" + ") : "\u4e0d\u660e")}
    @@ -218,7 +338,7 @@ function stateLabel(s) { play_ball: "\u30dc\u30fc\u30eb\u904a\u3073", seek_water: "\u6c34\u3092\u63a2\u3059", zunchi_sick: "\u305a\u3093\u3061\u75c5", - fight_sick: "きずつき病", + fight_sick: "\u304d\u305a\u3064\u304d\u75c5", system: "\u305a\u3093\u3061\u75c5", seek_friend: "\u4ef2\u9593\u3092\u63a2\u3059", follow_parent: "\u89aa\u306b\u3064\u3044\u3066\u3044\u304f", @@ -243,7 +363,7 @@ function reasonLabel(t) { if (t.state === "birth_ritual") return "\u5b50\u304c\u73fe\u308c\u308b\u524d\u306b\u4f53\u3092\u3086\u3059\u3063\u3066\u3044\u308b"; if (t.state === "seek_food") return "\u304a\u8179\u304c\u3059\u3044\u3066\u3044\u308b"; if (t.state === "seek_water") return t.explosionDisease ? "\u7206\u767a\u75c5\u3067\u6c34\u3092\u63a2\u3057\u3066\u3044\u308b" : "\u305a\u3093\u3061\u75c5\u3067\u6c34\u3092\u63a2\u3057\u3066\u3044\u308b"; - if (t.state === "fight_sick") return "きずつき病\u3067\u5f53\u3066\u3082\u306a\u304f\u5f77\u5fa8\u3063\u3066\u3044\u308b"; + if (t.state === "fight_sick") return "\u304d\u305a\u3064\u304d\u75c5\u3067\u5f53\u3066\u3082\u306a\u304f\u5f77\u5fa8\u3063\u3066\u3044\u308b"; if (t.state === "zunchi_sick" || t.state === "system") return "\u305a\u3093\u3061\u75c5"; return "\u5468\u56f2\u3092\u898b\u3066\u3044\u308b"; } @@ -251,7 +371,7 @@ function reasonLabel(t) { function targetLabel(target) { if (!target) return "\u306a\u3057"; if (target.name) return target.name; - if (target.type) return { sweet: "\u305a\u3093\u3060\u9905", love_mochi: "\u3078\u3053\u9905", fight_mochi: "\u3051\u3093\u304b\u9905", sleep_drug: "\u306d\u3080\u308a\u85ac", food: "\u98df\u4e8b", grass: "\u8349", water: "\u6c34", water_bowl: "\u6c34\u306e\u76bf", bed: "\u5e72\u8349\u5bdd\u5e8a", nest_box: "\u5de3\u7bb1", ball: "\u30dc\u30fc\u30eb", stone: "\u77f3", zunchi: "\u305a\u3093\u3061", system: "\u305a\u3093\u3061\u75c5", zunchi_sick: "\u305a\u3093\u3061\u75c5", fight_sick: "きずつき病", trace: "\u8db3\u8de1", splat: "\u3057\u3076\u304d" }[target.type] || target.type; + if (target.type) return { sweet: "\u305a\u3093\u3060\u9905", love_mochi: "\u3078\u3053\u9905", fight_mochi: "\u3051\u3093\u304b\u9905", sleep_drug: "\u306d\u3080\u308a\u85ac", food: "\u98df\u4e8b", grass: "\u8349", water: "\u6c34", water_bowl: "\u6c34\u306e\u76bf", bed: "\u5e72\u8349\u5bdd\u5e8a", nest_box: "\u5de3\u7bb1", ball: "\u30dc\u30fc\u30eb", stone: "\u77f3", zunchi: "\u305a\u3093\u3061", system: "\u305a\u3093\u3061\u75c5", zunchi_sick: "\u305a\u3093\u3061\u75c5", fight_sick: "\u304d\u305a\u3064\u304d\u75c5", trace: "\u8db3\u8de1", splat: "\u3057\u3076\u304d" }[target.type] || target.type; if (Number.isFinite(target.x) && Number.isFinite(target.y)) return "\u30ab\u30fc\u30bd\u30eb"; return "\u4e0d\u660e"; } @@ -366,8 +486,14 @@ function applyToolTips() { document.body.appendChild(pop); } const showTip = (btn) => { - const tip = btn?.dataset?.tip || ""; - if (!tip) return; + const baseTip = btn?.dataset?.tip || ""; + if (!baseTip) return; + let tip = baseTip; + if (btn?.dataset?.tool === "nest_box") { + const count = world?.nestBoxToolTipCount?.(); + if (count) tip = `${baseTip} +(${count.current}/${count.max})\u5339`; + } pop.textContent = tip; pop.classList.remove("hidden"); const rect = btn.getBoundingClientRect(); @@ -487,7 +613,7 @@ function syncTopButtons() { if (ui.soundBtn) ui.soundBtn.textContent = audio.enabled ? "\u97f3 ON" : "\u97f3 OFF"; } -const SCALABLE_TOOLS = new Set(["zunchi", "sweet", "love_mochi", "fight_mochi", "sleep_drug", "grass", "stone", "firecracker", "fence_v", "fence_h"]); +const SCALABLE_TOOLS = new Set(scalableToolIds()); const SIZE_ORDER = ["small", "medium", "large"]; const SIZE_LABELS = { small: "\u5c0f", medium: "\u4e2d", large: "\u5927" }; @@ -569,7 +695,13 @@ function bindUI() { const t = world.tarinai.find(x => x.id === id && !x.dead); if (!t) { showToast("\u305d\u306e\u500b\u4f53\u306f\u3082\u3046\u9078\u629e\u3067\u304d\u307e\u305b\u3093\u3002"); return; } world.selected = t; + t.focusPulseTimer = Math.max(t.focusPulseTimer || 0, 1.15); selectTool("observe"); + if (Number.isFinite(t.x) && Number.isFinite(t.y)) { + world.cameraX = t.x - (world.visibleWorldW ? world.visibleWorldW() : (world.viewportW || world.w)) / 2; + world.cameraY = t.y - (world.visibleWorldH ? world.visibleWorldH() : (world.viewportH || world.h)) / 2; + world.clampCamera?.(); + } renderStats(); showToast(`${t.name}\u3092\u9078\u629e\u3057\u307e\u3057\u305f\u3002`); }); @@ -582,6 +714,12 @@ function bindUI() { } ui.selectedInfo?.addEventListener("click", (e) => { + const focusBtn = e.target.closest("[data-focus-tarinai-id]"); + if (focusBtn) { + e.preventDefault(); + focusTarinaiById(focusBtn.getAttribute("data-focus-tarinai-id")); + return; + } const btn = e.target.closest("[data-selected-action=\"favorite\"]"); if (!btn || !world.selected || world.selected.dead) return; world.selected.favorite = !world.selected.favorite; @@ -590,6 +728,17 @@ function bindUI() { render(); showToast(world.selected.favorite ? "\u304a\u6c17\u306b\u5165\u308a\u306b\u3057\u307e\u3057\u305f\u3002" : "\u304a\u6c17\u306b\u5165\u308a\u3092\u89e3\u9664\u3057\u307e\u3057\u305f\u3002"); }); + ui.selectedInfo?.addEventListener("change", (e) => { + const input = e.target.closest("[data-selected-name]"); + if (!input) return; + renameSelectedTarinai(input.value); + }); + ui.selectedInfo?.addEventListener("keydown", (e) => { + const input = e.target.closest("[data-selected-name]"); + if (!input) return; + if (e.key === "Enter") { e.preventDefault(); input.blur(); } + if (e.key === "Escape") { e.preventDefault(); input.value = world.selected?.name || ""; input.blur(); } + }); ui.selectedCloseBtn?.addEventListener("click", () => { world.selected = null; uiCache.selectedSnapshot = ""; diff --git a/js/ui_charts.js b/js/ui_charts.js index 23996d9..caf9f7b 100644 --- a/js/ui_charts.js +++ b/js/ui_charts.js @@ -37,7 +37,7 @@ function updateColonyHistory(values) { uiCache.environmentInitialRow = null; uiCache.lastChartDraw = ""; } - const objectKeys = ["grass", "zunchi"]; + const objectKeys = ["grass", "zunchi", "trace"]; const makeBucket = (start) => ({ start, end: start + interval, @@ -90,7 +90,7 @@ function updateColonyHistory(values) { function chartRows(values) { const bucket = uiCache.chartBucketAccum; - const objectKeys = ["grass", "zunchi"]; + const objectKeys = ["grass", "zunchi", "trace"]; const preview = bucket && bucket.count > 0 ? { t: Math.max(world.time || 0, bucket.start || 0), pop: bucket.sums.pop / bucket.count, @@ -182,6 +182,7 @@ function chartSeries(mode = "population") { if (mode === "objects") return [ { key: "obj_grass", label: "\u8349", color: "#5b9d61" }, { key: "obj_zunchi", label: "\u305a\u3093\u3061", color: "#6f8a3f" }, + { key: "obj_trace", label: "\u6b7b\u9ab8", color: "#8a7054" }, ]; if (mode === "environment") return [ { key: "security", label: "\u6cbb\u5b89", color: "#d65e46", percent: true }, diff --git a/js/ui_family.js b/js/ui_family.js index 9035671..a6bff5d 100644 --- a/js/ui_family.js +++ b/js/ui_family.js @@ -152,6 +152,167 @@ function liveFamilyComponents(family) { return comps; } +function lineageIdleSchedule(fn, timeout = 180) { + const schedule = window.requestIdleCallback || ((cb) => setTimeout(cb, 0)); + schedule(fn, { timeout }); +} + +function lineageSameFamilyToken(token) { + return uiCache.archiveRenderToken === token; +} + +function lineageBuildComponentsIdle(family, token, onProgress, onDone) { + family = lineageEdgeFamily(family); + const entries = Object.values(family || {}).filter(n => n?.id); + const known = new Set(entries.map(n => n.id)); + const parentsByChild = new Map(); + const childrenByParent = new Map(); + const relatedIds = new Set(); + const graph = new Map(); + const comps = []; + let stage = "relations"; + let entryIndex = 0; + let nodeIndex = 0; + let nodes = []; + let sortedNodes = []; + let dfsIndex = 0; + const seen = new Set(); + + const addParent = (childId, parentId) => { + if (!childId || !parentId || childId === parentId || !known.has(childId) || !known.has(parentId)) return; + if (!parentsByChild.has(childId)) parentsByChild.set(childId, new Set()); + if (!childrenByParent.has(parentId)) childrenByParent.set(parentId, new Set()); + parentsByChild.get(childId).add(parentId); + childrenByParent.get(parentId).add(childId); + }; + const addGraphEdge = (a, b) => { + if (!a || !b || !graph.has(a) || !graph.has(b)) return; + graph.get(a).add(b); + graph.get(b).add(a); + }; + const validParentChild = (childId, parentId) => { + const child = family[childId]; + const parent = family[parentId]; + if (!child || !parent) return false; + const childListsParent = Array.isArray(child.parents) && child.parents.includes(parentId); + const parentListsChild = Array.isArray(parent.children) && parent.children.includes(childId); + return childListsParent || parentListsChild; + }; + const finishEmpty = () => { + lineageRelationIndexCache = { family, version: world.familyVersion || 0, index: { parentsByChild, childrenByParent } }; + onDone([]); + }; + + const pump = () => { + if (!lineageSameFamilyToken(token)) return; + const started = performance.now(); + while (performance.now() - started < 6) { + if (stage === "relations") { + if (entryIndex >= entries.length) { + lineageRelationIndexCache = { family, version: world.familyVersion || 0, index: { parentsByChild, childrenByParent } }; + stage = "related"; + entryIndex = 0; + onProgress?.("\u95a2\u4fc2\u3092\u6574\u7406\u4e2d", 0, entries.length); + continue; + } + const n = entries[entryIndex++]; + for (const parentId of n.parents || []) addParent(n.id, parentId); + for (const childId of n.children || []) addParent(childId, n.id); + } else if (stage === "related") { + if (entryIndex >= entries.length) { + nodes = Array.from(relatedIds).map(id => family[id]).filter(Boolean); + for (const n of nodes) graph.set(n.id, new Set()); + if (!nodes.length) return finishEmpty(); + stage = "graph"; + nodeIndex = 0; + onProgress?.("\u5bb6\u7cfb\u3092\u7d50\u5408\u4e2d", 0, nodes.length); + continue; + } + const n = entries[entryIndex++]; + const parents = parentsByChild.get(n.id) || new Set(); + const children = childrenByParent.get(n.id) || new Set(); + if (parents.size || children.size) relatedIds.add(n.id); + for (const id of parents) relatedIds.add(id); + for (const id of children) relatedIds.add(id); + } else if (stage === "graph") { + if (nodeIndex >= nodes.length) { + sortedNodes = nodes.slice().sort(lineageNodeSort); + stage = "components"; + dfsIndex = 0; + onProgress?.("\u5bb6\u7cfb\u3092\u5206\u5272\u4e2d", 0, sortedNodes.length); + continue; + } + const n = nodes[nodeIndex++]; + const parentCandidates = new Set((n.parents || []).filter(Boolean)); + for (const parentId of parentsByChild.get(n.id) || []) parentCandidates.add(parentId); + for (const parentId of parentCandidates) { + if (parentId !== n.id && graph.has(parentId) && validParentChild(n.id, parentId)) addGraphEdge(n.id, parentId); + } + const childCandidates = new Set((n.children || []).filter(Boolean)); + for (const childId of childrenByParent.get(n.id) || []) childCandidates.add(childId); + for (const childId of childCandidates) { + if (childId !== n.id && graph.has(childId) && validParentChild(childId, n.id)) addGraphEdge(n.id, childId); + } + } else if (stage === "components") { + while (dfsIndex < sortedNodes.length && seen.has(sortedNodes[dfsIndex].id)) dfsIndex += 1; + if (dfsIndex >= sortedNodes.length) { + comps.sort((a, b) => { + const ag = Math.min(...a.map(n => n.generation || 1)); + const bg = Math.min(...b.map(n => n.generation || 1)); + const at = Math.min(...a.map(n => n.birthTime || 0)); + const bt = Math.min(...b.map(n => n.birthTime || 0)); + return ag - bg || at - bt || b.length - a.length; + }); + onDone(comps); + return; + } + const start = sortedNodes[dfsIndex++]; + const stack = [start.id]; + const comp = []; + seen.add(start.id); + while (stack.length && performance.now() - started < 6) { + const id = stack.pop(); + const item = family[id]; + if (item) comp.push(item); + for (const next of graph.get(id) || []) { + if (seen.has(next)) continue; + seen.add(next); + stack.push(next); + } + } + if (stack.length) { + const continueComp = () => { + if (!lineageSameFamilyToken(token)) return; + const resumedStarted = performance.now(); + while (stack.length && performance.now() - resumedStarted < 6) { + const id = stack.pop(); + const item = family[id]; + if (item) comp.push(item); + for (const next of graph.get(id) || []) { + if (seen.has(next)) continue; + seen.add(next); + stack.push(next); + } + } + if (stack.length) return lineageIdleSchedule(continueComp, 180); + if (comp.some(x => x.alive)) comps.push(comp); + lineageIdleSchedule(pump, 180); + }; + return lineageIdleSchedule(continueComp, 180); + } + if (comp.some(x => x.alive)) comps.push(comp); + } + } + onProgress?.( + stage === "relations" ? "\u95a2\u4fc2\u3092\u6574\u7406\u4e2d" : stage === "related" ? "\u8868\u793a\u5bfe\u8c61\u3092\u9078\u5225\u4e2d" : stage === "graph" ? "\u5bb6\u7cfb\u3092\u7d50\u5408\u4e2d" : "\u5bb6\u7cfb\u3092\u5206\u5272\u4e2d", + stage === "graph" ? nodeIndex : entryIndex, + stage === "graph" ? nodes.length : entries.length + ); + lineageIdleSchedule(pump, 180); + }; + lineageIdleSchedule(pump, 160); +} + function familyStatusText(n) { if (!n) return "\u4e0d\u660e"; return n.alive ? "\u751f\u5b58" : "\u6b7b\u4ea1"; @@ -163,8 +324,8 @@ function familyDeathReasonLabel(rawReason, entity = null) { if (text.includes("\u3067\u8870\u5f31")) return text.length > 12 ? `${text.slice(0, 12)}\u2026` : text; if (/\u55a7\u5629|fight/.test(text)) return "\u55a7\u5629"; if (/\u7206\u7af9|firecracker|explosion/.test(text)) return "\u7206\u7af9"; - if (/仕様により画面外で削除|画面外で削除|out.*bounds|offscreen/.test(text)) return "仕様により画面外で削除"; - if (/衝突|collision/.test(text)) return "衝突"; + if (/\u4ed5\u69d8\u306b\u3088\u308a\u753b\u9762\u5916\u3067\u524a\u9664|\u753b\u9762\u5916\u3067\u524a\u9664|out.*bounds|offscreen/.test(text)) return "\u4ed5\u69d8\u306b\u3088\u308a\u753b\u9762\u5916\u3067\u524a\u9664"; + if (/\u885d\u7a81|collision/.test(text)) return "\u885d\u7a81"; if (/\u3064\u3064\u304b\u308c|\u3064\u3064\u304d|poke/.test(text)) return "\u3064\u3064\u304b\u308c\u3059\u304e\u305f"; if (/\u305a\u3093\u3061\u75c5|zunchi_sick|zunchi.*\u75c5/.test(text)) return "\u305a\u3093\u3061\u75c5"; if (/\u75c5/.test(text)) { @@ -173,7 +334,7 @@ function familyDeathReasonLabel(rawReason, entity = null) { } if (/\u98e2|\u7a7a\u8179|\u98df\u3079\u7269|hunger/.test(text)) return "\u98e2\u9913"; if (/\u30b9\u30c8\u30ec\u30b9|stress|\u6c17\u5206/.test(text)) return "\u30b9\u30c8\u30ec\u30b9\u904e\u591a"; - if (/\u5bff\u547d|天寿を全うした/.test(text)) return "天寿を全うした"; + if (/\u5bff\u547d|\u5929\u5bff/.test(text)) return "\u5929\u5bff\u3092\u5168\u3046\u3057\u305f"; if (/\u30dc\u30fc\u30eb|\u843d\u3061|\u843d\u4e0b|\u77f3|\u9053\u5177|\u4e8b\u6545|\u5f53\u305f|ball|drop|stone|accident/.test(text)) return "\u4e8b\u6545"; return "\u4e8b\u6545"; } @@ -196,9 +357,7 @@ function lineageTreeNodeHtml(n, x, y) { const rawReason = !n?.alive && n?.deathReason ? String(n.deathReason) : ""; const briefReason = familyDeathReasonLabel(rawReason, entity); const reason = briefReason ? ` / ${briefReason}` : ""; - const personality = live?.personalityLabel ? live.personalityLabel() : ((PERSONALITIES[n?.personality] || {}).label || n?.personality || ""); - const personalityPart = personality ? ` / \u6027\u683c ${personality}` : ""; - const title = escapeHtml(`${n?.name || "\u4e0d\u660e"} / \u4e16\u4ee3 ${n?.generation || "?"} / ${status}${personalityPart}${reason}`); + const title = escapeHtml(`${n?.name || "\u4e0d\u660e"} / \u4e16\u4ee3 ${n?.generation || "?"} / ${status}${reason}`); const deathLine = briefReason ? `${escapeHtml(briefReason)}` : ""; const cls = n ? ((live || n.alive) ? "alive" : "dead") : "missing"; const childCls = (n?.parents || []).length ? " child" : ""; @@ -485,7 +644,8 @@ function lineageRowsForLayout(nodes, generations, idToNode, idSet) { const partnerEdges = lineagePartnerEdgesByGeneration(nodes, idToNode, idSet); const totalNodes = nodes.length; const maxRow = Math.max(0, ...rows.map(row => row.length)); - const passes = totalNodes > 180 || maxRow > 32 ? 2 : (totalNodes > 90 || maxRow > 18 ? 3 : 6); + const veryLarge = totalNodes > 220 || maxRow > 44; + const passes = veryLarge ? 1 : (totalNodes > 180 || maxRow > 32 ? 2 : (totalNodes > 90 || maxRow > 18 ? 3 : 6)); for (let pass = 0; pass < passes; pass++) { let rank = lineageRankMap(rows); @@ -495,9 +655,11 @@ function lineageRowsForLayout(nodes, generations, idToNode, idSet) { const childRank = new Map(rows[i + 1].map((n, index) => [n.id, index])); rows[i] = lineageOrderParentsByChildren(rows[i], idSet, childRank); } - rank = lineageRankMap(rows); - rows = rows.map((row, i) => lineageOrderPartnerClusters(row, partnerEdges.get(generations[i]), rank, idToNode)); - if (totalNodes <= 90 && maxRow <= 16) rows = lineageOptimizeRows(rows, idSet); + if (!veryLarge) { + rank = lineageRankMap(rows); + rows = rows.map((row, i) => lineageOrderPartnerClusters(row, partnerEdges.get(generations[i]), rank, idToNode)); + if (totalNodes <= 90 && maxRow <= 16) rows = lineageOptimizeRows(rows, idSet); + } } return rows; } @@ -880,6 +1042,32 @@ function lineageHydrateFamilyHtml(html, index) { .split("{{LINEAGE_MASK_ID}}").join(`lineage-node-mask-${index}`); } +function lineageCaptureArchiveScroll() { + const root = ui.archiveContent; + if (!root) return null; + const familyScroll = {}; + for (const el of root.querySelectorAll(".lineage-family-tree[data-lineage-key]")) { + const key = el.getAttribute("data-lineage-key"); + if (key) familyScroll[key] = el.scrollLeft || 0; + } + return { top: root.scrollTop || 0, left: root.scrollLeft || 0, familyScroll }; +} + +function lineageRestoreArchiveScroll(state) { + const root = ui.archiveContent; + if (!root || !state) return; + const maxTop = Math.max(0, root.scrollHeight - root.clientHeight); + const maxLeft = Math.max(0, root.scrollWidth - root.clientWidth); + root.scrollTop = Math.min(state.top || 0, maxTop); + root.scrollLeft = Math.min(state.left || 0, maxLeft); + for (const el of root.querySelectorAll(".lineage-family-tree[data-lineage-key]")) { + const key = el.getAttribute("data-lineage-key"); + if (!key || !Object.prototype.hasOwnProperty.call(state.familyScroll || {}, key)) continue; + el.scrollLeft = Math.min(state.familyScroll[key] || 0, Math.max(0, el.scrollWidth - el.clientWidth)); + } +} + + function lineageExpectedChildEdgeCount(component, family) { family = lineageEdgeFamily(family); const idSet = new Set(component.map(x => x?.id).filter(Boolean)); @@ -1113,6 +1301,73 @@ function lineageCleanComponent(component, family) { return expanded.filter(n => lineageMutualParentIds(n, family, idSet).length || lineageMutualChildIds(n, family, idSet).length); } +function lineageFastLayoutNeeded(nodes, idSet, family) { + const edgeCount = nodes.reduce((sum, n) => sum + lineageParentIds(n, idSet, family).length, 0); + const maxGenerationWidth = Math.max(0, ...Array.from(new Set(nodes.map(n => n.generation || 1))).map(g => nodes.filter(n => (n.generation || 1) === g).length)); + return { + edgeCount, + fast: nodes.length > 140 || edgeCount > 260 || maxGenerationWidth > 34, + }; +} + +function lineageLayoutRowsFast(rows, idSet) { + const NODE_W = 132; + const NODE_H = 68; + const SIBLING_GAP = 22; + const ROW_GAP = 116; + const LEFT_PAD = 82; + const TOP_PAD = 44; + const RIGHT_PAD = 48; + const BOTTOM_PAD = 30; + const positions = new Map(); + let width = 420; + rows.forEach((row, rowIndex) => { + const y = TOP_PAD + rowIndex * (NODE_H + ROW_GAP); + let x = LEFT_PAD; + for (const n of row) { + positions.set(n.id, { x, y, rowIndex, node: n }); + x += NODE_W + SIBLING_GAP; + } + width = Math.max(width, x - SIBLING_GAP + RIGHT_PAD); + }); + const height = TOP_PAD + Math.max(0, rows.length - 1) * (NODE_H + ROW_GAP) + NODE_H + BOTTOM_PAD; + return { positions, width, height, nodeW: NODE_W, nodeH: NODE_H, topPad: TOP_PAD, rowGap: ROW_GAP, fastMode: true }; +} + +function lineageBuildLinksFast(nodes, idSet, layout) { + const { positions, nodeW, nodeH } = layout; + const partnerLinks = []; + const childLinks = []; + const seenPartners = new Set(); + let childLinkGroups = 0; + let childLinkEdges = 0; + for (const child of nodes) { + const childPos = positions.get(child.id); + if (!childPos) continue; + const parents = lineageParentIds(child, idSet).map(id => positions.get(id)).filter(Boolean).sort((a, b) => a.x - b.x); + if (!parents.length) continue; + childLinkGroups += 1; + childLinkEdges += parents.length; + const childX = childPos.x + nodeW / 2; + const childY = childPos.y; + const fromY = Math.max(...parents.map(p => p.y + nodeH)); + const joinX = parents.reduce((sum, p) => sum + p.x + nodeW / 2, 0) / parents.length; + if (parents.length >= 2) { + const left = parents[0]; + const right = parents[parents.length - 1]; + const partnerKey = parents.map(p => p.node?.id).filter(Boolean).sort().join("+"); + if (partnerKey && !seenPartners.has(partnerKey)) { + seenPartners.add(partnerKey); + const y = ((left.y + nodeH / 2) + (right.y + nodeH / 2)) / 2; + partnerLinks.push(`M ${(left.x + nodeW).toFixed(1)} ${y.toFixed(1)} L ${right.x.toFixed(1)} ${y.toFixed(1)}`); + } + } + const laneY = Math.min(childY - 18, fromY + Math.max(28, (childY - fromY) * 0.48)); + childLinks.push(`M ${joinX.toFixed(1)} ${fromY.toFixed(1)} L ${joinX.toFixed(1)} ${laneY.toFixed(1)} L ${childX.toFixed(1)} ${laneY.toFixed(1)} L ${childX.toFixed(1)} ${childY.toFixed(1)}`); + } + return { partnerLinks, childLinks, childLinkGroups, childLinkEdges }; +} + function buildLineageTreeLayout(component, family) { family = lineageEdgeFamily(family); const cleaned = lineageCleanComponent(component, family); @@ -1121,12 +1376,13 @@ function buildLineageTreeLayout(component, family) { const idSet = new Set(idToNode.keys()); const generations = Array.from(new Set(nodes.map(n => n.generation || 1))).sort((a, b) => a - b); const rows = lineageRowsForLayout(nodes, generations, idToNode, idSet); - const layout = lineageLayoutRows(rows, idSet); - const links = lineageBuildLinks(nodes, idSet, layout); + const perf = lineageFastLayoutNeeded(nodes, idSet, family); + const layout = perf.fast ? lineageLayoutRowsFast(rows, idSet) : lineageLayoutRows(rows, idSet); + const links = perf.fast ? lineageBuildLinksFast(nodes, idSet, layout) : lineageBuildLinks(nodes, idSet, layout); const labels = generations.map((g, rowIndex) => ({ generation: g, y: layout.topPad + rowIndex * (layout.nodeH + layout.rowGap) + 18 })); const renderedNodes = nodes.map(n => ({ node: n, ...(layout.positions.get(n.id) || {}) })).filter(n => Number.isFinite(n.x) && Number.isFinite(n.y)); - return { ...layout, labels, nodes: renderedNodes, childLinks: links.childLinks, partnerLinks: links.partnerLinks, childLinkGroups: links.childLinkGroups, childLinkEdges: links.childLinkEdges }; + return { ...layout, labels, nodes: renderedNodes, childLinks: links.childLinks, partnerLinks: links.partnerLinks, childLinkGroups: links.childLinkGroups, childLinkEdges: links.childLinkEdges, fastMode: perf.fast, edgeCount: perf.edgeCount }; } function lineageFamilyHtml(component, index, family, signature = "") { @@ -1146,7 +1402,7 @@ function lineageFamilyHtml(component, index, family, signature = "") { const nodeHtml = layout.nodes.map(p => lineageTreeNodeHtml(p.node, p.x, p.y)).join(""); const empty = !layout.childLinks.length ? `
    \u89aa\u5b50\u95a2\u4fc2\u306e\u7dda\u306f\u307e\u3060\u3042\u308a\u307e\u305b\u3093\u3002
    ` : ""; - const html = `
    + const html = `

    \u5bb6\u7cfb {{LINEAGE_INDEX}} / ${uniqueComponent.length}\u5339 / \u751f\u5b58 ${aliveCount}

    \u751f\u304d\u3066\u3044\u308b\u69cb\u6210\u54e1\u3092\u6301\u3064\u5bb6\u7cfb\u306f\u307e\u3060\u3042\u308a\u307e\u305b\u3093\u3002
    `; - uiCache.archiveRenderRunning = false; - world.familyTreeDirty = false; - uiCache.archivePendingDirtyAfterRun = false; - return; - } - - ui.archiveContent.innerHTML = `
    \u5bb6\u7cfb\u56f3\u3092\u63cf\u753b\u4e2d\u2026 0 / ${components.length}
    `; + ui.archiveContent.innerHTML = `
    \u5bb6\u7cfb\u56f3\u3092\u6e96\u5099\u4e2d\u2026
    `; + lineageRestoreArchiveScroll(scrollState); const status = ui.archiveContent.querySelector(".lineage-render-status"); const forest = ui.archiveContent.querySelector(".lineage-forest"); - let index = 0; - const pump = () => { + const renderComponents = (components) => { if (uiCache.archiveRenderToken !== token || !forest) { uiCache.archiveRenderRunning = false; return; } + const splitComponents = components.flatMap(lineageSplitByActualEdges).filter(c => c.length); + uiCache.archiveRows = splitComponents; + if (!splitComponents.length) { + ui.archiveContent.innerHTML = `
    \u751f\u304d\u3066\u3044\u308b\u69cb\u6210\u54e1\u3092\u6301\u3064\u5bb6\u7cfb\u306f\u307e\u3060\u3042\u308a\u307e\u305b\u3093\u3002
    `; + lineageRestoreArchiveScroll(scrollState); + uiCache.archiveRenderRunning = false; + world.familyTreeDirty = false; + uiCache.archivePendingDirtyAfterRun = false; + return; + } + if (status) status.textContent = `\u5bb6\u7cfb\u56f3\u3092\u63cf\u753b\u4e2d\u2026 0 / ${splitComponents.length}`; + let index = 0; + const pump = () => { + if (uiCache.archiveRenderToken !== token || !forest) { + uiCache.archiveRenderRunning = false; + return; + } const started = performance.now(); let nodeBudget = 28; let renderedThisSlice = 0; - while (index < components.length) { - const component = components[index]; + while (index < splitComponents.length) { + const component = splitComponents[index]; if (renderedThisSlice > 0 && component.length > nodeBudget) break; - forest.insertAdjacentHTML("beforeend", lineageFamilyHtml(component, index, family, signatures[index])); + const signature = lineageComponentSignature(component, family); + activeCacheKeys.add(lineageFamilyCacheKey(component, family, signature)); + forest.insertAdjacentHTML("beforeend", lineageFamilyHtml(component, index, family, signature)); nodeBudget -= Math.max(1, component.length); index += 1; renderedThisSlice += 1; - if (index < components.length && (nodeBudget <= 0 || performance.now() - started > 6)) break; + if (index < splitComponents.length && (nodeBudget <= 0 || performance.now() - started > 6)) break; } - if (status) status.textContent = `\u5bb6\u7cfb\u56f3\u3092\u63cf\u753b\u4e2d\u2026 ${index} / ${components.length}`; - if (index < components.length) { - const schedule = window.requestIdleCallback || ((fn) => setTimeout(fn, 0)); - schedule(pump, { timeout: 220 }); + lineageRestoreArchiveScroll(scrollState); + if (status) status.textContent = `\u5bb6\u7cfb\u56f3\u3092\u63cf\u753b\u4e2d\u2026 ${index} / ${splitComponents.length}`; + if (index < splitComponents.length) { + lineageIdleSchedule(pump, 220); } else { if (status) status.remove(); + for (const key of Array.from(uiCache.archiveHtmlCache.keys())) { + if (!activeCacheKeys.has(key)) uiCache.archiveHtmlCache.delete(key); + } + lineageRestoreArchiveScroll(scrollState); const renderDirtiedAgain = uiCache.archivePendingDirtyAfterRun || (world.familyVersion || 0) !== familyVersion; uiCache.archiveRenderRunning = false; world.familyTreeDirty = renderDirtiedAgain; if (uiCache.archiveDiagnostics) { uiCache.archiveDiagnostics.renders = (uiCache.archiveDiagnostics.renders || 0) + 1; uiCache.archiveDiagnostics.lastMs = Math.round((performance.now() - renderStarted) * 10) / 10; - uiCache.archiveDiagnostics.lastFamilies = components.length; - uiCache.archiveDiagnostics.lastNodes = components.reduce((sum, component) => sum + component.length, 0); + uiCache.archiveDiagnostics.lastFamilies = splitComponents.length; + uiCache.archiveDiagnostics.lastNodes = splitComponents.reduce((sum, component) => sum + component.length, 0); } if (renderDirtiedAgain) { uiCache.archivePendingDirtyAfterRun = false; @@ -1294,8 +1541,16 @@ function renderArchive() { } } }; - const schedule = window.requestIdleCallback || ((fn) => setTimeout(fn, 0)); - schedule(pump, { timeout: 160 }); + lineageIdleSchedule(pump, 160); + }; + lineageBuildComponentsIdle( + family, + token, + (label, done, total) => { + if (status) status.textContent = `${label}\u2026 ${Math.min(done || 0, total || 0)} / ${total || 0}`; + }, + renderComponents + ); } function validateFamilyTree() { diff --git a/js/world.js b/js/world.js index 4ac8673..c5dbe67 100644 --- a/js/world.js +++ b/js/world.js @@ -1,4 +1,4 @@ -"use strict"; +"use strict"; class World { constructor() { @@ -276,12 +276,12 @@ class World { } toolSizeFor(type = "") { - if (!["firecracker", "fence_v", "fence_h", "stone", "grass", "sweet", "love_mochi", "fight_mochi", "sleep_drug", "zunchi"].includes(type)) return "medium"; + if (!["firecracker", "fence_v", "fence_h", "stone", "grass", "food", "sweet", "love_mochi", "fight_mochi", "sleep_drug", "zunchi"].includes(type)) return "medium"; return (this.toolSizes && this.toolSizes[type]) || this.toolSize || "medium"; } toolSizeScale(type = "") { - if (!["firecracker", "fence_v", "fence_h", "stone", "grass", "sweet", "love_mochi", "fight_mochi", "sleep_drug", "zunchi"].includes(type)) return 1; + if (!["firecracker", "fence_v", "fence_h", "stone", "grass", "food", "sweet", "love_mochi", "fight_mochi", "sleep_drug", "zunchi"].includes(type)) return 1; return { small: 0.68, medium: 1.0, large: 1.48 }[this.toolSizeFor(type)] || 1; } @@ -292,7 +292,16 @@ class World { item.toolSize = size; this.toolSize = size; item.r *= scale; - if (["sweet", "love_mochi", "fight_mochi", "sleep_drug", "grass", "zunchi"].includes(item.type)) item.amount *= scale * scale; + if (typeof isServingFoodType === "function" && isServingFoodType(item.type)) { + const servings = typeof foodServingsForSize === "function" ? foodServingsForSize(size) : 5; + item.foodServingScale = scale; + item.foodServingsMax = servings; + item.foodServingsRemaining = servings; + item.amount = servings; + } else if (["grass", "zunchi"].includes(item.type)) { + item.amount *= scale * scale; + item.foodServingScale = scale; + } if (item.type === "firecracker") item.blastScale = scale; return item; } @@ -368,12 +377,13 @@ class World { let changed = false; const nextParents = uniqueIds(t.parents || []); const nextChildren = uniqueIds(t.children || []); + const nextPersonalityTags = getPersonalityTraitTags(t); if (!this.family[t.id]) { this.family[t.id] = { id: t.id, name: t.name, type: t.type, - personality: t.personality || "", + personalityTags: nextPersonalityTags, generation: t.generation, hasPaired: !!t.hasPaired, parents: nextParents, @@ -389,7 +399,7 @@ class World { const nextAlive = !t.dead; if (entry.name !== t.name) changed = true; if (entry.type !== t.type) changed = true; - if ((entry.personality || "") !== (t.personality || "")) changed = true; + if (!sameList(entry.personalityTags, nextPersonalityTags)) changed = true; if (entry.hasPaired !== !!t.hasPaired) changed = true; if (entry.generation !== t.generation) changed = true; if ((entry.deathReason || "") !== (t.deathReason || entry.deathReason || "")) changed = true; @@ -398,7 +408,8 @@ class World { if (!sameList(entry.children, nextChildren)) changed = true; entry.name = t.name; entry.type = t.type; - entry.personality = t.personality || entry.personality || ""; + delete entry.personality; + entry.personalityTags = nextPersonalityTags; entry.alive = nextAlive; entry.generation = t.generation; entry.hasPaired = !!t.hasPaired; @@ -449,7 +460,7 @@ class World { id, name: live?.name || n.name || id, type: live?.type || n.type || "smile", - personality: live?.personality || n.personality || "", + personalityTags: live ? getPersonalityTraitTags(live) : [...(n.personalityTags || [])], generation: Math.max(1, live?.generation || n.generation || 1), hasPaired: !!(live?.hasPaired || n.hasPaired), parents, @@ -565,7 +576,7 @@ class World { if (this.family[t.id].alive !== false || this.family[t.id].deathReason !== finalReason) { this.family[t.id].alive = false; this.family[t.id].deathReason = finalReason; - this.family[t.id].personality = t.personality || this.family[t.id].personality || ""; + delete this.family[t.id].personality; this.familyVersion = (this.familyVersion || 0) + 1; this.markFamilyTreeDirty("death"); } @@ -629,6 +640,7 @@ class World { startBirthRitual(a, b) { if (!a || !b || a.dead || b.dead) return false; if (a.isZunchiSlave || b.isZunchiSlave) return false; + if (a.sleepDisease || b.sleepDisease || a.fightDisease || b.fightDisease) return false; if (a.birthRitualTimer > 0.04 || b.birthRitualTimer > 0.04) return false; const aJoined = a.familyJoined ? a.familyJoined() : Boolean((a.parents || []).length || (a.children || []).length); const bJoined = b.familyJoined ? b.familyJoined() : Boolean((b.parents || []).length || (b.children || []).length); @@ -659,10 +671,15 @@ class World { finishBirthRitual(a, b) { if (!a || !b || a.dead || b.dead) return null; + const reproductionBlockedByDisease = a.sleepDisease || b.sleepDisease || a.fightDisease || b.fightDisease; a.birthRitualTimer = b.birthRitualTimer = 0; a.birthPartnerId = b.birthPartnerId = null; a.birthRitualLeader = b.birthRitualLeader = false; a.state = b.state = "idle"; + if (reproductionBlockedByDisease) { + a.birthRitualRole = b.birthRitualRole = 0; + return null; + } a.fightTimer = b.fightTimer = 0; a.fightTargetIds = []; b.fightTargetIds = []; a.fightTargetId = b.fightTargetId = null; @@ -707,8 +724,10 @@ class World { canStartFight(t) { if (!t || t.dead) return false; if (t.sleepDisease) return false; - if (t.explosionDisease || t.fightDisease) return true; - if (t.zunchiDisease) return false; + // Disease fight rule: explosion disease and zunchi disease can lash out; + // sleep disease cannot fight or be challenged, and other diseases cannot start fights. + if (t.explosionDisease || t.zunchiDisease) return true; + if (t.fightDisease) return false; return true; } @@ -723,10 +742,11 @@ class World { spawnChild(a, b, index = 0, total = 1) { const inherited = Math.random() < 0.56 ? a.type : b.type; const mutation = Math.random() < 0.18 ? baseSpriteId() : inherited; - const inheritedPersonality = a.personality === b.personality ? a.personality : (Math.random() < 0.5 ? a.personality : b.personality); + const childBirthPersonality = personalityFromParents(a, b); const child = this.addTarinai({ type: mutation, - personality: inheritedPersonality || personalityForSeed(`${a.id}:${b.id}:${this.time}:${index}`), + birthPersonality: childBirthPersonality, + currentPersonality: childBirthPersonality, name: makeName(), age: 0, x: (a.x + b.x) / 2 + rand(-14, 14) + (index - (total - 1) / 2) * 18, @@ -822,8 +842,10 @@ class World { if (this.areParentChild(a, b) || this.areCoParents?.(a, b)) return; if ((a.postBirthPeaceTimer || 0) > 0 || (b.postBirthPeaceTimer || 0) > 0) return; if (a.fightTimer > 0.04 || b.fightTimer > 0.04 || a.intimidateTimer > 0.04 || b.intimidateTimer > 0.04) return; - const scoreA = a.energy * 0.38 + a.mood * 0.18 + a.stress * 0.12 + (a.type === "angry" ? 12 : 0) + (a.personality === "irritable" ? 8 : 0) + ((b.relationTo(a.id).fear || 0) * 0.65) + (a.isZunchiSlave ? -10 : 0) + ((a.fightMochiTimer || 0) > 0.04 ? 9 : 0) + rand(-5, 5); - const scoreB = b.energy * 0.38 + b.mood * 0.18 + b.stress * 0.12 + (b.type === "angry" ? 12 : 0) + (b.personality === "irritable" ? 8 : 0) + ((a.relationTo(b.id).fear || 0) * 0.65) + (b.isZunchiSlave ? -10 : 0) + ((b.fightMochiTimer || 0) > 0.04 ? 9 : 0) + rand(-5, 5); + const aAggressiveIntent = a.shouldApplyPersonalityBehavior?.("aggression", 1) ? 1 : 0; + const bAggressiveIntent = b.shouldApplyPersonalityBehavior?.("aggression", 1) ? 1 : 0; + const scoreA = a.energy * 0.38 + a.mood * 0.18 + a.stress * 0.12 + (a.type === "angry" ? 12 : 0) + aAggressiveIntent * 8 + ((b.relationTo(a.id).fear || 0) * 0.65) + (a.isZunchiSlave ? -10 : 0) + ((a.fightMochiTimer || 0) > 0.04 ? 9 : 0) + rand(-5, 5); + const scoreB = b.energy * 0.38 + b.mood * 0.18 + b.stress * 0.12 + (b.type === "angry" ? 12 : 0) + bAggressiveIntent * 8 + ((a.relationTo(b.id).fear || 0) * 0.65) + (b.isZunchiSlave ? -10 : 0) + ((b.fightMochiTimer || 0) > 0.04 ? 9 : 0) + rand(-5, 5); const actor = scoreA >= scoreB ? a : b; const target = actor === a ? b : a; if (!this.canFightPair(actor, target)) return; @@ -843,7 +865,7 @@ class World { if (!actor || !target || actor.dead || target.dead) return false; if (actor.lowHealthSprite && actor.lowHealthSprite()) return false; const fearLoad = (target.relationTo(actor.id).fear || 0) * 0.72 + target.personalityProfile().fear * 8; - const resistance = target.energy * 0.30 + target.mood * 0.16 + (target.personality === "irritable" ? 5 : 0) + rand(-5, 5); + const resistance = target.energy * 0.30 + target.mood * 0.16 + (target.shouldApplyPersonalityBehavior?.("aggression", 1) ? 5 : 0) + rand(-5, 5); const successChance = clamp(0.62 + (actorScore - targetScore + fearLoad - resistance) / 76, 0.50, 0.96); actor.surpriseTimer = Math.max(actor.surpriseTimer, 0.20); target.surpriseTimer = Math.max(target.surpriseTimer, 0.32); @@ -902,8 +924,10 @@ class World { b.fightTargetIds = b.fightTargetIds.slice(-4); a.fightTargetId = a.fightTargetIds[0]; b.fightTargetId = b.fightTargetIds[0]; - const aScore = a.energy * 0.52 + a.mood * 0.30 + (a.type === "angry" ? 10 : 0) + (a.personality === "irritable" ? 5 : 0) + ((a.fightMochiTimer || 0) > 0.04 ? 12 : 0) + (a.isZunchiSlave ? -14 : 0) + rand(-7, 7); - const bScore = b.energy * 0.52 + b.mood * 0.30 + (b.type === "angry" ? 10 : 0) + (b.personality === "irritable" ? 5 : 0) + ((b.fightMochiTimer || 0) > 0.04 ? 12 : 0) + (b.isZunchiSlave ? -14 : 0) + rand(-7, 7); + const aAggressiveIntent = a.shouldApplyPersonalityBehavior?.("aggression", 1) ? 1 : 0; + const bAggressiveIntent = b.shouldApplyPersonalityBehavior?.("aggression", 1) ? 1 : 0; + const aScore = a.energy * 0.52 + a.mood * 0.30 + (a.type === "angry" ? 10 : 0) + aAggressiveIntent * 5 + ((a.fightMochiTimer || 0) > 0.04 ? 12 : 0) + (a.isZunchiSlave ? -14 : 0) + rand(-7, 7); + const bScore = b.energy * 0.52 + b.mood * 0.30 + (b.type === "angry" ? 10 : 0) + bAggressiveIntent * 5 + ((b.fightMochiTimer || 0) > 0.04 ? 12 : 0) + (b.isZunchiSlave ? -14 : 0) + rand(-7, 7); const loser = aScore <= bScore ? a : b; const winner = loser === a ? b : a; loser.defeatedById = winner.id; @@ -987,9 +1011,12 @@ class World { ny = Math.sin(a); } const distanceBoost = p * p * 0.55 + p * 0.45; - const power = (260 + distanceBoost * 820) * rand(0.78, 1.24) * (it.blastScale || 1); - t.vx += nx * power + rand(-95, 95) * (0.6 + p); - t.vy += ny * power + rand(-95, 95) * (0.6 + p); + const power = (260 + distanceBoost * 920) * rand(0.78, 1.24) * (it.blastScale || 1); + this.applyImpulse(t, nx * power + rand(-95, 95) * (0.6 + p), ny * power + rand(-95, 95) * (0.6 + p), { + panic: true, + target: { x, y }, + fearTimer: 1.7 + p, + }); t.fallTimer = Math.max(t.fallTimer, 1.45 + p * 1.85); t.fallMax = Math.max(t.fallMax || 0, t.fallTimer); t.fallDir = (dx >= 0 ? 1 : -1) * (Math.random() < 0.5 ? 1 : -1); @@ -1012,8 +1039,7 @@ class World { dx = Math.cos(a); dy = Math.sin(a); d = 1; } const blast = 430 + p * 960; - ball.vx = (ball.vx || 0) + dx / d * blast + rand(-80, 80); - ball.vy = (ball.vy || 0) + dy / d * blast + rand(-80, 80); + this.applyImpulse(ball, dx / d * blast + rand(-80, 80), dy / d * blast + rand(-80, 80)); const speed = Math.hypot(ball.vx || 0, ball.vy || 0); ball.spinVelocity = clamp((ball.spinVelocity || 0) + rand(-24, 24), -38, 38); ball.lastPokedAt = this.time || 0; @@ -1050,9 +1076,12 @@ class World { nx = Math.cos(a); ny = Math.sin(a); } - const diseaseBlast = (190 + q * 560) * rand(0.80, 1.22); - o.vx += nx * diseaseBlast + rand(-64, 64) * (0.5 + q); - o.vy += ny * diseaseBlast + rand(-64, 64) * (0.5 + q); + const diseaseBlast = (190 + q * 620) * rand(0.80, 1.22); + this.applyImpulse(o, nx * diseaseBlast + rand(-64, 64) * (0.5 + q), ny * diseaseBlast + rand(-64, 64) * (0.5 + q), { + panic: true, + target: { x, y }, + fearTimer: 1.0 + q, + }); o.hurtTimer = Math.max(o.hurtTimer || 0, 1.2 + q); o.fearTimer = Math.max(o.fearTimer || 0, 1.0 + q); if (!o.dead && Math.random() < 0.020 * q) o.infectExplosionDisease?.(t); @@ -1088,7 +1117,7 @@ class World { cleaned += p * 0.55; } for (const t of this.nearbyTarinai(x, y, radius + 70)) { - if (!t || t.dead) continue; + if (!t || t.dead || this.isTarinaiHiddenInNestBox(t)) continue; const d = distXY(t.x, t.y, x, y); if (d > radius + t.radius) continue; const p = clamp(1 - d / (radius + t.radius), 0, 1); @@ -1187,12 +1216,19 @@ class World { return Boolean(it && (it.type === "bed" || it.type === "nest_box")); } + isTarinaiHiddenInNestBox(t) { + return Boolean(t && !t.dead && t.insideNestBoxId); + } + bedOccupancy(bed) { if (!this.isSleepFurniture(bed)) return 0; + if (bed.type === "nest_box") { + return this.nestBoxOccupants ? this.nestBoxOccupants(bed, Infinity).length : 0; + } let n = 0; const radius = Math.max(86, bed.r * 2.45); for (const t of this.nearbyTarinai(bed.x, bed.y, radius)) { - if (t.dead) continue; + if (t.dead || this.isTarinaiHiddenInNestBox(t)) continue; if (t.state === "sleep" || t.state === "seek_bed" || t.target === bed) n += 1; } return n; @@ -1205,23 +1241,27 @@ class World { } bestBedFor(t, maxDist = 360) { - let best = null; - let bestScore = Infinity; - for (const bed of this.nearbyItems(t.x, t.y, maxDist)) { - if (bed.dead || !this.isSleepFurniture(bed)) continue; - if (bed.type === "nest_box" && t?.insideNestBoxId !== bed.id) { - const occupants = this.nestBoxOccupants ? this.nestBoxOccupants(bed, Infinity) : []; - if (occupants.length >= this.nestBoxCapacity(bed)) continue; + const choose = (kind) => { + let best = null; + let bestScore = Infinity; + for (const bed of this.nearbyItems(t.x, t.y, maxDist)) { + if (bed.dead || !this.isSleepFurniture(bed) || bed.type !== kind) continue; + if (bed.type === "nest_box" && t?.insideNestBoxId !== bed.id) { + const occupants = this.nestBoxOccupants ? this.nestBoxOccupants(bed, Infinity) : []; + if (occupants.length >= this.nestBoxCapacity(bed)) continue; + } + if (t?.shouldAvoidTarget && t.shouldAvoidTarget(bed)) continue; + const d = dist(t, bed); + const occ = this.bedOccupancy(bed); + const comfort = this.bedComfort(bed); + const crowdPenalty = bed.type === "nest_box" ? Math.max(0, occ - this.nestBoxCapacity(bed) + 1) * 120 : Math.max(0, occ - 3) * 34; + const score = d - comfort * (bed.type === "nest_box" ? 72 : 46) + crowdPenalty; + if (score < bestScore) { best = bed; bestScore = score; } } - if (t?.shouldAvoidTarget && t.shouldAvoidTarget(bed)) continue; - const d = dist(t, bed); - const occ = this.bedOccupancy(bed); - const comfort = this.bedComfort(bed); - const crowdPenalty = Math.max(0, occ - 3) * 34; - const score = d - comfort * 46 + crowdPenalty; - if (score < bestScore) { best = bed; bestScore = score; } - } - return best; + return best; + }; + // Prefer an available nest box, then fall back to a hay bed. + return choose("nest_box") || choose("bed"); } relationNotice(aId, bId, kind, cooldown = 30) { @@ -1233,6 +1273,52 @@ class World { return true; } + applyImpulse(entity, vx = 0, vy = 0, options = {}) { + if (!entity || entity.dead) return false; + if (!Number.isFinite(vx) || !Number.isFinite(vy)) return false; + if (entity instanceof Tarinai || "impulseVx" in entity || "impulseVy" in entity) { + entity.impulseVx = (Number.isFinite(entity.impulseVx) ? entity.impulseVx : 0) + vx; + entity.impulseVy = (Number.isFinite(entity.impulseVy) ? entity.impulseVy : 0) + vy; + } else { + entity.vx = (Number.isFinite(entity.vx) ? entity.vx : 0) + vx; + entity.vy = (Number.isFinite(entity.vy) ? entity.vy : 0) + vy; + } + if (options.panic && entity instanceof Tarinai) { + entity.state = "panic"; + entity.target = options.target || null; + entity.fearTimer = Math.max(entity.fearTimer || 0, options.fearTimer ?? 0.55); + } + return true; + } + + applyKnockback(entity, sourceX, sourceY, strength = 0, options = {}) { + if (!entity || !Number.isFinite(strength)) return false; + let dx = (entity.x || 0) - sourceX; + let dy = (entity.y || 0) - sourceY; + let d = Math.hypot(dx, dy); + if (!Number.isFinite(d) || d < 0.001) { + const a = Number.isFinite(options.angle) ? options.angle : rand(0, Math.PI * 2); + dx = Math.cos(a); + dy = Math.sin(a); + d = 1; + } + const random = options.random || 0; + return this.applyImpulse( + entity, + dx / d * strength + rand(-random, random), + dy / d * strength + rand(-random, random), + options, + ); + } + + applyImpactDamage(target, amount, cause = "\u885d\u7a81", options = {}) { + if (!target || target.dead || !Number.isFinite(amount) || amount <= 0) return false; + const normalized = options.cause || cause || "\u885d\u7a81"; + if (target.damage) target.damage(amount, normalized); + else if (Number.isFinite(target.hp)) target.hp -= amount; + return true; + } + resolveFightOutcome(winner, loser) { if (!winner || !loser || winner.dead || loser.dead) return; const key = `${winner.id}:${loser.id}:${Math.floor(this.time / 2)}`; @@ -1250,6 +1336,8 @@ class World { loser.relationTo(winner.id).fightsLost = (loser.relationTo(winner.id).fightsLost || 0) + 1; winner.totalFightWins = (winner.totalFightWins || 0) + 1; loser.totalFightLosses = (loser.totalFightLosses || 0) + 1; + winner.adjustPersonality?.("aggression", 0.018, "after winning fights."); + loser.adjustPersonality?.("aggression", -0.018, "after losing fights."); if ((loser.totalFightLosses || 0) >= 5 && loser.becomeZunchiSlave?.(winner)) { const oldName = loser.formerName || loser.name; this.spawnBubble(loser.x, loser.y - loser.radius * 1.20, "\u3076\u308a\u3085\u2026", "rgba(74,91,50,0.78)"); @@ -1272,7 +1360,7 @@ class World { const push = isStone ? rand(145, 210) : rand(54, 92); let hit = 0; for (const t of this.nearbyTarinai(it.x, it.y, radius + 48)) { - if (!t || t.dead) continue; + if (!t || t.dead || this.isTarinaiHiddenInNestBox(t)) continue; const d = Math.max(1, distXY(t.x, t.y, it.x, it.y)); const p = clamp(1 - d / (radius + t.radius), 0, 1); if (p <= 0) continue; @@ -1315,8 +1403,8 @@ class World { for (const [ball, arr] of groups) { if (arr.length <= 5) continue; arr.sort((a, b) => { - const ap = a.personality === "playful" ? -120 : 0; - const bp = b.personality === "playful" ? -120 : 0; + const ap = ((a.currentPersonality?.openness || 0) >= 0.5) ? -120 : 0; + const bp = ((b.currentPersonality?.openness || 0) >= 0.5) ? -120 : 0; return dist(a, ball) + ap - (dist(b, ball) + bp); }); for (const t of arr.slice(5)) { @@ -1355,7 +1443,8 @@ class World { ball.amount = Math.max(ball.amount || 999, 999); audio.poke(); this.effects.push(new Effect("ring", ball.x, ball.y, { size: Math.max(16, ball.r * (0.95 + ball.pokeCombo * 0.05)), life: 0.22, color: "rgba(255,255,255,0.58)" })); - // 繝懊・繝ォ繧偵▽縺、縺・◆繧、繝吶Φ繝医・隕ウ蟇欟I縺ク谿九&縺ェ縺・€・ return true; + this.log("\u30dc\u30fc\u30eb\u3092\u3064\u3064\u3044\u3066\u8ee2\u304c\u3057\u305f\u3002", "observe", { eventType: "ball_poke", hiddenFromObservation: true }); + return true; } resolveBallBallCollisions(dt) { @@ -1368,7 +1457,7 @@ class World { const avx = a.vx || 0; const avy = a.vy || 0; const aSpeed = Math.hypot(avx, avy); - const range = ar * 2 + Math.min(560, aSpeed * Math.max(0.016, dt || 0.016)) + 52; + const range = ar * 2 + aSpeed * Math.max(0.016, dt || 0.016) + 52; for (const b of this.nearbyItems(a.x, a.y, range) || []) { if (!b || b === a || b.dead || b.type !== "ball") continue; const key = a.id < b.id ? `${a.id}:${b.id}` : `${b.id}:${a.id}`; @@ -1460,7 +1549,7 @@ class World { const sy = ball.y - py; const segLenSq = sx * sx + sy * sy; for (const t of this.nearbyTarinai(ball.x, ball.y, range)) { - if (!t || t.dead || t.state === "sleep") continue; + if (!t || t.dead || t.state === "sleep" || this.isTarinaiHiddenInNestBox(t)) continue; let hitX = ball.x; let hitY = ball.y; if (segLenSq > 1) { @@ -1492,11 +1581,14 @@ class World { const bvy = ballSpeed > 0.01 ? (ball.vy || 0) / ballSpeed : ny; const damage = clamp((ballSpeed - 285) / 18, 3.5, 38); t.lastBallDamageAt = now; - t.vx = (t.vx || 0) * 0.35 + (ball.vx || 0) * 0.20; - t.vy = (t.vy || 0) * 0.35 + (ball.vy || 0) * 0.20; - t.damage(damage, "\u885d\u7a81"); - const timidStress = t.personality === "timid" ? 1.55 : 1.0; - const stressGain = clamp(damage * 0.55 * timidStress, 3, t.personality === "timid" ? 26 : 18); + this.applyImpulse(t, (ball.vx || 0) * 0.20, (ball.vy || 0) * 0.20, { + panic: true, + target: { x: ball.x, y: ball.y }, + fearTimer: 0.95, + }); + this.applyImpactDamage(t, damage, "\u885d\u7a81"); + const sensitiveHit = t.shouldApplyPersonalityBehavior?.("neuroticism", 1) ? 1.35 : (t.shouldApplyPersonalityBehavior?.("neuroticism", -1) ? 0.82 : 1.0); + const stressGain = clamp(damage * 0.55 * sensitiveHit, 3, sensitiveHit > 1 ? 24 : 18); t.addStress ? t.addStress(stressGain, { threshold: 8 }) : (t.stress = clamp(t.stress + stressGain, 0, 130)); t.state = "panic"; t.target = { x: ball.x, y: ball.y }; @@ -1513,14 +1605,14 @@ class World { ball.vx = (ball.vx || 0) * 0.58 - nx * Math.min(110, ballSpeed * 0.10); ball.vy = (ball.vy || 0) * 0.58 - ny * Math.min(110, ballSpeed * 0.10); ball.spinVelocity = clamp((ball.spinVelocity || 0) + (nx >= 0 ? -1 : 1) * 8.5, -38, 38); - if (t.dead) continue; + continue; } const relVx = (t.vx || 0) - (ball.vx || 0); const relVy = (t.vy || 0) - (ball.vy || 0); const relativeSpeed = Math.hypot(relVx, relVy); const playIntent = t.state === "play_ball" || t.target === ball; - const playful = t.personality === "playful"; + const playful = t.shouldApplyPersonalityBehavior?.("openness", 1); const impulse = clamp(48 + relativeSpeed * 0.72 + (playIntent ? 52 : 0) + (playful ? 24 : 0), 48, isDangerous ? 360 : 260); ball.vx = (ball.vx || 0) * (isDangerous ? 0.78 : 0.92) + nx * impulse + (t.vx || 0) * 0.52; ball.vy = (ball.vy || 0) * (isDangerous ? 0.78 : 0.92) + ny * impulse + (t.vy || 0) * 0.52; @@ -1534,8 +1626,8 @@ class World { t.vy -= ny * Math.min(22, impulse * 0.10); t.energy = clamp(t.energy - (playIntent ? 0.20 : 0.08), 0, 100); const playRelief = playful && playIntent ? 2.8 : playful ? 1.5 : playIntent ? 0.75 : 0.20; - const timidBump = t.personality === "timid" && !playIntent ? clamp(ballSpeed / 190, 0.9, 3.8) : 0; - t.stress = clamp(t.stress - playRelief + timidBump, 0, 130); + const sensitiveBump = t.shouldApplyPersonalityBehavior?.("neuroticism", 1) && !playIntent ? clamp(ballSpeed / 230, 0.6, 2.6) : 0; + t.stress = clamp(t.stress - playRelief + sensitiveBump, 0, 130); if (playful && playIntent) { t.loneliness = clamp(t.loneliness - 0.9, 0, 100); t.affection = clamp(t.affection + 0.18, 0, 100); @@ -1556,7 +1648,7 @@ class World { const now = this.time || 0; if (!this.tarinaiCollisionMemo) this.tarinaiCollisionMemo = new Map(); for (const a of this.tarinai || []) { - if (!a || a.dead) continue; + if (!a || a.dead || this.isTarinaiHiddenInNestBox(a)) continue; const avx = a.vx || 0; const avy = a.vy || 0; const aSpeed = Math.hypot(avx, avy); @@ -1568,7 +1660,7 @@ class World { const segLenSq = sx * sx + sy * sy; const range = (a.radius || 22) * 2.5 + aSpeed * Math.max(0.016, dt || 0.016) + 64; for (const b of this.nearbyTarinai(a.x, a.y, range)) { - if (!b || b === a || b.dead) continue; + if (!b || b === a || b.dead || this.isTarinaiHiddenInNestBox(b)) continue; const key = a.id < b.id ? `${a.id}:${b.id}` : `${b.id}:${a.id}`; if (now - (this.tarinaiCollisionMemo.get(key) || -999) < 0.42) continue; const bvx = b.vx || 0; @@ -1601,12 +1693,15 @@ class World { ny = Math.sin(aa); } const damage = clamp((relSpeed - 118) / 26, 1.2, 22); - target.vx += ivx * 0.20 + nx * 28; - target.vy += ivy * 0.20 + ny * 28; + this.applyImpulse(target, ivx * 0.20 + nx * 28, ivy * 0.20 + ny * 28, { + panic: true, + target: { x: impactor.x, y: impactor.y }, + fearTimer: 0.55, + }); impactor.vx = ivx * 0.72 - nx * Math.min(56, relSpeed * 0.10); impactor.vy = ivy * 0.72 - ny * Math.min(56, relSpeed * 0.10); - target.damage(damage, "\u885d\u7a81"); - if (!impactor.dead) impactor.damage(damage * 0.35, "\u885d\u7a81"); + this.applyImpactDamage(target, damage, "\u885d\u7a81"); + if (!impactor.dead) this.applyImpactDamage(impactor, damage * 0.35, "\u885d\u7a81"); for (const t of [target, impactor]) { if (!t || t.dead) continue; t.state = "panic"; @@ -1639,7 +1734,7 @@ class World { let best = null, bestD = maxDist; const candidates = Number.isFinite(maxDist) ? this.nearbyTarinai(entity.x, entity.y, maxDist) : this.tarinai; for (const o of candidates) { - if (o === entity || o.dead) continue; + if (o === entity || o.dead || this.isTarinaiHiddenInNestBox(o)) continue; if (predicate && !predicate(o)) continue; if (entity?.shouldAvoidTarget && entity.shouldAvoidTarget(o)) continue; const d = dist(entity, o); @@ -1707,6 +1802,47 @@ class World { return this.nestBoxSolidRects(it)[0] || null; } + nestBoxEntryPoint(box) { + const base = this.nestBoxBaseRect(box); + if (!base) return { x: box?.x || 0, y: box?.y || 0 }; + const r = box.r || 42; + // Move the approach point to the center of the open middle cell. The + // collision resolver also ignores this nest box for active sleepers near + // the door, so tarinai can cross the threshold instead of sliding off posts. + return { + x: clamp(box.x, CONFIG.worldPadding, this.w - CONFIG.worldPadding), + y: clamp(box.y + r * 0.02, base.top + r * 0.46, base.bottom - r * 0.18), + }; + } + + nestBoxExitPoint(box, occupant = null) { + const base = this.nestBoxBaseRect(box); + if (!base) return this.nestBoxEntryPoint(box); + const r = box.r || 42; + const side = occupant ? (stableUnit(occupant.id || "nest", `nest-exit-${box.id || "box"}`) - 0.5) * r * 0.36 : 0; + return { + x: clamp(box.x + side, CONFIG.worldPadding, this.w - CONFIG.worldPadding), + y: clamp(base.bottom + r * 0.22, CONFIG.worldPadding, this.h - CONFIG.worldPadding), + }; + } + + nestBoxInnerPoint(box, occupant = null) { + const base = this.nestBoxBaseRect(box); + if (!base) return { x: box?.x || 0, y: box?.y || 0 }; + const occupants = this.nestBoxOccupants ? this.nestBoxOccupants(box, Infinity) : []; + let index = occupants.indexOf(occupant); + if (index < 0) index = Math.min(occupants.length, this.nestBoxCapacity(box) - 1); + const r = box.r || 42; + const slots = [ + [0.00, -0.02], [-0.22, 0.04], [0.22, 0.04], [-0.11, 0.16], [0.11, 0.16], + ]; + const slot = slots[index % slots.length]; + return { + x: clamp(box.x + slot[0] * r, base.left + r * 0.46, base.right - r * 0.46), + y: clamp(box.y + slot[1] * r, base.top + r * 0.34, base.bottom - r * 0.18), + }; + } + solidObstacleRects(it) { if (!it || it.dead) return []; if (this.isFenceType(it.type)) { @@ -1717,6 +1853,20 @@ class World { return []; } + shouldIgnoreNestBoxCollisionFor(t, box) { + if (!t || !box || box.dead || box.type !== "nest_box") return false; + if (t.insideNestBoxId) return true; + if (t.target !== box || (t.state !== "seek_bed" && t.state !== "sleep")) return false; + const entry = this.nestBoxEntryPoint(box); + const base = this.nestBoxBaseRect(box); + const r = box.r || 42; + const entryD = distXY(t.x, t.y, entry.x, entry.y); + const centerD = distXY(t.x, t.y, box.x, box.y); + const aroundDoor = entryD <= Math.max(128, r * 2.25) || centerD <= Math.max(116, r * 2.0); + const inDoorColumn = base && t.x >= base.left + r * 0.18 && t.x <= base.right - r * 0.18 && t.y >= base.top + r * 0.02 && t.y <= base.bottom + r * 0.58; + return Boolean(aroundDoor || inDoorColumn); + } + nearbySolidObstacleRects(x, y, radius, { include = null, exclude = null, maxChecks = CONFIG.maxFenceCollisionChecks ?? 24 } = {}) { const rects = []; let checked = 0; @@ -1764,10 +1914,11 @@ class World { } resolveSolidObstacleCollision(t) { - if (!t || t.dead) return; + if (!t || t.dead || this.isTarinaiHiddenInNestBox(t)) return; const rr = Math.max(8, t.radius * 0.74); let pushed = false; for (const rect of this.nearbySolidObstacleRects(t.x, t.y, rr + 150)) { + if (rect?.type === "nest_box" && this.shouldIgnoreNestBoxCollisionFor(t, rect.item)) continue; if (this.pushTarinaiOutOfRect(t, rect, rr)) pushed = true; } if (pushed) { @@ -1833,7 +1984,7 @@ class World { grassOnTarinaiAt(x, y, minGap = 24) { for (const t of this.nearbyTarinai(x, y, minGap + 36)) { - if (t.dead) continue; + if (t.dead || this.isTarinaiHiddenInNestBox(t)) continue; if (distXY(x, y, t.x, t.y) < Math.max(minGap, t.radius * 1.15)) return true; } return false; @@ -2041,12 +2192,12 @@ class World { observeHighlightKind(t) { const s = this.selected; - if (!s || !t || t === s || t.dead) return ""; + if (!s || !t || t === s || t.dead || this.tool !== "observe") return ""; if ((s.parents || []).includes(t.id)) return "parent"; if ((s.children || []).includes(t.id)) return "child"; const rel = s.relationTo ? s.relationTo(t.id) : null; + if (rel && (rel.affinity || 0) >= FRIEND_AFFINITY_THRESHOLD) return "friend"; if (rel && (rel.fear || 0) >= 8) return "enemy"; - if (rel && (rel.affinity || 0) >= 10) return "friend"; return ""; } @@ -2066,8 +2217,22 @@ class World { if (d < bestD && d <= Math.max(80, it.r * 2.1)) { best = it; bestD = d; } } if (!best) return null; - const occupants = this.nestBoxOccupants(best); - return { box: best, occupants }; + const occupants = this.nestBoxOccupants(best, Infinity); + const capacity = this.nestBoxCapacity(best); + return { box: best, occupants, capacity }; + } + + nestBoxToolTipCount() { + const pointed = this.pointerNestBoxInfo?.(); + if (pointed?.box) return { current: pointed.occupants.length, max: pointed.capacity || this.nestBoxCapacity(pointed.box) }; + const boxes = (this.items || []).filter(it => it && !it.dead && it.type === "nest_box"); + if (!boxes.length) return { current: 0, max: this.nestBoxCapacity() }; + let current = 0, max = 0; + for (const box of boxes) { + current += this.nestBoxOccupants(box, Infinity).length; + max += this.nestBoxCapacity(box); + } + return { current, max }; } blastZunchiFrom(x, y, radius, strength = 1) { @@ -2100,7 +2265,11 @@ class World { dt = Math.min(dt, 0.12 * this.speed); this.time += dt; + const previousDay = this.day || 1; this.day = Math.floor(this.time / CONFIG.dayLength) + 1; + if (this.day !== previousDay) { + for (const t of this.tarinai || []) if (t) t.personalityDaily = { day: this.day, total: 0, byKey: {} }; + } if (this.pointer) this.pointer.motion = Math.max(0, (this.pointer.motion || 0) - dt * 2.4); this.updateWeather(dt); this.rebuildSpatial(); @@ -2242,7 +2411,7 @@ class World { t.vx = 0; t.vy = 0; t.entryTimer = 0; - t.die("莉墓ァ倥↓繧医j逕サ髱「螟悶〒蜑企勁"); + t.die(HEALTH?.CAUSES?.outOfBounds || "\u4ed5\u69d8\u306b\u3088\u308a\u753b\u9762\u5916\u3067\u524a\u9664"); } else if (result === "moved") { t.x = clamp(Number.isFinite(t.x) ? t.x : this.w * 0.5, pad, this.w - pad); t.y = clamp(Number.isFinite(t.y) ? t.y : this.h * 0.5, pad, this.h - pad); @@ -2289,11 +2458,104 @@ class World { return false; } + placementBlocked(item) { + if (!item || item.dead) return true; + const pad = CONFIG.worldPadding || 30; + const rects = this.solidObstacleRects(item); + if (rects.length) { + for (const rect of rects) { + if (rect.left < pad || rect.top < pad || rect.right > this.w - pad || rect.bottom > this.h - pad) return true; + } + } else { + const radius = Math.max(14, (item.r || 12) * (item.type === "bed" ? 1.55 : 1.25)); + if (item.x - radius < pad || item.y - radius < pad || item.x + radius > this.w - pad || item.y + radius > this.h - pad) return true; + } + if (item.type === "grass" && !this.grassSpotOpen(item.x, item.y, { avoidTarinai: true })) return true; + if (this.isFenceType(item.type) && this.fencePlacementBlocked(item)) return true; + if (item.type === "nest_box") { + const margin = Math.max(8, (item.r || 42) * 0.18); + for (const it of this.nearbyItems(item.x, item.y, Math.max(120, (item.r || 42) * 3))) { + if (!it || it === item || it.dead) continue; + for (const rect of this.solidObstacleRects(it)) { + for (const own of rects) { + const separated = own.right + margin < rect.left || own.left - margin > rect.right || own.bottom + margin < rect.top || own.top - margin > rect.bottom; + if (!separated) return true; + } + } + } + } + return false; + } + + placementClampPointFor(item, x = item?.x || 0, y = item?.y || 0) { + const pad = CONFIG.worldPadding || 30; + const rects = this.solidObstacleRects(item); + if (rects.length) { + let left = 0, right = 0, top = 0, bottom = 0; + for (const rect of rects) { + left = Math.max(left, (item.x || 0) - rect.left); + right = Math.max(right, rect.right - (item.x || 0)); + top = Math.max(top, (item.y || 0) - rect.top); + bottom = Math.max(bottom, rect.bottom - (item.y || 0)); + } + return { + x: clamp(x, pad + left, this.w - pad - right), + y: clamp(y, pad + top, this.h - pad - bottom), + }; + } + const radius = Math.max(14, (item.r || 12) * (item.type === "bed" ? 1.55 : 1.25)); + return { + x: clamp(x, pad + radius, this.w - pad - radius), + y: clamp(y, pad + radius, this.h - pad - radius), + }; + } + + placementProbeItem(item, x, y) { + return { ...item, x, y, dead: false }; + } + + findPlacementSpot(item, { allowOriginal = true, maxRadius = null, attempts = null } = {}) { + if (!item || item.dead) return null; + if (item.type === "grass") { + const spot = this.findGrassPlantingSpot + ? this.findGrassPlantingSpot(item.x, item.y, { allowOriginal, attempts: attempts || 42, maxRadius: maxRadius || 170, avoidTarinai: true }) + : null; + if (!spot) return null; + const probe = this.placementProbeItem(item, spot.x, spot.y); + return this.placementBlocked(probe) ? null : spot; + } + + const start = this.placementClampPointFor(item, item.x, item.y); + const original = this.placementProbeItem(item, start.x, start.y); + if (allowOriginal && !this.placementBlocked(original)) return start; + + const solid = this.isFenceType(item.type) || item.type === "nest_box"; + const searchRadius = maxRadius || (solid ? Math.max(150, (item.r || 42) * 4.2) : Math.max(90, (item.r || 16) * 3.2)); + const count = attempts || (solid ? 72 : 36); + const golden = Math.PI * (3 - Math.sqrt(5)); + let best = null; + let bestD = Infinity; + for (let i = 0; i < count; i++) { + const t = count <= 1 ? 1 : i / (count - 1); + const radius = Math.max(8, searchRadius * Math.sqrt(t)); + const angle = i * golden + stableUnit(`${item.type}:${item.x.toFixed(1)},${item.y.toFixed(1)}`, "place") * Math.PI * 2; + const rawX = item.x + Math.cos(angle) * radius; + const rawY = item.y + Math.sin(angle) * radius * 0.74; + const p = this.placementClampPointFor(item, rawX, rawY); + const probe = this.placementProbeItem(item, p.x, p.y); + if (this.placementBlocked(probe)) continue; + const d = distXY(item.x, item.y, p.x, p.y); + if (d < bestD) { best = p; bestD = d; } + if (d < Math.max(18, (item.r || 12) * 0.75)) break; + } + return best; + } + findGrabTargetAt(x, y) { let foundT = null; for (let i = this.tarinai.length - 1; i >= 0; i--) { const t = this.tarinai[i]; - if (!t || t.dead) continue; + if (!t || t.dead || this.isTarinaiHiddenInNestBox(t)) continue; if (t.contains ? t.contains(x, y) : distXY(x, y, t.x, t.y) <= (t.radius || 22) * 1.4) { foundT = t; break; } } let foundItem = null, foundItemD = Infinity; @@ -2324,10 +2586,10 @@ class World { showToast("\u67f5\u304c\u591a\u3059\u304e\u307e\u3059\u3002\u5148\u306b\u4e00\u90e8\u3092\u524a\u9664\u3057\u3066\u304f\u3060\u3055\u3044\u3002"); return null; } - if (this.fencePlacementBlocked(item)) { - showToast("\u305d\u3053\u306b\u306f\u67f5\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3002"); - return null; - } + } + if (this.placementBlocked(item)) { + showToast(this.isFenceType(item.type) ? "\u305d\u3053\u306b\u306f\u67f5\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3002" : "\u305d\u3053\u306b\u306f\u914d\u7f6e\u3067\u304d\u307e\u305b\u3093\u3002"); + return null; } if (dropped) { item.dropMax = item.type === "stone" ? 0.72 : 0.58; @@ -2345,7 +2607,7 @@ class World { if (tool === "observe") { let found = null; for (let i = this.tarinai.length - 1; i >= 0; i--) { - if (this.tarinai[i].contains(x, y)) { found = this.tarinai[i]; break; } + if (!this.isTarinaiHiddenInNestBox(this.tarinai[i]) && this.tarinai[i].contains(x, y)) { found = this.tarinai[i]; break; } } this.selected = found; if (found) this.log(`${found.name}\u3092\u9078\u629e\u3057\u305f\u3002`); @@ -2398,31 +2660,19 @@ class World { this.compactItems(); this.updateItemCounts(); this.rebuildSpatial(); - const label = { zunchi: "\u305a\u3093\u3061", food: "\u98df\u3079\u7269", sweet: "\u305a\u3093\u3060\u9905", love_mochi: "\u3078\u3053\u9905", fight_mochi: "\u3051\u3093\u304b\u9905", water: "\u6c34", water_bowl: "\u6c34\u306e\u76bf", sleep_drug: "\u306d\u3080\u308a\u85ac", grass: "\u8349", stone: "\u77f3", bed: "\u5e72\u8349\u5bdd\u5e8a", nest_box: "\u5de3\u7bb1", ball: "\u30dc\u30fc\u30eb", firecracker: "\u7206\u7af9", fence_v: "\u7e26\u306e\u67f5", fence_h: "\u6a2a\u306e\u67f5", trace: "\u8db3\u8de1", splat: "\u3057\u3076\u304d" }[best.type] || best.type; + const label = toolLabel(best.type); this.log(`${label}\u3092\u524a\u9664\u3057\u305f\u3002`, "observe"); return; } - const itemType = { - zunchi: "zunchi", sweet: "sweet", love_mochi: "love_mochi", fight_mochi: "fight_mochi", sleep_drug: "sleep_drug", water: "water", water_bowl: "water_bowl", grass: "grass", - stone: "stone", bed: "bed", nest_box: "nest_box", ball: "ball", firecracker: "firecracker", fence_v: "fence_v", fence_h: "fence_h" - }[tool]; + const itemType = toolItemType(tool); if (itemType) { let px = x, py = y; - if (itemType === "grass") { - const spot = this.findGrassPlantingSpot(x, y, { allowOriginal: true, minRadius: 22, maxRadius: 128, attempts: 48 }); - if (!spot) { - showToast("\u8349\u306b\u306f\u7a7a\u3044\u305f\u571f\u304c\u5fc5\u8981\u3067\u3059\u3002"); - this.log("\u305d\u3053\u306b\u306f\u8349\u304c\u690d\u3048\u3089\u308c\u308b\u7a7a\u304d\u5730\u304c\u3042\u308a\u307e\u305b\u3093\u3002"); - return; - } - px = spot.x; - py = spot.y; - } const rawItem = this.applyToolSize(new Item(itemType, px, py)); - // 譟オ縺ッ隕九◆逶ョ縺ョ遏ゥ蠖「縺後ヵ繧」繝シ繝ォ繝牙、悶↓縺ッ縺ソ蜃コ縺吩ス咲スョ縺ォ縺ッ鄂ョ縺九↑縺・€・ // 驟咲スョ繝励Ξ繝薙Η繝シ縺ョ襍、陦ィ遉コ縺ィ螳滄圀縺ョ驟咲スョ蜿ッ蜷ヲ繧剃ク€閾エ縺輔○繧九€・ const placed = this.placeItem(rawItem, true); + // Placement uses the same footprint that the preview validates. + const placed = this.placeItem(rawItem, true); if (!placed) return; - const label = { zunchi: "\u305a\u3093\u3061", food: "\u98df\u3079\u7269", sweet: "\u305a\u3093\u3060\u9905", love_mochi: "\u3078\u3053\u9905", fight_mochi: "\u3051\u3093\u304b\u9905", water: "\u6c34", water_bowl: "\u6c34\u306e\u76bf", sleep_drug: "\u306d\u3080\u308a\u85ac", grass: "\u8349", stone: "\u77f3", bed: "\u5e72\u8349\u5bdd\u5e8a", nest_box: "\u5de3\u7bb1", ball: "\u30dc\u30fc\u30eb", firecracker: "\u7206\u7af9", fence_v: "\u7e26\u306e\u67f5", fence_h: "\u6a2a\u306e\u67f5" }[itemType]; + const label = toolLabel(itemType); this.log(`${label}\u3092\u914d\u7f6e\u3057\u305f\u3002`); } } @@ -2441,22 +2691,25 @@ class World { return "note"; } - shouldHideFromObservationRecords(text = "") { - const s = String(text || ""); - return [ - "\u30dc\u30fc\u30eb\u3092\u9023\u7d9a\u3067\u3064\u3064", - "\u30dc\u30fc\u30eb\u3092\u3064\u3064\u3044\u3066", - "\u3092\u907f\u3051\u305f", - ].some(part => s.includes(part)); + shouldHideFromObservationRecords(entry = {}) { + const type = typeof entry === "string" ? "" : (entry.eventType || ""); + return type === "ball_poke" || type === "avoid_relationship"; } - log(text, kind = null) { - const entry = { time: this.time, text, kind: kind || this.inferLogKind(text) }; + log(text, kind = null, options = {}) { + const entry = { + time: this.time, + text, + kind: kind || this.inferLogKind(text), + eventType: options.eventType || "", + hiddenFromObservation: Boolean(options.hiddenFromObservation), + }; + if (this.shouldHideFromObservationRecords(entry)) entry.hiddenFromObservation = true; if (!this.eventCounters) this.eventCounters = {}; this.eventCounters[entry.kind] = (this.eventCounters[entry.kind] || 0) + 1; for (const t of this.tarinai || []) { if (!t || !t.name || !text || !String(text).includes(t.name)) continue; - if (!this.shouldHideFromObservationRecords(text) && t.addRecord) t.addRecord(text, entry.kind); + if (!entry.hiddenFromObservation && t.addRecord) t.addRecord(text, entry.kind); } this.logs.unshift(entry); this.logs = this.logs.slice(0, 100);