Новые виды добавлены СТРОГО в конец 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).
🎣 Рыбалка
Браузерная мобильная игра про рыбалку. Один HTML-файл, без зависимостей — просто открой в браузере и играй.
| Меню | Лавка | Вываживание | Улов |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
Как играть
Управление одним пальцем (вертикальный экран):
- Держи палец — заряжается мощность броска, отпусти — кидаешь удочку. Чем дальше, тем реже, но ценнее рыба.
- Когда поплавок нырнул и появилась «!» — быстро нажми экран, чтобы зацепить. У редких рыб окно на подсечку всего доли секунды.
- Вываживание: держишь палец — втягиваешь, но растёт нагрузка на шнур (жёлтая полоса справа). Рыба периодически тянет (⚡, с вибрацией) — в этот момент отпускай: леска проскальзывает через тормоз катушки, и теряешь только дистанцию. Полоса снизу — оставшаяся дистанция: доведи рыбку до лодки. Чем крупнее рыба, тем сильнее рвёт и дольше тянет. И не зависай без удержания — рыба сойдёт.
- У каждой рыбы свой вес, продажа — по цене за кг своего вида (от 20 до 1500 🪙/кг). Крупная рыба = большие деньги.
- У удочек есть предел веса (3–40 кг): зацепишь более тяжёлую — шнур лопнет почти мгновенно. Чем лучше удочка и приманка, тем выше шанс зацепить крупную. Новый максимум по виду отмечен бейджем «🏆 РЕКОРД!» на карточке улова.
- На монеты — новые удилища и приманки в лавке 🛒 (кнопка 🛒 в HUD или клик по счётчику монет).
- Награды 🎯: три квеста дня (уловы, монеты, забросы) с наградой за выполнение; стрик входов — ежедневная награда растёт до дня 7, «щит» прощает один пропуск в неделю; 29 достижений 🏅 с постоянными бонусами (+% к монетам, окно подсечки, нагрузка шнура).
- День/ночь: полный цикл суток ~5 минут (утро → день → вечер → ночь). Ночью свой состав рыб — сом, щука и окунь активнее, но без 🪯 фонарика клёва не будет — фонарик дают апгрейды удилищ (1-й апгрейд любого удилища).
- Осётр-босс: при поимке осётра есть шанс встретить босса. Бой идёт в 3 фазы — босс «рвёт и уходит», и каждая следующая фаза глубже; удерживай, чтобы втащить. Награда ×5 к цене.
- Симулятор боёв (релиз 5): у рыбы есть выносливость — тонкая фиолетовая полоска под дистанцией: свежая рыба тянет долго и сильно, а уставшая (💤) вянет — втягивай её именно тогда. У катушек — тормоз (drag): рывок сильнее тормоза — леска скользит. Иногда поплавок не берёт вовсе — пустой клёв, подожди ещё немного.
Возможности
- 16 видов рыб с собственным весом (0.05–40 кг) и ценой за кг (5 уровней редкости): Река — 8 базовых, Озёра — все 16 (судак, хариус, гигантский рак, плотва, густера, вьюн, линь, навага)
- Удилища: предел веса, прочность шнура, скорость подсечки, бонус на крупную рыбу
- Приманки: частота клёва, дальность броска, шанс редких и крупных
- Физика боя: выносливость рыбы (уставшая 💤 вянет и втягивается быстрее), тормоз катушки (drag) — сильнейший рывок проскальзывает, пустые клёвы
- Цикл дня и ночи (~5 мин на сутки): ночью своя таблица рыб (сом/щука/окунь активнее), ночью нужен 🪯 фонарик — апгрейд 1 удилища
- Апгрейды снастей: удилища и приманки улучшаются до 4 уровня (свет фонарика, крепость лески, тормоз, катушка, клёв, редкие и крупные рыбы); следующая снасть в лавке открывается после 4 уровня предыдущей
- Босс-рыба — Осётр-босс (шанс при поимке осётра): 3 фазы «рвёт и уходит», награда ×5, достижение «Босс-рыбак»
- Варианты рыб (особая рыба ≈31%): медная ×1.5, серебряная ×2, кварцевая ×2.5, золотая ×3, изумрудная ×4, алмазная ×4.5, радужная ×5 (топ, самая редкая) — бейдж и оформление карточки улова; снасть усиливает шанс (тип наживки и её уровень — редким вариантам прибавка больше, топ-снасть ≈×5 к шансу радужной)
- Погода: дождь (🌧️) — шанс особых рыб ×3; туман (🌫️) — клёв ×1,5; событие идёт 120 с, следующее — раз в 2–4 минуты —

- Скины лодки и поплавка 🎨 — вкладка «Скины» в лавке: лодка «Красная лодка» 800 🪙 / «Лодка-домик» 2000 🪙, поплавок «Красный» 500 🪙 / «Неоновый» 1500 🪙 — чистая косметика (без эффектов на геймплей)
- Локации: Озёра (100 000 🪙) — судак, хариус, гигантский рак; свой состав днём/ночью, свой цвет воды; покупка и переключение во вкладке 🗺️ лавки —

- Квесты дня (3 шт, генерация по дню), стрик входов со «щитом», 29 достижений с бонусами
- Дневник рыбака — коллекция, максимальный улов по каждому виду, статистика
- Магазин с вкладками: Лавка 🛒, Дневник 📔, Награды 🎯, Достижения 🏅, Скины 🎨, Локации 🗺️
- Прогресс и коллекция сохраняются в
localStorage(старые сейвы мигрируются автоматически) - Ночь: свой состав рыб и тёмная вода при
dayTime=0.85—
- Клик по монетам в HUD открывает лавку на вкладке «Лавка» 🛒
- Звуки на WebAudio, вибрация на телефоне
- Локализация RU/EN — язык определяется автоматически через SDK Яндекс Игр (
ysdk.environment.i18n.lang); меню адаптируется под устройство (тач/мышь) - Кнопка паузы (⏸ в HUD) — пауза игры и звука («Продолжить»/«В меню» → хаб «Меню»); звук/игра также ставятся на паузу при потере фокуса окна
- Вся графика нарисована на Canvas — внешних ресурсов нет
Документация
📋 Процесс разработки — этапы (ТЗ → прототип → автотесты → публикация), инструменты, найденные баги, гигиена секретов и как развивать игру дальше.
Запуск
Просто открой index.html в браузере (десктоп или телефон). Для локальной разработки:
python3 -m http.server 8000
# → http://localhost:8000
Публикация в Яндекс Играх
Архив для платформы (только index.html в корне архива, с самопроверкой — набор файлов, размер, имена, sha256, синтаксис JS):
node tools/pack.mjs # → dist/fishing-yandex.zip
node tests/pack-smoke.js # перед загрузкой в консоль: smoke упакованной копии (игра из архива, 6 проверок)
SDK подхватывается автоматически на площадке; локально (file://) игра работает без него (встроенный стаб). Локальная отладка с SDK: открыть игру с параметром ?sdk=1 и положить sdk.js рядом с игрой (или поднять локальный прокси SDK Яндекса). В консоли разработчика (games.yandex.ru): включить монетизацию, опция облачных сейвов — выключена (игра сама хранит сейв в localStorage), платформы — без Android TV, debug-mode=16 — для проверки лоадера.
Тесты
Автотест прогоняет весь геймплей (бросок, подсечка, все исходы вываживания, магазин, дневник, сохранение, варианты рыб (медь/серебро/кварц/золото/изумруд/алмаз/радуга), near-miss, миграция сейва, квесты, стрик, достижения, день/ночь с фонариком, босс-рыба в 3 фазы, SDK-стаб (YG), реклама: RV-бонус и гейты interstitial, i18n (RU/EN), пауза (кнопка + blur/focus окна)) в headless Chromium:
cd tests
npm install # ставит puppeteer-core
node test.js # 162 проверки
Нужен установленный Chromium (executablePath в test.js при необходимости поправить).
Есть и браузерный плейтест «вживую» во встроенном браузере Orca: node tests/orca-playtest.js (из каталога репо, требует запущенный Orca app) — полный геймплей, проверка консоли и pageerror; детали в docs/BROWSER-TESTING.md.
Скриншоты состояний — tests/gen-screenshots.js (headless, 10 кадров × 3 вьюпорта: десктоп 1280×720, мобильный портрет 360×640@2x, мобильный ландшафт 800×450@1.6x, 24-битный PNG без альфа). Без аргументов — русские скриншоты в screenshots-wiki/; с аргументом en — английские в screenshots-wiki-en/. README ссылается на screenshots-wiki/mobp-* (мобильный портрет).



