using Vanguard.Rules.Cards;
using Vanguard.Rules.Engine.Abilities;
namespace Vanguard.Rules.Engine;
public sealed class BattleState
{
public required int AttackerPlayer { get; init; }
/// Индекс атакующего: -1 — Авангард, 0..4 — круг Арьергарда.
public required int AttackerSlot { get; init; }
/// Индекс цели: -1 — Авангард противника.
public required int TargetSlot { get; init; }
public int GuardShield { get; set; }
public int ChecksRemaining { get; set; }
/// Атака отменена идеальной защитой: попадания не будет при любой силе.
public bool Nullified { get; set; }
/// Карта, вышедшая на перехват. Сила сравнения берётся по ней.
public CardInstance? Interceptor { get; set; }
/// Круг карты поддержки (-1 — поддержки не было).
public int BoosterSlot { get; set; } = -1;
public List GuardCards { get; } = new();
}
public sealed class GameState
{
public GameState(CardCatalog catalog, ulong seed, string firstPlayerName, string secondPlayerName)
{
Catalog = catalog;
Seed = seed;
RngState = seed;
Players[0] = new PlayerState(firstPlayerName);
Players[1] = new PlayerState(secondPlayerName);
}
public CardCatalog Catalog { get; }
public PlayerState[] Players { get; } = new PlayerState[2];
public int ActivePlayer { get; internal set; }
public Phase Phase { get; internal set; } = Phase.Mulligan;
public Step Step { get; internal set; } = Step.None;
public int TurnNumber { get; internal set; }
public ulong RngState { get; internal set; }
/// Исходное зерно партии: нужно для записи и воспроизведения реплея.
public ulong Seed { get; }
public int NextInstanceId { get; internal set; } = 1;
public BattleState? Battle { get; internal set; }
public PendingTrigger? PendingTrigger { get; internal set; }
/// Способность ждёт решения «да / нет».
public TriggeredAbility? PendingAbility { get; internal set; }
/// Сработавшие способности ждут выбора порядка.
public List? PendingOrder { get; internal set; }
/// Ожидание выбора цели или карты.
public PendingChoice? PendingChoice { get; internal set; }
/// Продолжение разрешения, которое надо выполнить после способностей.
public Action? Continuation { get; internal set; }
///
/// Триггеры, сработавшие во время другого эффекта. Разрешаются после него,
/// чтобы цепочка шла строго друг за другом.
///
public List? PendingQueue { get; internal set; }
///
/// Карты, которые уже покинули колоду, но ещё не положены в новую зону
/// (например, ожидают выбора круга для призыва).
///
public List<(int Player, CardInstance Card)> InTransit { get; } = new();
public bool IsFinished { get; internal set; }
public int? Winner { get; internal set; }
public PlayerState Active => Players[ActivePlayer];
public PlayerState Opponent => Players[1 - ActivePlayer];
public CardDefinition Definition(CardInstance card) => Catalog.CardOf(card.PrintingId);
///
/// Итоговая способность поддержки: выданная эффектом важнее печатной.
///
public bool CanBoost(CardInstance unit) =>
!HasRestriction(unit, RestrictionType.CannotBoost)
&& (unit.BoostOverride ?? Definition(unit).HasBoost);
/// Итоговая способность перехвата: выданная эффектом важнее печатной.
public bool CanIntercept(CardInstance unit) =>
!HasRestriction(unit, RestrictionType.CannotIntercept)
&& (unit.InterceptOverride ?? Definition(unit).HasIntercept);
/// Есть ли у карты запрет указанного вида.
public bool HasRestriction(CardInstance unit, RestrictionType type) =>
unit.Restrictions.Any(r => r.Type == type);
/// Действует ли на карте Сдерживание с учётом переопределения эффектом.
public bool IsRestraint(CardInstance unit) =>
unit.RestraintOverride ?? Definition(unit).IsRestraint;
public CardInstance? GetUnit(int player, int slot) =>
slot < 0
? Players[player].Vanguard
: Players[player].RearGuards[slot];
}