public static async Task ActAsync(SelfCtx ctx) { // Your presence may count as badlands and beast. int PresenceAsToken(GameState _, Space space) => ctx.Self.Presence.CountOn(space); ctx.GameState.Tokens.RegisterDynamic(PresenceAsToken, TokenType.Badlands, false); ctx.GameState.Tokens.RegisterDynamic(PresenceAsToken, TokenType.Beast, false); // (Decide per presence, per action) ... Not doing this bit exactly, both are always present, but can't be destroyed. // your presence cannot move. // !!! not implemented // if you have 2 plant 3 animal: if (await ctx.YouHave("2 plant,3 animal")) { // 2 fear and ctx.AddFear(2); // 2 damamge in one of your lands. var space = await ctx.Decision(new Select.Space("2 damage", ctx.Self.Presence.Spaces, Present.Always)); if (space != null) { await ctx.Target(space).DamageInvaders(2); } } }
public override async Task ActivateAsync(SelfCtx ctx) { if (ctx.Self is not FracturedDaysSplitTheSky fracturedDays) { return; } var minor = fracturedDays.DtnwMinor; var major = fracturedDays.DtnwMajor; PowerCard card = await ctx.Self.SelectPowerCard("Gain Power Card from Days That Never Were", minor.Union(major), CardUse.AddToHand, Present.Always); if (card == null) { return; // in case both hands are empty. } fracturedDays.AddCardToHand(card); if (minor.Contains(card)) { minor.Remove(card); } else { major.Remove(card); await fracturedDays.ForgetPowerCard_UserChoice(Present.Always); } }
static async Task TargetActions(SelfCtx ctx, bool bringCityAndBlight) { // target spirit gets +2 range with all Powers. ctx.GameState.TimePasses_ThisRound.Push(new PowerApiRestorer(ctx.Self).Restore); ctx.Self.RangeCalc = new TargetLandApi_ExtendRange(2, ctx.Self.RangeCalc); // Target spirit may push 1 of their presence to an adjacent land var(src, destination) = await ctx.Presence.PushUpTo1(); var mover = new TokenPusher_FixedDestination(ctx.Target(src), destination); // bringing up to 2 explorers, 2 towns and 2 dahan along with it. mover.AddGroup(2, Invader.Explorer); mover.AddGroup(2, Invader.Town); mover.AddGroup(2, TokenType.Dahan); // if you hvae 2 air, 2 water, the moved presence may also bring along up to 2 cities and up to 2 blight. if (bringCityAndBlight) { mover.AddGroup(2, Invader.City); mover.AddGroup(2, TokenType.Blight); } await mover.MoveUpToN(); }
public override async Task ActivateAsync(SelfCtx ctx) { var options = ctx.Self.Presence.Spaces.SelectMany(p => p.Range(2)).Distinct(); var to = await ctx.Decision(new Select.Space("Gather beast to", options, Present.Always)); await ctx.Target(to).GatherUpTo(1, TokenType.Beast); }
public override async Task ActivateAsync(SelfCtx ctx) { var element = ElementOptions.Length == 1 ? ElementOptions[0] : await ctx.Self.SelectElementEx("Gain element", ElementOptions); ctx.Self.Elements[element]++; }
static async Task DestroyBoard(SelfCtx ctx, Board board) { // destroy the board containing target land and everything on that board. // All destroyed blight is removed from the game instead of being returned to the blight card. await DestroyTokens(ctx, board); if (!ctx.Self.Text.StartsWith("Bringer")) // !!! Maybe Api should have method called "Destroy Space" or "DestroyBoard" // destroy presence { foreach (var spirit in ctx.GameState.Spirits) { foreach (var p in spirit.Presence.Placed.Where(p => p.Board == board).ToArray()) { await spirit.Presence.Destroy(p, ctx.GameState, DestoryPresenceCause.SpiritPower); } } // destroy board - spaces foreach (var space in board.Spaces.ToArray()) { board.Remove(space); } ctx.GameState.Island.RemoveBoard(board); } }
public static async Task ActAsync(SelfCtx ctx) { // Gain a Minor Power. // If you have 4 moon, You may gain a Major Power instead of a Minor Power. if (await ctx.YouHave("4 moon")) { await ctx.Draw(); } else { await ctx.DrawMinor(); } // You may Forget this Power Card to gain 3 Energy. var thisCard = ctx.Self.InPlay.SingleOrDefault(x => x.Name == ShapeTheSelfAnew.Name); if (thisCard != null && // might have already been forgotten when picking a major card. await ctx.Self.UserSelectsFirstText("Forget this card for +3 energy.", "Yes, forget it.", "no thanks.") ) { // Forget this Power Card ctx.Self.Forget(thisCard); // gain 3 energy ctx.Self.Energy += 3; } }
public async Task <bool> ResolveAction(Phase speed, Present present, SelfCtx ctx) { // ------------- // Select Actions to resolve // ------------- IActionFactory[] options = this.GetAvailableActions(speed).ToArray(); IActionFactory option = await this.SelectFactory("Select " + speed + " to resolve:", options, present); if (option == null) { return(false); } // if user clicked a slow card that was made fast, // slow card won't be in the options if (!options.Contains(option)) { // find the fast version of the slow card that was clicked option = options.Cast <IActionFactory>() .First(factory => factory == option); } if (!options.Contains(option)) { throw new Exception("Dude! - You selected something that wasn't an option"); } await TakeAction(option, ctx); return(true); }
// ! Can't used normal PlacePresence, because it must be range-1, range 0 not allowed. public override async Task ActivateAsync(SelfCtx ctx) { var options = ctx.Self.Presence.Spaces.First().Adjacent; var space = await ctx.Decision(new Select.Space("Add presence to", options, Present.Always)); ctx.Presence.PlaceOn(space); }
public override async Task ActivateAsync(SelfCtx ctx) { List <Space> gatherSpaces = ctx.Self.Presence.Spaces .Where(p => p.IsCoastal) .Select(p => p.Adjacent.Single(o => o.IsOcean)) .Distinct() .ToList(); while (0 < gatherSpaces.Count) { Space currentTarget = gatherSpaces[0]; Space source = await ctx.Decision(new Select.Space( $"Select source of Presence to Gather into {currentTarget}" , currentTarget.Adjacent .Where(ctx.Self.Presence.Spaces.Contains) .ToArray() , Present.Always )); // apply... ctx.Presence.Move(source, currentTarget); // next gatherSpaces.RemoveAt(0); } // while }
public bool RunAfterGrowthResult => false; // no dependencies public override async Task ActivateAsync(SelfCtx ctx) { if (ctx.Self is ShiftingMemoryOfAges smoa) { await smoa.PrepareElement(context); } }
public override async Task <object> GetTargetCtx(string powerName, SelfCtx ctx, TargettingFrom _) { Spirit target = ctx.GameState.Spirits.Length == 1 ? ctx.Self : await ctx.Decision(new Select.Spirit(powerName, ctx.GameState.Spirits)); return(ctx.TargetSpirit(target)); }
public override async Task ActivateAsync(SelfCtx ctx) { repeater.BeginAction(); await Inner.ActivateAsync(ctx); repeater.EndAction(ctx.Self); }
public override async Task ActivateAsync(SelfCtx ctx) { for (int i = 0; i < count; ++i) { await ctx.Self.Draw(ctx.GameState); } }
public override async Task ActivateAsync(SelfCtx ctx) { if (ctx.Self is FracturedDaysSplitTheSky fracturedDays) { await fracturedDays.GainTime(delta, ctx.GameState); } }
private static MultiSpace JoinSpaces(SelfCtx originatorCtx, Space space, Space other) { var gameState = originatorCtx.GameState; var multi = new MultiSpace(space, other); MoveAllItemsOnSpace(gameState, other, multi); MoveAllItemsOnSpace(gameState, space, multi); // Pick Board var board = space.Board; // !!! this is not correct when we start having multiple boards. // Disconnect space var spaceAdjacents = board.Remove(space); var otherAdjacents = board.Remove(other); // it has the terrain and land # of both lands. board.Add(multi, spaceAdjacents.Union(otherAdjacents).Distinct().ToArray()); // When this effect expires gameState.TimePasses_ThisRound.Push(async(gs) => { MoveAllItemsOnSpace(gs, multi, space); board.Remove(multi); board.Add(other, otherAdjacents); board.Add(space, spaceAdjacents); // divide pieces as you wish. await DistributePresence(space, other, gs); await DistributeTokens(originatorCtx, space, other, gs); }); return(multi); }
public StopPresenceDestructionFromBlightOrEvents(SelfCtx ctx) { this.spirit = ctx.Self; this.oldBehavior = ctx.GameState.Destroy1PresenceFromBlightCard; ctx.GameState.Destroy1PresenceFromBlightCard = this.DestroyPresenceDirectlyFromBlight; ctx.GameState.TimePasses_ThisRound.Push(Restore); }
static async Task PlayCardByPayingHalfCostOrForgetting(PowerCard card, SelfCtx ctx) { // target spirit may now play the major power they keep by: // * paying half its cost (round up) OR int cost = (card.Cost + card.Cost % 2) / 2; var payingHalfCostOption = new SelfAction( $"paying {cost}", ctx => ctx.Self.PlayCard(card, cost) ).Matches(x => cost <= x.Self.Energy); // * forgetting it at the end of turn. var forgettingCardOption = new SelfAction( $"forgetting at end of turn", ctx => { ctx.Self.PlayCard(card, 0); ctx.GameState.TimePasses_ThisRound.Push((gs) => { ctx.Self.Forget(card); return(Task.CompletedTask); // this must run befire cards are moved to discard, or it will be forgotten for Shifting Memories }); } ); // !!! It gains all elmemental thresholds. - implement! await ctx.SelectAction_Optional($"Play {card.Name} now by:", payingHalfCostOption, forgettingCardOption ); }
public bool RunAfterGrowthResult => true; // uses growth-earned energy; public override async Task ActivateAsync(SelfCtx ctx) { if (2 <= ctx.Self.Energy && await ctx.Self.UserSelectsFirstText("Draw Power Card?", "Yes, pay 2 energy", "No, thank you.")) { ctx.Self.Energy -= 2; await ctx.Draw(); } }
protected override PowerCard[] GetCardOptions(SelfCtx ctx) { return(base.GetCardOptions(ctx) .GroupBy(pc => pc.Cost) .OrderBy(grp => grp.Key) .First() // group with lowest cost .ToArray()); // all cards in group }
public override Task ActivateAsync(SelfCtx ctx) { var oceanSpaces = ctx.GameState.Island.Boards .Select(b => b.Spaces.Single(s => s.IsOcean)) .ToArray(); return(ctx.Presence.Place(oceanSpaces)); }
public static async Task AssignNewElementToTrack(SelfCtx ctx, Track track) { var el = await ctx.Self.SelectElementEx("Select permanent element for this slot.", ElementList.AllElements); track.Elements = new Element[] { el }; ctx.Self.Elements[el]++; track.Icon.ContentImg = el.GetTokenImg(); }
public PayEnergyToTakeFromCard(SelfCtx ctx, int cost) { this.spirit = ctx.Self; this.cost = cost; this.oldBehavior = ctx.GameState.TakeFromBlightSouce; ctx.GameState.TakeFromBlightSouce = this.AddBlight; ctx.GameState.TimePasses_ThisRound.Push(Restore); }
static async Task Replace1PresenceWith1Disease(SelfCtx ctx) { var space = await ctx.Presence.SelectDeployed("Replace Presence with 1 disease"); await ctx.Presence.RemoveFrom(space); await ctx.Target(space).Disease.Add(1); }
public override Task ActivateAsync(SelfCtx ctx) { var spirit = ctx.Self; spirit.Hand.AddRange(spirit.DiscardPile); spirit.DiscardPile.Clear(); return(Task.CompletedTask); }
public override async Task ActivateAsync(SelfCtx ctx) { var gameState = ctx.GameState; var options = gameState.Island.AllSpaces.Where(space => gameState.Tokens[space].Beasts.Any); var space = await ctx.Decision(new Select.Space("Add presence to", options, Present.Always)); ctx.Presence.PlaceOn(space); }
public bool RunAfterGrowthResult => true; // might receive additional presence public override async Task ActivateAsync(SelfCtx ctx) { var src = await ctx.Decision(Select.DeployedPresence.All("Move presence from:", ctx.Self, Present.Always)); var dstOptions = src.Range(Range).Where(s => !s.IsOcean); var dst = await ctx.Decision(Select.Space.ForAdjacent("Move preseence to:", src, Select.AdjacentDirection.Outgoing, dstOptions, Present.Always)); ctx.Presence.Move(src, dst); }
public override async Task TakeAction(IActionFactory factory, SelfCtx ctx) { actionElements = null; // make sure these are cleared out for every action try { await base.TakeAction(factory, ctx); } finally { actionElements = null; } }
public override Task ActivateAsync(SelfCtx ctx) { if (!ran) { ctx.Self.Energy++; ran = true; } return(Task.CompletedTask); }
static public async Task Option1(SelfCtx ctx) { var deck = ctx.GameState.InvaderDeck.unrevealedCards; IInvaderCard topCard = deck[0]; await ctx.Self.SelectText(topCard.Text, new string[] { "Shuffle with next top card." }, Present.Always); deck.RemoveAt(0); InsertIntoTop2(deck, topCard); }