/// <returns>(city-dead,town-dead,explorer-dead)</returns> public async Task DamageAttackers(int damageFromDefenders) { @event.attackerDamageFromDefenders = damageFromDefenders; if (damageFromDefenders == 0) { return; } @event.attackerDamageFromBadlands = BadLandsCount; int remainingDamageToApply = damageFromDefenders + BadLandsCount; // ! must use current Attackers counts, because some have lost their strife so tokens are different than when they started. var remaningAttackers = currentAttackers.Clone(); while (remainingDamageToApply > 0 && remaningAttackers.Any()) { HealthToken attackerToDamage = PickSmartInvaderToDamage(remaningAttackers, remainingDamageToApply); // Apply real damage var(damageInflicted, _) = await grp.ApplyDamageTo1(remainingDamageToApply, attackerToDamage, true); remainingDamageToApply -= damageInflicted; // Apply tracking damage --remaningAttackers[attackerToDamage]; var damagedAttacker = attackerToDamage.AddDamage(damageInflicted); if (damagedAttacker.RemainingHealth > 0) { ++remaningAttackers[damagedAttacker]; } } @event.endingAttackers = remaningAttackers; }
public static async Task Downgrade(TargetSpaceCtx ctx, params HealthTokenClass[] groups) { var options = ctx.Tokens.OfAnyType(groups); HealthToken oldInvader = (HealthToken)await ctx.Self.Action.Decision(Select.Invader.ToReplace("downgrade", ctx.Space, options)); if (oldInvader == null) { return; } // remove old invader ctx.Tokens.Adjust(oldInvader, -1); // Add new var newInvaderClass = oldInvader.Class == Invader.City ? Invader.Town : Invader.Explorer; var newTokenWithoutDamage = ctx.Tokens.GetDefault(newInvaderClass).AddStrife(oldInvader.StrifeCount); var newTokenWithDamage = newTokenWithoutDamage.AddDamage(oldInvader.Damage); if (!newTokenWithDamage.IsDestroyed) { ctx.Tokens.Adjust(newTokenWithDamage, 1); } else if (newInvaderClass != Invader.Explorer) { // add the non-damaged token, and destory it. ctx.Tokens.Adjust(newTokenWithoutDamage, 1); await ctx.Invaders.Destroy(1, newTokenWithoutDamage); } }
static async Task DefaultDestroyDahan(DahanGroupBinding dahan, int count, HealthToken token) { if (count <= 0) { return; } await dahan.Destroy(count, token); }
public async Task Destroy(int count, HealthToken original) { if (Frozen) { return; } await _tokens.Remove(original, count, _destroyReason); }
public async Task <int> Destroy(int countToDestroy, HealthToken invaderToDestroy) { int numToDestroy = Math.Min(countToDestroy, this[invaderToDestroy]); for (int i = 0; i < numToDestroy; ++i) { await DestroyStrategy.OnInvaderDestroyed(Space, invaderToDestroy, false); } return(numToDestroy); }
public override async Task OnInvaderDestroyed(Space space, HealthToken token, bool fromRavage) { if (token.Class == Invader.City) { AddFear(space, 5, false); // not actually destroying towns/cities } else { if (token.Class == Invader.Town) { AddFear(space, 2, false); // not actually destroying towns/cities } await BringerPushNInvaders(space, 1, token.Class); } }
public void AddingStrife() { int expected = 0; HealthToken inv = city; void Add(int delta) { expected += delta; inv = inv.AddStrife(delta); inv.StrifeCount.ShouldBe(expected); } Add(1); Add(3); Add(-2); }
public virtual async Task OnInvaderDestroyed(Space space, HealthToken token, bool fromRavage) { var reason = fromRavage ? RemoveReason.DestroyedInBattle : RemoveReason.Destroyed; await gs.Tokens[space].Destroy(token, 1); // !!! see if we can invoke this through the Token-Publish API instead - so we can make TokenRemovedArgs internal to Island_Tokens class await gs.Tokens.TokenRemoved.InvokeAsync(new TokenRemovedArgs( gs, token, reason ) { Space = space, Count = 1, }); // Don't assert token is destroyed (from damage) because it is possible to destory healthy tokens AddFear(space, token.Class.FearGeneratedWhenDestroyed, true); }
/// <summary> Not Badland-aware </summary> /// <returns>(damage inflicted,damagedInvader)</returns> public async Task <(int, Token)> ApplyDamageTo1(int availableDamage, HealthToken invaderToken, bool fromRavage = false) // !! change Token to HealthToken { var damagedInvader = invaderToken.AddDamage(availableDamage); if (!damagedInvader.IsDestroyed) { Tokens.Adjust(invaderToken, -1); Tokens.Adjust(damagedInvader, 1); } else { await DestroyStrategy.OnInvaderDestroyed(Space, invaderToken, fromRavage); } int damageInflicted = invaderToken.RemainingHealth - damagedInvader.RemainingHealth; return(damageInflicted, damagedInvader); // damage inflicted }
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 AdjustHealthOf(HealthToken token, int delta, int count) { count = Math.Min(_tokens[token], count); if (count == 0) { return; } var newToken = token.AddHealth(delta); if (newToken.IsDestroyed) { await this.Destroy(count, token); } else { _tokens.Adjust(token, -count); _tokens.Adjust(newToken, count); } }
public async Task <int> ApplyDamageToToken(int damageToDahan, HealthToken token) { // Destroy what can be destroyed if (token.RemainingHealth <= damageToDahan) { int destroyed = damageToDahan / token.RemainingHealth; await Destroy(destroyed, token); damageToDahan -= destroyed * token.RemainingHealth; } // if we can apply partial damage if (0 < damageToDahan && 0 < _tokens[token]) { _tokens.Adjust(token, -1); _tokens.Adjust(token.AddDamage(damageToDahan), 1); damageToDahan = 0; // damage should be used up } return(damageToDahan); }
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 Strife_Tests() { city = Tokens.City; strifedCity = Tokens.City.HavingStrife(1); }
static int DefaultDamageFromInvader(HealthToken invader) => invader.Class.Attack;
static (int, HealthToken) GetDamageFromInvader(TokenCountDictionary tokens, HealthToken invader) { return(0 < invader.StrifeCount ? (0, tokens.RemoveStrife(invader, 1)) : (invader.Class.Attack, invader)); }