Модуль Армии (Bogatyri.Army, без Unity): - гарнизон — часть воинов в городе: защищает город и в походы не уходит, всего воинов столько же - IArmy: GarrisonTotal, GetGarrison(type), AvailableForMarch, SetGarrison(count) - гарнизон набирается по составу армии, не больше воинов в городе; после потерь обрезается по типам - в поход уходят только свободные воины (TakeForMarch) - сохранение: строка garrison= в секции army (старые сохранения — без гарнизона); сброс очищает - TroopsChangedEvent.Garrison Интерфейс: - окно «Войска» в городе: карточка «Гарнизон города» (0, -10, -1, +1, +10, «Все») - карта мира: «Свободно / Гарнизон / В походе», ползунок похода и прогноз — только по свободным воинам - понятная ошибка, если воины есть, но все в гарнизоне Тест «один солдат в одном месте»: 30 воинов, 10 в гарнизон → 20 свободны, всего 30 (решение команды от 19.10.2026). Документы Army, Core, World, README обновлены. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
9.7 KiB
Армия
Войска и их характеристики: сколько воинов каждого типа в городе, сколько из них в гарнизоне, сколько в походах, обучение, потери, уход в поход и возвращение. Единственное место, где хранятся войска.
- Сборка:
Bogatyri.Army(без Unity). - Папка:
Assets/Scripts/Modules/Army. - Зависит от: ядра.
Контракт IArmy
| Член | Что делает |
|---|---|
TypeCount |
Типов войск — 4 (пехота, лучники, кавалерия, осадные; порядок как в GameData.Troops). |
GetTroops(type) |
Воинов этого типа в городе. |
SoldiersAtHome |
Всего воинов в городе (вместе с гарнизоном). |
TroopsInMarches |
Воинов в походах. |
GarrisonTotal, GetGarrison(type) |
Сколько воинов в гарнизоне — всего и по типам. |
AvailableForMarch |
Свободные воины: в городе минус гарнизон. Только их можно отправить в поход. |
SetGarrison(count) |
Назначить гарнизон: набирается по составу армии в городе (30 пехоты и 10 лучников, гарнизон 8 → 6 пехоты и 2 лучника). Не больше, чем воинов в городе; возвращает, сколько назначено. |
AddTroops(type, count) |
Добавить воинов (обучение в Казармах). |
LoseFraction(fraction) |
Потери в бою: от каждого типа погибает доля (с округлением вниз); возвращает, сколько погибло. |
TakeForMarch(marchId, count) |
Забрать свободных воинов (без гарнизона) в поход пропорционально составу и запомнить состав. |
ReturnFromMarch(marchId, survivors) |
Вернуть выживших по тем же типам (пропорционально). |
GetMarchUnits(marchId) |
Состав похода по типам — для боя с типами войск. |
ReturnUnits(marchId, survivorUnits) |
Вернуть выживших точно по типам, как посчитал бой. Больше, чем ушло, не вернётся. |
Получить: GameServices.Get<IArmy>(). Регистрирует App/GameModules. GameProgress (обучение, кампания, арена, сила армии) и панели работают с войсками только через этот контракт.
Правило «один солдат в одном месте»
Воин либо в городе, либо в походе. Поход забирает воинов из города и запоминает состав, возвращение раздаёт выживших по тем же типам. Тест ArmyService_MarchNeverCreatesOrLosesSoldiers проверяет, что «дома + в походах» всегда равно общему числу.
Гарнизон — часть воинов города. Они по-прежнему в городе (SoldiersAtHome), но в поход не уходят:
- 30 воинов, 10 в гарнизоне → 20 свободны, всего по-прежнему 30 (тест
ArmyService_Garrison_OneSoldierInOnePlace); - гарнизон по каждому типу никогда не больше воинов этого типа: после потерь (
LoseFraction) он обрезается; - новые воины из Казарм становятся свободными, гарнизон не меняется;
- назначается в окне «Войска» в городе, карточка «Гарнизон города»: кнопки 0, -10, -1, +1, +10, «Все».
Пока гарнизон только держит воинов дома: на город игрока никто не нападает. Защита города, еда гарнизона и дебаффы при голоде — по плану ниже.
События
- Публикует:
TroopsChangedEvent(воинов в городе, из них в гарнизоне, и в походах) — при обучении, потерях, походе, возвращении, загрузке, сбросе. По немуApp/GameModulesперерисовывает панели HUD. - Слушает: ничего.
Сохранение
Секция "army". Модуль без Unity, поэтому формат — простые строки:
troops=<пехота>,<лучники>,<кавалерия>,<осадные>
garrison=<пехота>,<лучники>,<кавалерия>,<осадные> (часть troops)
march=<id похода>:<пехота>,<лучники>,<кавалерия>,<осадные>
Старое сохранение без строки garrison читается: гарнизона нет.
Сброс (ResetState): войск, гарнизона и походов нет.
Перенос из старых сохранений:
- Раньше войска лежали в
progress.json:troopsхранилGameProgress,sashaMarchUnits— мостArmyBridge. - Если в
save.jsonнет секции"army", после загрузкиApp/GameModulesпереносит их в модуль (ImportLegacy). - Из
progress.jsonони удаляются только после записиsave.json. ФлагarmyInModuleотмечает, что перенос сделан.
Файлы
| Файл | Что это |
|---|---|
ArmyService.cs |
Хранилище войск, реализует IArmy и ISaveParticipant. |
ArmyMath.cs |
TakeProportional — кого взять в поход; SplitSurvivors — как вернуть выживших. |
Решения и план
- Этап 5 (план разработки): солдат стоит 1 человека, 15 еды, 5 металла, 5 золота; содержание 0,2 еды в час; погибшие уменьшают население. Делается вместе с модулем «Население».
- Решение команды от 19.10.2026:
- войска набираются из населения с сохранением гражданского минимума;
- гарнизон поселения: часть солдат назначается защищать город;
- общая армия = гарнизон + доступные отряды + войска в походах, на точках и в гарнизоне Круга, один солдат не может быть в двух местах;
- гарнизон ест еду и участвует в защите;
- при голоде дебаффы действуют и на гарнизон, и на походы.
- Сделано 27.10.2026: гарнизон города (
SetGarrison,AvailableForMarch). - Дальше по гарнизону: участие в защите города (когда на него смогут напасть — PvP), еда гарнизона (сейчас все воины едят одинаково, считает модуль Населения), дебаффы при голоде. Выбор состава по типам — если понадобится.
- Описания типов войск (
GameData.Troops: цена, сила, время обучения) пока в слое приложения; цены перейдут вEconomyConfig.
Журнал изменений
| Дата | Кто | Что |
|---|---|---|
| 27.10.2026 | Claude | Гарнизон города: GarrisonTotal, GetGarrison, AvailableForMarch, SetGarrison; в поход уходят только свободные; строка garrison= в сохранении; поле Garrison в TroopsChangedEvent; карточка «Гарнизон города» в окне «Войска». Тест «один солдат в одном месте» с гарнизоном. |
| 27.10.2026 | Claude | GetMarchUnits и ReturnUnits: бой с типами войск получает состав похода, выжившие возвращаются точно по типам. |
| 23.10.2026 | Claude | Войска переехали в модуль: ArmyService — единственное хранилище войск (секция "army"), IArmy расширен (типы, обучение, потери, войска в походах), событие TroopsChangedEvent. Перенос из progress.json с удалением старых данных только после записи save.json. ArmyBridge удалён — контракты и перенос сохранений проверены тестами. |
| 19.10.2026 | Claude | ArmyBridge.TroopsInMarches для панели «Войска». После удаления маленькой карты войска в походах учитываются только здесь (sashaMarchUnits). |
| 19.10.2026 | Claude | Модуль создан: ArmyMath (правила деления войск, без Unity, тесты на отсутствие двойного учёта). ArmyBridge сохранён и теперь реализует IArmy через ArmyMath; формат sashaMarchUnits не изменён. |