From 812c65bd908cd6882ab2a0ed8f5388522e64efda Mon Sep 17 00:00:00 2001 From: andrey Date: Fri, 18 Sep 2026 20:10:15 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D1=85=D0=BE=D0=B4=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D1=8C=20=D0=9E=D0=B7=D1=91=D1=80=20100+=20?= =?UTF-8?q?=F0=9F=AA=99=20(=D0=AD=D1=82=D0=B0=D0=BF=2034):=20LAKE=5F*=5FWE?= =?UTF-8?q?IGHTS=20=E2=80=94=20=D1=81=D0=B4=D0=B2=D0=B8=D0=B3=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=BB=D0=B5=D0=B9=20=D0=B2=20=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D1=83=20=D0=B4=D0=BE=D1=80=D0=BE=D0=B3=D0=BE=D0=B9=20?= =?UTF-8?q?=D1=80=D1=8B=D0=B1=D1=8B,=20=D0=B4=D0=B5=D0=BD=D1=8C=2084.7?= =?UTF-8?q?=E2=86=92110.4=20(=C3=971.70=20=D1=80=D0=B5=D0=BA=D0=B8),=20?= =?UTF-8?q?=D0=BD=D0=BE=D1=87=D1=8C=20122.2=E2=86=92145.5=20(=C3=971.16=20?= =?UTF-8?q?=D1=80=D0=B5=D0=BA=D0=B8).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Пользователь предлагал «просто увеличить вес озёрных рыб», но pickSpecies() нормирует веса (шанс = w/total из тех же w), поэтому ожидаемая выручка за улов = Σ(w·V)/Σw (V — середина диапазона веса × цена) инвариантна к умножению всех весов на константу: масштабирование дало бы ровно те же 84.7. Заявленный эффект достигнут тем же инструментом — правкой двух озёрных таблиц, но сдвигом ДОЛЕЙ: вниз размыватели carass 60→55 (V≈9 🪙, был 21% всех роллов) и bleak 30→18 (V≈6), плюс bream 30→24, perch 40→36, chuch 22→18, roundel 18→12, carp 25→24; вверх дорогая рыба — sturge 3.5→5, gold 1.6→2.2, tench 10→14, catfish 8→10, navaga 2.5→3.4, zander 14→16, pike 12→14, crayfish 2→2.4. Попутно исправлено расхождение, которое комментировалось как норма: ночью Озёра были УБЫТОЧНЕЕ ночи Реки (122.2 < 125.9) при «смещении к хищникам». Ночная таблица выправлена в том же направлении — perch 70→60, carass 25→22, bream/chuch 10→9, tench 8→11, zander 18→20, catfish 16→18, sturge 4.5→6, gold 1.6→2.2, crayfish 2.5→2.6, navaga 2→2.4. Река не тронута (RIVER_IDS, weight в SPECIES, NIGHT_WEIGHTS) — роллы реки прежние, pin lc3 цел. Пол редких видов не тронут вниз: минимальный вес 2.2 (gold/navaga/crayfish) — за 3000 роллов ожидается ≥25 попаданий против ~20 у gold раньше, так что lc4 («каждый вид ≥1», где из-за отсутствия аргумента не действует штраф minDist) проходит с вероятностью провала ~e⁻²⁵ вместо прежнего меньшего запаса. Ниже ~2 в этих таблицах опускать нельзя — зафиксировано в AGENTS.md/KODA.md. Тесты: конкретных значений озёрных весов пинов нет (lc2 — длина 16 и «вес — число», lc4 — факт выпадения), правка таблиц не потребовала правок тестов: 178/178 PASS, exit 0; check.mjs OK; pack.mjs + pack-smoke 6/6 (115.5 КБ). Скриншоты не перегенерированы осознанно: кадры рила и карточки форсируют sturge в gen-screenshots.js, остальные от весов не зависят. Доки: DEVLOG — «Этап 34» (инвариантность к масштабу, полный список весов, ночное расхождение, пол 2.2), AGENTS.md и KODA.md — правило «дороже = сдвиг долей, а не масштаб» + текущие ориентиры Озёра 110.4/145.5 против Реки 65.1/125.9 и минимальный вес ~2.2; README — Озёра «улов в ~1.2–1.7 раза доходнее Реки». --- AGENTS.md | 1 + README.md | 2 +- docs/DEVLOG.md | 13 +++++++++++++ index.html | 14 +++++++++++--- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index adec243..e4c51a1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -40,6 +40,7 @@ - Погода (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)` — все 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 не менять — старые сейвы). +- **Баланс Озёр (этап 34):** ожидаемая выручка за улов = Σ(w·V)/Σw, V — середина диапазона веса × цена. `pickSpecies()` нормирует веса, так что **умножение всех весов на константу доход НЕ меняет** — для «стало дороже» правят СДВИГ долей (меньше `carass`/`bleak` — самые дешёвые V≈9/6 🪙, больше `sturge`/`gold`/`catfish`/`tench`/`navaga`). Текущие ориентиры: Озёра день 110.4 / ночь 145.5 🪙, Река день 65.1 / ночь 125.9 (Озёра доходнее в обе фазы — проверять при любой правке `LAKE_*_WEIGHTS`). **Минимальный вес вида ≥ ~2.2**: ниже — тест lc4 (3000 роллов, «каждый вид ≥1») начинает плавать. - Сложность вываживания: `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. diff --git a/README.md b/README.md index ddb6d2b..a437cb2 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ - Варианты рыб (особая рыба ≈31%): медная ×1.5, серебряная ×2, кварцевая ×2.5, золотая ×3, изумрудная ×4, алмазная ×4.5, радужная ×5 (топ, самая редкая) — бейдж и оформление карточки улова; снасть усиливает шанс (тип наживки и её уровень — редким вариантам прибавка больше, топ-снасть ≈×5 к шансу радужной) - Погода: дождь (🌧️) — шанс особых рыб ×3; туман (🌫️) — клёв ×1,5; событие идёт 120 с, следующее — раз в 2–4 минуты — дождь - Скины лодки и поплавка 🎨 — вкладка «Скины» в лавке: лодка «Красная лодка» 800 🪙 / «Лодка-домик» 2000 🪙, поплавок «Красный» 500 🪙 / «Неоновый» 1500 🪙 — чистая косметика (без эффектов на геймплей) -- Локации: Озёра (100 000 🪙) — судак, хариус, гигантский рак; свой состав днём/ночью, свой цвет воды; покупка и переключение во вкладке 🗺️ лавки — озёра +- Локации: Озёра (100 000 🪙) — судак, хариус, гигантский рак; свой состав днём/ночью, свой цвет воды, улов в ~1.2–1.7 раза доходнее Реки; покупка и переключение во вкладке 🗺️ лавки — озёра - Квесты дня (3 шт, генерация по дню), стрик входов со «щитом», 29 достижений с бонусами - Дневник рыбака — коллекция, максимальный улов по каждому виду, статистика - Магазин с вкладками: Лавка 🛒, Дневник 📔, Награды 🎯, Достижения 🏅, Скины 🎨, Локации 🗺️ diff --git a/docs/DEVLOG.md b/docs/DEVLOG.md index a928b13..f0b1437 100644 --- a/docs/DEVLOG.md +++ b/docs/DEVLOG.md @@ -643,3 +643,16 @@ git add -A && git commit -m "что изменилось" && git push **Тесты:** lc1 — `SPECIES.length` 11→16, пины параметров пяти новых видов, порядок (`slice(0,8)` не сдвинут, `slice(8)` — ровно 8 озёрных) и заполненность всех полей (включая `nameEn` — иначе EN-ветка `trName()`); lc2 — `LAKE_SPECIES(_NIGHT)` 11→16, `SPECIES_NIGHT.length` 16 + веса числа; lc3 — без изменений (Река = старые 8); lc4 — текстовка «все 16» (состав берётся из `SPECIES.map`, подстраивается сам); lc9 — строк дневника 11→16; lc10 — сетап «+3 новых» → «+8 озёрных». Итого **178/178 PASS, exit 0**. **Флейка, которую стоит помнить:** lc4 вызывает `pickSpecies()` **без аргумента** → `dist = undefined`, `undefined < s.minDist` === false, штраф ×0.06 не применяется. На «каждый вид ≥1 за 3000 роллов» влияет **только вес** — новому озёрному виду нужен вес ≥ ~2 в обеих озёрных таблицах (у navaga 2.5 / 2). + +## Этап 34. Доходность Озёр 100+ 🪙 (веса) + +**Задача:** «для озёр доходность желательно 100+, предлагаю просто увеличить вес рыб озёрных». + +**Решения:** +- **Масштаб весов доход не меняет.** `pickSpecies()` нормирует веса (шанс = `w / total`, где `total` — сумма тех же `w`), поэтому ожидаемая выручка за улов (середина диапазона веса × цена, взвешенная по вероятностям) инвариантна к умножению ВСЕХ весов на константу: «просто увеличить все веса» дало бы ровно те же 84.7 🪙. Поднят **сдвиг долей** в пользу дорогой рыбы — заявленный эффект достигнут тем же инструментом (правкой `LAKE_*_WEIGHTS`). +- **Убраны размыватели, поднята дорогая рыба (день):** `carass` 60→55 (выручка ≈9 🪙, был 21% всех роллов) и `bleak` 30→18 (≈6 🪙) — главные «копейки» Озёр; вверх `zander` 14→16, `catfish` 8→10, `pike` 12→14, `tench` 10→14, `navaga` 2.5→3.4, `sturge` 3.5→**5**, `gold` 1.6→**2.2**, `crayfish` 2→2.4; вниз `bream` 30→24, `perch` 40→36, `chuch` 22→18, `roundel` 18→12, `carp` 25→24. +- **Ночь Озёр была убыточнее ночи Реки** (122.2 против 125.9 🪙) — вопреки комментарию про «ночное смещение к хищникам». Исправлена тем же сдвигом: `perch` 70→60, `carass` 25→22, `bream`/`chuch` 10→9, `tench` 8→11, `zander` 18→20, `catfish` 16→18, `sturge` 4.5→**6**, `gold` 1.6→**2.2**, `crayfish` 2.5→2.6, `navaga` 2→2.4. +- **Итог:** Озёра **день 84.7 → 110.4** 🪙 (×1.70 к дневному руслу реки 65.1), **ночь 122.2 → 145.5** (×1.16 к ночной реке 125.9). Река не тронута (`RIVER_IDS`, `SPECIES.weight`, `NIGHT_WEIGHTS`). +- **Пол редких видов сохранён:** минимальный вес 2.2 (`gold`/`navaga`/`crayfish`) — за 3000 роллов ожидается ≥25 попаданий (у `gold` раньше было ~20). Тест lc4 («каждый вид ≥1») проходит с вероятностью провала ~e⁻²⁵; ниже ~2 опускать нельзя (флейка выше: штраф `minDist` в тесте не действует). + +**Тесты:** конкретных значений озёрных весов никто не пинит (lc2 — только длина 16 и «вес — число», lc4 — факт выпадения всех видов), правка таблиц не потребовала правок тестов: **178/178 PASS, exit 0**; `check.mjs` OK; `pack.mjs` + `pack-smoke` 6/6 (115.5 КБ). Скриншоты перегенерированы не нужны: кадр рила и карточка форсируют `sturge` в `gen-screenshots.js`, остальные кадры от весов не зависят. diff --git a/index.html b/index.html index 4be6b9f..5bdf040 100644 --- a/index.html +++ b/index.html @@ -404,9 +404,17 @@ const RIVER_SPECIES_NIGHT=SPECIES_NIGHT.filter(s=>RIVER_IDS.indexOf(s.id)>=0); LAKE_NIGHT_WEIGHTS — правьте ночные озёра здесь. Этап 33: +пять новых видов (bleak/roundel/eelpout/tench/navaga) и подъём дорогой рыбы (gold 1.2→1.6, sturge 3→3.5/4.5, crayfish 1.5→2/2.5) — иначе мелочь размывает доход Озёр: - E[выручка/улов] 91.9→73.5 🪙, с подъёмом 84.7 (Река для сравнения 65.1) */ -const LAKE_DAY_WEIGHTS={carass:60,perch:40,bream:30,carp:25,zander:14,chuch:22,pike:12,catfish:8,crayfish:2,sturge:3.5,gold:1.6,bleak:30,roundel:18,eelpout:6,tench:10,navaga:2.5}; -const LAKE_NIGHT_WEIGHTS={carass:25,perch:70,bream:10,carp:8,zander:18,chuch:10,pike:24,catfish:16,crayfish:2.5,sturge:4.5,gold:1.6,bleak:14,roundel:10,eelpout:12,tench:8,navaga:2}; + E[выручка/улов] 91.9→73.5 🪙, с подъёмом 84.7 (Река для сравнения 65.1). + Этап 34: доход Озёр поднят до 100+ 🪙. Средневзвешенный доход Σ(w·V)/Σw НЕ зависит от + общего масштаба весов — «увеличить все веса» дохода не даёт, поэтому поднят именно + СДВИГ ДОЛЬ в пользу дорогой рыбы: carass 60→55 и bleak 30→18 (главные размыватели, + V=9 и 6 🪙), carp/zander/pike/catfish/tench вверх, sturge 3.5→5/6, gold 1.6→2.2. + Стало день 110.4 (×1.70 дневной реки 65.1), ночь 145.5 (×1.16 ночной реки 125.9); + раньше ночью Озёра были УБЫТОЧНЕЕ ночи Реки (122.2 < 125.9) — исправлено. + Пол редких видов: минимальный вес 2.2 (gold/navaga/crayfish) — за 3000 роллов ожидается + ≥25 попаданий, тест lc4 («каждый вид ≥1») проходит с огромным запасом */ +const LAKE_DAY_WEIGHTS={carass:55,perch:36,bream:24,carp:24,zander:16,chuch:18,pike:14,catfish:10,crayfish:2.4,sturge:5,gold:2.2,bleak:18,roundel:12,eelpout:6,tench:14,navaga:3.4}; +const LAKE_NIGHT_WEIGHTS={carass:22,perch:60,bream:9,carp:9,zander:20,chuch:9,pike:24,catfish:18,crayfish:2.6,sturge:6,gold:2.2,bleak:12,roundel:9,eelpout:12,tench:11,navaga:2.4}; const LAKE_SPECIES=SPECIES.map(s=>Object.assign({},s,{weight:LAKE_DAY_WEIGHTS[s.id]})); const LAKE_SPECIES_NIGHT=SPECIES.map(s=>Object.assign({},s,{weight:LAKE_NIGHT_WEIGHTS[s.id]}));