Triggered Abilities – Continued

I worked hard in the last week to implement triggered abilities. It was pretty straightforward in retrospect. It opens up the possibilities for a lot more cards to be implemented. I already talked about Megrim in my last post. I also implemented Angelic Chorus as a proof of concept:


[CardFactory("Angelic Chorus")]
public class AngelicChorusCardFactory : MTGCardFactory
{
  // Whenever a creature comes into play under your control,
  // you gain life equal to its toughness.
  class GainLifeAbility : AnyCreatureComesIntoPlayUnderControlAbility
  {
    override IEnumerable<ImmediateCost> Play(Spell spell, Resolvable<Card> card)
    {
      spell.Effect = context =>
      {
        Card resolvedCard = card.Resolve(context.Game);
        context.Controller.GainLife(resolvedCard.Toughness);
      };
      yield break;
    }
  }

  override void Initialize(Card card, InitializationContext context)
  {
    base.Initialize(card, context);
    CreateAbility<GainLifeAbility>(card);
  }
}

As you can see, I abstracted most of the complexity of the triggering into a base ability class (AnyCreatureComesIntoPlayUnderControlAbility). It is still however possible to handle the more complex cases by deriving directly from TriggeredAbility and handling the events yourself.

I think in the long term, I might benefit from splitting up the abilities into clearly separate (orthogonal) components. For example, this ability could become:

  • ComesIntoPlayAbility (trigger) + Creature (type filter) + Under Control (controller filter).

This also makes it easier to generate these abilities from a intermediate script language.

Ending note: I just noticed that Mox has now more than 1000 unit tests (1095 to be precise). Yay!

Advertisements

About fparadis2

Lead Game programmer
This entry was posted in Mox. Bookmark the permalink.

One Response to Triggered Abilities – Continued

  1. frwololo says:

    In Wagic we use the “TargetChooser” objects for everything related to a card “matching” certain conditions.
    an event such as “A creature comes into play under my control” involves two TargetChooser.

    The first one checks that the card “comes from” a valid zone (in that case, the card can come from everywhere).
    The second one checks that the card lands in a valid situation (it has to be a creature, in my battlefield).

    These two TargetChooser objects are wrapped in a “TriggeredAbility” object that calls them only if a “CardChangedZone” event is received.

    congrats on your unit tests. Wagic now has around 250 regression tests, but unfortunately no unit tests 😦

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s