4 Commits
Author SHA1 Message Date
andrey 1ebaf6e2ae Этап 53: ребаланс прогрессии и экономики + масштабируемые квесты. (1) Цены снастей: RODS 0/875/4500/15000 → 0/150/500/30000; LURES 0/625/3000/11250 → 0/100/2000/22000 (Воблер 300→2000 по правке владельца). Апгрейды id 0: ROD_UPG_COST 70/210/500 → 20/50/100, LURE_UPG_COST 60/160/400 → 15/40/80; UPG_MULT 0.2/0.6/1.2 → 0.15/0.35/0.6. Гейт «предыдущая снасть на 4 ур.» оставлен, но апгрейды сильно удешевлены. (2) Цены локаций: Озёра 65536→500, Болото 90000→10000, Море 131072→100000, Океан 196608→300000; порядок по цене Река<Озёра<Болото<Море<Океан сохранён. (3) Веса Болота снижены до уровня Озёр и ниже (цель «тащить легче, доход меньше»): SWAMP_DAY_WEIGHTS={glowfin:4,moonfish:32,emberfin:3,violetlure:6,spiritfin:7}, SWAMP_NIGHT_WEIGHTS={glowfin:4,moonfish:28,emberfin:3,violetlure:10,spiritfin:3}; per-catch E 240.3/328.9 → 133.9/162.5 (доля дешёвой лёгкой moonfish поднята, дорогая violetlure/emberfin срезана); по 🪙/мин Болото ≈ Озёра. Инвариант balance.mjs «дороже вода доходнее» для Болота сознательно не выполняется. (4) Квесты дня масштабируются по save.earned: questScale()=clamp(round((earned/2000)^0.6),1,30); QUEST_TPLS масштабирует ВСЕ шаблоны (earn_coins goal×scale, casts ×(1+0.15·scale), catch_weight порог от localMedianW() — медиана середин весов рыб ТЕКУЩЕЙ локации ×scale^0.35, catch_rarity r=clamp(1+floor(1.5·log10(scale+1)),1,4), catch_species вид из SPECIES_BY_LOCATION[save.location] с rarity≤2), qReward(base)=round(base·scale^0.6); questText RU/EN терпим к неречным id (fallback trName). (5) Новый tools/progression.mjs (read-only, данные из index.html): моделирует улов (pickSpecies+rollWeight+варианты+обрыв по maxW) и цикл ловли (biteChance/таймеры/fishForce+updateReel ботом), жадный маршрут покупок → 🪙/мин по водам и ETA целей; what-if --rod/--lure/--loc/--rod-upg/--lure-upg/--upg-mult/--set/--set-day/--set-night. Калибровочные цели: Стекло 4.4 мин · Озёра 10.3 (5.9 после Стекло) · Карбон 6.9 · Болото 22.9 (13.3 после Карбона) · Титан ~50 мин · Море 2 ч 17 · Океан 4 ч 04. (6) Тесты 233→234: обновлены пины M5 (150/100, апгрейды 20/50/100 и 15/40/80, upgCost-строки), lc1 (costs 0,500,100000,300000,10000), lc8 (покупки локаций), ранний магазин; новый §9e2 — questScale/localMedianW/рост целей. Прогон: 234/234 PASS, exit 0; check.mjs OK; balance.mjs — Болото 133.9/162.5, остальные пины (Река/Озёра/Море/Океан) не сдвинуты. (7) Доки: AGENTS.md (Баланс/Локации/Баланс Озёр/Баланс-скрипт + пункт «Прогрессия»/Награды + тест-глобалы), README (локации/цены/прогрессия), docs/PLAN-PROGRESSION.md (новый), DEVLOG (Этап 53). 2026-10-05 15:42:49 +03:00
andrey 7f545347b4 Этап 45: локация «Волшебное болото» (id 4, 90 000 🪙) — светящиеся рыбы, лягушки, кувшинки/лилии. (1) Данные: LOCATIONS[4] (тёмно-моховая вода 6 hex, слабая рябь; в массиве ПОСЛЕДНИЙ, по цене — между Озёрами 65536 и Морем 131072); 5 новых видов строго в КОНЕЦ SPECIES (32→37, по одному на редкость r0–r4, у каждого glow:'#hex' — 5 разных цветов): glowfin Светлячок #5ff2ff 8🪙, moonfish Лунная рыбка #b9c8ff 13, emberfin Изумрудный светляк #57ffa8 20, violetlure Фиалковый огонёк #d17bff 38, spiritfin Дух болота #ffe07a 70; SWAMP_IDS/SWAMP_DAY_WEIGHTS/SWAMP_NIGHT_WEIGHTS/SWAMP_SPECIES(_NIGHT) — паттерн LAKE/SEA/OCEAN без пересечений; NIGHT_WEIGHTS — ключи всем 37 id. (2) pickSpecies(): вложенный тернарник → табличный доступ SPECIES_BY_LOCATION(_NIGHT) по save.location + guard (вне 0..4 → Река); роллы 0..3 бит-в-идентичны (lc3/lc4/lc4b/lc4c + речные §9j/M4/M6 не тронуты). (3) Свечение (только ночь): nightMix()>0.35 — тот же порог, что у фонаря; drawGlowAura() (радиальный градиент + 'lighter', save/restore, кэш GLOW_RGBA) — фоновые рыбы болота (AMBIENT_FISH[4] — 7 рыб + palette из 4 цветов, цвет стабильно по индексу), зацепившаяся/вываживаемая (fishGlow — вид с glow), боссовая золотая аура сохранена; карточка — класс glow-card + --glow (только normal-вариант, drop-shadow, не конфликтует с фильтрами вариантов), дневник — drop-shadow на SVG. (4) Декорации: initScenery() ветка i===4 (bank+reed+snag+pine в болотной гамме), ГЛОБАЛЬНЫЕ pads[] (8–14 кувшинок с вырезом, 45% с лилиями — жёлтые/белые/розовые) и frogs[] (3–5, sit→jump по параболе на соседнюю кувшинку, 3–7 с) — очищаются/пересобираются в initScenery() (resize + обе ветки shopClick); updateDecor(dt) — покачивание/прыжки; drawSwampDecor() — ОТДЕЛЬНЫЙ слой после drawWater/drawAmbientFish и до drawBoat (дusk берега не гасит; локальное притухание ночью). (5) Босс: BOSS_BY_LOCATION[4]='spiritfin' (Дух болота, 20–50 кг, ×5 — паттерн Этапа 37). (6) Магазин/i18n/ачивки: тост welcome_swamp (ru/en, тернарник → if/else), ачивки 34→36: swamp_first (bonus:{coinPct:0.02}, locations-based) + swamp_boss (bonus:{}, bosses.spiritfin) → пин achBonus().coinPct 0.16→0.18; species_8 = все 37. (7) Баланс: SWAMP_DAY_WEIGHTS {glowfin:3,moonfish:4,emberfin:28,violetlure:13,spiritfin:4.5}, SWAMP_NIGHT_WEIGHTS {glowfin:2.5,moonfish:2.5,emberfin:20,violetlure:30,spiritfin:4} — Болото 240.3/328.9 🪙 (ночь/день ×1.37), порядок по цене Озёра 194.1/249.0 < Болото < Море 297.3/476.7 в ОБЕ фазы; пины остальных вод не изменились (Река 65.1/125.9 · Озёра 194.1/249.0 · Море 297.3/476.7 · Океан 329.1/552.7). (8) tools/balance.mjs: 8→10 таблиц, +SWAMP_SPECIES(_NIGHT) в return, сводка/пары отношений — сортировка ПО ЦЕНЕ (болото встает между Озёрами и Морем), пины в шапке. (9) Портреты: 5 flat-SVG (каждый — отдельным художником) assets/fish/fish-{glowfin,moonfish,emberfin,violetlure,spiritfin}.svg (viewBox 0 0 160 100, var(--f1..f4,hsl-fallback)); embed-fish.mjs IDS 32→37 (в конец), 37 <symbol> в index.html; fish-preview.html 32→37 карточек. (10) Тесты (тот же коммит): lc1 (37/5 локаций/90000/names/sprites 37/oceanOrder slice(23,32)/swampOrder/swampGlow/swampRar), lc2 (+SWAMP-таблицы, пересечения, nightW 37), lc4d (новый: 3000+3000 роллов болота — все 5 ≥1, чужих нет), lc5 (+location:4 не сбрасывается, location:5→0), lc8w (новый: покупка 90000 + welcome_swamp), lc9 (37), lc10 (mid29), lc11 (новый: glow #rrggbb, 5 цветов различны, веса покрывают id, NIGHT_WEIGHTS — все 37), a22d (36), a36loc (+swamp_first), пин 0.18, §9k2 (+{loc:4, spiritfin, swamp_boss}). 198→204 PASS, exit 0. (11) Скриншоты: gen-screenshots.js +кадры swamp/swamp-night (12→14 × 3 вьюпорта, dayTime 0.3/0.85) — 42 RU + 42 EN PNG (screenshots-wiki/, screenshots-wiki-en/). (12) Доки: AGENTS.md (локации/босс/баланс/баланс-скрипт/награды/портреты/скриншоты), README (5 локаций, 37 видов, 36 ачивок, 204 теста, 14 кадров, mobp-swamp*), KODA.md (SWAMP_*, SPECIES_BY_LOCATION, drawGlowAura/fishGlow/GLOW_RGBA, drawSwampDecor, pads/frogs), DEVLOG (Этап 45), PLAN-SWAMP.md (статус «реализован»). Проверено: 204/204 PASS exit 0, check.mjs OK, balance.mjs — пины без изменений + Болото в цели, emoji-font --check OK (52 глифа, новых emoji нет), ревью @oracle — критичных замечаний нет (.gitignore + .opencode/, fish-preview, осколок комментария species_8 — закрыты в этом же коммите). Миграция сейва не тронута (граница из LOCATIONS.length; location=4 покрыт lc5(f)). 2026-09-21 22:59:15 +03:00
andrey 48dd6ae22a Цены Озёр/Моря/Океана под цели ×3/×4/×5 Реки (Этап 39): после лестницы весов Этапа 38 доходность новых вод была ×5–15 — урезаны цены 24 видов (Озёра k≈0.201: zander 8, chuch 6, crayfish 40, bleak 4, roundel 5, eelpout 11, tench 16, navaga 50, rudd 5, cisco 18; Море k≈0.253: herring 8, mackerel 18, flounder 33, tuna 46, swordfish 81; Океан k≈0.192: moray 5, grouper 5, turtle 9, angler 21, octopus 23, manta 29, shark 31, squid 37, whale 67), цены Реки не тронуты. tools/balance.mjs: новая опция --price id:цена (what-if 🪙/кг, паттерн --set: парсинг/валидация id/calcTable/WHAT-IF строка/help) — набор цен собран и сверен через скрипт ДО и ПОСЛЕ правки index.html (цифры совпали). Итог (нейтральная снасть): Озёра 194.1/214.5 (×2.98/×1.70 Реки), Море 262.7/304.2 (×4.04/×2.42), Океан 329.1/398.9 (×5.06/×3.17), Река 65.1/125.9 — цель по ДНЮ (×3/×4/×5): единый множитель масштабирует обе фазы, а ночь/день у новых вод ×1.11–1.21 против ×1.93 у Реки — «обе фазы» ценами недостижимо (нужна правка *_WEIGHTS); зафиксировано в AGENTS.md. Инвариант «новая вода доходнее в ОБЕ фазы» держится с запасом: Море/Озёра ×1.35/×1.42, Океан/Море ×1.25/×1.31 (тонкий запас этапа 38 ×1.06 снят). Тесты: пины lc1 (10f) — 24 строки (колонка price) + текст ассерта; тесты наград M4/§9k2/M6/shiny читают w×price динамически — без изменений (босс-рак 200→40). 193/193 PASS, exit 0; check.mjs OK. Доки: AGENTS.md (финальные пины + --price), README (4–1500 🪙/кг), KODA.md (0.05–100 кг, 4–1500 🪙/кг), шапка balance.mjs (пины), DEVLOG (Этап 39). 2026-09-19 23:49:07 +03:00
andrey ae5e2c1094 Локация «Океан» (Этап 36): SPECIES 23→32 — 9 глубоководных видов (мурена/горбуна/черепаха/удильщик/осьминог/скат-манта/большая белая акула/гигантский кальмар/синий кит), эксклюзив Океана; OCEAN_IDS/OCEAN_DAY/NIGHT_WEIGHTS (ночь — смещение к крупным), LOCATIONS[3] Океан 196608 🪙 (= ×1.5 Моря), своя вода; pickSpecies() — развилка на 4 локации (0/1/2/3); тост welcome_ocean RU/EN; ачивки sea_first «Широкая вода» ⚓ / ocean_first «Глубина» 🌊 (locations-based, 29→31, пин §10c(8)=0.16 не тронут). Попутный баг: граница loadSave() save.location>1 (с этапа 5, не обновлялась в этапе 35) → >=LOCATIONS.length — купленное Море сбрасывалось на Реку при каждом reload; регресс-кейсы lc5 (d)/(e). tools/balance.mjs — скрипт расчёта доходности таблиц ролла (--set/--dist/--lure), расширен на 4 локации (8 таблиц); пины: Река 65.1/125.9 · Озёра 121.2/134.1 · Море 190.8/222.0 · Океан 539.5/671.3 (×2.8–3.0 Моря — точная подгонка отдельным этапом). Кит wMax 50 > maxW Титана 40: ≥40 кг при технике «держи кнопку» — гарантированный обрыв, вываживается только управлением натяжением (28–38 с боя) — зафиксировано в DEVLOG как материал баланс-этапа. Emoji-шрифт: +6 глифов 🐢🐙🦑🐳🌊⚓ (58→64), --check OK. Тесты: пины 10f переписаны (32 вида/4 локации/costs), +роллы Океана lc4c (3000×2), +покупка lc8c, +lc5 (d)/(e), +sea_first/ocean_first — 183/183 PASS, exit 0; check.mjs OK. Доки README/AGENTS/KODA/DEVLOG синхронизированы (включая устаревшие числа: 162→183 проверки, 15→10 кадров, пример --set на латинских id). 2026-09-19 15:29:14 +03:00