VanguardReMaster/server/src/Vanguard.Rules/Engine/GameState.cs

116 lines
5.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Vanguard.Rules.Cards;
using Vanguard.Rules.Engine.Abilities;
namespace Vanguard.Rules.Engine;
public sealed class BattleState
{
public required int AttackerPlayer { get; init; }
/// <summary>Индекс атакующего: -1 — Авангард, 0..4 — круг Арьергарда.</summary>
public required int AttackerSlot { get; init; }
/// <summary>Индекс цели: -1 — Авангард противника.</summary>
public required int TargetSlot { get; init; }
public int GuardShield { get; set; }
public int ChecksRemaining { get; set; }
/// <summary>Атака отменена идеальной защитой: попадания не будет при любой силе.</summary>
public bool Nullified { get; set; }
/// <summary>Карта, вышедшая на перехват. Сила сравнения берётся по ней.</summary>
public CardInstance? Interceptor { get; set; }
/// <summary>Круг карты поддержки (-1 — поддержки не было).</summary>
public int BoosterSlot { get; set; } = -1;
public List<CardInstance> 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; }
/// <summary>Исходное зерно партии: нужно для записи и воспроизведения реплея.</summary>
public ulong Seed { get; }
public int NextInstanceId { get; internal set; } = 1;
public BattleState? Battle { get; internal set; }
public PendingTrigger? PendingTrigger { get; internal set; }
/// <summary>Способность ждёт решения «да / нет».</summary>
public TriggeredAbility? PendingAbility { get; internal set; }
/// <summary>Сработавшие способности ждут выбора порядка.</summary>
public List<TriggeredAbility>? PendingOrder { get; internal set; }
/// <summary>Ожидание выбора цели или карты.</summary>
public PendingChoice? PendingChoice { get; internal set; }
/// <summary>Продолжение разрешения, которое надо выполнить после способностей.</summary>
public Action? Continuation { get; internal set; }
/// <summary>
/// Триггеры, сработавшие во время другого эффекта. Разрешаются после него,
/// чтобы цепочка шла строго друг за другом.
/// </summary>
public List<TriggeredAbility>? PendingQueue { get; internal set; }
/// <summary>
/// Карты, которые уже покинули колоду, но ещё не положены в новую зону
/// (например, ожидают выбора круга для призыва).
/// </summary>
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);
/// <summary>
/// Итоговая способность поддержки: выданная эффектом важнее печатной.
/// </summary>
public bool CanBoost(CardInstance unit) =>
!HasRestriction(unit, RestrictionType.CannotBoost)
&& (unit.BoostOverride ?? Definition(unit).HasBoost);
/// <summary>Итоговая способность перехвата: выданная эффектом важнее печатной.</summary>
public bool CanIntercept(CardInstance unit) =>
!HasRestriction(unit, RestrictionType.CannotIntercept)
&& (unit.InterceptOverride ?? Definition(unit).HasIntercept);
/// <summary>Есть ли у карты запрет указанного вида.</summary>
public bool HasRestriction(CardInstance unit, RestrictionType type) =>
unit.Restrictions.Any(r => r.Type == type);
/// <summary>Действует ли на карте Сдерживание с учётом переопределения эффектом.</summary>
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];
}