/// <summary> /// Restores all of the tokens to their default / healthy state. /// </summary> static public void HealTokens(TokenCountDictionary counts) { void RestoreAllToDefault(Token token) { if (token is not HealthToken ht || ht.Damage == 0) { return; } int num = counts[token]; counts.Adjust(ht.Healthy, num); counts.Adjust(token, -num); } void HealGroup(TokenClass group) { foreach (var token in counts.OfType(group).ToArray()) { RestoreAllToDefault(token); } } HealGroup(Invader.City); HealGroup(Invader.Town); HealGroup(TokenType.Dahan); }
async Task BringerPushNInvaders(Space source, int countToPush, params TokenClass[] healthyInvaders) { // We can't track which original invader is was killed, so let the user choose. // TokenCountDictionary tokens = ctx.Target(source).Tokens; TokenCountDictionary tokens = ctx.GameState.Tokens[source]; Token[] CalcInvaderTypes() => tokens.OfAnyType(healthyInvaders); var invaders = CalcInvaderTypes(); while (0 < countToPush && 0 < invaders.Length) { var invader = await ctx.Decision(Select.TokenFrom1Space.TokenToPush(source, countToPush, invaders, Present.Always)); if (invader == null) { break; } var destination = await ctx.Decision(new Select.Space( "Push " + invader.ToString() + " to", source.Adjacent.Where(s => ctx.Target(s).IsInPlay(Invader.Explorer)) , Present.Always )); await tokens.MoveTo(invader, destination); --countToPush; invaders = CalcInvaderTypes(); } }
//public override void HealAll( GameState gs ) { // // Invaders and dahan in your lands don't heal Damage. // skipHealSpaces.UnionWith( spirit.Presence.Spaces ); // base.HealAll( gs ); //} public override void HealSpace(TokenCountDictionary tokens) { if (!spirit.Presence.IsOn(tokens.Space)) { base.HealSpace(tokens); } }
public static int DamageFrom1StrifedInvaders(TokenCountDictionary tokens) { var strifedInvaderWithMostDamage = tokens.Invaders().OfType <HealthToken>() .OrderByDescending(x => x.FullHealth) .FirstOrDefault(); return(strifedInvaderWithMostDamage != null ? strifedInvaderWithMostDamage.FullHealth : 0); }
public TokenCountDictionary this[Space space] { get { if (!tokenCounts.ContainsKey(space)) { tokenCounts[space] = new TokenCountDictionary(space, new CountDictionary <Token>(), this); } return(tokenCounts[space]); } }
public static void Init(this TokenCountDictionary currentTokens, string expectedInvaderSummary) { CountDictionary <Token> desiredTokens = new(); if (!string.IsNullOrEmpty(expectedInvaderSummary)) { foreach (var part in expectedInvaderSummary.Split(',')) { Token token = part[1..] switch {
public void InitTokens(TokenCountDictionary tokens) { StartUpCounts initialCounts = StartUpCounts; tokens.InitDefault(Invader.City, initialCounts.Cities); tokens.InitDefault(Invader.Town, initialCounts.Towns); tokens.InitDefault(Invader.Explorer, initialCounts.Explorers); tokens.Dahan.Init(initialCounts.Dahan); tokens.Blight.Init(initialCounts.Blight); // don't use AddBlight because that pulls it from the card and triggers blighted island }
static async Task EachInvaderReduceHealthByStrifeCount(TokenCountDictionary tokens, int minimum) { var strifedInvaders = tokens.Invaders() .Where(x => 0 < x.StrifeCount) .OrderBy(x => x.RemainingHealth) .ToArray(); // get the lowest ones first so we can reduce without them cascading foreach (HealthToken strifedInvader in strifedInvaders) { await ReduceInvaderHealthByItsOwnStrife(tokens, strifedInvader, minimum); } }
static async Task EachInvaderTakesDamageByStrifeCount(TokenCountDictionary tokens) { var strifedInvaders = tokens.Invaders() .Where(x => 0 < x.StrifeCount) .OrderBy(x => x.RemainingHealth) .ToArray(); // get the lowest ones first so we can reduce without them cascading // !!! ??? Do badlands cause damage here? foreach (HealthToken strifedInvader in strifedInvaders) { await DamageInvaderHealthByItsOwnStrife(tokens, strifedInvader); } }
/// <summary> /// Conditionally Removes an invader based on the Total # of invaders in a space /// </summary> static async Task RemoveInvaderWhenMax(FearCtx ctx, int invaderMax, params TokenClass[] removeableInvaders) { foreach (var spirit in ctx.Spirits) { var options = spirit.AllSpaces.Where(s => { TokenCountDictionary counts = ctx.GameState.Tokens[s]; return(counts.HasAny(removeableInvaders) && counts.InvaderTotal() <= invaderMax); }).ToArray(); if (options.Length == 0) { return; } await spirit.RemoveTokenFromOneSpace(options, 1, removeableInvaders); } }
static async Task DamageInvaderHealthByItsOwnStrife(TokenCountDictionary tokens, HealthToken originalInvader) { var newInvader = originalInvader.AddDamage(originalInvader.StrifeCount); if (newInvader == originalInvader) { return; } if (newInvader.IsDestroyed) { await tokens.Destroy(originalInvader, tokens[originalInvader]); } else { tokens.Adjust(newInvader, tokens[originalInvader]); tokens.Init(originalInvader, 0); } }
public async Task <string> Exec( BuildingEventArgs args, TokenCountDictionary tokens, GameState gameState ) { if (!tokens.HasInvaders()) { return("No invaders"); } BuildingEventArgs.BuildType buildType = args.GetBuildType(tokens.Space); this.tokens = tokens; this.buildType = buildType; this.gameState = gameState; if (await StopBuildWithDiseaseBehavior()) { return(tokens.Space.Label + " build stopped by disease"); } // Determine type to build int townCount = tokens.Sum(Invader.Town); int cityCount = tokens.Sum(Invader.City); HealthTokenClass invaderToAdd = townCount > cityCount ? Invader.City : Invader.Town; // check if we should bool shouldBuild = buildType switch { BuildingEventArgs.BuildType.CitiesOnly => invaderToAdd == Invader.City, BuildingEventArgs.BuildType.TownsOnly => invaderToAdd == Invader.Town, _ => true, }; // build it if (shouldBuild) { await tokens.AddDefault(invaderToAdd, 1, AddReason.Build); } return(invaderToAdd.Label); }
static async Task ReduceInvaderHealthByItsOwnStrife(TokenCountDictionary tokens, HealthToken originalInvader, int minimum) { int newHealth = Math.Min(minimum, originalInvader.FullHealth - originalInvader.StrifeCount); var newInvader = new HealthToken(originalInvader.Class, newHealth, originalInvader.Damage, originalInvader.StrifeCount); if (newInvader == originalInvader) { return; } if (newInvader.IsDestroyed) { await tokens.Destroy(originalInvader, tokens[originalInvader]); } else { tokens.Adjust(newInvader, tokens[originalInvader]); tokens.Init(originalInvader, 0); // !!! Need something at end of turn to restore health. } }
public BlightTokenBinding(TokenCountDictionary tokens) : base(tokens, TokenType.Blight) { }
public DefendTokenBinding(TokenCountDictionary tokens) { this.tokens = tokens; }
/// <summary> Clone / copy constructor </summary> public TokenCountDictionary(TokenCountDictionary src) { this.Space = src.Space; counts = src.counts.Clone(); tokenApi = src.tokenApi; }
static public string InvaderSummary(this TokenCountDictionary dict) {
public static int DamageFromStrifedInvaders(TokenCountDictionary tokens) { return(tokens.Invaders().OfType <HealthToken>().Where(x => x.StrifeCount > 0).Sum(si => si.FullHealth * tokens[si])); }
public InvaderBinding(TokenCountDictionary tokens, DestroyInvaderStrategy destroyStrategy) { this.Tokens = tokens; this.DestroyStrategy = destroyStrategy; }
static public int Sum(this TokenCountDictionary counts, TokenClass generic) => counts.OfType(generic).Sum(k => counts[k]);
public DahanGroupBinding(TokenCountDictionary tokens, RemoveReason destoryReason = RemoveReason.Destroyed) { _tokens = tokens; _tokenGroup = TokenType.Dahan; _destroyReason = destoryReason; }
public WreakVengeanceForTheLandsCorruption(TokenCountDictionary tokens) : base(tokens, TokenType.Badlands) { blight = new TokenBinding(tokens, TokenType.Blight); }
static public Token[] OfType(this TokenCountDictionary counts, TokenClass healthyType) => counts.Keys.Where(specific => healthyType == specific.Class).ToArray();
static public bool HasAny(this TokenCountDictionary counts, params TokenClass[] healthyInvaders) => counts.OfAnyType(healthyInvaders).Any();
static public HealthToken[] OfAnyType(this TokenCountDictionary counts, params HealthTokenClass[] healthyTypes) => counts.Keys.Where(specific => healthyTypes.Contains(specific.Class)).Cast <HealthToken>().ToArray();
public static TokenFrom1Space ForStrife(TokenCountDictionary tokens, params TokenClass[] groups) => new TokenFrom1Space("Add Strife", tokens.Space, (groups != null && groups.Length > 0) ? tokens.OfAnyType(groups) : tokens.Invaders(), Present.Always );
static public int SumAny(this TokenCountDictionary counts, params TokenClass[] healthyInvaders) => counts.OfAnyType(healthyInvaders).Sum(k => counts[k]);
static (int, HealthToken) GetDamageFromInvader(TokenCountDictionary tokens, HealthToken invader) { return(0 < invader.StrifeCount ? (0, tokens.RemoveStrife(invader, 1)) : (invader.Class.Attack, invader)); }
static public bool Has(this TokenCountDictionary counts, TokenClass inv) => counts.OfType(inv).Any();
public TokenBinding(TokenCountDictionary tokens, Token token) { this.tokens = tokens; this.token = token; }