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.
Tuesday, November 30, 2010
Friday, October 1, 2010
Monday, August 23, 2010
Tuesday, August 10, 2010
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).
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
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:
- 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).
- While there is an effect E with an empty dependsOn list, add E to the final list of Effects for the layer.
- (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.
- 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
- They are the activated abilities of permanents.
- They are the act of casting any spell.
- 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
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
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
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!).
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.
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.
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.
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. ;)
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.