static async Task <Space> SelectLandAdjacentToBoth(TargetSpaceCtx ctx, Space origin) { return(await ctx.Decision(new Select.Space( "Select land for 1 damge to each invader", ctx.Adjacent .Intersect(ctx.Target(origin).Adjacent) .Where(s => ctx.Target(s).IsInPlay(default)),
static public async Task ActAsync(TargetSpaceCtx ctx) { // add 2 disease var disease = ctx.Disease; await disease.Add(2); // for each disease in target land, defend 1 in target and all adjacent lands ctx.Defend(disease.Count); foreach (var adjacent in ctx.Adjacent) { ctx.Target(adjacent).Defend(disease.Count); } // if you have 2 earthn 4 animal: if (await ctx.YouHave("2 earth,4 animal")) { // 2 fear. ctx.AddFear(2); // For each disease in target land, do 1 damage in target or adjacent land int damage = disease.Count; var space = await ctx.Decision(new Select.Space($"Select space to apply {damage} damage", ctx.Range(1), Present.Always)); // can we wrap this and make it easier to call? await ctx.Target(space).DamageInvaders(damage); } }
public static async Task ActAsync(TargetSpaceCtx ctx) { // 2 fear. ctx.AddFear(2); // in both origin land and target land: 1 damage to each invader. var origin = await FindOriginLand_SS(ctx, 1); await ctx.DamageEachInvader(1); await ctx.Target(origin).DamageEachInvader(1); // if you have 2 fire 3 air 2 water: if (await ctx.YouHave("2 fire,3 air,2 water")) { // +1 fear. ctx.AddFear(1); // This Power has +1 range. (see attribute) // in a land adjacent to both origin and target Space thirdSpace = await SelectLandAdjacentToBoth(ctx, origin); // 1 damage to each invader. await ctx.Target(thirdSpace).DamageEachInvader(1); // in lands where you did Damage, Destroy 1 town foreach (var space in new[] { ctx.Space, origin, thirdSpace }.Distinct()) { await ctx.Target(space).Invaders.Destroy(1, Invader.Town); } } }
static async Task RemoveBlightFromLandOrAdjacent(TargetSpaceCtx ctx) { // remove 1 blight from target or adjacent land var blightedLands = ctx.Space.Range(1).Where(s => ctx.Target(s).HasBlight).ToArray(); var unblightLand = await ctx.Decision(new Select.Space("Remove 1 blight from", blightedLands, Present.Always)); if (unblightLand != null) { await ctx.Target(unblightLand).RemoveBlight(); } }
public static async Task ActAsync(TargetSpaceCtx ctx) { // target land and a land adjacent to it become a single land for this turn. var other = (await ctx.SelectAdjacentLand($"Join {ctx.Space.Label} to.")).Space; MultiSpace multi = JoinSpaces(ctx, ctx.Space, other); // if you have 4 air: if (await ctx.YouHave("4 air")) { // isolate the joined land. var joinedCtx = ctx.Target(multi); joinedCtx.Isolate(); // If it has invaders, if (joinedCtx.HasInvaders) { // 2 fear, joinedCtx.AddFear(2); // and Remove up to 2 invaders await joinedCtx.Invaders.Remove(); await joinedCtx.Invaders.Remove(); } } }
static public async Task ActAsymc(TargetSpaceCtx ctx) { // 1 fear if invaders are present. if (ctx.HasInvaders) { ctx.AddFear(1); } var beastSources = ctx.Adjacent.Where(s => ctx.Target(s).Beasts.Any).ToArray(); // If you can gather 1 beast, if (beastSources.Length > 0) { // do so, await ctx.Gather(1, TokenType.Beast); // then push 1 explorer. await ctx.Push(1, Invader.Explorer); } else { // othersie, add 1 beast await ctx.Beasts.Add(1); } }
static async Task DamageLandWithinRange(TargetSpaceCtx ctx, int range) { // !!! could make this a single SpaceToken step. var space = await ctx.Decision(new Select.Space("Select land for 1 Damage", ctx.Range(range), Present.Always)); await ctx.Target(space).DamageInvaders(1); }
static public async Task ActAsync(TargetSpaceCtx ctx) { // destroy all explorers. await ctx.Invaders.Destroy(int.MaxValue, Invader.Explorer); // Add 1 wilds. await ctx.Wilds.Add(1); // Add 1 wilds in the originating Sands. // !! won't find original if this was picked using a range-extender - would need to capture that info during the targetting process var originatingOptions = ctx.Range(1) .Where(a => ctx.Self.Presence.Spaces.Contains(a) && a.IsSand) .ToArray(); var originalCtx = await ctx.SelectSpace("Select origination space", originatingOptions, Present.AutoSelectSingle); if (originalCtx != null) { await originalCtx.Wilds.Add(1); } // 1 damage per wilds in / adjacent to target land. int wildsDamage = ctx.Space.Range(1).Sum(s => ctx.Target(s).Wilds.Count); // if you have 2 fire, 3 plant: // +1 damage per wilds in / adjacent to target land. if (await ctx.YouHave("2 fire,3 plant")) { wildsDamage += wildsDamage; } await ctx.DamageInvaders(wildsDamage); }
static async Task ActAsync(TargetSpaceCtx ctx, int damage) { // Destroy 1 dahan await ctx.DestroyDahan(1); // 4 plant split this power's damage however desired between target land and another 1 of your lands int damageToTarget = ctx.Self.Elements[Element.Plant] < 4 && ctx.Self.Presence.Spaces.Count() > 1 ? damage : await ctx.Self.SelectNumber("Damage to apply to " + ctx.Space.Label, damage); await ctx.DamageInvaders(damage); int remainingDamage = damage - damageToTarget; if (remainingDamage > 0) { var secondaryTarget = await ctx.Decision(new Select.Space( $"Apply {remainingDamage} reamaining damage" , ctx.Self.Presence.Spaces , Present.Always )); await ctx.Target(secondaryTarget).DamageInvaders(remainingDamage); } }
public static async Task BoostDahanHealthForRound(TargetSpaceCtx ctx, int boost) { // Boost ALL Dahan in land await ctx.Dahan.AdjustHealthOfAll(boost); // Move(,) triggers 'Add' and 'Remove' events also // This covers simple-add AND move-in ctx.GameState.Tokens.TokenAdded.ForRound.Add(async args => { if (args.Token.Class == TokenType.Dahan && args.Space == ctx.Space) { await ctx.Dahan.AdjustHealthOf((HealthToken)args.Token, boost, args.Count); } }); // Move out ctx.GameState.Tokens.TokenMoved.ForRound.Add(async args => { // if removing dahan from this space if (args.Token.Class == TokenType.Dahan && args.RemovedFrom == ctx.Space) { // In the destination space await ctx.Target(args.AddedTo) // reduce the health by boost amount .Dahan.AdjustHealthOf((HealthToken)args.Token, -boost, args.Count); } }); // Add handler to restore ALL at end of round. ctx.GameState.TimePasses_ThisRound.Push(async gs => { // Ensure the dahan are healed before we restore their health. ctx.GameState.Healer.HealSpace(ctx.Tokens); await ctx.Dahan.AdjustHealthOfAll(-boost); }); }
public static async Task ActAsync(TargetSpaceCtx ctx) { // 6 damage. await ctx.DamageInvaders(6); // Add 2 badlands/strife var addBadlandsOrStrife = Cmd.Pick1("Add badlands/strife", Cmd.AddBadlands(1), Cmd.AddStrife(1)); await addBadlandsOrStrife.Repeat(2).Execute(ctx); // and 1 blight. await ctx.AddBlight(1); await TakeActionInUpToNLands(ctx // In up to 3 adjacent lands with blight , 3, ctx.Adjacent.Where(s => ctx.Target(s).HasBlight) // add 1 badland/strife. , addBadlandsOrStrife ); // if you have 3 fire 3 water: if (await ctx.YouHave("3 fire,3 water")) { await TakeActionInUpToNLands(ctx // in up to 3 adjacent lands, , 3, ctx.Adjacent // 1 damage to each invader. , new SpaceAction("1 damage to each invader", ctx => ctx.DamageEachInvader(1)) ); } }
static public async Task ActAsync(TargetSpaceCtx ctx) { // == Pick 2nd target - range 2 from same SS == var spiritSS = ctx.Self.Presence.SacredSites.ToArray(); var possibleSacredSiteSourcesForThisSpace = ctx.Space.Range(1).Where(s => spiritSS.Contains(s)).ToArray(); // IEnumerable<Space> secondTargetOptions = ctx.Presence.GetValidDestinationOptionsFromPresence( 2, Target.Any, possibleSacredSiteSourcesForThisSpace ); IEnumerable <Space> secondTargetOptions = ctx.Self.RangeCalc.GetTargetOptionsFromKnownSource(ctx.Self, ctx.GameState, TargettingFrom.PowerCard, possibleSacredSiteSourcesForThisSpace, new TargetCriteria(2)); var secondTarget = await ctx.Decision(new Select.Space("Select space to target.", secondTargetOptions, Present.Always)); // 4 damage in each target land (range must be measured from same SS) await ctx.DamageInvaders(4); await ctx.Target(secondTarget).DamageInvaders(4); // if 3 fire if (await ctx.YouHave("3 fire")) { await Apply3DamageInOneOfThese(ctx, secondTarget, "fire"); } // if 3 water if (await ctx.YouHave("3 water")) { await Apply3DamageInOneOfThese(ctx, secondTarget, "water"); } }
static void Given_NoSuroundingTowns(TargetSpaceCtx spaceCtx) { // Simplifies power card because it has a Gather-Towns we don't want to deal with. foreach (var adj in spaceCtx.Adjacent) { spaceCtx.Target(adj).Tokens.InitDefault(Invader.Town, 0); } }
static void Given_NoSuroundingDahan(TargetSpaceCtx spaceCtx) { // Simplifies power card because it has a Gather-dahan we don't want to deal with. foreach (var adj in spaceCtx.Adjacent) { var dahan = spaceCtx.Target(adj).Tokens.Dahan; dahan.Init(0); } }
static public async Task ActAsync(TargetSpaceCtx ctx) { // For each adjacent land with your presence, 1 Damage to a different Invader. int count = ctx.Space.Adjacent.Count(s => ctx.Target(s).Presence.IsHere); await ctx.Apply1DamageToDifferentInvaders(count); // Push 2 dahan await ctx.PushDahan(2); }
static Task DamageLandFromBlight(TargetSpaceCtx ctx) { // 2 damage per blight in target land int damage = ctx.BlightOnSpace * 2 // +1 damage per blight in adjacent lands + ctx.Adjacent.Sum(x => ctx.Target(x).BlightOnSpace); return(ctx.DamageInvaders(damage)); }
// A Real Flair for Discord // After one of your Powers adds strife in a land, you may pay 1 Energy to add 1 strife within Range-1 of that land." public override async Task AddStrife(TargetSpaceCtx ctx, Token invader) { await base.AddStrife(ctx, invader); if (Energy == 0) { return; } var nearbyInvaders = ctx.Space.Range(1) .SelectMany(s => ctx.Target(s).Tokens.Invaders().Select(t => new SpaceToken(s, t))) .ToArray(); var invader2 = await Action.Decision(new Select.TokenFromManySpaces("Add additional strife for 1 energy", nearbyInvaders, Present.Done)); if (invader2 == null) { return; } Energy--; await base.AddStrife(ctx.Target(invader2.Space), invader2.Token); }
static async Task DistributeDamageToLands(TargetSpaceCtx ctx, List <Space> newDamageLands, int additionalDamage) { Space[] targetLandOptions; while (additionalDamage > 0 && (targetLandOptions = newDamageLands.Where(s => ctx.Target(s).HasInvaders).ToArray()).Length > 0 ) { var newLand = await ctx.Decision(new Select.Space($"Apply up to {additionalDamage} vengeanance damage in:", targetLandOptions, Present.Always)); if (newLand == null) { break; } int damage = await ctx.Self.SelectNumber("How many damage to apply?", additionalDamage, 0); await ctx.Target(newLand).DamageInvaders(damage); additionalDamage -= damage; } }
static public async Task Option4(TargetSpaceCtx ctx) { // In a land with blight and presence (Select a space, not necessarily the one you targetted with power (I guess...) var spacesWithPresenceAndBlight = ctx.Self.Presence.Spaces .Where(s => ctx.Target(s).HasBlight); var space = await ctx.Decision(new Select.Space($"Push all dahan, destroy invaders and beast, 1 blight", spacesWithPresenceAndBlight, Present.Always)); var spaceCtx = ctx.Target(space); // Push all Dahan await spaceCtx.PushDahan(int.MaxValue); // Destroy all invaders and Beasts var beasts = spaceCtx.Beasts; await beasts.Destroy(beasts.Count); await spaceCtx.Invaders.DestroyAny(int.MaxValue, Invader.Explorer, Invader.Town, Invader.City); // Add 1 blight await ctx.AddBlight(1); }
static public async Task ActAsync(TargetSpaceCtx ctx) { // 2 fear ctx.AddFear(2); // +8 damage await ctx.DamageInvaders(8); // destroy 2 dahan await ctx.DestroyDahan(2); if (await ctx.YouHave("3 water,2 earth")) { var otherCoastalsOnSameBoard = ctx.Space.Board .Spaces.Where(s => s != ctx.Space && ctx.Target(s).IsCoastal) .ToArray(); foreach (var otherCoast in otherCoastalsOnSameBoard) { await DamageOtherCoast(ctx.Target(otherCoast)); } } }
static public async Task ActionAsync(TargetSpaceCtx ctx) { // Push up to 2 dahan. var destinationSpaces = await ctx.PushUpToNDahan(2); // if pushed dahan into town or city bool pushedToBuildingSpace = destinationSpaces .Any(neighbor => ctx.Target(neighbor).Tokens.HasAny(Invader.Town, Invader.City)); if (pushedToBuildingSpace) { ctx.AddFear(1); } }
private static async Task DoFireDamageToMultipleTargets(TargetSpaceCtx ctx, int fireDamage) { await ctx.DamageInvaders(1); // because they targetted a land, only select invaders from that land. --fireDamage; var spacesWithPresenceAndBlight = ctx.Self.Presence.Spaces .Select(s => ctx.Target(s)) .Where(x => x.HasBlight) .ToArray(); // ! don't .ToArray() this because we want it to re-execute each time. var invaderTokens = spacesWithPresenceAndBlight .SelectMany(ctx => ctx.Tokens.Invaders().Select(t => new SpaceToken(ctx.Space, t))); while (fireDamage > 0 && invaderTokens.Any()) { SpaceToken token = await ctx.Decision(new Select.TokenFromManySpaces($"Apply fire damage. ({fireDamage} remaining)", invaderTokens, Present.Always)); await ctx.Target(token.Space).Invaders.ApplyDamageTo1(1, (HealthToken)token.Token); --fireDamage; } }
public static async Task ActAsync(TargetSpaceCtx ctx) { // 2 damage per dahan in target land await ctx.DamageInvaders(2 *ctx.Dahan.Count); if (await ctx.YouHave("3 sun,2 animal")) { // you may push up to 2 dahan. var pushedToLands = await ctx.PushUpToNDahan(2); // 2 damage per dahan foreach (var neighbor in pushedToLands.Distinct()) { await DahanDeal2DamageEach(ctx.Target(neighbor)); } } }
static public async Task ActionAsync(TargetSpaceCtx ctx) { // 3 fear ctx.AddFear(3); // 5 damage await ctx.DamageInvaders(5); if (await ctx.YouHave("3 fire,3 air")) { // destroy 1 town in each adjacent land foreach (var neighbor in ctx.Space.Adjacent) { await ctx.Target(neighbor).Invaders.Destroy(1, Invader.Town); } } }
static public async Task ActAsync(TargetSpaceCtx ctx) { // if you have 2 sun, 2 air, 2 animal, // First Gather up to 3 dahan if (await ctx.YouHave("2 sun,2 air,2 animal")) { await ctx.GatherUpToNDahan(3); } // move up to 5 dahan from target land to any land. Space destination = await ctx.MoveTokensOut(max : 5, TokenType.Dahan, range : 100); // defend 5 in that land if (destination != null) { ctx.Target(destination).Defend(5); } }
static public async Task ActAsync(TargetSpaceCtx ctx) { // 1 fear. ctx.AddFear(1); // 1 damage. await ctx.DamageInvaders(1); // You may pay 1 Energy to deal 1 Damage in an adjacent land. if (1 <= ctx.Self.Energy && await ctx.Self.UserSelectsFirstText("Pay 1 energy to deal 1 Damage in an adjacent land?", "Yes, pay 1 energy for 1 damage", "No, thank you")) { ctx.Self.Energy--; var adjInvaders = ctx.Adjacent.SelectMany(s => ctx.GameState.Tokens[s].Invaders().Select(t => new SpaceToken(s, t))).ToArray(); var adjInvader = await ctx.Decision(new Select.TokenFromManySpaces("Select invader for 1 damage", adjInvaders, Present.Always)); await ctx.Target(adjInvader.Space).Invaders.ApplyDamageTo1(1, (HealthToken)adjInvader.Token); } }
static public async Task Option3Async(TargetSpaceCtx ctx) { await Option2Async(ctx); if (7 <= ctx.Self.Energy && await ctx.Self.UserSelectsFirstText("Activate Teir 3?", "Pay 7 to cause damage from presence", "skip")) { // -7 Energy. ctx.Self.Energy -= 7; // In every land in the game: X Damage, where X is the number of presence you have in and adjacent to that land. var invaderLands = ctx.AllSpaces.Where(space => ctx.Target(space).HasInvaders).ToArray(); foreach (var land in invaderLands) { var landsCreatingDamage = new HashSet <Space>(land.Range(1)); int damage = ctx.Self.Presence.Placed.Count(landsCreatingDamage.Contains); await ctx.DamageInvaders(damage); } } }
public static Task ActAsync(TargetSpaceCtx ctx) { // defend 2 in target land and all adjacent lands. int defense = 2; // Defense 2 // For every presence on your Deep Slumber track, Defend 1 in target land and all adjacent lands. if (ctx.Self.Presence is SerpentPresence sp) // don't crash if card was gifted to someone else { defense += sp.AbsorbedPresences.Count; } ctx.Defend(defense); foreach (var adj in ctx.Adjacent) { ctx.Target(adj).Defend(defense); } return(Task.CompletedTask); }
public static async Task ActAsync(TargetSpaceCtx ctx) { // 2 fear. 2 damage. ctx.AddFear(2); await ctx.DamageInvaders(2); // if no beasts are present, add beast. if (!ctx.Beasts.Any) { await ctx.Beasts.Add(1); } else { // otherwise, +2 Damage, await ctx.DamageInvaders(2); // and Push up to 1 beast. await ctx.PushUpTo(1, TokenType.Beast); } if (await ctx.YouHave("2 fire,3 animal")) { // 1 fear and ctx.AddFear(1); // destroy 1 explorer/town in an adjacent land with beast var tokens = ctx.Adjacent .Select(ctx.Target) .Where(x => x.Beasts.Any) .SelectMany(x => x.Tokens.OfType(Invader.Explorer) .Select(t => new SpaceToken(x.Space, t)) ) .ToArray(); var st = await ctx.Decision(new Select.TokenFromManySpaces("Destroy Explorer", tokens, Present.Always)); if (st != null) { await ctx.Target(st.Space).Invaders.Destroy(1, (HealthToken)st.Token); } } }
static public async Task ActionAsync(TargetSpaceCtx ctx) { // for each dahan in target land, 1 damage and defend 2 // -- damage -- await ctx.DamageInvaders(ctx.Dahan.Count); // if you have 2 sun, 2 earth, 2 plant if (await ctx.YouHave("2 sun, 2 earth, 2 plant")) { // you may push up to 2 dahan Space[] dest = await ctx.PushUpToNDahan(2); // defend pushed foreach (var d in dest) { ctx.Target(d).Defend(2); } } // -- defend remaining -- ctx.Defend(ctx.Dahan.Count * 2); }