Ещё пять озёрных видов (Этап 33): SPECIES 11→16 — плотва/густера/вьюн/линь/навага, чтобы «побольше разных рыб» не трогало Реку.
Новые виды добавлены СТРОГО в конец SPECIES (после crayfish этапа 5): SPECIES[0..7] пинятся тестами (§573/§1524/§2446 SPECIES[0], §9j/M4/M6 по id) и квестами (QUEST_TPLS индексы 0..2) — вставка в середину ломала их молча. Параметры: bleak r0 18🪙/кг 0.05–0.6, roundel r0 24 0.1–0.9, eelpout r1 55 0.05–0.4 (🐍), tench r2 80 0.3–4.0, navaga r3 250 0.3–2.5; minDist/strength вписаны в существующую кривую (0.05→0.75, 0.28→0.70), поэтому fishForce()/updateReel() не тронуты и Monte-Carlo по PHYSICS-RESEARCH не требовался. Река не изменилась: RIVER_IDS не тронут → роллы реки прежние (pin lc3). NIGHT_WEIGHTS дополнен всеми пятью id — SPECIES_NIGHT строится как NIGHT_WEIGHTS[s.id], у пропущенного id вес стал бы undefined (упал бы lc2 и сам ролл). Баланс Озёр удержан подъёмом дорогой рыбы: прикидка E[выручка/улов] (середина диапазона веса × цена) давала просадку 91.9→73.5 🪙 день (ночь 134.1→113.1) — мелочь размывает доход, а Река для сравнения 65.1. Компенсация в LAKE_*_WEIGHTS: gold 1.2→1.6, sturge 3→3.5 (день)/4→4.5 (ночь), crayfish 1.5→2/2→2.5 → стало 84.7/122.2 при доле gold 0.56%/0.68% (было 0.55%/0.64%): Озёра остаются доходнее Реки. Emoji: четыре вида взяли 🐟/🐠 из уже покрытого субсета, только 🐍 потребовал перегенерации — субсет 57→58 глифов, woff2 80 КБ (+107 КБ base64). LOCATIONS[1].desc/descEn — перечисление озёрных рыб; комментарии «все 11» → «все 16» в pickSpecies() и у species_8 (check = SPECIES.every, масштабируется сам, id ради старых сейвов не тронут). Сейв-миграция не нужна: caught[id] создаётся в catchFish(), в старых сейвах новых записей нет — дневник показывает «???». Тесты: lc1 — SPECIES.length 16, пины параметров пяти новых видов, порядок (slice(0,8) не сдвинут, slice(8) — ровно 8 озёрных) и заполненность всех полей включая nameEn (иначе EN-ветка trName()); lc2 — LAKE_SPECIES(_NIGHT) 16, SPECIES_NIGHT.length 16 + веса числа; lc3 без изменений; lc4 — текстовка «все 16» (состав из SPECIES.map, подстраивается сам); lc9 — строк дневника 16; lc10 — сетап «+3 новых» → «+8 озёрных». 178/178 PASS, exit 0; check.mjs OK; pack.mjs + pack-smoke 6/6 (115.1 КБ, один index.html в корне). Скриншоты RU/EN перегенерированы (дневник вырос). Доки: README (16 видов + состав Озёр), AGENTS.md (раздел «Локации»: 16 видов + правило «новые виды только в конец SPECIES» и обязательность ключей во всех трёх таблицах весов), DEVLOG Этап 33 (включая флейку: lc4 зовёт pickSpecies() без аргумента → dist=undefined, штраф minDist не действует, значит на «каждый вид ≥1 за 3000 роллов» влияет только вес — новому озёрному виду нужно ≥ ~2).
This commit is contained in:
@@ -39,7 +39,7 @@
|
||||
- Варианты рыб (M6): таблица `VARIANTS` — 8 вариантов, порядок ролла = порядок массива: copper ×1.5 @0.12 → silver ×2 @0.08 → quartz ×2.5 @0.07 → gold ×3 @`SHINY_CHANCE` (0.06, живая) → emerald ×4 @0.01 → diamond ×4.5 @0.007 → rainbow ×5 @0.005 (топ), иначе normal; P(особой)≈31% без буста снасти, E[mult]≈1.36. `variantChance()` — единственная точка вероятностей (дождь M8 уже здесь — ×3, см. строку «Погода (M8)»; буст снасти M6+ тоже здесь: `variantBoost()` = `lure().rare×0.15 + (уровень наживки−1)×0.05`, множитель ×(1+B·r), r — номер в лестнице 1..7 — редким больше; простая наживка 1 ур. → B=0; блёстка 4 ур. → B=0.6, rainbow ×5.2), счётчики улова — `VARIANT_KEY` (cp/sv/qz/sn/em/dm/rb; sn = «shiny» = gold), миграция счётчиков в `loadSave()` (дефолт 0), тест-форс `forceVariant`, босс всегда normal. Рыбу нельзя улучшать: «Улучшить вариант» (M6) убрано в этапе 21 — карточка улова только бейдж/оформление по варианту. Пины шансов в тестах (§10c(1)/(5), M8(2)) — при нейтральной снасти (снапшот/рестор `save.lure`/`lureLv` в eval).
|
||||
- Погода (M8): таблица `WEATHER` (rain — `variantMult` ×3; fog — `biteMult` ×1,5), таймеры в реальном времени — `updateWeather()` в `frame()` (gap `WEATHER_GAP_MIN..MAX` 120–240 с, длительность `WEATHER_DURATION` 120 с, под форсом не гоняются), `weatherActive()` — единственная точка чтения (форс приоритетнее), эффекты только в `variantChance()` (rain) и `biteChance()` (fog), тест-форс `forceWeather` ('rain'/'fog'/null, паттерн `forceBoss`); погода не персистится в сейв. Тост погоды — из `T` (`t('wx_'+weather)`; `WEATHER.*.toast` — не используется). Заметка: туман может дать p>1 → насыщение 100% клёва (осознанно).
|
||||
- Скины (M-skins): таблицы `BOAT_SKINS`/`BOBBER_SKINS` (лодка: Обычная 0 / «Красная лодка» 800 / «Лодка-домик» 2000 🪙; поплавок: Обычный 0 / Красный 500 / Неоновый 1500 🪙), сейв `save.boatSkin(s)`/`save.bobberSkin(s)` + миграция в `loadSave()` (включая гарантию бесплатного скина 0), вкладка «Скины» 🎨 (`#tabSkins`, строка `skinRow(list,i,owned,equipped,group)`, ветки buyskin/select в `shopClick()`: покупка со списанием и авто-экипировкой, выбор — только купленное), отрисовка `drawBoat()`/`drawBobber()` с clamp 0..2 (скин 2: каюта у лодки, неоновое свечение `shadowBlur` в save/restore у поплавка); чистая косметика — без эффектов на геймплей.
|
||||
- Локации (этап 5): таблица `LOCATIONS` (Река 0 — бесплатно / «Озёра» 100000 🪙; `water` — 6 hex [dayTop,dayMid,dayBot,nightTop,nightMid,nightBot] для градиента `drawWater()`, nightMix-логика та же), сейв `save.locations[]`/`save.location` + миграция в `loadSave()` (гарантия бесплатной Реки, паттерн скинов), вкладка «Локации» 🗺️ (`#tabLocations`, строка `locationRow(loc,i,owned,selected)`, ветки buylocation/selectlocation в `shopClick()`: покупка — списание, push, АВТО-ПЕРЕХОД `save.location`, тост «Добро пожаловать на Озёра!»; выбор — только купленное). Таблицы рыб: `RIVER_SPECIES(_NIGHT)` — ТОЛЬКО 8 базовых видов (роллы реки не меняются: pin-тесты §9j(b)/M4/M6 завязаны на веса и порядок — новые виды в реку НЕ добавлять!), `LAKE_SPECIES(_NIGHT)` — все 11 видов (веса `LAKE_DAY_WEIGHTS`/`LAKE_NIGHT_WEIGHTS`); `SPECIES`/`SPECIES_NIGHT` — полный словарь 11 видов (новые: zander/chuch/crayfish, ночные веса 6/10/2.5). `pickSpecies()` выбирает таблицу по `save.location` и dayPhase (логика ролла та же); босс (sturge) есть в обеих локациях; ачивка species_8 — теперь «Поймай все виды» (все 11, id не менять — старые сейвы).
|
||||
- Локации (этап 5): таблица `LOCATIONS` (Река 0 — бесплатно / «Озёра» 100000 🪙; `water` — 6 hex [dayTop,dayMid,dayBot,nightTop,nightMid,nightBot] для градиента `drawWater()`, nightMix-логика та же), сейв `save.locations[]`/`save.location` + миграция в `loadSave()` (гарантия бесплатной Реки, паттерн скинов), вкладка «Локации» 🗺️ (`#tabLocations`, строка `locationRow(loc,i,owned,selected)`, ветки buylocation/selectlocation в `shopClick()`: покупка — списание, push, АВТО-ПЕРЕХОД `save.location`, тост «Добро пожаловать на Озёра!»; выбор — только купленное). Таблицы рыб: `RIVER_SPECIES(_NIGHT)` — ТОЛЬКО 8 базовых видов (роллы реки не меняются: pin-тесты §9j(b)/M4/M6 завязаны на веса и порядок — новые виды в реку НЕ добавлять!), `LAKE_SPECIES(_NIGHT)` — все 16 видов (веса `LAKE_DAY_WEIGHTS`/`LAKE_NIGHT_WEIGHTS`); `SPECIES`/`SPECIES_NIGHT` — полный словарь 16 видов (этап 5: zander/chuch/crayfish, этап 33: bleak/roundel/eelpout/tench/navaga; ночные веса — в `NIGHT_WEIGHTS`, ключ обязателен каждому id, иначе `weight=undefined`). **Новые виды добавлять только в КОНЕЦ `SPECIES`** — `SPECIES[0..7]` запинены тестами (§573/§1524/§2446 `SPECIES[0]`, §9j/M4/M6 по id) и квестами (`QUEST_TPLS` индексы 0..2); вставка в середину молча сломает их. `pickSpecies()` выбирает таблицу по `save.location` и dayPhase (логика ролла та же); босс (sturge) есть в обеих локациях; ачивка species_8 — «Поймай все виды» (все 16, check = `SPECIES.every`, id не менять — старые сейвы).
|
||||
- Сложность вываживания: `updateReel()`.
|
||||
- Физика боя (спринт 4): `fishForce()` (сила рыбы: рывок `(16+34·st)·(0.5+0.9·ag)·(0.7+0.5·ov)`, затишье `5+7·ag`, уставшая ×0.45) и `updateReel()` — выносливость `st` (старт `st0`, флаг `tired` при `st≤0.12`: рывки ×0.45, втягивание быстрее до ×1.6), тормоз катушки (черта `drag` в `RODS`: в рывке выше тормоза леска скользит `over·0.22`), натяжение (`10+over·1.1+22·ag`, ×0.35 в затишье), втягивание `(11+3·reel)·(1+0.6·(1−st))`, свободный бег `F·0.32`, escape-бар растёт только при затишье без удержания (отпускание в рывок безопасно), near-miss `1.45·d0`, `d0=45+7·w`. Пустые клёвы: ролл `biteChance()` в ветке WAIT (тест-форс `forceBite`). Тесты (§10) завязаны на эти константы — при ребалансе гонять Monte-Carlo точными формулами (docs/PHYSICS-RESEARCH.md, §4.7) и править тесты в том же коммите.
|
||||
- Награды (M2): шаблоны квестов `QUEST_TPLS`, награды стрика `STREAK_REWARDS`, достижения `ACHIEVEMENTS` — секция «M2. Награды» после сейва. Этап 22: ачивок 29 (идут `ACHIEVEMENTS`-записями по темам: снасти у экономики, варианты/погода/вес/ночь у рыболовных, скины/локации у магазинных); новые счётчики сейва `save.kgTotal`/`nightCatch`/`wxRainV`/`wxFog` (чтение через `||0` — без миграции) ставятся в `catchFish()` до `checkAchievements()` (rain-счётчик — только вариант ≠ normal, босс всегда normal); тест-пин §10c(8): сумма `achBonus().coinPct` (все 8 видов × 8 вариантов) = 0.16.
|
||||
|
||||
Reference in New Issue
Block a user