177 lines
13 KiB
Markdown
177 lines
13 KiB
Markdown
# План: ребаланс прогрессии и экономики (Этап 53, в работе)
|
||
|
||
Статус: **реализован (Этап 53)** — см. запись «Этап 53» в `docs/DEVLOG.md`.
|
||
Финальные цены: Стекло/Червь 150/100, Карбон/Воблер 500/2000, Титан/Блёстка 30000/22000;
|
||
апгрейды 20/50/100 и 15/40/80, `UPG_MULT` 0.15/0.35/0.6; Озёра 500, Болото 10000,
|
||
Море 100000, Океан 300000. Веса Болота — день `4/32/3/6/7`, ночь `4/28/3/10/3`
|
||
(per-catch 133.9/162.5). Квесты масштабируются по `save.earned`. Тело плана ниже —
|
||
историческая фиксация решения. Ссылки на строки — на момент составления плана.
|
||
Ориентир по коду: `index.html` ~5608 строк.
|
||
|
||
## 1. Задача
|
||
|
||
Ранняя игра должна быстро давать апгрейды (2-я удочка/приманка и первая новая локация),
|
||
дальше прогресс должен **плавно замедляться** без «застревания», а поздние цели — занимать
|
||
несколько игровых сессий (ориентир: 15 минут в день × 2–3 дня на удочку «Титан»).
|
||
|
||
Дополнительно: ежедневные задания должны масштабироваться по прогрессу игрока, чтобы
|
||
оставаться осмысленными и не доминировать на поздних этапах.
|
||
|
||
## 2. Зафиксированные решения (ответы владельца)
|
||
|
||
| Развилка | Решение |
|
||
|---|---|
|
||
| Темп раннего этапа | 2-я удочка + 2-я приманка + Озёра ≈ 4–6 минут (гарантированно < 5 мин по опыту) |
|
||
| Что меняем | **Только цены снастей/локаций** + веса рыб Болота + логика квестов. Доходность остальных вод не трогаем |
|
||
| Гейт лавки | Оставляем «предыдущая снасть на 4 ур.», но сильно удешевляем апгрейды |
|
||
| Локации | Озёра 500 · Болото 5 000 · Море 100 000 · Океан 200 000 |
|
||
| Болото | Перебалансировать веса рыб, чтобы доходность стала **примерно как у Озёр** (~194/249 🪙) |
|
||
| Титан | ~1 час игры, апгрейды Титана — опциональны и в расчёт до Моря не входят |
|
||
| Море / Океан | ~2 часа / ~4 часа игры (задаётся ценой; проверить `progression.mjs`) |
|
||
| Ежедневные задания | Масштабировать **все** шаблоны; метрика прогресса — `save.earned` |
|
||
| Стартовый капитал | Не выдаём |
|
||
|
||
## 3. Целевая кривая прогрессии
|
||
|
||
Времена — накопительные от старта сессии, фаза — самая выгодная доступная вода.
|
||
|
||
| # | Цель | Когда | Цена | Текущая цена |
|
||
|---|---|---|---|---|
|
||
| 1 | Дедова удочка 1→4 ур. | ~1 мин | апгрейды 20/50/100 | 70/210/500 |
|
||
| 2 | Стеклопластик + Червь | ~2–3 мин | 150 + 100 | 875 + 625 |
|
||
| 3 | **Озёра** | < 5 мин | **500** | 65 536 |
|
||
| 4 | Карбон + Воблер | 5–10 мин | 500 + 300 | 4 500 + 3 000 |
|
||
| 5 | **Болото** | +15 мин после Карбона и 2-й приманки | **5 000** | 90 000 |
|
||
| 6 | Блёстка | ~40–50 мин | 22 000 | 11 250 |
|
||
| 7 | **Титан** (без апгрейдов) | ~1 час | 30 000 | 15 000 |
|
||
| 8 | Апгрейды Титана/Блёстки (опция) | 1–2 ч | из `UPG_MULT` | — |
|
||
| 9 | **Море** | ~2 часа | **100 000** | 131 072 |
|
||
| 10 | **Океан** | ~4 часа | **200 000** | 196 608 |
|
||
|
||
Порядок вод по цене сохраняется: Озёра (500) < Болото (5 000) < Море (100 000) < Океан (200 000).
|
||
|
||
## 4. Цены (первый проход)
|
||
|
||
| Константа | Где | Сейчас | Стало |
|
||
|---|---|---|---|
|
||
| `RODS` cost | `index.html:2226-2230` | 0 / 875 / 4500 / 15000 | **0 / 150 / 500 / 30000** |
|
||
| `LURES` cost | `:2232-2237` | 0 / 625 / 3000 / 11250 | **0 / 100 / 300 / 22000** |
|
||
| `ROD_UPG_COST` | `:2240` | 70 / 210 / 500 | **20 / 50 / 100** |
|
||
| `LURE_UPG_COST` | `:2241` | 60 / 160 / 400 | **15 / 40 / 80** |
|
||
| `UPG_MULT` | `:2242` | 0.2 / 0.6 / 1.2 | **0.15 / 0.35 / 0.6** |
|
||
| Озёра `cost` | `:2088` | 65536 | **500** |
|
||
| Болото `cost` | `:2097` | 90000 | **5000** |
|
||
| Море `cost` | `:2091` | 131072 | **100000** |
|
||
| Океан `cost` | `:2094` | 196608 | **200000** |
|
||
|
||
Апгрейды id>0 считаются `upgCost()` (`:2250`) от новой базы — формула не меняется.
|
||
|
||
**Калибровка `progression.mjs`** (what-if с ценами выше и весами Болота из раздела 5):
|
||
|
||
| Цель | Модель | Целевое | Комментарий |
|
||
|---|---|---|---|
|
||
| Стеклопластик | 4.5 мин | < 5 мин | ок |
|
||
| Озёра | 8.1 мин (3.6 после Стекло) | < 5 мин после Стекло | ок |
|
||
| Карбон | 7.1 мин | 5–10 мин | ок |
|
||
| Болото (цена 5000) | 14.2 мин | +15 мин после Карбона/Воблера | от Карбона 6.7 мин — **мало**; под 15 мин цена ≈ **12 000** |
|
||
| Титан | 32.5 мин (44 мин при Болоте 12000) | 2–3 дня × 15 мин = 30–45 мин | ок для чистой игры |
|
||
| Море | 1 ч 37 мин (при Болоте 12000 ≈ 1 ч 46) | ~2 ч | близко |
|
||
| Океан | 2 ч 48 мин (при Болоте 12000 ≈ 2 ч 57) | ~4 ч | **мало**; при необходимости поднять цену |
|
||
|
||
Модель — «идеальный» игрок и оптимистична (реальная игра медленнее на промахи/меню),
|
||
поэтому реальные времена будут выше модельных — цели по реальной игре могут сойтись.
|
||
Итог по цене Болота: **5000 даёт ~7 мин**, для целевых 15 мин нужно ~**12 000** (уточнить у владельца).
|
||
|
||
## 5. Веса рыб Болота (снизить доход до уровня Озёр)
|
||
|
||
Цель: `SWAMP_*_WEIGHTS` дают день ≈194 / ночь ≈249 🪙 (как Озёра). Текущие 240.3/328.9.
|
||
Двигаем **доли** (умножение всех весов доход не меняет). Подобраны точные векторы:
|
||
|
||
| Таблица | glowfin | moonfish | emberfin | violetlure | spiritfin | E, 🪙 |
|
||
|---|---|---|---|---|---|---|
|
||
| `SWAMP_DAY_WEIGHTS` | 8 | 5 | 28 | 8 | 8 | **194.1** |
|
||
| `SWAMP_NIGHT_WEIGHTS` | 4 | 8 | 12 | 14 | 3 | **249.0** |
|
||
|
||
Все веса ≥3 (тест «каждый вид ≥1» за 3000 роллов с запасом). Ночь богаче долей
|
||
`violetlure` (14 против 8), день — долей `emberfin`. Финал сверить
|
||
`node tools/balance.mjs` после правки.
|
||
|
||
**Важно (расхождение метрик):** per-catch E совпадает с Озёрами, но **🪙/мин у Болота всё
|
||
равно выше** (~1800 против ~1400, `tools/progression.mjs`): болотная рыба легче и бой
|
||
короче, цикл быстрее. Если владелец имел в виду паритет именно по 🪙/мин, веса Болота
|
||
нужно опустить сильнее (≈−25%) — уточнить.
|
||
|
||
**Внимание:** это ломает инвариант `balance.mjs` «каждая новая (по цене) вода доходнее
|
||
предыдущей в ОБЕ фазы» (Болото/Озёра станет ≈1.0). Инвариант и пины в шапке `balance.mjs`
|
||
обновить осознанно.
|
||
|
||
## 6. Ежедневные задания с масштабированием
|
||
|
||
- Метрика `P = save.earned` (только доход с рыбалки; награды квестов его не разгоняют).
|
||
- `questScale() = clamp(round((P/2000)^0.6), 1, 30)`.
|
||
- `QUEST_TPLS` (`:2488`) — масштабируем все:
|
||
- `earn_coins`: `goal = base(150/250/400)·scale`, `reward = round(goal·0.25)`;
|
||
- `casts`: `goal = base(8/10/15)·(1+scale·0.15)`;
|
||
- `catch_species`: вид — из текущей воды (`SPECIES_BY_LOCATION[save.location]`), цель 3–5;
|
||
- `catch_weight`: `param` — от медианного веса рыб воды (`localMedianW()`), не 2/3/5 кг;
|
||
- `catch_rarity`: `param = clamp(1+floor(log10(scale+1)), 1, 4)`;
|
||
- `catch_shiny`: цель 1, растёт награда.
|
||
- Итог: 3 квеста/день ≈ 5–10 минут текущего дохода на любом этапе.
|
||
|
||
## 7. Инструмент `tools/progression.mjs` (новый)
|
||
|
||
По образцу `tools/balance.mjs` — чистое чтение `index.html`:
|
||
|
||
- вырезает данные (`SPECIES`, таблицы локаций, `VARIANTS`, `RODS`, `LURES`,
|
||
`ROD/LURE_UPG_COST`, `UPG_MULT`, `LOCATIONS`);
|
||
- моделирует улов: `pickSpecies` + `rollWeight` (стат `size`) + ожидаемый множитель
|
||
вариантов (буст `rare`) + **обрыв, если `w > rod.maxW`**;
|
||
- время цикла: `biteChance` (`:2974`), таймер клёва (`:3178`), `fishForce`/`updateReel`
|
||
(`:3021`/`:3043`) — бот «держать в затишье, отпускать в рывке»;
|
||
- жадный путь покупок по маршруту (по умолчанию — цели раздела 3) → печатает
|
||
доход по этапам (`🪙/мин`) и **ETA каждой цели**;
|
||
- флаги `--rod/--lure/--loc/--rod-upg/--lure-upg/--upg-mult` (what-if), `--start-coins`,
|
||
`--per-day <мин>`, `--route`, `--help`.
|
||
|
||
## 8. Карта изменений по коду (`index.html`)
|
||
|
||
| Что | Где | Правка |
|
||
|---|---|---|
|
||
| Цены снастей/апгрейдов | `:2226-2242` | новые числа (раздел 4) |
|
||
| Цены локаций | `:2084-2100` | новые числа (раздел 4) |
|
||
| Веса Болота | `:2148-2149` | новые `SWAMP_DAY/NIGHT_WEIGHTS` (раздел 5) |
|
||
| Квесты | `:2488-2501` | `questScale()`, масштаб goal/reward, `localMedianW()` |
|
||
| i18n подписи | `T` | при необходимости — подписи новых шаблонов |
|
||
|
||
**Не трогаем:** `catchFish()`/экономику улова, доходность Реки/Озёр/Моря/Океана,
|
||
физику боя, формат сейва (новых персистентных полей нет).
|
||
|
||
## 9. Тесты (`tests/test.js`) — в том же коммите
|
||
|
||
- M5: `:1271-1272` (`'875 🪙'/'625 🪙'`), `:1379-1380` (покупка Стеклопластика и остаток),
|
||
`:1383-1387` (апгрейд), `:1390-1397` (строка `upgCost`).
|
||
- lc1: `:2035` (`costs` → `0,500,100000,200000,5000`).
|
||
- lc8: `:2240-2338` (остатки монет при покупках).
|
||
- Новые: `questScale`/масштаб `QUEST_TPLS`, `localMedianW`.
|
||
- `balance.mjs`: обновить пины Болота (и, при решении, инвариант).
|
||
|
||
## 10. Проверка (порядок команд)
|
||
|
||
1. `node tools/check.mjs`
|
||
2. `node tools/balance.mjs` — Болото в цели, остальные пины не сдвинуты
|
||
3. `node tools/progression.mjs` — ETA целей совпадают с разделом 3
|
||
4. `cd tests && npm test` — все PASS, exit 0
|
||
5. Плейтест первых 5 минут + симуляция «15 мин/день × 2–3 дня»
|
||
6. При релизе: `node tools/minify.mjs`
|
||
|
||
## 11. Риски и открытые вопросы
|
||
|
||
1. **Болото ≈ Озёра** ломает инвариант «дороже вода = доходнее» — принято осознанно.
|
||
2. **Море/Океан дают меньше 🪙/мин, чем Озёра/Болото** (длиннее бой, ниже доля
|
||
удержания) — это существующая особенность баланса рыб; задаём только цену.
|
||
Отдельная задача, если владелец захочет поднять их доход.
|
||
3. **Разброс RNG** (варианты/золотая рыбка) — «< 5 мин» гарантируется с запасом
|
||
квестами первого дня; строгого детерминизма не будет.
|
||
4. Точные цены Моря/Океана (100000/200000) — по решению владельца; `progression.mjs`
|
||
покажет итоговые ETA, при расхождении — скорректировать.
|