/
romashov.z
/
PPAGame
Обзор
Документация
Войти
/
romashov.z
/
PPAGame
Код
Запросы
1
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Core/Strategies/WallStrategy.cs
164 строки
7 KB
Zakhar Romashov
Добавили логику с бафами
29 апр 2026, 13:06
29 апр 2026, 13:06
7623dfb
Код
Авторство
О чём код?
using System; using System.Collections.Generic; namespace ArmyBattleGame { // Стенка на стенку: одна шеренга (1 ряд × N колонок). // Все юниты атакуют одновременно. Если напротив никого - можно использовать SA. class WallStrategy : FormationStrategyBase { public const string StrategyName = "Wall"; public override string Name => StrategyName; public override string DisplayName => "Стенка на стенку"; // Колонок столько, сколько юнитов (минимум 1). public override int ColumnCountFor(int unitCount) => Math.Max(1, unitCount); public override void ExecuteMeleePhase(BattleField field, IBattleLogger logger) { var attackerArmy = field.IsArmy1Turn ? field.Army1 : field.Army2; var defenderArmy = field.IsArmy1Turn ? field.Army2 : field.Army1; // Волна 1: активная армия бьёт всех противостоящих по колонкам. var wave1 = BuildMeleeWave(attackerArmy, defenderArmy); ApplyDamageWave(wave1, logger); attackerArmy.Compact(); defenderArmy.Compact(); if (!attackerArmy.HasAliveUnits || !defenderArmy.HasAliveUnits) return; // Волна 2: контратака. var wave2 = BuildMeleeWave(defenderArmy, attackerArmy); ApplyDamageWave(wave2, logger); attackerArmy.Compact(); defenderArmy.Compact(); } private static List<(IUnit attacker, IUnit target, double damage)> BuildMeleeWave( Army attackerArmy, Army targetArmy) { var wave = new List<(IUnit, IUnit, double)>(); int width = Math.Min(attackerArmy.ColumnCount, targetArmy.ColumnCount); for (int col = 0; col < width; col++) { var a = attackerArmy.GetAt(0, col); var t = targetArmy.GetAt(0, col); if (a == null || !a.IsAlive) continue; if (t == null || !t.IsAlive) continue; if (a.Damage <= 0) continue; double damage = a.Damage * 100 / (100 + t.Shield); wave.Add((a, t, damage)); } return wave; } public override void ExecuteSpecialsPhase(BattleField field, IBattleLogger logger) { var ctx1 = new BattleContext(field.Army1, field.Army2, this, logger); var ctx2 = new BattleContext(field.Army2, field.Army1, this, logger); for (int col = 0; col < field.Army1.ColumnCount; col++) TryUseSpecial(ctx1, 0, col); for (int col = 0; col < field.Army2.ColumnCount; col++) TryUseSpecial(ctx2, 0, col); field.Army1.Compact(); field.Army2.Compact(); } private static void TryUseSpecial(BattleContext ctx, int row, int col) { var unit = ctx.OwnArmy.GetAt(row, col); if (unit is ISpecialAbility special && unit.IsAlive) { var pos = new UnitPosition(row, col); if (ctx.Strategy.CanUseSpecial(ctx.OwnArmy, pos)) special.UseSpecial(ctx, pos); } } // Одна шеренга: все на передовой — общие SA не срабатывают. public override bool CanUseSpecial(Army own, UnitPosition attackerPos) => CanUseSpecialIfNotFrontLine(own, attackerPos); // Цели лучника: в той же или соседних колонках (±1) у противника. public override IEnumerable<(IUnit unit, UnitPosition pos)> GetEnemyTargets( Army own, Army enemy, UnitPosition attackerPos, int range) { // В стенке range интерпретируется как горизонтальный радиус по колонкам. int from = Math.Max(0, attackerPos.Col - range); int to = Math.Min(enemy.ColumnCount - 1, attackerPos.Col + range); // Сначала прямо напротив. var direct = enemy.GetAt(0, attackerPos.Col); if (direct != null && direct.IsAlive) yield return (direct, new UnitPosition(0, attackerPos.Col)); // Затем по соседним колонкам, расширяясь. for (int delta = 1; delta <= range; delta++) { int left = attackerPos.Col - delta; int right = attackerPos.Col + delta; if (left >= 0 && left < enemy.ColumnCount) { var u = enemy.GetAt(0, left); if (u != null && u.IsAlive) yield return (u, new UnitPosition(0, left)); } if (right >= 0 && right < enemy.ColumnCount) { var u = enemy.GetAt(0, right); if (u != null && u.IsAlive) yield return (u, new UnitPosition(0, right)); } } } // Союзники "впереди": в стенке нет понятия "впереди" по строке, // поэтому интерпретируем как "соседи слева" (с меньшим col) в радиусе. public override IEnumerable<(IUnit unit, UnitPosition pos)> GetForwardAllies( Army own, UnitPosition attackerPos, int range) { int rangeStart = Math.Max(0, attackerPos.Col - range); var self = own.GetAt(attackerPos.Row, attackerPos.Col); for (int c = rangeStart; c < attackerPos.Col; c++) { var u = own.GetAt(0, c); if (u != null && u.IsAlive && !ReferenceEquals(u, self)) yield return (u, new UnitPosition(0, c)); } } // Клон вставляется в шеренгу слева от мага (новая колонка). public override UnitPosition? PlaceClone(Army own, UnitPosition wizardPos, IUnit clone) { var flat = own.Flatten(); var wizard = own.GetAt(wizardPos.Row, wizardPos.Col); if (wizard == null) return null; int wizardIndex = -1; for (int i = 0; i < flat.Count; i++) { if (ReferenceEquals(flat[i], wizard)) { wizardIndex = i; break; } } if (wizardIndex < 0) return null; flat.Insert(wizardIndex, clone); own.RebuildFromFlat(flat, ColumnCountFor(flat.Count)); own.NotifyUnitAdded(clone); return own.FindPosition(clone); } } }