using System.Collections.Immutable; namespace CardGame.Core; public sealed class RunStats { public int HealReceived { get; set; } public int AttacksDeclared { get; set; } public int FriendlyDestroyed { get; set; } public int FatigueTicks { get; set; } public Dictionary KillsByTag { get; } = new(StringComparer.Ordinal); public int Kills(string tag) => KillsByTag.GetValueOrDefault(tag); public RunStats Clone() { var copy = new RunStats { HealReceived = HealReceived, AttacksDeclared = AttacksDeclared, FriendlyDestroyed = FriendlyDestroyed, FatigueTicks = FatigueTicks }; foreach (var (key, value) in KillsByTag) { copy.KillsByTag[key] = value; } return copy; } } public enum PackConditionKind { HealReceivedAtLeast, AttacksAtLeast, FriendlyDestroyedAtLeast, FatigueAtLeast, DeckTagAtLeast, KillTagAtLeast } public sealed record PackCondition(PackConditionKind Kind, int Amount = 0, string? Tag = null); public sealed record PackDefinition( string Id, string Name, bool Base, ImmutableArray CoreActions, ImmutableArray Cards, ImmutableArray AllOf); public static class Packs { public static bool IsUnlocked(GameState state, int playerIndex, PackDefinition pack) { if (pack.Base) { return true; } return pack.AllOf.All(c => Met(state, playerIndex, c)); } public static IReadOnlyList Unlocked(GameState state, int playerIndex, IEnumerable catalog) => catalog.Where(p => IsUnlocked(state, playerIndex, p)).ToList(); public static int CountTag(GameState state, int playerIndex, string tag) { var player = state.Players[playerIndex]; return player.Deck.Concat(player.Hand).Concat(player.Graveyard) .Concat(state.Board.Where(e => e.ControllerIndex == playerIndex)) .Count(e => e.Definition.HasTag(tag)); } private static bool Met(GameState state, int playerIndex, PackCondition condition) { var run = state.Players[playerIndex].Run; return condition.Kind switch { PackConditionKind.HealReceivedAtLeast => run.HealReceived >= condition.Amount, PackConditionKind.AttacksAtLeast => run.AttacksDeclared >= condition.Amount, PackConditionKind.FriendlyDestroyedAtLeast => run.FriendlyDestroyed >= condition.Amount, PackConditionKind.FatigueAtLeast => run.FatigueTicks >= condition.Amount, PackConditionKind.DeckTagAtLeast => CountTag(state, playerIndex, condition.Tag ?? "") >= condition.Amount, PackConditionKind.KillTagAtLeast => run.Kills(condition.Tag ?? "") >= condition.Amount, _ => false }; } }