CCCPaste
using System;
using System.Collections.Generic;

namespace OOP_10
{
internal class Program
{
static void Main(string[] args)
{
Squad squadAlpha = new Squad("Страна Один");
squadAlpha.AddSoldier(new BasicSoldier("Aleksei"));
squadAlpha.AddSoldier(new StrongSoldier("Boris", multiplier: 2.0));
squadAlpha.AddSoldier(new MultiSoldierUnique("Cyril", targetsCount: 2));
squadAlpha.AddSoldier(new MultiSoldierRepeatable("Dmitri", attackTimes: 3));

Squad squadBeta = new Squad("Страна Два");
squadBeta.AddSoldier(new BasicSoldier("Egor"));
squadBeta.AddSoldier(new BasicSoldier("Fedor"));
squadBeta.AddSoldier(new MultiSoldierUnique("Gennady", targetsCount: 3));
squadBeta.AddSoldier(new StrongSoldier("Herman", multiplier: 1.7));
squadBeta.AddSoldier(new MultiSoldierRepeatable("Igor", attackTimes: 2));

Battle battle = new Battle(squadAlpha, squadBeta);
battle.Start();

Console.WriteLine("\nНажмите любую клавишу для выхода...");
Console.ReadKey();
}
}
abstract class Soldier
{
protected Soldier(string name, int health, int damage, int armor)
{
Name = name ?? "Unnamed";
Health = health;
Damage = damage;
Armor = armor;
}

public string Name { get; }
public int Health { get; protected set; }
public int Damage { get; protected set; }
public int Armor { get; protected set; }
public bool IsAlive => Health > 0;

public abstract void Attack(Squad enemySquad, Random random);

public virtual void TakeDamage(int incomingDamage)
{
int actualDamage = incomingDamage - Armor;

if (actualDamage < 0) actualDamage = 0;

Health -= actualDamage;

if (Health < 0) Health = 0;

Console.WriteLine($" {Name} получил(а) {actualDamage} урона (Health: {Health}).");
}

public override string ToString()
{
return $"{Name} [Health:{Health}, Damage:{Damage}, Armor:{Armor}]";
}
}

class BasicSoldier : Soldier
{
public BasicSoldier(string name) : base(name, health: 100, damage: 20, armor: 5) { }

public override void Attack(Squad enemySquad, Random random)
{
Soldier target = enemySquad.GetRandomAliveSoldier(random);

if (target == null) return;

Console.WriteLine($"{Name} (Basic) атакует {target.Name} на {Damage} урона.");
target.TakeDamage(Damage);
}
}

class StrongSoldier : Soldier
{
private readonly double _damageMultiplier;

public StrongSoldier(string name, double multiplier = 1.5) : base(name, health: 110, damage: 25, armor: 6)
{
_damageMultiplier = multiplier;
}

public override void Attack(Squad enemySquad, Random random)
{
Soldier target = enemySquad.GetRandomAliveSoldier(random);

if (target == null) return;

int computedDamage = (int)Math.Round(Damage * _damageMultiplier);
Console.WriteLine($"{Name} (Strong) мощно атакует {target.Name} на {computedDamage} урона (мульт.{_damageMultiplier}).");
target.TakeDamage(computedDamage);
}
}

class MultiSoldierUnique : Soldier
{
private readonly int _numberOfTargets;

public MultiSoldierUnique(string name, int targetsCount = 2) : base(name, health: 90, damage: 15, armor: 3)
{
_numberOfTargets = Math.Max(1, targetsCount);
}

public override void Attack(Squad enemySquad, Random random)
{
List<Soldier> aliveEnemies = enemySquad.GetAliveSoldiersSnapshot();

if (aliveEnemies.Count == 0) return;

int attacksToPerform = _numberOfTargets;

if (attacksToPerform > aliveEnemies.Count) attacksToPerform = aliveEnemies.Count;

List<int> chosenIndices = new List<int>();

while (chosenIndices.Count < attacksToPerform)
{
int index = random.Next(aliveEnemies.Count);
bool alreadyChosen = false;

for (int i = 0; i < chosenIndices.Count; i++)
{
if (chosenIndices[i] == index)
{
alreadyChosen = true;

break;
}
}

if (alreadyChosen == false)
{
chosenIndices.Add(index);
}
}

Console.WriteLine($"{Name} (MultiUnique) атакует {attacksToPerform} целей (по {Damage} урона каждой).");

for (int i = 0; i < chosenIndices.Count; i++)
{
Soldier target = aliveEnemies[chosenIndices[i]];

if (target.IsAlive)
{
Console.WriteLine($" {Name} атакует {target.Name} ({Damage}).");
target.TakeDamage(Damage);
}
else
{
Console.WriteLine($" {target.Name} уже мертв(а), атака пропущена.");
}
}
}
}

class MultiSoldierRepeatable : Soldier
{
private readonly int _attackCount;

public MultiSoldierRepeatable(string name, int attackTimes = 3) : base(name, health: 95, damage: 12, armor: 2)
{
_attackCount = Math.Max(1, attackTimes);
}

public override void Attack(Squad enemySquad, Random random)
{
Console.WriteLine($"{Name} (MultiRepeat) выполняет {_attackCount} атак (по {Damage} урона), цели могут повторяться.");

for (int i = 0; i < _attackCount; i++)
{
Soldier target = enemySquad.GetRandomAliveSoldier(random);

if (target == null)
{
return;
}
Console.WriteLine($" {Name} атака {i + 1}: {target.Name} получает {Damage} урона.");
target.TakeDamage(Damage);
}
}
}

class Squad
{
private readonly List<Soldier> _soldiers;

public Squad(string country)
{
Country = country ?? "Unknown";
_soldiers = new List<Soldier>();
}

public string Country { get; }

public void AddSoldier(Soldier soldier)
{
if (soldier != null) _soldiers.Add(soldier);
}

public bool HasAliveSoldiers()
{
for (int i = 0; i < _soldiers.Count; i++)
{
if (_soldiers[i].IsAlive) return true;
}

return false;
}

public Soldier GetRandomAliveSoldier(Random random)
{
List<Soldier> alive = new List<Soldier>();

for (int i = 0; i < _soldiers.Count; i++)
{
if (_soldiers[i].IsAlive) alive.Add(_soldiers[i]);
}

if (alive.Count == 0) return null;
int index = random.Next(alive.Count);

return alive[index];
}

public List<Soldier> GetAliveSoldiersSnapshot()
{
List<Soldier> snapshot = new List<Soldier>();

for (int i = 0; i < _soldiers.Count; i++)
{
if (_soldiers[i].IsAlive) snapshot.Add(_soldiers[i]);
}
return snapshot;
}

public void RemoveDead()
{
List<Soldier> survivors = new List<Soldier>();

for (int i = 0; i < _soldiers.Count; i++)
{
if (_soldiers[i].IsAlive) survivors.Add(_soldiers[i]);
}

_soldiers.Clear();

for (int i = 0; i < survivors.Count; i++)
{
_soldiers.Add(survivors[i]);
}
}

public void ShowStatus()
{
Console.WriteLine($"\n[{Country}] статус взвода:");

if (_soldiers.Count == 0)
{
Console.WriteLine(" (взвод пуст)");
return;
}

for (int i = 0; i < _soldiers.Count; i++)
{
Soldier s = _soldiers[i];
string aliveText = s.IsAlive ? $"жив (HP:{s.Health})" : "погиб";
Console.WriteLine($" - {s.Name} : {aliveText}");
}
}
}

class Battle
{
private readonly Squad _leftSquad;
private readonly Squad _rightSquad;
private readonly Random _randomGenerator;

public Battle(Squad squadLeft, Squad squadRight)
{
_leftSquad = squadLeft ?? throw new ArgumentNullException(nameof(squadLeft));
_rightSquad = squadRight ?? throw new ArgumentNullException(nameof(squadRight));
_randomGenerator = new Random(); }

public void Start()
{
Console.WriteLine("=== Начало сражения ===");
Console.WriteLine($"{_leftSquad.Country} VS {_rightSquad.Country}\n");

int roundNumber = 1;
while (_leftSquad.HasAliveSoldiers() && _rightSquad.HasAliveSoldiers())
{
Console.WriteLine($"\n--- Раунд {roundNumber} ---");

ExecuteSquadAttackPhase(attackingSquad: _leftSquad, defendingSquad: _rightSquad);

ExecuteSquadAttackPhase(attackingSquad: _rightSquad, defendingSquad: _leftSquad);

_leftSquad.RemoveDead();
_rightSquad.RemoveDead();

_leftSquad.ShowStatus();
_rightSquad.ShowStatus();

roundNumber++;
}

Console.WriteLine("\n=== Сражение окончено ===");
if (_leftSquad.HasAliveSoldiers())
{
Console.WriteLine($"Победил взвод: {_leftSquad.Country}");
}
else if (_rightSquad.HasAliveSoldiers())
{
Console.WriteLine($"Победил взвод: {_rightSquad.Country}");
}
else
{
Console.WriteLine("Оба взвода уничтожены — ничья.");
}
}

private void ExecuteSquadAttackPhase(Squad attackingSquad, Squad defendingSquad)
{
Console.WriteLine($"\nФаза атаки: {attackingSquad.Country} -> {defendingSquad.Country}");

List<Soldier> attackersSnapshot = attackingSquad.GetAliveSoldiersSnapshot();

if (attackersSnapshot.Count == 0)
{
Console.WriteLine($" У {attackingSquad.Country} нет живых бойцов для атаки.");
return;
}

for (int i = 0; i < attackersSnapshot.Count; i++)
{
Soldier attacker = attackersSnapshot[i];

if (!attacker.IsAlive)
{
continue;
}

attacker.Attack(defendingSquad, _randomGenerator);

if (!defendingSquad.HasAliveSoldiers())
{
Console.WriteLine($" Все бойцы {defendingSquad.Country} уничтожены во время фазы.");
break;
}
}
}
}
}