squad-proto/engine/project.h
z.kirill 7d6266aaf3 Tile2D: движок отдельным продуктом, игра — проектом в нём (M11-M20)
Десять вех одним состоянием: разделять их пофайлово нечем, потому что
src/game.cpp менялся почти в каждой. Собирается начисто без предупреждений,
все проверки проходят.

ДВИЖОК (engine/, цель tile2d)

  Каталог свой, и решение «это движок» принимается тем, куда положен файл.
  Компилятор нашёл три зависимости движка от игры, и все сняты: размеры кадра
  и карты уехали в engine/config.h, потолок населения этажа стал своим
  (MAX_LEVEL_SPAWNS против игровой MAX_TARGETS), запасная точка старта стала
  центром карты вместо позиции отряда.

  engine/projection.*  единственное место, где движок знает про изометрию;
                       видов сразу два — абстракция с одной реализацией ничем
                       не проверена и обычно оказывается неправильной
  engine/project.*     манифест проекта: пути, вид, кривая глубины
  engine/app.*         окно, кадр, fixed timestep — вместо двух копий цикла
  engine/tilemap_draw  движок научился показывать свою карту

РЕДАКТОР (editor/, цель tile2d_editor)

  Открывает любой проект и ни одной игры по имени не знает.
  --tool  одиннадцать безоконных команд: комнаты, каталог, кривая, сборка
          этажа, ASCII-карта, проверка набора. Правку делают файлами,
          последствия читают командой (docs/19-agent.md)
  терминал снизу: те же инструменты, git, сборка и запросы к claude/codex,
          открытый проект уходит потомкам через TILE2D_PROJECT

ПРИМЕР (samples/walk, цель tile2d_walk)

  Второй потребитель движка. Игра и редактор самостоятельность движка
  проверить не могут: редактор мира не рисует, а игра — то место, куда общий
  код и уезжает незаметно.

ИГРА (src/)

  Экстракшен: вес и два порога переноски, конечный боезапас, расходники
  применяются сами, общая сумка отряда, трата опыта на улучшения.

  Каждое из правил проверяется прогоном, а не глазами, и проверки поймали:
  вес дважды не связывал ничего (мерил по бинтам прогона, а не по добыче);
  боец с клинком не тратил найденные патроны при запасном стволе в сумке;
  массив виджетов экрана переполнился и молча съел хвост схрона; проверка
  улучшений сама ломала забег, вызывая NewRun посреди спуска.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 21:07:19 +03:00

69 lines
4.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
// -----------------------------------------------------------------------------
// Проект: всё, что отличает одну игру на Tile2D от другой.
//
// Движок не знает ни одного имени содержимого. Он знает, что у проекта есть
// каталог сущностей, набор комнат, вид отображения и кривая глубины, — а какие
// именно твари, комнаты и числа за этим стоят, читается из project.txt.
//
// Отсюда правило, которое легко нарушить и трудно заметить: НИ ОДИН путь к
// содержимому не может быть зашит в код движка. Раньше движок сам искал
// assets/rooms и assets/catalog, то есть в нём было зашито имя ровно одной
// игры; такой «движок» работает с одним проектом и притворяется общим.
//
// Формат — построчный `ключ значение`, как у комнат и каталога. Причина та же:
// файл лежит в git, правится руками и обязан читаться в diff.
//
// name DESCENT
// view iso # iso | topdown
// rooms rooms # каталог с *.room, относительно проекта
// catalog catalog/entities.txt
// startdepth 1
// danger 3.0 2.2 0.10 # база, линейный рост, квадратичный хвост
// density 0.05 1.5 # прирост за этаж, упор
// loot 2 4 3 # база, этажей на +1 предмет, этажей на тир
// sight 0.035 0.60 # сжатие за этаж, нижний упор
// xp 0.15 # прирост множителя опыта за этаж
// themes 1 4 8 13 # с какого этажа начинается каждая тема
// -----------------------------------------------------------------------------
#include <string>
#include <vector>
#include "engine/progression.h"
#include "engine/projection.h"
struct Project
{
std::string dir; // корень проекта
std::string name = "UNTITLED";
ViewMode view = ViewMode::ISO_2_1;
// Пути уже склеены с корнем проекта: вызывающему не приходится знать,
// относительно чего они были записаны.
std::string roomsDir;
std::string catalogPath;
int startDepth = 1;
FloorCurve curve;
// false — проект не читается; err объясняет, чего именно не хватает.
bool Load(const std::string& projectDir, std::string* err = nullptr);
// Поставить проект на движок: вид отображения и кривую глубины. Отдельно от
// Load намеренно — прочитать манифест, чтобы показать его в списке, и
// ПЕРЕКЛЮЧИТЬ на него движок это разные действия.
void Apply() const;
};
// Где искать проект. wanted — либо путь к каталогу проекта, либо просто имя
// (тогда ищется projects/<имя>). Пусто — берётся переменная окружения
// TILE2D_PROJECT, а если и её нет — единственный найденный проект.
//
// Поиск идёт от текущего каталога вверх: запуск из корня репозитория и запуск
// из build/bin одинаково рабочие, и это не должно требовать ключей.
std::string FindProjectDir(const std::string& wanted = {});
// Имена проектов, которые видны отсюда, — для сообщения об ошибке и для списка
// в редакторе. «Проект не найден» без ответа на «а какие есть» бесполезно.
std::vector<std::string> AvailableProjects();