Keep dist/exe/zip out of git so GitHub no longer rejects the 109 MB build. Co-authored-by: Cursor <cursoragent@cursor.com>
PEAK HOUR 97
Час пик. Одна смена. Ни одного свободного места.
1997 год. Ночной диспетчер узла файлового обмена: принимайте пакеты, раскладывайте файлы-полимино по папкам, собирайте контейнеры запросов, проходите мини-игры и держите SLA. UI — «Kaleidos»: тёплая бумага, тонкие контуры и бирюзовый акцент.
Жанр: менеджмент / тайм-менеджмент, retro UI.
Платформа: Godot 4.7.2 → Web (HTML5, без threads), RU-only.
Окно: 1920×1080, логический viewport 1280×720, fractional scale.
Забег: 9 игровых часов — 120 / 150 / 180 / 210 / 240 / 270 / 300 / 330 /
360 с (120 + 30×(h−1), всего 36 минут) + подготовка между часами.
Статус v3.0
Играбельный веб-прототип полного цикла: меню → подготовка → час → итоги часа → … → итоги забега. Актуальная спецификация — GDD v3.0, решения — DECISIONS (актуальны D45–D61, D01–D44 — история).
Реализовано:
- 9 часов, длительность 120 → 360 с (+30 с за час), старт 50 $,
SLA 60/60 (кап +40 за уровень
lot_slaдо 220), 1 слот (макс. 5), канал 10 (макс. 46), буфер 6 (макс. 12), таймер запроса 30 с (макс. 65), таймер пакета 20 с. - 4 типа файлов-полимино: текст 1, звук 2, фото 3, видео 4 клетки;
поворот
R/ПКМ во время drag; сетка папки 5×4 → 6×4 → 7×5 → 8×5 → 8×6 → 9×6 (до 54 клеток). Новая папка — 180 $, всего до 6. - Стол сортировки 4×6 в подготовке; файлы со стола нельзя прикрепить, на старте часа они автоматически возвращаются в папки (если места нет — час не начинается).
- Запросы на 1–4 конкретных именованных файла: имена видны на карточке
сеткой 2×2, прикрепление проверяется по точному
file_id, потерянный файл помечается «ПОТЕРЯН», обязательные файлы жёстко зарезервированы. H1 стартует с seed-файла и сразу с запроса на него. Отдельногоrequest_capнет: одновременно живут не большеactive_requestsзапросов, новые не появляются в последние 10 с часа; анти-голодание срабатывает только для первого запроса часа, дальше темп задаётsend_interval. - Файлы — каталог, а не расходник: успешная отправка только снимает
привязку к запросу, файл остаётся в папке и может быть затребован снова.
Приход задаётся только скоростью: окно спавна 75 % часа, интервал —
spawn_window / hours[].filesс джиттером ±20 %, без переноса и общего лимита файлов (carry = 0). - 9 лотов магазина; ровно 3 предложения, рероллы 40/80/120 (макс. 3 за
подготовку), замок отдельного предложения. Магазин — с H2 и только в
подготовке. Полное дерево — **8 825
** (было 8 085с 8 лотами), новый лотlot_udp— «UDP-повторитель». - 6 мини-игр отправки (
dots,sound,text,video,photo,maze; 3 ступени) и 4 мини-игры атак (junk,ddos,phishing,ransomware; 4 ступени); без таймеров, с шапкой «название + цель», полосой прогресса и экраном результата: имя игры,q%, полоса качества, вердикт, детали иПРОДОЛЖИТЬ/Esc. - TCP как отдельное соединение: до
ПОДКЛЮЧИТЬСЯфайлы в запрос не прикрепляются. Успех (3 попадания) занимает out-слот, в слоте — имя клиента и случайный IP; мини-игра отправки сама не открывается.ОТПРАВИТЬзапускает её, только когда прикреплены все файлы. После успешной отправки запрос исчезает, файлы возвращаются в папку и остаются доступны новым запросам, выплата начисляется, но TCP-слот остаётся занятым (idle) до ручногоОТКЛЮЧИТЬна слоте. TCP платит ×1.15. - UDP без соединения: время передачи ×0.8, выплата ×0.85, но
успех — ролл в конце передачи: база 40 %, +10 % за уровень
lot_udp, максимум 80 % (цены 60/120/210/350). Провал: −3 SLA, без выплаты и денежного штрафа, файлы не расходуются, запрос остаётся, повтор через 4 с, слот освобождается. Файлы не расходуются ни при успешной отправке, ни при отмене/таймауте/отключении. - Слоты общие для приёма и отправки:
1 + slot_level, максимум 5. TCP-соединение может занять единственный слот и заблокировать приём — это осознанное требование. Открепление файла — двойной клик по чипу. - Шрифты: тело — Kechusilka Regular (нормализован под Golos, fallback Golos Text), крупный текст — DisplayOTF, цифры/счётчики — Press Start 2P; шкала 11/13/17/26.
- «ЖАРА»: в меню-баре вместо часов 03:42 —
TemperatureGauge(216×18, колба, деления, °C); поверх игры —StressOverlayс heat-моделью и alpha-only шейдером без чтения экрана. Пульс SLA/CRIT, тряска панелей ≤2 px, «Снизить эффекты» (reduce_motion) отключает движение; в headless слой скрыт. Анимации карточек, слотов и drag — черезUiMotion(Lane B). - 20 атак за забег (
0,1,1,2,2,3,3,4,4), 4 вида, 4 ступени; атака — это мини-игра, которая ставит час на паузу. Щит «Заземление» гасит атаку автоматически (70 % награды, без штрафа). - Пошаговый туториал v3: 5 шагов (пакет → прикрепление → TCP-соединение →
мини-игра → SLA/атаки), пульсирующие рамки у цели и кнопка «ДАЛЕЕ».
Прохождение хранится в
Game.stats["tutorial_done"]; кнопка «ОБУЧЕНИЕ» в главном меню запускает повтор. - Save VERSION 2: позиции только в
folder.files/table, метаданные вfiles; v1-сейвы мигрируют без потери файлов и без уменьшения сеток; офферы/рероллы/замки, стол иtutorial_doneсохраняются. - Мета-награды после 3/5/9 часов, маскот БАЙТ, UI v3 «Kaleidos», ambient машинного зала, VHS только в главном меню.
Ограничения:
- Сохранение в Web идёт через IndexedDB (
user://save.json); проверяйте продолжение после перезагрузки вкладки. - Средний расход магазина в симуляторе — 44,9 % дерева 8 825 $;
итог 7 205 $ в полосе 6 982–8 500 $, поражений 0/240.
H2, H4 и H5 идут близко к нижней границе −20 % (−16,4 %, −15,3 %, −15,1 %),
поэтому дальше ужесточать темп нельзя. Подробности —
tests/SIM_BALANCE_REPORT.md. - Remote push ещё не выполнен; сборка для itch.io готовится локально.
Управление
| Действие | Ввод |
|---|---|
| Выбор, меню, перетаскивание | ЛКМ |
| Контекстное меню | ПКМ |
| Поворот фигуры во время drag | R или ПКМ |
| Пакет из «Приёма» → папка | drag&drop |
| Файл из папки → карточка запроса | drag&drop (TCP — только после ПОДКЛЮЧИТЬСЯ) |
| Файл ↔ стол сортировки | drag&drop |
| TCP-соединение | кнопка ПОДКЛЮЧИТЬСЯ справа снизу, 3 попадания в зелёную зону |
| Отправка запроса | кнопка ОТПРАВИТЬ слева снизу |
| Отклонить запрос | кнопка ОТКЛОНИТЬ слева снизу |
| Закрыть TCP-соединение | ОТКЛЮЧИТЬ на слоте (мгновенно) |
| Открепить файл от запроса | двойной клик по чипу |
| TCP/UDP | переключатель на карточке запроса до соединения |
| Мини-игра: действие | ЛКМ / Space / стрелки (по игре) |
dots: линия |
нажать на «С» и вести курсор по клеткам |
| Пропустить мини-игру | ПРОПУСТИТЬ/СДАТЬСЯ + второй клик |
| Результат мини-игры | ПРОДОЛЖИТЬ или Esc |
| Магазин: закрыть | ЗАКРЫТЬ или Esc |
| Пауза | Esc |
Запуск
Нужен Godot 4.7.2. Команды выполняются из корня репозитория; ниже
GODOT — путь к бинарю Godot.
# один раз после клона: импорт шрифтов и темы
"$GODOT" --headless --path . --import
# игра
"$GODOT" --path .
# редактор
"$GODOT" -e --path .
В Windows удобно задать путь один раз:
$env:GODOT_BIN = "D:\Apps\godot\Godot_v4.7.2-stable_win64_console.exe"
& $env:GODOT_BIN --path .
Сборка Web
mkdir -p build/web
"$GODOT" --headless --path . \
--export-release "Web" build/web/index.html
Результат: build/web/index.html, index.wasm, index.pck и служебные
.js/.png. Пресет thread_support=false: COOP/COEP не нужны. Локальный
просмотр — только по HTTP:
python -m http.server 8000 --directory build/web
# http://localhost:8000
Нужны export templates 4.7.2 (web_nothreads_release.zip). Каталог шаблонов
должен называться 4.7.2.stable.
Тесты
Актуальный список — полный набор + parse-check в
scripts/run_all_tests.sh / scripts/run_all_tests.ps1 (см. также tests/;
число наборов и проверок может меняться между волнами, поэтому здесь не
хардкодится). Core-наборы (test_hour, test_economy, test_save,
test_slots, test_controller, test_integration, test_fuzz,
test_full_playthrough, test_shop, test_shop_modal) обновлены и зелёные;
UI-наборы (test_main_*, ui_smoke) прогоняются отдельно.
# Windows
powershell -ExecutionPolicy Bypass -File scripts/run_all_tests.ps1
# Linux / macOS
bash scripts/run_all_tests.sh
Windows-раннер сам ищет Godot (сначала GODOT_BIN, затем стандартный путь,
затем godot4/godot из PATH); путь можно передать явно:
-GodotBin <path>.
Точечно:
"$GODOT" --headless --path . --script tests/run_tests.gd
"$GODOT" --headless --path . --script tests/test_fuzz.gd
"$GODOT" --headless --path . --script tests/test_full_playthrough.gd
"$GODOT" --headless --path . --script scripts/ui/ui_smoke.gd
Баланс (240 сидов, отчёт tests/SIM_BALANCE_REPORT.md):
python tests/sim_balance.py
Отчёт tests/SIM_BALANCE_REPORT.md (240 сидов, 9 часов, q=0.85, TCP):
средний итог 7 205 $ (payout 6 344 + recv_fee 177 + атаки 684) в полосе
6 982–8 500 $, расход магазина 3 964 $ (44,9 % дерева 8 825 $),
0 поражений из 240, SLA в конце H9 — 64,9, запросов выполнено — 62,0,
вердикт PASS, exit code 0. H1 income_target — 100 $ (2-минутный
час), H2, H4 и H5 близко к −20 %.
Подробности — в AI_REPORT.
E2E-прогоны на реальной сцене Main и веб-смоук проводились в предыдущей
волне; после изменений TCP/UDP-модели и UI их нужно перепроверить перед
публикацией. Финальный счёт UI-наборов здесь не хардкодится.
Структура
Game-JAM/
├─ project.godot # 1920×1080 / 1280×720, GL Compatibility
├─ export_presets.cfg # Web (no threads)
├─ scenes/ # Main + UI/мини-игры
├─ scripts/
│ ├─ main.gd # UI, ввод, модалки, drag&drop, туториал
│ ├─ game_controller.gd # цикл menu → prep → hour → results
│ ├─ run_all_tests.ps1/.sh # полный headless-прогон
│ ├─ autoload/ # Game, Data, Audio, Rng, Ambient
│ ├─ core/ # HourDirector, FileRegistry, SlotManager, Economy
│ ├─ entities/ # файлы, папки, секции, пакеты, запросы, слоты
│ ├─ systems/ # Shop, AttackDirector, SaveManager
│ ├─ ui/ # Theme90, FileGrid, SortingTable, ShopModal, VHS,
│ │ # TemperatureGauge, StressOverlay, UiMotion
│ └─ minigames/ # MiniGame, factory, connection_game, send/, attack/
├─ data/ # balance.json, strings_ru.json, names_ru.json
├─ art/fonts/ # Kechusilka, DisplayOTF, Golos fallback, Press Start 2P
├─ art/icons/ # пиксельные иконки + generate_icons.py
├─ audio/ # sfx/, music/, amb/, generate_*py
├─ shaders/ # vhs.gdshader (только главное меню)
├─ tests/ # headless-наборы, sim_balance.py
├─ docs/ # GDD, DECISIONS, UI_REFRESH, скриншоты
└─ build/ # артефакты экспорта (gitignored)
Требования
- Godot 4.7.2 (GL Compatibility).
- Для Web: export templates 4.7.2,
web_nothreads_release.zip. - Python 3 — для баланса и пересборки SFX/ambient.
- Никаких секретов и внешних сервисов.
Документация
- GDD — правила и числа v3.0.
- DECISIONS — решения D01–D61 (актуальны D45–D61).
- AI_REPORT — модели, приёмы и проверки.
- ASSETS — шрифты, иконки, звук, лицензии и воспроизведение.
- UI_REFRESH — UI v3 «Kaleidos».
- IMPLEMENTATION и TEST_PLAN — исторические контракты v1 и матрица тестов (v3-дельты — в начале IMPLEMENTATION).
- ITCH_PAGE — текст страницы itch.io.
- screenshots — кадры меню, подготовки, часа и атак.
Лицензии
Код — MIT (LICENSE). Шрифты: Golos Text и Press Start 2P —
SIL OFL 1.1, Kechusilka — лицензия подтверждена владельцем проекта,
DisplayOTF — freeware/personal (Denis A Serikov). UI, пиксельные иконки
(art/icons/) и иконка — MIT. SFX и hum.wav — MIT/CC0, сгенерированы
audio/generate_sfx.py. Подробности и тексты лицензий — в ASSETS.md.