Monday, July 26, 2010

Activatables

If not for Activatables, cards in Sharpening would be very useless, unless you turn it into some sort of collector's simulator. So what are activatables? A lot of things.
  1. They are the activated abilities of permanents.
  2. They are the act of casting any spell.
  3. They are any alternate way of casting any spell. (Flashback,Buyback,Cycling,Ninjutsu,"You may X instead of paying this card's casting cost")

Basically, they're everything you can do with a card beyond holding it in your hand.Activatables contain:

  • A Condition, "CanBeActivated"
  • A CompoundEffect, "ActivatedEffect"
  • A CompoundCost
  • A CardBase, "CardSource"
  • A string, "Description"
  • Tags for wether the Activatable is a mana ability or a regular ability.

The plan is that when you click on a card in the GUI side of things, the UI raises an event in it's bridge to the Sharpening core (More on the bridge in a future entry) and the library will round up all the Activatables of the clicked card and ask them if they could be used at the moment. For this, each Activatables "CanBeActivated" checks whatever is needed. For instance, Flashback "CanBeActivated"s checks that the card is in the graveyard and returns true if so.Then, the library will make a call back in to the GUI to present the player with a choice of the Activatables that were usable (unless of course there was only one, then that will be run). Then, the chosen or lone Activatable's CompoundEffect(One or more effects) "ActivatedEffect" is run. The effect will often, but not always, start by setting the InputStateMachine to "Pay Cost" mode so that it's CompoundCost(One or more Costs, of any type) can be paid one by one. Then, the Effect will do whatever it specifically should. Continuing with the Flashback example, this would be "Do the same as the hardcasting Activatables Effect, AND then exile the card.".

To simplify card creation, I provide two Factory classes that the cards can use to create Costs(not just mana costs) or full-on Activatables. For example, to add Flashback to a card, you could simply use a statement like

this.activatables.Add(ActivatableFactory.Create(this,"Flashback:2 U
U,Discard(1,Any)"));

and the ActivatableFactory would create the two costs for you (using the CostFactory), insert the proper CanBeActivated condition and copy the hardcasting directly from the card(with the added Exile effect).

If at anytime a card would require an activatable that the ActivatableFactory can't create(not a rare situation), a custom Activatable can be written directly in the cards code using anonymous delegates for the Condition and Effects. I am also thinking about letting the ActivatableFactory create a BaseActivatable that only takes care of paying the costs and let the card writer tack on the actual effect at the end. Otherwise, you'd have to write boilerplate cost-paying code everytime you write a custom Activatable.

Oh crap, I'm starting to ramble. Well, that's Activatables.If something doesn't make sense, it could be either that I muddled it up or because it depends on something else that I havn't touched on yet. In closing, I want to make a pledge.

"I'd swear on my mother's grave, were she not alive and well, that I will never, EVER, place card-specific code in the core of Sharpening, so help me Niv-Mizzet." Amen.

Friday, July 23, 2010

Continuous Dependencies

Just a quick post today, since I've only just gotten home late last night and am settling back in.

However, this is not really an issue that will be tackled quickly. I will describe the idea I had for dependencies in the layer system,though.

613.7a An effect is said to “depend on” another if (a) it’s applied in the same layer (and, if applicable, sublayer) as the other effect (see rules 613.1 and 613.3); (b) applying the other would change the text or the existence of the first effect, what it applies to, or what it does to any of the things it applies to; and (c) neither effect is from a characteristic-defining ability. Otherwise, the effect is considered to be independent of the other effect.
The idea I had is that, in C# (and other languages on the .NET platform) you can use techniques known as "Reflection" to access to structure of the various objects your program. I will use reflection to obtain, for each entry into the layer system, information about which of the characteristics(Members of the card object, or possibly the card objects CharacteristicCollection object) that entry depends on and what values it depends on these characteristics being.(Sentence trainwreck, woo) as well as what characteristics it changes. This way, I have all the data I need to sort after first CDA(Characteristic Defining Ability)/non-CDA, then dependency, then timestamp in each layer before running the effects of the layers.

Sunday, July 18, 2010

The Sharpening (or YAMTGREE)

So yeah, I'm programming a MTG rule enforcement engine.Again. Last time was a mess, and alot of that was because A) I didn't actually *know* about the comprehensive rules document and B) the magic I had played the most was in the form of Shandalar. That's what? Fourth or fifth edition? Now I feel like that is less of an issue with a lot of Forge,MagicWars,Botarena and even cardboard time logged and a kneejerk reaction to open up comprules.doc every time the AI does something suspicious.

So what's this program all about?
Glad you asked.It was born from a coding spurt combining with some random floating thoughts about implementing text-changing effects in Forge. It takes the shape of a C# class library and not a full program, because I will probably end up making a basic UI with WinForms, which will probably not be portable. This way, any .NET UI can be made and hooked into the library.
The card format that will be used is a little odd. It's sort of halfway between scripted and hardcoded in that the cards aren't compiled until the decks used by each player is loaded, but they are written as full-on C# classes in source files. With the help of some reflection and run-time compilation shenanigans, card classes (inheriting from a CardBase) will have access to all of the various facilities of the engine, such as the Input State Machine(inspired by Forge's), the Activatables (Which basically define everything that a player can do with a card, from hardcasting to activating abilities), the Scheduler (For effects with durations) and a hopefully correct Continuous Effects Layering System(Oh, the important horror!).

Open source?
Eventually. Like any new project of mine, it's ugly. Hideous, in fact. Until I clean it up and document it, it will remain closed source. The cards, however, are fine to read and use as example/base of another card once it get's to that point.

What's done/missing?
Done:
A lot of things are partially done, but that's how it is. Certain things require parts of other things that in turn do the same.That said, I don' think the Scheduler,Priority or Phase mechanics needs more work.
Missing:
The Input State Machine needs tinkering with in order to correctly pass data between the user and the library. Something important is also missing: Spell facilities.No stack,no nothing.
It is very possible that I've gone about this project in an awkward/wrong way, as I do, because while I already have facilities for Text-changing effects already in place, spells are not supported as I mentioned.

Release?
I have 5 criteria for when I will make a first alpha release of Sharpening: A basic UI, of course, Basic Lands implemented and working fine, a creature working fine, a continuous effect working fine and an instant working fine. If you follow this blog, you'll know when any of this happens. ;)

Next?
More Input State Machine tinkering, and beginning the Spell framework.I hope this'll keep your attention (and mine xD ) for a while longer!

Oh god, when I finished writing this I reflexively reached for the "Build Solution" shortcut key.. I've been programming too much already.