Pull to refresh

Разрабатываем полноценную игру целиком при помощи ИИ (LLMDD, часть 1)

Level of difficultyEasy
Reading time52 min
Views5.9K

С детства я мечтал разработать свою игру, много раз пытался, но каждый раз отказывался от этой идеи - слишком уж тяжёлая задача, особенно для одного человека. Нужно уметь программировать логику, графику, рисовать и работать со звуком - и это только технические задачи. Игра должна быть интересной, сбалансированной, механики - увлекательными. Существуют трудолюбивые таланты способные всё это осилить, но для простого бекендера, даже с большим опытом и кучей успешных проектов это оставалось непосильной задачей. Пока не появились они - большие языковые модели (aka LLM). Они умеют писать код, рисовать спрайты, создавать звуки, работать с текстами и быть помощниками в работе над идеей игры, её механиками и фишками. Но не всё так просто. Есть множество подводных камней, и чтобы их обойти я решил создать методологию разработки софта с упором на использование больших языковых моделей - LLMDD. И в этой статье на примере создания опенсорсной игры я расскажу вам о всех моих наработках. Возможно, это позволит и вам создавать софт по-новому.

Инструменты

Для работы с проектной документацией достаточно Claude 4 Sonnet или Opus через браузер, но для разработки я рекомендую использовать Claude Code. На базовом тарифе за 20 баксов лимиты жёсткие, на 1 час активной разработки будет 4 часа ожидания когда лимиты обнулятся - но для того чтобы попробовать, наверное, достаточно. На тарифе за 100 баксов уже можно комфортно работать, только обязательно выставите /model sonnet 4, иначе периодически будете упираться в лимиты. Тариф за 200 баксов позволяет использовать opus 4, она лучше, но различия не столь важны, особенно для небольшого проекта. Для генерации изображений я использовал модель 4o от OpenAI - с правильными промптами она способна создавать почти консистентные спрайты. Лучше ничего пока не нашёл. С анимациями сложнее. Качественный результат удалось получить только от Veo 3 basic. Если в ходе разработки проекта зашли в тупик и нет идей что делать дальше, можно использовать Gemini 2.5 pro, но обязательно через ai studio - можно скормить ей до 3М кода (преобразовав весь код, доки и прочую текстовую инфу в 1 файл) и попросить всяческой помощи по проекту.

Язык и движок

Для разработки я выбрал go - отчасти оттого, что хорошо им владею, но главное - этот язык показывает замечательные результаты при кодировании с LLM. Его ограничения позволяют модели совершать меньше ошибок, а удобные встроенные средства тестирования, и так же сторонние линтеры - не дают поломать рабочий код в ходе разработки.

В качестве движка я взял ebitengine - маленькая и быстрая го-нативная либа. Двумерного движка достаточно для моего проекта, в сети достаточно примеров на которых LLM обучились использованию этой либы.

Начало

Навык общения с LLM возникает постепенно. По началу - не знаешь что вообще писать. Но рецепт тут один - надо пробовать, надо пытаться решать проблемы при помощи умных чатиков. Вам может показаться сложным сразу писать большие детальные промпты, но постепенно, незаметно для себя вы обнаружите, что построили интерфейс к "внешнему мозгу". А если дать ему инструменты разработки, то он превращается в интеллектуального исполнителя - LLM-агента. А вы начинаете заниматься агентной разработкой используя LLMDD - методику эффективного управления разработкой при помощи LLM.

Дизайн-документ

Для начала нужно понять. Какую игру вы вообще хотели бы сделать? Это не такой простой вопрос. Я долго общался с ChatGPT, у нас большая история общения и он умеет создавать портрет личности на основе чатов, поэтому я выбрал его для этой задачи. Я приводил ему примеры игр, которые мне понравились и запомнились, какие механики мне показались интересными. Мы рассуждали о жанрах, идеях и том, что из этого всего можно было бы взять как основу для первого простого, но интересного проекта игры.

Собрав мысли в кучку, я обратился к Opus 4:

Я хочу сделать проект для своего удовольствия. Это будет небольшая игра. Я хочу сделать её опенсорсной и написать статью на Хабр о её создании. Одна из целей этого проекта - показать, что при помощи современных моделей можно создать полноценный программный продукт полагаясь исключительно на агентную разработку. При разработке я хочу по максимуму использовать Opus 4 через веб-интерфейс и Sonnet 4 через Claude code. Для создания статьи мне пригодится отслеживать все мои взаимодействия c LLM. Как ты порекомендуешь организовать работу, чтобы ничего не потерялось? Или мне не надо об этом заботиться и я всегда смогу найти историю переписок? В целом, подскажи как мне лучше организовать такую разработку.

Весь текст нашего диалога

Отличная идея для проекта! Вот как я рекомендую организовать работу:

## Сохранение истории взаимодействий

Веб-интерфейс Claude:

- История чатов сохраняется автоматически в вашем аккаунте

- НО полагаться только на это рискованно - чаты могут быть случайно удалены

- Рекомендую регулярно экспортировать важные диалоги (копировать в markdown файлы)

Claude Code:

- История команд сохраняется в терминале

- Создайте отдельную папку для логов и настройте сохранение всех сессий

## Рекомендуемая структура проекта

game-project/
├── docs/
│   ├── llm-interactions/     # Все диалоги с LLM
│   │   ├── 01-architecture-design.md
│   │   ├── 02-core-mechanics.md
│   │   └── ...
│   ├── article-draft/        # Черновики статьи
│   └── development-log.md    # Дневник разработки
├── src/                      # Исходный код игры
└── README.md

## Рабочий процесс

1. Ведите дневник разработки - после каждой сессии записывайте:

- Что планировали сделать

- Какие промпты использовали

- Что получилось/не получилось

- Выводы и инсайты

2. Используйте git с осмысленными коммитами:

git commit -m "feat: добавил систему инвентаря (Claude Code session #5)"

3. Разделяйте задачи между инструментами:

- Opus 4 (веб): архитектура, дизайн, сложная логика, рефакторинг

- Sonnet 4 (Claude Code): реализация конкретных фич, отладка, тесты

4. Создавайте артефакты в веб-интерфейсе для важного кода - их легче потом найти и скопировать

5. Используйте теги в промптах для удобного поиска:

#architecture #game-loop Помоги спроектировать основной игровой цикл...

## Советы для статьи

- Сохраняйте не только успешные попытки, но и неудачные - это ценный опыт

- Фиксируйте моменты, когда приходилось корректировать подход

- Отмечайте, сколько итераций потребовалось для каждой фичи

- Делайте скриншоты промежуточных результатов

## Инструменты для автоматизации

Можете написать простой скрипт для экспорта чатов:

# Периодически сохраняйте важные диалоги в markdown

# Добавляйте метаданные: дата, тема, используемая модель

Такой подход поможет вам не только сохранить всю информацию, но и проанализировать процесс разработки для написания качественной статьи. Удачи с проектом!

=====

У меня возникла мысль создать игру-песочницу. Эмулятор экосистемы. Я подумал о саванне. Вроде бы это достаточно разнообразная интересная и при этом довольно понятная экосистема. Пусть там живут несколько видов животных. У каждого свои принципы поведения, кормовая база и т.п. Это могут быть совершенно разные животные от сусликов до носорогов. Главное - чтобы между ними всеми могли бы быть какие-то взаимодействия. Пусть все виды действий на природу, друг друга и других животных не будут жёстко привязаны к каждому животному, а можно будет как-бы собрать своё собственное животное (типа как в настольной карточной игре эволюция). И цель игры... не обязательно должна быть явной, как в CK2, там же нет цели, ты сам её себе придумываешь. Можно придумать много разных ачивок, чтобы дать понять игроку чего тут вообще можно добиться. Можно открывать варианты прокачки по мере открытия ачивок. Типа, стать доминантным хищником, или набрать максимальную биомассу вида. Саму игру я вижу с графикой организованной как в Starcraft - причём первом. У животных будут спрайты (нагенеренные ИИ), описывающие разные движения и взаимодействия. Каждый юнит будет как-бы круглым, но не жёстким, чтобы была механика распихивания. Короче, нравится мне принцип по которому сделана карта и юниты в SC1 (ну и SC2, но там 3D). Мне кажется он очень хорошо подходит, когда есть юниты очень разных размеров. Я подумал, что десктопное приложение на го будет хорошим вариантом. Наверное, можно использовать библиотеку ebitengine. Геймплейный луп я представляю так:

* Игрок запускает игру, генерируется карта, на ней типичный для африканской саванны ландшафт и звери. Игрок может по началу просто изучать этот мир, как он живёт и движется. Меняются времена года заставляя зверей мигрировать. Львы охотятся, травоядные пасутся, стервятники ищут падаль. Мне кажется, нужно дать возможность скроллом менять масштаб от "вида из космоса" (всякие оверлеи в поздней части разработки) до "рассмотрим эту пару мышей".

* Когда игрок решает создать своё животное, ему по началу даётся не много вариантов, чтобы не перегружать возможностями. Можно выбрать один из существующих наборов спрайтов, но, например, поменять цветовую гамму. Можно выбрать размер, время жизни, способ питания, всякие такие базовые штуки сразу (жирафы размером с суслика будут выглядеть прикольно). А всякие перки типа "падальщик", "пират", "камуфляж", "стадное" и т.п. пока закрыты. Все опции должны иметь свою цену, чтобы нельзя было сделать уберзверя. По балансу и разнообразию вариантов мне нравилась система создания расы в Master of Orion 2.

* Создав животное игрок может просто его сохранить, а может закинуть на карту. Следует ограничить количество биомассы, которое игрок может закинуть разом, чтобы нельзя было читить. Закинул 5 саблезубых кошек - всё, жди пока постепенно восстановится мана.

* Животные игрока начинают взаимодействовать с экосистемой. Ничем в мире: ни погодой, ни другими зверьми управлять нельзя (можно разлочить какие-нибудь катаклизмы к концу прокачки). Смысл в том, чтобы создать животное, которое разовьётся в экосистеме и сможет получить пока закрытые ачивки. Их открытие позволяет прокачиваться и создавать более кастомизированных животных.

* Когда игрок открыл новые возможности и подкопилась мана, он может снова дизайнить и выпускать животных.

Я хочу чтобы ты мне помог создать полноценный дизайн-документ игры. Но для начала не пиши ничего своего - задай мне вопросы, чтобы помочь мне раскрыть аспекты игры.

=====

Отличная концепция! Чтобы помочь создать полноценный дизайн-документ, мне нужно лучше понять несколько аспектов:

## Механика экосистемы

1. Масштаб симуляции: Сколько примерно животных одновременно на карте? Десятки, сотни, тысячи? Это повлияет на глубину поведения каждого юнита.

2. Пищевые цепи: Как детально ты видишь систему питания? Просто "хищник ест травоядного" или более сложные механики (охота стаей, конкуренция за добычу, разная питательность)?

3. Ресурсы среды: Что кроме животных есть на карте? Водоёмы, растительность, укрытия? Как они влияют на поведение?

4. Время и сезоны: Как быстро идёт время? День/ночь важны? Что конкретно меняется между сезонами?

## Создание животных

5. Система баланса: Ты упомянул "цену" опций. Это очки при создании? Или каждая способность имеет недостатки?

6. Визуальная кастомизация: Насколько глубоко можно менять внешний вид? Только цвет или также пропорции, детали?

7. Поведенческие шаблоны: Животные игрока следуют заданным паттернам или у них есть какой-то ИИ, который адаптируется?

## Прогрессия

8. Ачивки и разблокировки: Какие примеры ачивок ты видишь кроме упомянутых? Как они связаны с новыми возможностями?

9. "Мана" для создания: Как она восстанавливается - просто со временем или нужны какие-то действия?

10. Сохранение прогресса: Это одна длинная сессия или можно сохраняться? Переносится ли прогресс между картами?

## Геймплей

11. Взаимодействие игрока: После выпуска животных игрок только наблюдает или может как-то влиять (выделять, следить за конкретными)?

12. Условия победы/поражения: Могут ли созданные виды полностью вымереть? Что происходит в этом случае?

13. Конкуренция с ИИ-видами: Могут ли обычные животные эволюционировать/адаптироваться в ответ на виды игрока?

=====

1. Думаю, для интересной симуляции потребуется поддержка тысяч животных на огромной карте. Но в целом экосистема должна быть стабильна и для небольших карт. Может быть понадобится задавать немного разные правила для мира в зависимости от его размера. Я думаю, можно будет использовать ИИ чтобы натюнить правила мира при разных настройках. В целом, размер карты должен быть ограничен только желанием игрока и возможностями его железа. Сам принцип игры таков, что будет легко распараллелить вычисления по разным участкам карты.

2. Питание должно быть весьма детальным. Рост зелени зависит от влажности и погоды. Разная зелень доступна разным травоядным (трава, кусты, верхушки деревьев, может быть фрукты и коренья), но в целом любая зелёная биомасса питательна для любого травоядного. Не каждый хищник может "пробить броню" другого зверя, но в целом любое мясо питательно. Всеядность тоже опция. Соотношение питательности мяса и зелени - вопрос баланса.

3. Всё что ты описал - есть на карте. Обезьяна или гепард может взобраться на дерево (но это перк). Животные могут плавать (перк). Разные аспекты поведения, типа стайной охоты или способности сбиваться в стада - тоже перки.

4. Смена дня и ночи - очень интересный аспект влияющий на геймплей. Но я наверное не стану прорабатывать его в начальной версии. В целом скорость игры должна быть такой, чтобы одно поколение крупных зверей могло смениться за разумное время (5-10 минут на нормальной скорости?), т.е. год должен длиться 5-10 минут. Соответственно, это будут не настоящие дни и ночи, а весьма растянутые (если будут). А вот сезоны прям важны. Мне кажется это ещё более интересный аспект экосистемы. Меняется температура (животное может замёрзнуть или перегреться), осадки, это меняет рост зелени, вызывая миграции и всякие прочие приколы.

5. Мне кажется, будет хорошо сделать как в MOO2, есть начальный набор очков, позитивные перки стоят очки, негативные дают очки. Есть взаимоисключающие и т.п. - классическая система.

6. Для начала хватит цвета (не влияет на геймплей) и размера (влияет). Потом можно будет ещё что придумать (шапки как в TF2? =)

7. Все звери - автоматы без адаптации (не представляю сколько ресурсов ушло бы на подсчёт адаптаций и как они ломали бы баланс). Сложность поведения получается за счёт сочетания перков.

8. Я надеюсь, ты нагенеришь мне разных прикольных вариантов ачивок, а я смогу из них выбрать. Будет прикольно взять ачивки свойственные каким-то существующим видам животных. Должны быть самые простые для начальной прокачки, типа: добейтесь популяции в 10 животных, или переживите засуху. Промежуточные, чтобы открыть основные перки, типа: животное заняло 10% биомассы травоядных, или вытеснить существующий (с самого анчала игры, дефолтный) вид хищников. Ну и топовые ачивки для достигаторов, типа: уничтожить экосистему (создать зверя, который всех сожрёт и сам сдохнет, например). Открытие ачивок даёт возможность открыть перки при создании новых животных. Перки, понятное дело, имеют разную цену. Для траты очков полученных за самые сложные ачивки можно внести всякие штуки за ману. Типа, возможность запускать дожди или засухи и пожары.

9. Мана восстанавливается со временем. Её смысл - не дать игроку начитерить ачивки, типа, создав хищника, а потом кормить его беспомощными коровами. Хочешь больше маны - промотай время.

10. У игры должно быть локальное и глобальное сохраняемое состояние. Т.е. можно сохранить прогресс на карте или создать новую карту, но на ней будут сохранены открытые ранее перки. Можно подумать над другими режимами игры, например, с той же эволюцией. Сначала ты создаёшь животное и помещаешь на карту с другими ИИ-игроками. Виды прокачиваются, ты можешь добавлять перки к своему виду. Если твой вид исчез - ты проиграл. Способы победы можно придумать разные.

11. Мне кажется, эта игра должна быть про наблюдения и эксперименты. Должна быть возможность ткнуть в любое животное и понять чем оно занимается, какое у него состояние и т.п. Потом можно добавить какие-нибудь метрики с графиками. Основной способ влияние на мир - добавление нового животного. Они должны иметь свойство пола, кстати, и размножение - важная часть игры, но без генетических приколов (можно оставить их для других режимов).

12. Любой вид может вымереть. Могут вымереть даже все виды. Игрок в таком случае может попытаться заново заселить саванну своими видами или создать новую карту.

13. Это интересный вопрос. По идее, созданный с нуля мир должен быть сбалансирован (виды устойчивы). А игрок не должен иметь возможность создать уберзверя, по крайней мере до самого конца игры. Т.е. кажется, что тут не надо подтюнивать игру под игрока и созданные им виды.

=====

Отлично, картина проясняется! Теперь несколько уточняющих вопросов по техническим и дизайнерским аспектам:

## Технические вопросы

1. Производительность и оптимизация: При тысячах юнитов как ты видишь LOD (уровни детализации)? Например, животные вдали считаются упрощённо, а вблизи - детально?

2. Генерация карты: Процедурная генерация? Какие биомы кроме саванны (река, лес, скалы)? Как они влияют на геймплей?

3. Сохранение: Формат данных для созданных видов? Возможность делиться ими между игроками?

## Система перков

4. Примеры перков: Можешь набросать 5-10 конкретных перков с их эффектами? Например, что делает "пират" или "камуфляж"?

5. Взаимоисключающие перки: Какие логические конфликты? (маленький размер vs броня?)

6. Цепочки перков: Есть ли перки, требующие других перков как пререквизит?

## Визуализация и UI

7. Спрайты: Сколько анимаций на животное? Idle, walk, run, eat, attack, die - достаточно?

8. Интерфейс создания: Видишь это как отдельный экран-конструктор или прямо на карте?

9. Информационные оверлеи: Какие данные важно видеть на карте? Тепловые карты популяций, маршруты миграций?

## Механика размножения

10. Условия размножения: Что нужно для появления потомства? Сытость, безопасность, сезон?

11. Скорость популяции: Как контролировать экспоненциальный рост? Ограничение на количество детёнышей?

## MVP и приоритеты

12. Минимальный набор для первой версии: Сколько видов животных, перков и ачивок достаточно для интересного геймплея?

13. Что точно НЕ входит в первую версию: Кроме дня/ночи, что ещё оставим на потом?

=====

1. Игровое поле прямоугольное, изометрия как в SC1, т.е. по сути нет ничего ближнего и дальнего. Можно нагенерить мелких спрайтов, которые будут использоваться при большом удалении, при максимальном - точки. Но просчитывать действия животных придётся в любом случае одинаково детально на всей карте, смотрят на них или нет. Если хватает ресурсов железа, чтобы ускорять игру - хорошо. Если нет - придётся ждать или создавать карту поменьше. Понятно, что модель животного надо будет оптимизировать по вычислениям. Поэтому я и не хочу вводить всякие хитрости. Каждое животное - детерминированный автомат, чтобы можно было быстро считать тысячи объектов. Если есть стайное/стадное поведение, то оно тоже работает через условные функции. Животное стремится к подобным своего вида. Или если видит, что другое охотится - тоже начинает охотиться в ту же сторону. "Все побежали и я побежал", без какого-то объекта для стаи, это должно быть эмерджентное поведение.

2. Процедурная генерация конечно. Биом - саванна (ну можно расширить опции в аддонах, конечно). Объекты - всё что в ней встречается: озёра, реки, кустарники, деревья, холмы и скалы. От наличия воды зависит и растительность и возможность животных пить. Водные преграды не все могут преодолевать. Холмики в стиле SC1 этакие псевдовысоты с которых радиус зрения больше. Скалы - непроходимые перепады высот. Деревья и кусты: для кого препятствия, для кого корм, для кого - место для жизни.

3. Да, надо дать возможность экспортировать виды. Обычно это делается через бинарник в текстовом формате. Импортировать спрайты? Почему бы нет. Но вот насчёт перков и прочих модификаторов поведения? Было бы неплохо, но как импортировать кастомное поведение и при этом сохранять скорость обработки? Может быть дефолтные виды поведения будут прописаны кодом, а кастомные - через какой-то скриптовый язык (типа lua?) Хочешь кастомных действий - терпи торомоза. В любом случае, возможность модов это на потом.

4. Пират - будет пытаться стырить чужую добычу (другого вида или своего). Камуфляж - будет незаметен на фоне определённых видов растительности. Можно взять часть перков из настольной игры Эволюция - они там прикольные. М.б. даже не совсем правильно называть их перками. Просто свойствами? Хищник, травоядное (в сумме - всеядное), летающее, бронированное (сложнее пробить чем животное того же размера), стадное/стайное (двигается к представителям своего вида, держится их, копирует движения, даже если нет потребности). Звери живородящие млекопитающие. Птицы яйцекладущие. Кто там ещё есть? Но не хотелось бы для начальной версии делать слишком много преков. Но кроме перков должны быть и обычные свойства. Типа размера/веса, скорости, метаболизма, ну и прочих параметров описывающих любое животное. На более высокие показатели так же тратятся очки.

5. Можно быть маленьким и бронированным, почему бы нет? Нельзя быть летающим подземным, наверное =) Взаимоисключение должно быть продиктовано скорее логикой и природой, чем балансом. А баланс должен получаться через разную стоимость перков и дебафамми неотрывно связанными с баффами. Типа, бронированность снижает скорость, а птица вообще не может быть бронированной.

6. Конечно. Веселье во все поля. Логика и природа подскажут что без чего невозможно.

7. Ты чётко определил список. М.б. даже не нужно для ходьбы отдельного набора. Хотя, не знаю. Нейронке же рисовать. Эстетически было бы приятно чтобы была ходьба. Для мелких сдвигов достаточно дрейфа стоящего животного. Скорость бега может влиять на скорость (скипы) смены спрайтов. Для размножения достаточно сердечек над головами.

8. Для создания зверя нужен специальный интерфейс. М.б. как модельное окно, а м.б. и вообще отдельная вкладка.

9. Оверлеи можно оставить на потом. М.б. температура, влажность, количество зелени, живой биомассы. Придумаем.

10. Сытость и безопасность - ок. Сезон опционально.

11. Как и в живой природе, популяцию контролируют внешние ресурсы. За год падает сколько-то осадков и солнца, это даёт сколько-то зелени, которая делится между травоядными. Травоядные делятся между хищниками. На различные действия тратится энергия. Т.е. потраченной энергии никогда не может быть больше, чем входящей энергии, это и будет ограничивать популяции.

12. Это непростой вопрос. Вот прям для самого-самого MVP, нужно 2 зверя: травоядное и хищник - только эти 2 перка. Условные заяц и волк (не стайный). Другие перки и ачивки не нужны. Весь геймплей - сгенерить зайца/волка/зайцеволка(всеядного) с разным балансом параметров и смотреть будет ли он эффективнее. Карта статична, просто растёт немного травы постоянно. После готовности такого MVP можно постепенно наращивать число перков, видов, потом добавить прокачку с ачивками, сезоны и т.д.

13. Всё что не описано выше не входит. А вот что действительно сложный вопрос: что следует добавлять и в каком порядке. Какие перки будут давать максимальный импакт? Каких животных добавить 3-м, 4-м, 5-м? Но, у нас будет время подумать над этим.

=====

Отлично! У меня теперь есть полная картина. Давай создам структурированный дизайн-документ для твоей игры.Вот полноценный дизайн-документ для твоей игры! Я структурировал всю информацию из нашего диалога и добавил план поэтапной разработки.

Несколько предложений для следующих шагов:

1. Техническая архитектура

Рекомендую начать с прототипа на Ebitengine, проверив:

- Производительность с 1000+ спрайтов

- Базовую ECS систему для животных

- Простейший pathfinding

2. Генерация спрайтов

Для MVP можно использовать простые геометрические фигуры, но стоит заранее продумать пайплайн для AI-генерации. Какой стиль тебе больше нравится - пиксель-арт или что-то более детализированное?

3. Первые эксперименты с балансом

После создания MVP с зайцем и волком, ключевой вопрос - найти правильные коэффициенты для:

- Скорости роста травы

- Энергетической ценности пищи

- Затрат энергии на движение/охоту

4. Структура проекта для статьи

Начни вести лог с первого дня - фиксируй не только код, но и дизайн-решения, тупики, озарения. Это будет золотой материал для статьи на Хабр.

Что тебе кажется самым критичным для старта? Может, начнём с технического прототипа движения юнитов или сразу накидаем более детальную спецификацию для MVP?

=====

Отличное описание, мне очень нравится. Давай добавим в него некоторые мысли, которые мне пришли в голову пока я его читал:

* Насчёт объектов. Для начала хватит одного вида деревьев: акации. Один вид травы: злаковые. Кусты могут быть укрытиями для зайцев, препятствием для волков но распределены неравномерно.

* Кроме явных параметров следует добавить неявные. Например хиты, зависят от размера, длительности жизни и возраста, метаболизма. Динамические параметры, например, заметность - зависит от: размера, скорости движения, перков (которых ещё нет). Ещё не знаю, сделать ли все параметры настраиваемыми за очки, или оставить некоторые косвенными. Следует ли давать игроку понижать заметность животного просто за очки, или надо набирать нужные перки?

* Чем больше хитов, тем больше урона животное может впитать. Но чем больше оно потеряло хитов, тем сильнее падают все другие параметры. Хиты медленно восстанавливаются во время сна у сытого животного. В каких-то промежуточных версиях можно добавить критический урон, статус кровотечения, реакцию этот статус и следы крови (хотя ХЗ, будет ли этот элемент геймплея заметен, чтобы его прорабатывать?)

* Ещё важный параметр - сытость. От него тоже должны зависеть другие параметры. Если он низкий или слишком высокий, например, должна страдать скорость. От возраста тоже должно много чего зависеть.

* Кстати! Не знаю насчёт анимации ходьбы, но анимация сна нужна! Ты вообще записал типы анимации из нашего обсуждения в доку? Может что-то ещё забыл? Перенеси в доку всё важное.

* Потомки животных - точные их копии по всем начальным характеристикам с некоторым псевдорандомом. Размер и прочие характеристики взрослого животного зависят от его питания пока оно росло. М.б. можно сделать адаптивный дрейф, некоторых параметров. Типа размера. Но не понятно как это будет влиять на баланс долгосрочно.

* Не вижу сильной разницы между "Миграцией" и "Выживанием". Должно быть что-то посложнее. Типа сохранить размер стада не менее 30 единиц на протяжении года.

* Для поиска маршрутов в довольно разреженном пространстве саванны могу сразу предложить простую оптимизацию. Если можно проложить прямую линию - двигаться по ней. Но в целом поиск пути не должен быть большой проблемой, т.к. животные не видят очень далеко и соответственно не могут планировать движение сильно дальше области своей видимости. Скорее даже в принципе двигаясь по вектору притяжения/отталкивания. Для достижения далёких точек притяжения можно использовать вектор "чутья". Чем ближе к воде/добыче, тем сильнее вектор.

* Насчёт детерминированной системы - ты меня правильно понял. Одно зерно генерирует и карту, и расположение зверей, и отвечает за весь рандом симуляции. Т.е. если запустить игру по одному зерну и не вмешиваться в неё (или вмешиваться строго одинаково), события будут развиваться одинаково. Полезно для тестов, поиска багов, записи реплеев.

=====

Отлично, давай обновлю дизайн-документ с этими важными деталями!Отлично! Я обновил дизайн-документ со всеми твоими уточнениями.

По поводу твоего вопроса про явные vs неявные параметры - это важное дизайнерское решение. Вот мои соображения:

Вариант 1: Всё настраивается явно

- Плюсы: максимальный контроль, прозрачность для игрока

- Минусы: перегруженный интерфейс, сложность для новичков

Вариант 2: Часть параметров только через перки/комбинации

- Плюсы: более интересные решения, эмерджентность

- Минусы: может фрустрировать min-max игроков

Я бы предложил гибридный подход:

- Базовые параметры (размер, скорость) - настраиваемые

- Продвинутые (заметность, регенерация) - только через комбинации

Например:

- Низкая заметность = маленький размер + медленная скорость + перк "камуфляж"

- Быстрая регенерация = высокий метаболизм + перк "толстая шкура"

Это создаст интересные компромиссы и сделает перки более ценными.

Ещё пара мыслей:

1. Следы крови - может быть крутой механикой для стервятников/падальщиков, но согласен, что это на потом

2. Адаптивный дрейф - супер идея! Можно сделать опциональной настройкой для хардкорных игроков

Что думаешь начать кодить первым - базовую ECS систему или прототип генерации карты?

=====

Отлично, мне всё нравится. Есть много идей, но надо остановиться пока что и начать пилить проект. Но для начала мне нужны ответы на некоторые вопросы. Какие виды тестов существуют и применимы для разработки игры по типу нашей? Какие аспекты мне следует учитывать, на какие тонкости обращать внимание, каким принципам следовать? Расскажи мне, я никогда раньше игры не разрабатывал - только бекенд/фронтенд для веб-приложений. Что я должен знать о разработке игр, что может быть важно учесть сейчас, в самом начале?

=====

Отличный вопрос! Разработка игр действительно имеет свою специфику. Вот что важно знать:

## Типы тестирования для игр

### 1. Unit-тесты (как в вебе, но...)

- Детерминированность критична: тестируй логику животных, формулы урона, расчёт сытости

- Фиксированный deltaTime: в играх время не реальное, всегда используй фиксированный шаг

// Плохо
animal.Move(time.Since(lastUpdate))

// Хорошо  
animal.Move(FIXED_DELTA_TIME)

### 2. Интеграционные тесты симуляции

- Запусти мини-экосистему с известным seed

- Проверь, что через N тиков все животные на ожидаемых позициях

- Это твой главный инструмент отладки!

### 3. Тесты производительности

- Сколько животных можно обработать за 16ms (60 FPS)?

- Профилируй с первого дня - потом будет поздно

### 4. Визуальные регрессионные тесты

- Делай скриншоты ключевых состояний

- Сравнивай при изменениях рендеринга

## Ключевые отличия от веб-разработки

### Game Loop vs Event-driven

// Веб: ждём событий
http.HandleFunc("/", handler)

// Игра: крутим цикл 60 раз в секунду
for !game.ShouldQuit() {
  game.Update(deltaTime)
  game.Draw()
  game.Present()
}

### Состояние - это всё

- В вебе стейт минимизируют, в играх - это core

- Каждый кадр = полный пересчёт мира

- Никаких race conditions! Обновляй последовательно

### Оптимизация с первого дня

// Веб: "потом оптимизируем"
animals := []Animal{}

// Игра: сразу думай о кэш-миссах
type AnimalData struct {
  positions [MAX_ANIMALS]Vec2
  velocities [MAX_ANIMALS]Vec2
  // Данные в массивах, не объектах!
}

## Специфика симуляторов

### Пространственные структуры обязательны

type SpatialGrid struct {
  cellSize float64
  cells map[CellCoord][]*Animal
}

// Без этого поиск соседей убьёт производительность

### Фиксированная точность чисел

// Плохо: float64 может дать разные результаты
// Хорошо: fixed-point или аккуратные float32
type Fixed32 int32 // 16.16 fixed point

### LOD (Levels of Detail) с самого начала

- Далёкие животные считай реже

- Невидимые - ещё реже

- Но результат должен быть идентичным!

## Архитектурные принципы

### 1. Data-Oriented Design

// Плохо: ООП стиль
type Animal struct {
  pos Vec2
  health int
  Update() {...}
}

// Хорошо: данные отдельно
type World struct {
  positions []Vec2
  healths []int
}

### 2. Избегай аллокаций в game loop

// Плохо
func Update() {
  nearbyAnimals := FindNearby(animal) // аллокация!
}

// Хорошо  
var nearbyBuffer [MAX_NEARBY]AnimalID
func Update() {
  count := FindNearbyInto(animal, nearbyBuffer[:])
}

### 3. Предсказуемость важнее элегантности

- Никаких горутин в симуляции

- Никаких map с range (порядок не гарантирован)

- Explicit лучше implicit

## Практические советы для старта

### 1. Начни с фиксированного мира

const (
  WORLD_SIZE = 100x100
  MAX_ANIMALS = 1000
)

// Динамический размер - потом

### 2. Сделай debug режим сразу

- Визуализация коллайдеров

- Векторы движения

- Статус каждого животного

- Slow-motion режим

### 3. Профилируй с первого дня

import _ "net/http/pprof"

// localhost:6060/debug/pprof

### 4. Используй ECS, но просто

type EntityID uint32
type World struct {
  // Components as arrays
  positions [MAX_ENTITIES]Vec2
  velocities [MAX_ENTITIES]Vec2
  animalTypes [MAX_ENTITIES]AnimalType
  
  // Entity management
  alive [MAX_ENTITIES]bool
}

## Специфика Ebitengine

### 1. Draw вызывается отдельно от Update

func (g *Game) Update() error {
  // Логика - строго 60 TPS
}

func (g Game) Draw(screen ebiten.Image) {
  // Рендеринг - может скипаться
}

### 2. Избегай создания изображений каждый кадр

// Загрузи все спрайты заранее

sprites := LoadAllSprites()

### 3. Батчинг критичен

// Рисуй однотипные объекты вместе
DrawAllGrass()
DrawAllAnimals()

// Не смешивай типы

## Что делать прямо сейчас

1. Создай простейший прототип:

- Поле 50x50

- 10 "зайцев" (просто круги)

- Движение к ближайшей "траве"

- Измерь FPS

2. Настрой тесты:

- Unit-тест для расчёта расстояния

- Интеграционный для движения

- Benchmark для 1000 животных

3. Заложи масштабируемость:

- Spatial grid с первого дня

- Профилирование в CI

- Метрики производительности

Главное правило: в играх нельзя "потом отрефакторить производительность". Архитектура должна быть производительной изначально.

Хочешь, я покажу базовую структуру проекта или пример простейшего ECS для начала?

=====

На основе нашего диалога и дизайн-документа создай в виде артефакта подробный план работ для агентной разработки при помощи Claude Code. Разбей разработку на отдельные этапы. Результатом каждого этапа должен быть тестируемый (и покрытый всеми видами подходящих тестов) инкремент. Для компиляции, запуска и тестирования должен использоваться единый мейк-файл. У приложения должен быть headless-режим, чтобы можно было быстро тестировать функционал и запускать симуляции для балансировки игры. Сразу проработай структуру папок. Если требуется сделать что-то, что не может сделать LLM, например, сгенерировать спрайты для игры, составляй инструкции для оператора (меня). Результатом выполнения плана работ должен быть играбельный MVP (как описано в дизайн-документе)

=====

Готово! Я создал подробный план агентной разработки с 10 этапами, каждый из которых даёт тестируемый результат.

Ключевые особенности плана:

1. Инкрементальность - каждый этап добавляет функциональность к уже работающему коду

2. Чёткие промпты - для каждого этапа прописан точный промпт для Claude Code

3. Тестирование - встроено в каждый этап

4. Headless режим - с самого начала для автоматизации

5. Инструкции для человека - где LLM не справится (генерация спрайтов)

Рекомендуемый порядок работы:

1. Начни с Этапа 0 - создай структуру проекта

2. Проходи этапы последовательно, не пропуская

3. После каждого этапа запускай тесты через make test

4. Сохраняй промпты и ответы для статьи

5. При проблемах возвращайся к чек-листу и типовым решениям

Особое внимание обрати на:

- Этап 3 - здесь появляется первая рабочая симуляция

- Этап 6 - единственное место где нужно твоё участие

- Этап 9 - критически важен для баланса

План рассчитан на ~30 часов работы с Claude Code. С учётом отладки и экспериментов - около недели разработки.

Готов начать с Этапа 0?

=====

Ты уверен, что в полученном артефакте (Этапы разработки) присутствует весь необходимый контекст из нашего диалога? Модель получит только этот файл и должна будет разработать полноценный MVP игры. Дополни задание всей необходимой информацией

=====

Вы абсолютно правы! План получился слишком абстрактным. Давайте дополню его всем необходимым контекстом из нашего обсуждения.Отлично! Теперь план содержит весь необходимый контекст из нашего диалога:

Концепция игры - симулятор экосистемы саванны с наблюдением и экспериментами

Детальные механики - голод, здоровье, движение, размножение

Конкретные параметры - размеры, скорости, радиусы для зайцев и волков

Формулы баланса - энергетический поток, метаболизм, рост травы

Технические требования - детерминированность, производительность, изометрия

Алгоритмы - векторное движение, spatial grid, ECS архитектура

Пошаговые промпты - точные инструкции для каждого этапа

План готов к использованию! Модель, получив только этот документ, сможет пошагово разработать полноценный MVP игры.

Несколько рекомендаций для начала работы:

1. Сохрани план в отдельный файл - он будет твоим основным референсом

2. Создай git репозиторий перед началом для отслеживания всех изменений

3. Документируй проблемы - если Claude Code застрянет, это материал для статьи

4. Делай скриншоты прогресса после каждого этапа

Готов начинать? Первый шаг - создание структуры проекта (Этап 0). Удачи! 🚀

Если вы прочитали текст диалога, то наверное задаётесь вопросом: "А где, собственно полученные документы?". Их модель создала в виде отдельных артефактов - файлов, которые ей удобно редактировать.

Проект

Я открыл vscode, создал новый проект в папке savanna и сохранил туда 2 файла, скачанных из веб-версии Claude: docs/article/design.md и docs/tasks/2025-06-11-mvp.md - они станут основой проекта. Вот их содержимое:

design.md

# Дизайн-документ: Симулятор экосистемы саванны

## Концепция игры

### Жанр

Песочница с симуляцией экосистемы, где игрок создаёт и наблюдает за развитием собственных видов животных в африканской саванне.

### Основная идея

Игрок изучает живую экосистему, экспериментирует с созданием новых видов животных и наблюдает, как они взаимодействуют с окружающей средой. Прогрессия через систему достижений открывает новые возможности для создания более сложных существ.

### Целевая платформа

Десктопное приложение на Go с использованием Ebitengine.

## Геймплей

### Основной игровой цикл

1. Наблюдение: Игрок изучает сгенерированную экосистему саванны

2. Создание: Дизайн нового вида животного с доступными параметрами и перками

3. Выпуск: Размещение животных на карте (ограничено маной)

4. Эксперимент: Наблюдение за взаимодействием с экосистемой

5. Прогресс: Получение достижений и разблокировка новых возможностей

### Управление

- Скролл мыши: масштабирование от общего вида до детального

- ЛКМ: выбор и информация о животном

- ПКМ: перемещение камеры

- Пробел: пауза/ускорение времени

- Tab: переключение между режимами просмотра и создания

## Технические характеристики

### Визуальный стиль

- Изометрическая проекция в стиле StarCraft 1

- 2D спрайты для всех объектов

- Круглые "мягкие" юниты с механикой распихивания

- AI-генерированные спрайты животных

### Анимации

- Idle - стояние на месте

- Walk - медленное передвижение

- Run - быстрый бег

- Eat - поедание пищи

- Attack - атака

- Sleep - сон/отдых

- Die - смерть

- Breed - размножение (сердечки)

### Производительность

- Поддержка тысяч юнитов на больших картах

- LOD для спрайтов: полный → упрощённый → точка

- Детерминированные автоматы для всех животных

- Параллельные вычисления по секторам карты

### Временная модель

- 1 игровой год = 5-10 минут реального времени

- Сезонные изменения (температура, осадки, миграции)

- День/ночь отложены на будущие версии

## Экосистема

### Карта

- Процедурная генерация

- Масштабируемый размер (ограничен железом игрока)

- Элементы ландшафта:

- Водоёмы (озёра, реки)

- Растительность:

- Трава (злаковые) - основной корм травоядных

- Деревья (акации) - верхушки для высоких травоядных

- Кусты - укрытия для мелких животных, препятствия для крупных

- Рельеф (холмы с увеличенным обзором)

- Скалы (непроходимые препятствия)

### Пищевые цепи

- Солнечная энергия → растительность → травоядные → хищники

- Рост растений зависит от влажности и температуры

- Типы растительной пищи: трава, листья кустов, верхушки деревьев

- Ограничения хищников по размеру добычи

### Энергетический баланс

- Закон сохранения энергии в экосистеме

- Естественное ограничение популяций через доступные ресурсы

## Создание животных

### Явные параметры (настраиваемые за очки)

- Размер/вес

- Скорость передвижения

- Продолжительность жизни

- Метаболизм

- Сила (для хищников)

- Броня (защита от хищников)

### Неявные параметры (вычисляемые)

- Хиты - зависят от размера, возраста, продолжительности жизни, метаболизма

- Заметность - зависит от размера, скорости движения, перков

- Выносливость - зависит от метаболизма и возраста

- Радиус обзора - зависит от размера и положения (холмы)

### Динамические параметры

- Сытость (0-100%):

- Влияет на скорость (низкая или слишком высокая снижают)

- Определяет возможность размножения

- Влияет на регенерацию хитов

- Здоровье (текущие хиты):

- Потеря хитов снижает все параметры пропорционально

- Медленно восстанавливается во время сна при высокой сытости

- Возраст (0 - макс):

- Молодые: сниженные параметры, быстрый рост

- Взрослые: пик всех характеристик

- Старые: постепенное снижение всех параметров

### Система перков

#### MVP перки

1. Травоядное - питается растительностью

2. Хищник - питается другими животными

#### Базовые перки (первая волна)

3. Всеядное - комбинация травоядного и хищника

4. Стадное/Стайное - группируется с сородичами

5. Пират - крадёт чужую добычу

6. Камуфляж - маскировка в определённой растительности

7. Плавающее - может пересекать водоёмы

8. Лазающее - может забираться на деревья

#### Продвинутые перки (требуют разблокировки)

9. Летающее - птицы (несовместимо с бронёй)

10. Бронированное - усиленная защита (снижает скорость)

11. Падальщик - питается мертвечиной

12. Ночное - активно ночью (для будущих версий)

### Размножение

- Требования: сытость + безопасность

- Визуализация: сердечки над головами

- Потомство:

- Наследует все базовые характеристики вида

- Небольшой псевдорандом для вариативности (±5%)

- Финальный размер взрослой особи зависит от питания в период роста

- Возможен адаптивный дрейф параметров (экспериментально)

## Прогрессия

### Мана

- Ресурс для создания животных

- Восстанавливается со временем

- Предотвращает читерство массовым спавном

### Достижения

#### Начальные

- "Первые шаги": создать вид с популяцией 10+ особей

- "Выживание": пережить первую засуху

- "Охотник": ваш хищник успешно поохотился 10 раз

#### Промежуточные

- "Доминирование": занять 10% биомассы экосистемы

- "Эволюция": вытеснить один из стартовых видов

- "Стойкость": сохранить стадо 30+ особей в течение года

#### Продвинутые

- "Апекс-хищник": стать единственным видом хищников

- "Травоядная империя": 50% всей биомассы

- "Армагеддон": уничтожить всю экосистему

### Разблокировки

- Новые перки привязаны к достижениям

- Поздние достижения открывают катаклизмы (засухи, пожары)

- Глобальный прогресс сохраняется между картами

## План разработки

### MVP (Минимально играбельный продукт)

1. Статичная карта с постоянным ростом травы

2. Два вида: условные "заяц" и "волк"

3. Базовые параметры без перков

4. Простейший UI для создания животных

5. Наблюдение и базовая статистика

### Версия 0.2

- Добавить перк "всеядное"

- Процедурная генерация карты

- Водоёмы и их влияние

- Первые 3-5 достижений

### Версия 0.3

- Сезонность и миграции

- Перки: стадное, плавающее, камуфляж

- Расширенная статистика и графики

- 10+ достижений

### Версия 0.4

- Полная система перков

- Все типы ландшафта

- Сохранение/загрузка

- Экспорт/импорт видов

### Версия 1.0

- Балансировка всех систем

- 30+ достижений

- Оверлеи и продвинутая визуализация

- Катаклизмы для поздней игры

## Технические решения

### Архитектура

- ECS (Entity Component System) для животных

- Квадродерево для оптимизации коллизий

- Секторная система для параллелизации

- Детерминированная симуляция для воспроизводимости

### Система движения

- Прямая линия - основной способ движения при отсутствии препятствий

- Векторы притяжения/отталкивания:

- Притяжение к пище, воде, сородичам

- Отталкивание от хищников, препятствий

- Ограниченный обзор - планирование только в радиусе видимости

- "Чутьё" - градиентный вектор к удалённым целям (вода, добыча)

- Простой обход препятствий без сложного pathfinding

### Детерминированность

- Единое зерно генерации для всей симуляции

- Воспроизводимость всех событий при одинаковых действиях

- Поддержка записи и воспроизведения реплеев

- Упрощение отладки и тестирования

### Форматы данных

- JSON для сохранений и конфигов

- Base64 для экспорта видов

- PNG для спрайтов

### Моддинг (отложено)

- Lua для кастомного поведения

- Поддержка пользовательских спрайтов

- Steam Workshop интеграция

## Вдохновение и референсы

- StarCraft 1 - визуальный стиль и управление

- Master of Orion 2 - система создания рас

- Настольная игра "Эволюция" - перки и взаимодействия

- Crusader Kings 2 - песочница без явной цели

## Открытые вопросы для итераций

1. Порядок добавления новых животных после MVP

2. Приоритеты перков по импакту на геймплей

3. Баланс между реализмом и fan-фактором

4. Оптимальная скорость восстановления маны

5. Визуальные эффекты для разных состояний животных

## Идеи для будущих версий

- Критический урон и статус кровотечения

- Следы крови как визуальный элемент

- День/ночь с соответствующими изменениями поведения

- Продвинутые территориальные механики

- Болезни и паразиты как фактор популяции

- Более сложные социальные взаимодействия

2025-06-11-mvp.md

# План агентной разработки: Симулятор экосистемы саванны

## Описание проекта

### Концепция

Игра-песочница с симуляцией экосистемы африканской саванны. Игрок наблюдает за живой экосистемой и может создавать собственные виды животных, экспериментируя с их параметрами. Цель - создать устойчивые виды, которые смогут выжить и процветать в экосистеме.

### Ключевые особенности

- Детерминированная симуляция: один seed = одинаковый результат

- Изометрическая графика: стиль StarCraft 1

- Масштабируемость: от десятков до тысяч животных

- Энергетический баланс: солнце → трава → травоядные → хищники

- Реалистичное поведение: голод, жажда, размножение, смерть

### MVP функциональность

- Статичная карта с растущей травой

- Два вида животных: зайцы (травоядные) и волки (хищники)

- Базовые потребности: голод и здоровье

- Простое поведение: поиск еды, охота, размножение

- Устойчивая экосистема без вмешательства игрока

## Детальные требования

### Животные и их поведение

#### Заяц (травоядное)

- Размер: малый (радиус ~5 единиц)

- Скорость: средняя (20 единиц/сек)

- Здоровье: 50 хитов

- Поведение:

- При голоде < 70%: ищет ближайшую траву

- При виде волка в радиусе 50: убегает в противоположном направлении

- При сытости > 80% и безопасности: может размножаться

- Ест траву при контакте (10 единиц травы = 20% сытости)

#### Волк (хищник)

- Размер: средний (радиус ~10 единиц)

- Скорость: быстрая (30 единиц/сек при охоте)

- Здоровье: 100 хитов

- Поведение:

- При голоде < 60%: ищет ближайшего зайца

- Преследует выбранную жертву до поимки

- Атакует при контакте (убивает зайца за 1-2 удара)

- Поедание зайца восстанавливает 50% сытости

### Механики

#### Голод

- Уменьшается на 1% каждые 5 секунд

- При 0% животное начинает терять здоровье (1 хит/сек)

- Влияет на скорость:

- 0-20%: скорость x0.5

- 80-100%: скорость x0.8 (переедание)

#### Здоровье

- Восстанавливается при сытости > 50%: +1 хит/10 сек

- Влияние на параметры: при 50% здоровья все параметры x0.7

#### Движение

- Векторная система притяжения/отталкивания

- Прямое движение при отсутствии препятствий

- Обход препятствий простым отклонением

- Инерции нет, повороты мгновенные

#### Размножение

- Требования: сытость > 80%, здоровье > 70%, рядом особь того же вида

- Появляется 1-2 детёныша рядом с родителями

- Детёныши имеют 50% размера и параметров взрослых

### Мир и окружение

#### Карта (MVP)

- Размер: 50x50 тайлов (1 тайл = 32 пикселя)

- Плоская местность с травой

- Несколько водоёмов (круглые озёра)

- Группы кустов (препятствия и укрытия)

#### Трава

- Начальное покрытие: 70% карты

- Рост: +1 единица каждые 2 секунды до максимума 100

- Поедание: заяц съедает 10 единиц за 1 секунду контакта

- Не растёт на воде и в радиусе 1 тайл от воды

### Технические детали

#### Константы производительности

const (
  MAX_ENTITIES = 1000
  WORLD_SIZE = 50
  TILE_SIZE = 32
  FIXED_TIMESTEP = 1.0/60.0  // 60 TPS
)

#### Детерминированность

- Фиксированный timestep

- Seed-based генерация

- Стабильная сортировка сущностей

- Никаких недетерминированных map итераций

## Структура проекта

savanna/
├── Makefile                    # Единая точка входа для всех команд
├── go.mod                      # Go модуль
├── go.sum
├── README.md                   # Документация проекта
├── config/
│   ├── config.go              # Конфигурация игры
│   └── config.yaml            # Дефолтные настройки
├── cmd/
│   ├── game/                  # GUI версия
│   │   └── main.go
│   └── headless/              # Консольная версия для тестов
│       └── main.go
├── internal/
│   ├── core/                  # Ядро симуляции
│   │   ├── world.go          # Основной мир
│   │   ├── entity.go         # ECS базовые типы
│   │   ├── components.go     # Компоненты ECS
│   │   └── systems.go        # Системы ECS
│   ├── simulation/           # Логика симуляции
│   │   ├── animal.go         # Поведение животных
│   │   ├── vegetation.go     # Система растительности
│   │   ├── movement.go       # Система движения
│   │   └── feeding.go        # Система питания
│   ├── physics/              # Физика и коллизии
│   │   ├── vector.go         # Векторная математика
│   │   ├── collision.go      # Детекция коллизий
│   │   └── spatial.go        # Пространственная сетка
│   ├── rendering/            # Отрисовка (только для GUI)
│   │   ├── renderer.go       # Основной рендерер
│   │   ├── camera.go         # Камера и масштаб
│   │   └── sprites.go        # Загрузка спрайтов
│   └── generator/            # Генерация мира
│       ├── terrain.go        # Генерация ландшафта
│       └── population.go     # Начальная популяция
├── assets/                    # Ресурсы игры
│   ├── sprites/              # Спрайты животных
│   │   ├── rabbit/           # idle.png, walk.png, eat.png...
│   │   └── wolf/             # idle.png, walk.png, attack.png...
│   └── terrain/              # Спрайты местности
├── tests/
│   ├── unit/                 # Unit тесты
│   ├── integration/          # Интеграционные тесты
│   ├── performance/          # Тесты производительности
│   └── fixtures/             # Тестовые данные
├── scripts/
│   ├── generate_sprites.md   # Инструкции для генерации
│   └── balance_test.go       # Скрипты балансировки
└── docs/
    ├── architecture.md       # Архитектура проекта
    └── llm-prompts/         # Сохранённые промпты

## Makefile команды

# Основные команды
make build          # Собрать обе версии
make run            # Запустить GUI версию
make run-headless   # Запустить headless версию
make test           # Все тесты
make test-unit      # Только unit тесты
make test-perf      # Тесты производительности
make bench          # Бенчмарки

# Разработка
make fmt            # Форматирование кода
make lint           # Линтер
make generate       # Генерация кода
make profile        # Запуск с профилированием

# Симуляция
make simulate       # Запуск headless симуляции
make balance        # Тесты баланса

## Этапы разработки

### Этап 0: Инициализация проекта (30 мин)

Промпт для Claude Code:

Создай базовую структуру Go проекта для игры-симулятора экосистемы:
1. Инициализируй go.mod с именем github.com/aiseeq/savanna
2. Создай структуру папок согласно плану
3. Создай Makefile с базовыми командами (build, test, run)
4. Добавь .gitignore для Go проектов
5. Создай заглушки main.go для cmd/game и cmd/headless
6. Настрой go.mod с зависимостями: github.com/hajimehoshi/ebiten/v2

Результат: Компилируемый проект с базовой структурой

### Этап 1: Математика и физика (2 часа)

Промпт для Claude Code:

Реализуй базовую математику для 2D симуляции:
1. internal/physics/vector.go - Vec2 с операциями (add, sub, mul, normalize, distance)
2. internal/physics/collision.go - проверка коллизий круг-круг, круг-прямоугольник
3. internal/physics/spatial.go - пространственная сетка для быстрого поиска соседей
4. Покрой всё unit тестами с table-driven подходом
5. Добавь бенчмарки для критичных операций

Результат: Математическая база с тестами

### Этап 2: ECS архитектура (3 часа)

Промпт для Claude Code:

Создай простую но эффективную ECS систему для симулятора:

1. internal/core/entity.go:

type EntityID uint16  // До 65535 сущностей
type EntityManager struct {
   nextID EntityID
   freeIDs []EntityID  // Переиспользование ID
   alive [MAX_ENTITIES]bool
}
// Методы: CreateEntity(), DestroyEntity(id), IsAlive(id)

2. internal/core/components.go - компоненты как простые структуры:

type Position struct { X, Y float32 }
type Velocity struct { X, Y float32 }
type Health struct { Current, Max int16 }
type Hunger struct { Value float32 }  // 0-100
type Age struct { Seconds float32 }
type AnimalType uint8

const (
  TypeNone AnimalType = iota
  TypeRabbit
  TypeWolf
)

type Size struct { Radius float32 }
type Speed struct { Base, Current float32 }

3. internal/core/world.go - Arrays of Structs для оптимальной производительности:

type World struct {
  // Entity management
  entities EntityManager
  
  // Components - индексируются по EntityID
  positions [MAX_ENTITIES]Position
  velocities [MAX_ENTITIES]Velocity
  healths [MAX_ENTITIES]Health
  hungers [MAX_ENTITIES]Hunger
  ages [MAX_ENTITIES]Age
  types [MAX_ENTITIES]AnimalType
  sizes [MAX_ENTITIES]Size
  speeds [MAX_ENTITIES]Speed
  
  // Битовые маски для быстрой проверки наличия компонентов
  hasPosition [MAX_ENTITIES/64]uint64
  hasVelocity [MAX_ENTITIES/64]uint64
  // и т.д.
  
  // Вспомогательные данные
  time float32  // Общее время симуляции
  rng *rand.Rand  // Детерминированный генератор
}

4. Методы для работы с компонентами:

- AddComponent[T](entity, component) - generic метод

- GetComponent[T](entity) (T, bool)

- RemoveComponent[T](entity)

- HasComponent[T](entity) bool

Используй битовые операции для hasComponent масок

5. Системы запросов:

// Итератор по сущностям с определёнными компонентами
func (w *World) ForEachWith(components ComponentMask, fn func(EntityID))
  // Пример использования:
  w.ForEachWith(MaskPosition|MaskVelocity, func(e EntityID) {
  w.positions[e].X += w.velocities[e].X * dt
})

6. Тесты:

- Создание/удаление 1000 сущностей

- Добавление/удаление компонентов

- Проверка переиспользования ID

- Бенчмарк итерации по 1000 сущностям

- Проверка что нет утечек памяти при удалении

Результат: Высокопроизводительная ECS система без аллокаций в runtime

### Этап 3: Базовая симуляция (4 часа)

Промпт для Claude Code:

Реализуй основной цикл симуляции для экосистемы саванны:
1. internal/core/systems.go - интерфейс System с методом Update(world, dt)

2. internal/simulation/movement.go - MovementSystem:
- Обновление позиций по velocity
- Ограничение границами мира (50x50 тайлов)
- Мягкое расталкивание при коллизиях (круги)

3. internal/simulation/animal.go - базовое поведение животных:
   Константы:
- RABBIT_RADIUS = 5, RABBIT_SPEED = 20
- WOLF_RADIUS = 10, WOLF_SPEED = 30
- RABBIT_MAX_HEALTH = 50, WOLF_MAX_HEALTH = 100
- VISION_RANGE_RABBIT = 50, VISION_RANGE_WOLF = 100
   Поведение зайца:
- Если видит волка: velocity = normalize(rabbit_pos - wolf_pos) * RABBIT_SPEED
- Иначе: случайное блуждание (меняет направление каждые 2-5 сек)
   Поведение волка:
- Если голоден (hunger < 60): ищет ближайшего зайца в VISION_RANGE_WOLF
- Преследует: velocity = normalize(prey_pos - wolf_pos) * WOLF_SPEED
- Иначе: случайное блуждание с WOLF_SPEED * 0.5

4. internal/simulation/feeding.go - система голода:
- Hunger уменьшается на 0.2 каждый Update (1% за 5 сек при 60 TPS)
- При hunger = 0: health -= 1 каждую секунду
- При hunger < 20: скорость x0.5
- При hunger > 80: скорость x0.8

5. cmd/headless/main.go:
- Создать мир 50x50
- Разместить 20 зайцев и 3 волка случайно
- Каждую секунду выводить: кол-во живых зайцев/волков
- Детерминированный random с фиксированным seed

6. Интеграционный тест:
- 10 зайцев, 2 волка на поле 20x20
- Проверить что за 30 секунд хотя бы 1 заяц съеден
- Проверить детерминированность (2 запуска = одинаковый результат)

Результат: Работающая headless симуляция с базовым поведением

### Этап 4: Генерация мира (2 часа)

Промпт для Claude Code:

Добавь детерминированную генерацию карты саванны:
1. internal/generator/terrain.go:
   Структура мира:
   type Terrain struct {
       tiles [WORLD_SIZE][WORLD_SIZE]TileType
       grass [WORLD_SIZE][WORLD_SIZE]float32  // 0-100
   }

   Генерация:
- Базовый слой: вся карта - трава
- Водоёмы: 2-3 круглых озера радиусом 3-5 тайлов
- Вокруг воды: полоса влажной земли (1 тайл) где трава растёт быстрее
- Кусты: 5-10 групп по 3-7 кустов (препятствия для движения)
- Начальная трава: 50-100 единиц на 70% тайлов, 0 на воде

2. internal/generator/population.go:
   Размещение животных:
- Входные параметры: количество зайцев, волков
- Зайцы: группами по 2-4 особи (семьи)
- Волки: поодиночке, минимум в 20 тайлах друг от друга
- Не размещать на воде и кустах
- Начальные параметры: hunger=80%, health=100%

3. config/config.go и config.yaml:
   ```yaml
world:
size: 50
seed: 42
terrain:
water_bodies: 3
water_radius_min: 3
water_radius_max: 5
bush_clusters: 7
bush_per_cluster: 5
population:
rabbits: 30
wolves: 3
rabbit_group_size: 3
min_wolf_distance: 20
   ```

4. Детерминированность:
- Используй rand.NewSource(seed) для каждого генератора
- Генерация в фиксированном порядке: terrain → vegetation → animals
- Сохранение/загрузка seed для воспроизведения

5. Тесты:
- Генерация с одним seed 10 раз = идентичные карты
- Проверка что животные не в воде/кустах
- Валидация минимальных расстояний

Результат: Генерируемый мир с контролируемыми параметрами

### Этап 5: Растительность и питание (3 часа)

Промпт для Claude Code:

Реализуй полную систему питания для экосистемы:
1. internal/simulation/vegetation.go:
- Компонент Grass: amount float32 (0-100)
- GrassSystem: 
* Рост: +0.5 каждый Update если amount < 100
* Не растёт на воде и в радиусе 1 тайла от воды
- Сетка травы 50x50 (по тайлам)
- Начальное заполнение: 70% тайлов с grass = 50-100

2. Обнови internal/simulation/feeding.go:
   Питание зайца:
- При контакте с тайлом травы (amount > 10):
* grass.amount -= 10 за секунду
* rabbit.hunger += 20
- Максимум hunger = 100
   Охота волка:
- При контакте с зайцем: наносит 30 урона
- Если заяц умер: wolf.hunger += 50
- Труп исчезает сразу (в будущем - оставлять для падальщиков)

3. internal/simulation/animal.go - обнови поведение:
   Приоритеты зайца:
1. Если видит волка - убегать (всегда)
2. Если hunger < 70 - идти к ближайшей траве
3. Если сыт - случайное движение или отдых
   Приоритеты волка:
1. Если hunger < 60 - охотиться на ближайшего зайца
2. Если сыт - патрулировать территорию

4. Баланс экосистемы
- 1 тайл травы (100 единиц) должен кормить зайца ~50 секунд
- 1 заяц должен кормить волка ~100 секунд
- При 30 зайцах и 3 волках популяция должна быть стабильной

5. Тесты баланса:
- Запустить симуляцию на 10 минут
- Проверить что популяции не вымерли
- Проверить что трава не закончилась
- Вывести графики популяций

Результат: Замкнутая пищевая цепь с устойчивым балансом

### Этап 6: Графический интерфейс - Подготовка (1 час)

Инструкции для оператора:

# Генерация спрайтов
Необходимо создать базовые спрайты для MVP. Используй любой доступный AI генератор изображений.

## Требования к спрайтам:
- Размер: 32x32 пикселя
- Формат: PNG с прозрачным фоном
- Стиль: простой, читаемый при масштабировании
- Изометрическая проекция (вид 3/4)

## Необходимые спрайты:
### Заяц (assets/sprites/rabbit/)
- idle.png - стоит
- walk_1.png, walk_2.png - анимация ходьбы
- eat.png - ест
- sleep.png - спит
- dead.png - мёртв

### Волк (assets/sprites/wolf/)
- idle.png - стоит
- walk_1.png, walk_2.png - анимация ходьбы  
- run_1.png, run_2.png - бег
- attack.png - атакует
- eat.png - ест
- dead.png - мёртв

### Terrain (assets/terrain/)
- grass.png - тайл травы 32x32
- water.png - тайл воды 32x32
- bush.png - куст 32x32

## Цветовая схема:
- Заяц: коричневый/серый
- Волк: серый/тёмный
- Трава: жёлто-зелёная (саванна)
- Вода: голубая
- Кусты: тёмно-зелёные

Сохрани все спрайты в соответствующие папки.

Промпт для Claude Code после генерации спрайтов:

Создай систему загрузки и управления спрайтами:
1. internal/rendering/sprites.go:
   - LoadSprites() - загрузка всех спрайтов
   - GetSprite(entity, state) - получение нужного спрайта
   - Кеширование загруженных изображений

2. Обработка ошибок если спрайты не найдены
3. Заглушки (цветные квадраты) для отсутствующих спрайтов

### Этап 7: Базовый рендеринг (4 часа)

Промпт для Claude Code:

Реализуй графическую версию игры в изометрическом стиле:
1. internal/rendering/renderer.go:
   Порядок отрисовки (важно!):
   1. Тайлы местности (трава, вода)
   2. Кусты и препятствия
   3. Животные, отсортированные по Y (дальние сначала)

   Преобразование координат:
   - Мир: 50x50 тайлов, каждый 32x32 пикселя
   - Изометрия: screen_x = (world_x - world_y) * TILE_WIDTH/2
   - screen_y = (world_x + world_y) * TILE_HEIGHT/4

   Отрисовка животных:
   - Позиция в центре спрайта
   - Выбор спрайта по состоянию (idle/walk/eat/dead)
   - Плавное движение между тайлами

2. internal/rendering/camera.go:
   - Позиция камеры в мировых координатах
   - Zoom уровни: 0.5x, 1x, 2x, 4x
   - Ограничения камеры границами мира
   - Плавное движение (lerp)

3. cmd/game/main.go - Ebiten приложение:
   type Game struct {
       world *core.World
       renderer *rendering.Renderer
       camera *rendering.Camera
       lastUpdate time.Time
   }

   Update():
   - WASD - движение камеры (10 тайлов/сек)
   - Колесо мыши - zoom in/out
   - Обновление симуляции с FIXED_TIMESTEP
   - Накопление времени для стабильного FPS

   Draw():
   - Отрисовка только видимых тайлов (frustum culling)
   - Батчнг однотипных спрайтов
   - FPS счётчик в углу

4. Оптимизация:
   - Предзагрузка всех спрайтов
   - Повторное использование DrawImageOptions
   - Пропуск отрисовки за пределами экрана
   - Целевой FPS: 60 при 100 животных

5. Дебаг режим (F3):
   - Показать границы тайлов
   - Радиусы коллизий животных  
   - Векторы движения
   - ID сущностей

Результат: Играбельная версия с изометрической графикой

### Этап 8: UI и взаимодействие (3 часа)

Промпт для Claude Code:

Добавь интерфейс и базовые механики размножения:
1. Информация о животном при клике:
   internal/rendering/ui.go:
   - Определение клика по животному (с учётом изометрии)
   - Панель информации:
     * Тип (Заяц/Волк)
     * Здоровье: 45/50 HP
     * Сытость: 67%
     * Возраст: 2.5 минут
     * Состояние: "Ищет еду" / "Убегает" / "Охотится"
   - Подсветка выбранного животного

2. Глобальная статистика (правый верхний угол):
   - Зайцы: 24 (рождений: 5, смертей: 11)
   - Волки: 3 (рождений: 0, смертей: 0)
   - Общая биомасса травы: 4250
   - Время: 05:42
   - FPS: 60 / TPS: 60

3. Управление временем (клавиши 1-4 или UI кнопки):
   - Пауза (пробел)
   - x1 - нормальная скорость
   - x2 - ускорение
   - x5 - максимальное ускорение
   - При ускорении можно пропускать отрисовку кадров

4. Добавь базовое размножение:
   internal/simulation/breeding.go:
   - Проверка условий каждые 5 секунд:
     * Сытость > 80%
     * Здоровье > 70% 
     * Возраст > 1 минута
     * Партнёр того же вида в радиусе 10
   - Рождение 1-2 детёнышей (50% вероятность на 2)
   - Детёныши:
     * 50% размера родителей
     * Растут до полного размера за 1 минуту
     * Начальные hunger=50%, health=100%
   - Визуализация: сердечки над родителями 2 сек

5. Сохранение/загрузка (JSON):
   - F5 - быстрое сохранение в savegame.json
   - F9 - быстрая загрузка
   - Сохранять: позиции, параметры всех животных, состояние травы, время, seed

6. Расширенный дебаг режим (F3):
   - ID животных над спрайтами
   - Векторы движения (стрелки)
   - Радиусы обзора (полупрозрачные круги)
   - Сетка тайлов
   - Количество травы на тайле

Результат: Полноценный интерактивный интерфейс с размножением

### Этап 9: Балансировка и тесты (4 часа)

Промпт для Claude Code:

Создай систему для балансировки:
1. scripts/balance_test.go - автоматические тесты баланса:
   - Запуск 100 симуляций с разными параметрами
   - Проверка устойчивости популяций
   - Поиск оптимальных коэффициентов

2. cmd/headless/main.go - режим для массовых тестов:
   - Параметры через флаги командной строки
   - CSV вывод результатов
   - Режим ускоренной симуляции

3. tests/integration/ecosystem_test.go:
   - Тест на вымирание
   - Тест на перенаселение
   - Тест на стабильность

4. Makefile targets для автоматической балансировки

Результат: Сбалансированная экосистема

### Этап 10: Полировка MVP (2 часа)

Промпт для Claude Code:

Финальная полировка:
1. README.md с инструкциями по запуску
2. Дефолтный config.yaml с хорошим балансом
3. Обработка всех edge cases (выход за границы и т.д.)
4. Логирование важных событий
5. Проверка производительности (1000 животных = 60 FPS)
6. Финальный прогон всех тестов
7. Добавь комментарии к публичным функциям

Результат: Готовый к релизу MVP

## Формулы и коэффициенты

### Энергетический баланс

Солнечная энергия (условно 1000 единиц/сек на всю карту)
↓
Трава (КПД 10%): 100 единиц энергии/сек
↓
Зайцы (КПД 10%): 10 единиц энергии/сек  
↓
Волки (КПД 10%): 1 единица энергии/сек

### Метаболизм и потребление

- Заяц: тратит 0.2 энергии/сек (голод), получает 2.0 от травы

- Волк: тратит 0.1 энергии/сек (голод), получает 50 от зайца

- Трава: растёт +0.5/сек до максимума 100

### Детерминированность - критические моменты

1. Никогда не используй:

- time.Now() для игровой логики

- rand без фиксированного seed

- итерацию по map (используй слайсы)

- горутины в симуляции

2. Всегда используй:

- Фиксированный timestep (1/60 сек)

- Стабильную сортировку (sort.SliceStable)

- Один глобальный rand с seed

- Целочисленную или фиксированную арифметику где возможно

### Оптимизация - ключевые точки

// Spatial hash для поиска соседей
type SpatialGrid struct {
  cellSize float32
  cells map[uint64][]EntityID  // key = (x/cellSize) << 32 | (y/cellSize)
  
  // Для избежания аллокаций
  queryBuffer [MAX_NEARBY]EntityID
}

// Добавление в сетку (вызывается при движении)
func (g *SpatialGrid) Update(id EntityID, oldX, oldY, newX, newY float32) {
  oldKey := g.getKey(oldX, oldY)
  newKey := g.getKey(newX, newY)
  if oldKey != newKey {
    g.removeFromCell(oldKey, id)
    g.addToCell(newKey, id)
  }
}

// Поиск соседей без аллокаций
func (g *SpatialGrid) FindNearby(x, y, radius float32) []EntityID {
  count := 0
  cellRadius := int(radius/g.cellSize) + 1
  centerI := int(x / g.cellSize)
  centerJ := int(y / g.cellSize)
  
  for di := -cellRadius; di <= cellRadius; di++ {
    for dj := -cellRadius; dj <= cellRadius; dj++ {
      key := g.getKey(float32((centerI+di)*int(g.cellSize)), 
      float32((centerJ+dj)*int(g.cellSize)))
      for _, id := range g.cells[key] {
        // Точная проверка расстояния
        if distance(x, y, positions[id].X, positions[id].Y) <= radius {
          g.queryBuffer[count] = id
          count++
          if count >= MAX_NEARBY { 
            return g.queryBuffer[:count] 
          }
        }
      }
    }
  }
  return g.queryBuffer[:count]
}

// Object pooling для частых аллокаций
var vector2Pool = &sync.Pool{
  New: func() interface{} { return &Vec2{} },
}

// SOA (Structure of Arrays) вместо AOS для компонентов
type Components struct {
  // Хорошо для кэша CPU - данные расположены последовательно
  positions [MAX_ENTITIES]Vec2    
  velocities [MAX_ENTITIES]Vec2
    
  // Плохо для кэша - разрозненные данные
  // entities [MAX_ENTITIES]Entity{pos, vel, health...}
}

## Дополнительные детали реализации

### Векторная система движения

// Расчёт результирующего вектора движения
func CalculateMovement(animal EntityID, world *World) Vec2 {
  var result Vec2
  // 1. Отталкивание от угроз (приоритет)
  threats := FindThreatsInRadius(animal, VISION_RANGE)
  for _, threat := range threats {
    diff := animal.pos.Sub(threat.pos)
    weight := 1.0 - (diff.Length() / VISION_RANGE)
    result = result.Add(diff.Normalize().Mul(weight * THREAT_WEIGHT))
  }
  
  // 2. Притяжение к цели (еда)
  if animal.hunger < 70 {
    food := FindNearestFood(animal)
    if food != nil {
      diff := food.pos.Sub(animal.pos)
      result = result.Add(diff.Normalize().Mul(FOOD_WEIGHT))
    }
  }
  
  // 3. Случайное блуждание (если нет других стимулов)
  if result.Length() < 0.1 {
    result = RandomDirection().Mul(WANDER_WEIGHT)
  }
  return result.Normalize().Mul(animal.speed)
}

### Состояния животных (для выбора спрайтов)

type AnimalState int

const (
  StateIdle AnimalState = iota
  StateWalking
  StateRunning  
  StateEating
  StateAttacking
  StateSleeping
  StateDead
)

func GetAnimalState(e EntityID, w *World) AnimalState {
  if w.healths[e] <= 0 { return StateDead }
  if w.velocities[e].Length() < 0.1 { return StateIdle }
  if w.velocities[e].Length() > WALK_SPEED { return StateRunning }
  if w.isEating[e] { return StateEating }
  return StateWalking
}

## Чек-лист готовности MVP

- [ ] Мир 50x50 с травой

- [ ] Зайцы и волки с базовым поведением

- [ ] Зайцы едят траву, волки едят зайцев

- [ ] Трава восстанавливается

- [ ] Устойчивая экосистема

- [ ] GUI с масштабированием

- [ ] Headless режим для тестов

- [ ] Все тесты проходят

- [ ] 60 FPS при 100 животных

- [ ] Документация

## Метрики успеха

1. Производительность: 1000 животных при 60 FPS

2. Стабильность: популяции не вымирают 10+ минут

3. Детерминированность: одинаковый seed = одинаковый результат

4. Тестируемость: 80%+ покрытие кода

5. Модульность: легко добавить нового зверя

## Важные принципы для промптов

1. Всегда проси тесты - каждая функция должна быть покрыта

2. Фиксированные размеры - используй константы MAX_ENTITIES

3. Никаких аллокаций в циклах - переиспользуй буферы

4. Детерминированность - никаких map итераций

5. Профилирование - проси добавлять pprof точки

## Советы для работы с Claude Code

### Структура промптов

1. Начинай с контекста: "Мы разрабатываем симулятор экосистемы саванны..."

2. Указывай файлы явно: "Создай файл internal/physics/vector.go"

3. Проси тесты сразу: "...и напиши unit тесты в vector_test.go"

4. Уточняй производительность: "Функция будет вызываться 1000 раз за кадр"

### Частые проблемы и решения

- Claude забывает константы: держи файл config/constants.go и напоминай о нём

- Неоптимальный код: явно проси избегать аллокаций в циклах

- Недетерминированность: проверяй каждый use case с rand и map

- Путаница с координатами: рисуй схемы в комментариях

### Отладка производительности

# Встрой в Makefile
profile:
go run -cpuprofile=cpu.prof cmd/headless/main.go -duration=30s
go tool pprof -http=:8080 cpu.prof

# Добавь в main.go
import _ "net/http/pprof"

go func() { http.ListenAndServe("localhost:6060", nil) }()

## Финальные напоминания

1. MVP first: не усложняй! Сначала рабочая версия, потом фичи

2. Тесты важны: каждый этап должен завершаться зелёными тестами

3. Сохраняй промпты: для статьи на Хабр это золото

4. Коммить часто: после каждого успешного этапа

5. Профилируй рано: проблемы производительности сложно фиксить потом

## Ожидаемые метрики MVP

- 20-30 зайцев + 2-3 волка = стабильная популяция

- 100 животных = 60 FPS на среднем ПК

- 10 минут симуляции без вымирания

- Детерминированность: diff между прогонами = 0

## Команда для старта

# Этап 0: Инициализация
mkdir savanna && cd savanna

# Далее копируй промпт из Этапа 0 в Claude Code

Удачи в разработке! 🐰🐺🌿

Рекомендую использовать наработки из моего файла CLAUDE.md - этот файл содержит инструкции для агента, которые он получает после каждой очистки памяти. Естественно, вам следует адаптировать его под особенности вашего проекта. Я здесь привожу не тот файл с которого я начинал, а тот, что использую на момент написания статьи. Этот документ должен эволюционировать вместе с вашим проектом подстраивая модель под него и под ваш стиль управления. Этот файл хранится в корне проекта.

CLAUDE.md

# CLAUDE.md

Руководство для Claude Code при работе с кодовой базой проекта Savanna.

## Основные принципы

Я всегда отвечаю пользователю на русском языке.

У меня есть время сделать всё правильно, максимально качественно. Я не оставляю проблемы на потом. Я не использую заглушки, хардкод, моки, упрощённую логику. Избегаю всяческих workarounds. Я пишу чистый полноценный код соблюдая все стандарты качества, или не пишу кода вовсе.

Когда я пишу тесты, они проверяют работу реального функционала, не используют моков, все вызовы делаются к реальным функциям.

Я тщательно исследую проект перед выполнением любых задач. Я проверяю, что уже реализовано в проекте, чтобы не дублировать функциональность. Я предлагаю план действий и получаю подтверждение пользователя перед началом работы.

Я проверяю реальное состояние системы перед любыми заявлениями о результатах.

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

Я честно сообщаю как об успехах, так и о проблемах, начиная отчёт с того, что требует внимания.

Я пишу в профессиональном тоне без излишней эмоциональности - избегаю капслока (ЗАГЛАВНЫХ БУКВ) кроме редчайших критически важных случаев.

Я создаю конкретные и содержательные коммиты, описывающие что именно было сделано, а не общие фразы вроде "100% тестов" или "всё работает". Перед коммитом я удаляю все временные и мусорные файлы.

Я стремлюсь к краткости при редактировании CLAUDE.md - оставляю только критически важную информацию, из которой смогу сделать нужные выводы, избегаю избыточных деталей и примеров.

## Принципы качества кода

Я ВСЕГДА следую принципам SOLID, DRY и Clean Architecture при разработке:

### SOLID принципы:

- SRP: Каждый класс/функция имеет одну ответственность

- OCP: Код открыт для расширения, закрыт для изменения  

- LSP: Подклассы заменяемы базовыми классами

- ISP: Интерфейсы специфичны для клиентов

- DIP: Зависимости от абстракций, не от конкретных реализаций

### Архитектурные паттерны:

- Специализированные handler'ы по доменам

- Единые модели данных в отдельном пакете

- Четкое разделение concerns между слоями

### Стандарты качества:

- Никогда не дублирую код - создаю переиспользуемые компоненты

- Разбиваю большие файлы на специализированные модули

- Использую dependency injection для лучшей тестируемости

## 🚫 АБСОЛЮТНЫЙ ЗАПРЕТ НА МОКИ 🚫

Я КАТЕГОРИЧЕСКИ ЗАПРЕЩАЮ себе использовать любые моковые данные в production коде:

❌ НИКОГДА НЕ ИСПОЛЬЗУЮ:

- Тестовые константы в UI компонентах

- Hardcoded "примеры" данных

✅ ВСЕГДА ИСПОЛЬЗУЮ:

- Актуальные данные

### Test-First Development Процесс

ВСЕГДА перед любыми изменениями кода:

1. СНАЧАЛА пишу ПАДАЮЩИЙ тест который воспроизводит проблему или требуемую функциональность

2. Проверяю что тест падает с правильной ошибкой

3. Пишу минимальный код для прохождения теста

4. Проверяю что тест проходит

5. Рефакторю код при необходимости, поддерживая прохождение тестов

6. Запускаю все связанные тесты для проверки отсутствия регрессий

### Meaningful Testing Strategy

✅ ПРИОРИТЕТНЫЕ виды тестов (создаю в первую очередь):

- Critical Path E2E тесты - полные user journeys без моков internal компонентов

- Real Integration тесты - real calls, real business logic

- Error Scenario тесты - comprehensive обработка всех видов ошибок

🔄 ДОПУСТИМЫЕ виды тестов (создаю при необходимости):

- Unit тесты complex logic - только для сложной бизнес-логики и математических функций

- Component integration тесты - тестирование integration между реальными компонентами

❌ ЗАПРЕЩЁННЫЕ виды тестов (НЕ создаю):

- Trivial тесты - expect(2+2).toBe(4), тестирование библиотечных функций

- Shallow тесты - expect(component).toRender() без проверки functionality

- Mock-heavy тесты - тесты где все dependencies замокированы

- Duplicate тесты - multiple tests проверяющие одинаковую functionality

### Test Quality Standards

Каждый тест ОБЯЗАТЕЛЬНО:

- Тестирует real business value - решает реальную проблему пользователя

- Использует real integrations - минимум моков, максимум real calls

- Имеет clear failure scenarios - понятно что именно сломалось

- Проверяет end-to-end behavior - не только happy path, но и error cases

- Independent и isolated - может выполняться отдельно от других тестов

### Проверка и валидация

Я не доверяю слепо сообщениям об ошибках - если код говорит "порт занят" или "файл не найден", я проверяю это самостоятельно.

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

Я использую полные абсолютные пути к файлам и командам в проекте.

## КРИТИЧЕСКИ ВАЖНО: Валидация результатов тестирования

Я НИКОГДА не заявляю об успехе тестов, основываясь только на выводе "PASS" отдельных тестовых функций.

Я ОБЯЗАТЕЛЬНО проверяю финальный exit code команды тестирования:

- make test; echo "Exit code: $?"

- go test ./...; echo "Exit code: $?"

Я понимаю, что все отдельные тесты могут проходить (показывать PASS), но пакет в целом может падать с FAIL из-за:

- Игнорирования ошибок

- Проблем с TestMain функцией

- Ошибок cleanup после тестов  

- Проблем сборки или связывания модулей

- Конфликтов зависимостей

Я честно сообщаю пользователю, если exit code != 0, даже когда все отдельные тесты показывают PASS.

Я НЕ называю тестирование "100% успешным", пока не убежусь что exit code = 0.

## КРИТИЧЕСКИ ВАЖНО: Запрет на преждевременные заявления о готовности

Я НИКОГДА НЕ ЗАЯВЛЯЮ о готовности решения без ПОЛНОГО E2E тестирования.

Я ОБЯЗАТЕЛЬНО провожу E2E тестирование для проверки:

- Реальной работы приложения

- Корректного отображения данных в UI

- Отсутствия ошибок

- Правильной интеграции

❌ НЕДОСТАТОЧНО для заявления о готовности:

- Успешные unit тесты

- Логи показывающие что приложение работает

- Smoke тесты общего здоровья системы

### Принципы работы с падающими тестами

Философия: Падающий тест = ценный сигнал, НЕ препятствие

Я понимаю, что падающие тесты ловят регрессии и предотвращают поломку функциональности.

СТРОГО ЗАПРЕЩЕННЫЕ действия:

- ❌ УДАЛЯТЬ падающие тесты (это скрывает регрессии!)

- ❌ УПРОЩАТЬ тесты до бессмысленности

- ❌ ИГНОРИРОВАТЬ падающие тесты ради новых фич

Правильный алгоритм работы с падающими тестами:

- Падающий тест = сигнал о регрессии в коде

- СНАЧАЛА понять что сломалось в реальной функциональности

- Исправить первопричину в коде, а не в тесте

### Принципы тестирования

Даже для отладки использую только headless режим или другие методы диагностики.

Я всегда запускаю тесты после реализации или модификации кода.

Я использую реальные вызовы между компонентами системы.

Я создаю тесты, которые работают с реальными данными и моделями, а не с заглушками.

Я ВСЕГДА запускаю параллельные тесты везде, где это возможно - это значительно ускоряет разработку.

Я НЕ запускаю тесты в 1 потоке без явной причины - это медленно и может приводить к таймаутам.

Одиночный поток использую ТОЛЬКО для отладки конкретного падающего теста

## Принципы качественного кода

### SOLID принципы

Я следую принципам SOLID для поддержания высокого качества кода:

Single Responsibility (SRP):

- Каждый класс/функция имеет одну ответственность

- Избегаю "god objects" с множественными задачами

- Разделяю бизнес-логику, валидацию и персистентность

Open/Closed (OCP):

- Код открыт для расширения, закрыт для модификации

- Использую интерфейсы и абстракции

- Применяю паттерны Strategy и Template Method

Liskov Substitution (LSP):

- Подтипы должны быть заменяемы базовыми типами

- Соблюдаю контракты интерфейсов

- Избегаю нарушения ожиданий клиентского кода

Interface Segregation (ISP):

- Интерфейсы должны быть специфичными и узкими

- Клиенты не должны зависеть от неиспользуемых методов

- Разбиваю большие интерфейсы на мелкие, сфокусированные

Dependency Inversion (DIP):

- Модули высокого уровня не зависят от модулей низкого уровня

- Оба зависят от абстракций

- Использую dependency injection где возможно

### DRY и принципы переиспользования

Устранение дублирования:

- Выношу общую логику в utility функции

- Создаю базовые компоненты для повторяющихся UI элементов

- Использую константы для повторяющихся значений

- Централизую конфигурацию и типы

Принцип единой истины

### Clean Code практики

Читаемость кода:

- Использую осмысленные имена переменных и функций

- Пишу самодокументируемый код

- Избегаю глубокой вложенности (max 3 уровня)

- Ограничиваю размер функций (max 30 строк)

Структура и организация:

- Следую принципу "screaming architecture"

- Группирую связанные концепции вместе

- Применяю consistent code style

- Использую линтеры и форматтеры

Управление зависимостями:

- Минимизирую внешние зависимости

- Регулярно обновляю зависимости

### Архитектурные принципы

Слоистая архитектура:

- Repository layer для доступа к данным

- Service layer для бизнес-логики  

- Controller/Handler layer

- Presentation layer для UI

Разделение ответственности:

- UI компоненты только отображают данные

- Бизнес-логика изолирована в сервисах

- Валидация происходит на границах слоёв

- Персистентность абстрагирована репозиториями

### Принципы безопасности кода

## Технические стандарты

### Обработка ошибок

Я никогда не подавляю и не скрываю ошибки - всегда ищу и устраняю первопричину.

Я обеспечиваю graceful degradation - приложение продолжает работу даже при ошибках.

Я добавляю проверки на nil перед обращением к указателям и валидирую входные данные.

Я логирую проблемы, но не допускаю panic.

### Именование и форматирование

Я использую camelCase везде в frontend и backend коде (кроме Go пакетов):

- JSON поля: walletAddress, createdAt

- Go переменные: userAccount, depositAmount

Я оставляю snake_case только для:

- Имён Go пакетов

- Переменных окружения (SCREAMING_SNAKE_CASE)

### Работа с кодом

Я выполняю dos2unix для shell-скриптов после создания.

Я не создаю и не использую mock - всегда работаю с реальным кодом.

## Отчётность

Я заканчиваю отчёты обнаруженными проблемами и тем, что требует доработки.

Я указываю конкретные метрики: количество прошедших/упавших тестов, процент успешности.

Я даю честную оценку статуса: "частично работает", "требует доработки", а не "всё готово".

Я считаю систему готовой только когда все тесты проходят на 100%.

## Git и коммиты

🚫 СТРОЖАЙШИЙ ЗАПРЕТ НА КОММИТЫ БЕЗ РАЗРЕШЕНИЯ 🚫

Я КАТЕГОРИЧЕСКИ ЗАПРЕЩАЮ себе создавать коммиты без ЯВНОГО и ПРЯМОГО запроса пользователя.

Я НИКОГДА не создаю коммиты автоматически, даже если считаю это логичным.

Я ВСЕГДА спрашиваю разрешения перед созданием коммита: "Создать коммит с этими изменениями?"

Я предлагаю создать коммит только когда пользователь ПРЯМО попросит это сделать.

Если я нарушу это правило - это серьёзная ошибка с моей стороны.

Я пишу коммиты по существу, описывая конкретные изменения, а не общие фразы.

Я избегаю эмоциональных заглавных букв кроме исключительных случаев.

### РЕАЛЬНЫЕ ТЕСТЫ

Никаких моков для внутренних компонентов. Тесты используют реальный сервер

ЗАПРЕЩЕНО:

- Моки сервисов, репозиториев, handlers

- Fake данные в production коде

- Hardcoded responses

- WORKAROUNDS без согласования - всегда исправляй корневую проблему

### ПИРАМИДА ТЕСТОВ

Основной слой тестов — интеграционные. Unit-тесты — для утилит. E2E — для критических путей.

```

     E2E (Few)

  Integration (Many) ← ОСНОВНОЙ СЛОЙ

Unit (Some utilities only)

```

## 📏 Принципы качества

### Краткость

- Отвечаю на русском языке

- Минимизирую вывод токенов  

- Избегаю ненужных пояснений

- Один-три предложения максимум

### Точность

- Проверяю реальное состояние системы

- Ищу первопричины проблем

- Доверяю фактам, а не сообщениям об ошибках

- Честно сообщаю о проблемах

### Эффективность  

- Использую полные абсолютные пути

- Запускаю параллельные команды где возможно

- Пакетирую tool calls в одном сообщении

- НЕ создаю файлы без необходимости

### Детерминированность

Я СТРОГО соблюдаю принцип: headless и GUI режимы ДОЛЖНЫ использовать абсолютно одинаковые функции и логику.

Deteminism requirements:

- Фиксированный timestep (1/60 секунды)

- Единый RNG через world.GetRNG() для всей игровой логики

- Отсутствие time.Now() в симуляции

- Стабильная сортировка вместо итерации по map

## Рабочие процессы

### КРИТИЧЕСКИ ВАЖНО: Управление рабочими директориями

Я КАТЕГОРИЧЕСКИ ОБЯЗАН начинать КАЖДУЮ команду с cd к полному пути!

# ✅ ПРАВИЛЬНО
cd ~/savanna && make test
cd ~/savanna && make build

# ❌ НЕДОПУСТИМО
make test              # где я нахожусь?!
go build ./...         # что я билдлю?!

## Технические стандарты

### КРИТИЧЕСКИ ВАЖНО: Система единиц измерения

🎯 ЕДИНСТВЕННАЯ ЕДИНИЦА ИЗМЕРЕНИЯ В ИГРЕ - ТАЙЛЫ 🎯

Я СТРОГО соблюдаю принцип:

ФИЗИЧЕСКАЯ ШИРИНА ТАЙЛА = 1.0 (единица измерения)

- Все размеры, расстояния, радиусы измеряются в ТАЙЛАХ

- Пиксели используются ТОЛЬКО для отрисовки (32 пикселя = 1 тайл в изометрии)

- Константы в game_balance.go указаны в ТАЙЛАХ, не в пикселях

Примеры правильного мышления:

- ✅ "Заяц имеет радиус 0.25 тайла"

- ✅ "Волк видит на расстояние 4.16 тайла"

- ✅ "Карта размером 50x38 тайлов"

- ❌ "Заяц имеет радиус 8 пикселей" - НЕПРАВИЛЬНО!

В коде:

const (
    RabbitBaseRadius = 0.25  // Заяц - 0.25 тайла радиус
    WolfBaseRadius   = 0.5   // Волк - 0.5 тайла радиус
    RabbitBaseSpeed  = 0.6   // Заяц - 0.6 тайла/сек
    WolfBaseSpeed    = 1.0   // Волк - 1.0 тайл/сек
)

Разумные размеры для геймплея:

- ✅ Заяц: радиус 0.5 тайла, видение 3.0 тайла, скорость 0.6 тайла/сек

- ✅ Волк: радиус 0.75 тайла, видение ≈5.0 тайлов, атака 0.9 тайла, скорость 1.0 тайл/сек

### Константы и магические числа

Я НИКОГДА не использую "магические числа" в коде.

Все константы игрового баланса централизованы в internal/simulation/game_balance.go.

### Логика радиусов атак

- Радиус атаки атакующего должен быть БОЛЬШЕ его собственного радиуса (множитель > 1.0)

- Проверка возможности атаки: attack_range + target_radius > distance_between_centers

- Во всех константах атак я использую множители, а не абсолютные числа

### Команды Makefile

Сборка:

make build              # Собрать все версии (без линтинга)
make build-with-lint    # Собрать с проверкой линтера
make build-fast         # Собрать без линтинга (быстро)
make build-windows      # Собрать для Windows с отключенным DPI awareness

Запуск:

make run                # Запустить GUI версию
make run-animviewer     # Запустить просмотрщик анимаций
make run-visual-test    # Запустить визуальный тестовый режим (результаты в visual_analysis/)
make simulate           # Запуск симуляции
make profile            # Запуск с профилированием

Тестирование:

make test               # Все тесты с виртуальным дисплеем
make test-advanced      # Все продвинутые тесты (property, contract, behavioral, chaos)
make test-gui           # E2E тесты с виртуальным дисплеем
make test-all           # Все тесты включая GUI
make test-unit          # Только unit тесты (без виртуального дисплея)
make test-property      # Property-based тесты
make test-contract      # Contract тесты
make test-behavioral    # Behavioral тесты (Given-When-Then)
make test-chaos         # Chaos Engineering тесты
make test-mutation      # Mutation testing (проверка качества тестов)
make test-perf          # Тесты производительности
make bench              # Бенчмарки

Качество кода:

make fmt                # Форматирование кода
make lint-install       # Установить golangci-lint
make lint               # Линтер (автоустановка если нужно)
make lint-fix           # Автоисправление проблем линтера
make check              # Полная проверка кода (форматирование + линтер + тесты)

Утилиты:

make generate           # Генерация кода
make balance            # Тесты баланса
make clean              # Очистить сборочные файлы
make help               # Показать справку

## Контекст проекта: Симулятор экосистемы саванны

### Описание проекта

Детерминированная симуляция экосистемы африканской саванны с:

- Изометрическая графика: стиль StarCraft 1

- Масштабируемость: цель 1000 животных при 60 FPS

- Энергетический баланс: солнце → трава → травоядные → хищники

### Структура проекта

savanna/
├── cmd/                       # 3 исполняемых: game, headless, animviewer
├── internal/                  # ECS архитектура + игровая логика
│   ├── core/                  # ECS ядро системы
│   ├── simulation/            # Бизнес-логика животных
│   ├── physics/               # Векторная математика
│   ├── animation/             # Анимационная система
│   └── constants/             # Константы
├── assets/fonts/              # Централизованные ресурсы
├── tests/                     # 8 типов тестов
└── Makefile                   # Единая точка входа

### Животные и поведение

Заяц (травоядное):

- При голоде < 90%: ищет ближайшую траву

- При виде волка в радиусе 100: убегает

- При сытости > 80%: может размножаться

Волк (хищник):

- При голоде < 60%: охотится на зайцев

- Поедание зайца восстанавливает 50% сытости

### Целевые метрики

- 20-30 зайцев + 2-3 волка = стабильная популяция

- 10 минут симуляции без вымирания видов  

- 1000 животных при 60 FPS

- 100% детерминированность

Среда разработки

Claude code использует node.js, есть простые инструкции по установке для Linux и Mac, которые вы можете найти на сайте Anthropic. Но с Windows всё немного сложнее. Сначала вам надо поставить WSL, потом node и claude. Я так же крайне рекомендую создать отдельного не-рутового пользователя в WSL, чтобы ненароком claude чего-нибудь не испортил в вашей системе.

Я не буду приводить здесь инструкций по настройке и установке, особенно учитывая как быстро они устаревают, но рекомендую такую последовательность запросов к вашей любимой LLM:

  • Как установить WSL

  • Как создать не-рутового пользователя в WSL с правом на sudo

  • Как в WSL установить node.js и claude code

  • Как установить far2l в WSL (Я его использую вместо дефолтной консоли, очень удобно)

Но папка с кодом игры и VS Code в Windows, а Claude Code в WSL - как быть? Я просто создал симлинк из папки с нужным диском в домашнюю папку claude (я так пользователя назвал). После чего переходим в эту папку и запускаем claude. После короткой настройки обязательно выбираем /model sonnet (только если у вас не тариф за 200 баксов) и можно начать с вашей первой команды агенту.

Агент

Проанализируй задачу в docs\tasks\2025-06-11-mvp.md и добавь в claude.md весь необходимый контекст, который понадобится при её выполнении, даже если пока ни мейк-файла, ни структкры папок не существует.

Я не буду приводить здесь весь текст ответа от LLM. Но смысл в том, что нейронка проанализировала имеющиеся файлы и действительно обновила claude.md, и это - единственный файл, который я редактирую вручную после обновления, т.к. это даже не код, но по сути вступительная часть любого общения с агентом. Такую важную штуку полностью доверять нейронке нельзя.

Хорошо, коммит

И не нужно больше слов, модель умеет пользоваться гитом и другими инструментами доступными в консоли.

Теперь выполни первый этап из плана docs\tasks\2025-06-11-mvp.md

Модель послушно выполняет задание. Я компилирую код, и он успешно рисует пустое окно в Windows, но не в WSL.

Мы ведь можем решить проблему с запуском оконного приложения в wsl?

И модель решила проблему! Она предложила мне поставить необходимые пакеты (я разрешил ей использовать sudo), и после пары попыток я увидел рабочее окно.

Консоль Claude Code и окно игры Savanna
Консоль Claude Code и окно игры Savanna

Конец первой части

В этой статье мы разобрали процесс подготовки к агентной разработке и слегка прикоснулись непосредственно к процессу создания приложения. В следующей статье вас ждёт больше интересных историй, невероятных откровений, а главное - методик работы с агентной LLM. Приложение станет больше похоже на демку: зайцы, волки, охота, переход из прямоугольного поля в изометрию и многое другое. Актуальную версию проекта можно найти тут: https://github.com/aiseeq/savanna

Tags:
Hubs:
+5
Comments14

Articles