Files
MVP1/Assets/Scripts/Modules/Army/ArmyMath.cs
T
AlexanderandClaude Opus 5.5 964cb23d9d Модульная система: игровое ядро + 6 модулей, документы Docs/Modules
- Ядро (Bogatyri.Core): контракты модулей, EventBus, GameServices, SaveRegistry
- Модули: Экономика, Поселение, Армия, Глобальный мир, Боевая система, Сохранения
  (каждый — отдельный asmdef, видит только ядро)
- App/GameModules: регистрация модулей и связь с GameProgress/Казармами
- Сохранения v2 по секциям модулей, перенос старого save.json и походов из progress.json
- Сброс сохранений: ISaveSystem.ResetAll, ResetState у модулей, меню Tools
- EditMode-тесты модулей, документы по каждому модулю с журналом изменений

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 18:39:28 +02:00

59 lines
2.4 KiB
C#

using System;
using System.Collections.Generic;
// МОДУЛЬ АРМИИ: войска и их распределение. Документ: Docs/Modules/Army.md
// Без Unity: правила деления войск одинаковы на клиенте и на сервере.
public static class ArmyMath
{
// Сколько воинов каждого типа взять, чтобы набрать count, пропорционально составу армии.
// Остаток округления раздаётся типам с наибольшей дробной частью. null -- столько воинов нет.
public static int[] TakeProportional(int[] troops, int count)
{
int total = 0;
foreach (var t in troops) total += t;
if (count <= 0 || count > total) return null;
var taken = new int[troops.Length];
int given = 0;
var remainders = new List<KeyValuePair<int, double>>();
for (int i = 0; i < troops.Length; i++)
{
double exact = (double)count * troops[i] / total;
taken[i] = Math.Min(troops[i], (int)Math.Floor(exact));
given += taken[i];
remainders.Add(new KeyValuePair<int, double>(i, exact - taken[i]));
}
remainders.Sort((a, b) => b.Value.CompareTo(a.Value));
for (int k = 0; given < count && k < remainders.Count * 2; k++)
{
int i = remainders[k % remainders.Count].Key;
if (taken[i] < troops[i]) { taken[i]++; given++; }
}
return taken;
}
// Как разложить survivors выживших по типам, если в поход ушли sentUnits.
// Остаток округления -- в самый многочисленный тип похода.
public static int[] SplitSurvivors(int[] sentUnits, int survivors)
{
var back = new int[sentUnits.Length];
survivors = Math.Max(0, survivors);
int sent = 0;
foreach (var u in sentUnits) sent += u;
int given = 0;
for (int i = 0; i < sentUnits.Length; i++)
{
back[i] = sent > 0 ? (int)Math.Floor((double)survivors * sentUnits[i] / sent) : 0;
given += back[i];
}
int best = 0;
for (int i = 1; i < sentUnits.Length; i++) if (sentUnits[i] > sentUnits[best]) best = i;
if (back.Length > 0) back[best] += survivors - given;
return back;
}
}