Tuesday, November 30, 2010

Utopia: Crushed

Not dead. Dreaming.

So, seemingly just to spite my pledge, it turns out that even if you somehow implement every rule of Magic perfectly, with every obscure corner case handled, there must always be card-specific code. That is because there is a card that basically has card-specific rules, the comprules.doc equivalent of card-specific code.I'm talking about Rasputin Dreamweaver. I'm pretty sure it is the only card in MtG history to make use of the state based action:
704.5s If a permanent with an ability that says it can’t have more than N counters of a certain kind on it has more than N counters of that kind on it, all but N of those counters are removed from it.
So an MTG-implementation can't yet be truly without card-specific code because MtG itself has basically card-specific rules.
And before you point out Shahrazad as another card that is alone in the use of a rule, let me be nitpicky and point out Enter the Dungeon.
Just a curious thought.

Friday, October 1, 2010

*Hellfish casts Rise From The Grave targeting blog*

Because of a job-issue (the lack of any), things have been quiet for a while. I refuse to let this turn into an emo whinepost about it, though, this is a programming blog, damnitall! Just know that I have uncommitted code working further towards modifiable costs as well as the beginnings of a UI outline.

Monday, August 23, 2010

Quick Attack!

Just a quick post to update y'all on what's going on: I'm ripping out the InputStateMachine code into a separate project for testing and ironing out design issues. Also, I'll take the opportunity to test out the UIBridge.

Though that DS sure is tempting... Damn Pokemon Pearl! Havn't been this addicted since Blue!

Tuesday, August 10, 2010

In which you'll get an opportunity to point and laugh at ugly ugly code

So I've implemented a first stage prototype (I love using those words) of the "Dependency Walker" continuous effects sorter, the basics of which I went through in the last post. So now the process will be something like:

Card tells the engine it wants to supply a continuous effect, and supplies the different parts of the effect in addition to what the entire effect(or parts of it) depends on (such as "Targets type" for Gaia's Anthem) as well as which layer each part goes in. The engine sorts those layers first by CDA-nonCDA,then by Dependency using this code below and then by timestamp (also below).
http://sharpening.pastebin.com/5PSCpt4U

NOTE: That I still think I have some corner cases to handle, but the principle will be the same.
EDIT: Of course, there's also the rather BIG corner case (:P) of having no circular dependency, in which case the walker shouldn't be used at all. Fixed.

Wednesday, August 4, 2010

The roots kiss the sky and the crown bites the dust

I bet alot of you who read my second entry on this blog chuckled quietly to yourself. "Oh, he'll feel the pain of actually trying to *implement* a continuous effects system with dependencies soon enough." :P Well, if you did, you were right. Dependencies are beating me up, though I have made some headway. The tracking of their dependency wasn't the problem, that works in theory (everytime I say something works, you should probably add "in theory" because until I start prototyping cards I can't actually test anything),the problem is of course comparing the dependencies/targets and sorting accordingly.

In addition, I must be able to weed out circular dependencies and apply those effects in timestamp order instead. The idea I have so far is:
  1. Determine all dependencies for all effects. That is for each effect E: Loop through each other effect F and if that F's target field is in E's list of dependent fields, add E to F's list of dependants and F to E's list of dependsOn. To represent this visually, it kind of becomes an "upside-down tree structure" (Damn language difficulties).
  2. While there is an effect E with an empty dependsOn list, add E to the final list of Effects for the layer.
  3. (This is the part I'm wrestling with currently.What we have left is a bunch of effects that all depend on one or more of the other effects.) What I'm pondering is designing a sort of recursive function "tree walker" that will traverse the tree and mark each effect it passes as visited and branch for each effect the current effect dependsOn and if a branch returns to a previously visited effect before reaching a leaf(an effect that no other effects dependOn), all the effects it visited will be part of a dependency loop and should be added to the final list of Effects in timestamp order.
  4. If there are still effects remaining, go to step 2.

This sorting WILL be expensive but probably has to be done everytime a continous effect is added/removed.

Thank Urza I have other things to do to clear my head! Costs are now mutable and Activatables have been restructured to further simplify "cast without paying". Now you cannot create your own Activatables anymore, you have to go through the ActivatableFactory and get a "Base Activatable" that only handles the cost payment(s). Then, you append the desired effect to the base activatable. The reason is that this way I can depend on payment being the first effect listed and as such, skip it everytime cast-without-pay is needed. Now to figure out how conditional cast-without-pay will be handled there. (Traps).

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.