ec2-3-230-154-90.compute-1.amazonaws.com | ToothyWiki | ChrisHowlett | RecentChanges | Login | Webcomic

BNF: ChrisHowlett/MCGManaCostModule

This looks to be a [Mammoth] undertaking; let's take it in chunks, shall we?
It'll be incredibly cool if we can get this working. I love the idea of people playing a future form of TypeFourGenerated? specifying "I'm playing a red-green deck" and generating a hand of 7 red or green Generated cards with sane manacosts... (But insane effects, naturally :) (either randomly including mostly-basic lands, or being able to choose to draw land when you wish or some such) --AlexChurchill
My initial thought was that players could play any card as a basic land of a type appropriate to one of its colours. Don't forget that generator also makes lands now, as well. --CH

I reckon the sanest thing to do is to give each card a base cost based on its type, colour and power/toughness (for creatures). This is then modified as we pass through the various granted abilities. I suggest that during development, we output all the modifications as we go along, to make bug fixing easier.

I also think that simply having an integer notion of the mana cost is not fine-grained enough; for instance, MTG: Eager Cadet is over-costed by a smidge (compare with MTG: Savannah Lions - although that is, admittedly, rare; or MTG: Suntail Hawk, which is the same as MTG: Eager Cadet, but with a "cheap" white ability). I therefore propose that we have mana-cost and fractional-mana-cost. The latter can take only the values "under", "over" or "none". If two abilities need to affect the fractional-mana-cost, then
 "under & over" -> "none"
"under & under" -> "none" & decrease mana-cost
"over & over" -> "none" & increase mana-cost
This all seems reasonable. --AC
Having seen it in practice, though, it appears to be in two minds as to whether it's being 1/2 or 1/3. "3&under" is distinct from "2&over", but either of them plus one "over" will yield "3". Is it worth consolidating so that there's no such thing as "under"? Or is it going to be possible to distinguish effectively between "3&under" and "2&over"? Or should we go ahead with adding more costs before we decide one way or the other? --AC
Pasting from chat: I don't know. I think I'd reckoned on it being roughly equivalent to half-a-mana. But then, should a 2.5-cost card be a cheap 2 or an expensive 3? In some ways, I like the current system, since it means the fraction is always "half", but can theoretically produce either integer cost. I agree it's not the epitome of elegance, though. --CH''

I also wonder whether it might be best (long-term, at least) to have converted-mana-cost, fractional-mana-cost and required-coloured-symbols. That would make it easier to correctly cost multicoloured cards and those with multiple instances of a single colour.

I suggest starting out by defining base costs for various things. I reckon everything except creatures have base costs of 0, since they are precisely the abilities on them (although instants should perhaps have a base cost of 1). So I've been looking in [Gatherer] for vanilla or nearly-vanilla creatures in standard, and have found the following:

 White (I had to use Legacy for this. Not enough standard or extended vanillas)
  W = 1/1 (under)
  1W = 2/2 (under)
  2W = 2/3
      1/4 (under)
  3W = 3/3

 Blue                Black
  U = 1/1 (under)      B = 1/1 (under)
  1U = 2/1            1B = 2/1 (under)
      1/3            2B = 2/2
  2U = 1/4            3B = 3/3
  3U = 3/3                  4/2
  6U = 6/6                  5/1

 Red                 Green
  R = 1/1 (under)      G = 1/2
  1R = 2/1 (under)    1G = 2/2 (under)
  2R = 2/2 (under)    GG = 2/3
      3/2 (over)    1GG = 3/3
1RR = 3/2            3G = 4/3
  3R = 3/3            4G = 5/4
3RR = 5/3            5G = 5/5 (under)
                      4GG = 6/4
                      6G = 7/7
                      7G = 7/6 (yes, really)

So, what does this tell us about how the various colours cost creatures, other than that Green fatties are inconsistent? My thoughts will follow, but I invite thoughts from others as well.

Wow. Funky. And utterly insane, as you said in the edit summary. Those vanilla costings look good, although you obviously also get, say, 1/2s for 2G with two cheap abilities[1], or 4/4s for 4G with one cheap ability[2], or even 1/1s for 3G with an expensive ability[3]; not quite sure how to manage slippability along those lines. --AC
Yes, I'd realised that, and the idea is that it would work automatically. For instance, MTG: Silhana Starfletcher would be treated as a 1/2 Green creature (costs G) with a mana-add ability (cheap for green, 1 mana additional) and blocks flyers (cheap for green, 1 mana additional). MTG: Suntail Hawk is viewed as a 1/1 White creature (costs W-and-a-fraction-under) with flying (very cheap for white, fractional mana additional).

I think the vanilla costs above produce roughly the following results, at least for small P/T:
 Colour    C buys    Increment of 1 buys
                      Power | Toughness
White      2/1        1  |    1
Blue      1/1        1  |    1.5
Black      1/1        1.5 |    1.5
Red        1/1+        1  |    1    (and (1)->(R) buys 1 power)
Green      1/2        1.5 |    1.5

Which is odd, as it means that White - except for getting a 1-power bonus at the 1-cost, is worse than most other colours at creatures... In fact, I reckon I've just misjudged White, because it's highly confusing. Consider the step from 2W to 3W. That could buy you 1 power, 1 toughness or 3 toughness. Eh? I suppose it's viewable as "White gets a boost at the 1-cost, but is worse at fatties".
Yes, that was how I was about to characterise it. White is the best colour at weenies, green is second-best; green is best at fatties, with probably black next. White's one- and two-drops tend to be better in and of themselves than any other colour's, although green's mana accelerants are extremely powerful in terms of what else they enable. Notable is the comparison between MTG: Deftblade Elite and MTG: Goblin Grappler, for example. But this will mean that white's "base cost" is cheaper but its "incremental cost" is higher. The data point of 2/3 for 2W seems a bit odd - what is it you're thinking of there? --AC
MTG: Alaborn Trooper, MTG: Regal Unicorn, MTG: Shu Foot Soldiers
Hmm. Fair enough, I guess. Seems plausible that either white or green could get a 2/3 for CC (MTG: Elvish Warrior) or 2C (the examples you mention. I just wasn't aware of them :) --AC

In any case, this looks like a nice starting point. Sorceries, artifacts and enchantments have base cost 0. Instants have base cost 1. Creatures have variable base costs, and also alternative ways to add/remove cost points other than from their cost. That's all fine. Incidentally, abilities also can be varied to adjust the cost. I propose the following: Static abilities have base cost 0. Common triggered abilities have base cost 0. Rare triggered abilities can give some level of discount. Activated abilities have a variety of cost options, normally mana and tapping, but also including sacrificing the permanent in question, sacrificing other permanents, paying life, discarding cards, and even RFGing cards from library or graveyard.
This means that on a 1/1 with an activated ability to give something -1/-1, say, you can either make the [creature cheap and the ability expensive], or the [creature expensive and the ability cheap].
Yes, that makes sense. Activated abilities are going to be the tricky case - but we knew that anyway, I reckon. It feels right that hard-to-trigger abilities should be discounted. --CH
Actually... since almost all effects on permanents are going to have potential for multiple uses as opposed to one-offs, perhaps instants should have base cost 0 and sorceries -1? --AC

However, it doesn't get anywhere unless we can make the calculation of effecttext produce a sensible cost count. --AC

Yes, that is the big one, isn't it? I'd initially thought that keyword abilities, at least, would be easy - but you have to distinguish between "Flying" and "Tap target creature with Flying" at some stage. Might it work if we can carry with us a stack of whether the thing we're considering is "On this card" (for instance - Flying on MTG: Suntail Hawk), "Being granted" (for instance, Flying on MTG: Flying Carpet) or "Restricting" (for instance, Flying on MTG: Elvish Skysweeper)? Does that enable us to distinguish all the appropriate cases? --CH
Aahhh... Now that already exists :) Look in the AlexChurchill/MagicCardGenerator around line 254, the section with the comments
 // Non-grantable abilities
 // Grantable numbered abilities
. "Specific" means "I've got this"; "grantable" means "I'm giving something else this"; "general" means "I'm referring to something with this". That could tie in quite nicely with your plans. --AC
Yes, that looks quite handy. Then we redefine creaturekeywordability_blue, say, to be "flying setupcostmods_blue_fly##myAbilityContext? updatemanacost", where updatemanacost does the additions of integer and fractional costs. Then you can have
 setupcostmods_blue_fly_specific = <manacostmod=0> <fractionalcostmod=over> // Flying is cheap on a blue card
setupcostmods_blue_fly_grantable = <manacostmod=1> <fractionalcostmod=0> // Easily grantable by blue
setupcostmods_green_fly_general = <manacostmod=-2> <fractionalcostmod=0> // Green finds it easier to affect flyers
or somesuch, as appropriate. We may need more definition on "general", since green finds it much easier to damage or destroy flying creatures, but not (much easier) to pump them.--CH
That all looks good. I'd say rather than add in extra bits in commoncreaturekeywordability_blue, and all the multitudinous variations thereof, we'd do better to just replace all hardcoded "flying" with calls to "flyingability", which expands to "flying setupcosts_flying##myColour##myAbilityContext? updatemanacosts". And replace all the current calls to "ninjutsuability##myAbilityContext?" with simply "ninjutsuability", which expands to "ninjutsuability##myAbilityContext? setupcosts_ninjutsu##myColour##myAbilityContext? updatemanacosts". Ah - except that some calls to ninjutsuability resolve to "no, you can't have ninjutsu, choose a different one" - specifically, those in context grantable. So it would have to be inside ninjutsuability_specific and ninjutsuability_general that we put the setupcosts and updatemanacosts. Does that make sense? --AC
Yes, it does. And it probably gives us enough information to start implementing costs on keywords. The only piece remaining is to pivot the base-cost tables above into a form where we can map P/T onto cost, instead of vice-versa. Agree? --CH
Hmm... not necessarily. Once we have the card's text, then we generate a cost for it. This should probably call a separate subroutine in the case of creatures, for choosing a P/T-and-manacost combination given the required costs for the abilities - this subroutine can be colour-specific. I think it should randomly choose a cost-P/T pair that's appropriate for the current colour, and then add or subtract the abilities' total costs to get the final mana cost. If the sum comes out negative, it needs to choose a new cost-P/T pair with a higher starting cost; either that or ensure that the cost is chosen to be at least as large as the negative offset from the abilities if appropriate. Either way, I think we'll end up having the "choose a cost and P/T" routine want to choose cost first, then P/T. --AC
Ah, interesting. And probably sensible. I was assuming you'd generate the P/T first - as you do now - and hence a base cost that's increased and decreased by the abilities. But that could result in negative-cost cards, you're right. Putting the P/T at the end is probably better, as is choosing cost and then P/T. Of course, it'll change the order of the Generator output, but we probably don't care? It does make it hard to generate arbitrary-sized creature for each colour, but that might not be a caring issue either. So what we need is a table that maps Colour and base-CMC to possible "vanilla" P/T combinations. I'll follow up with one when I next have time, unless you get there first. --CH

 CMC\Colour      White            Blue      Black      Red      Green
  1-under        1/1
    1            2/1
  2-under        1/2
    2          2/2,3/1
  3-under        1/3
    3        2/3,3/2,1/4
  3-over          4/1
    4        2/4,3/3,1/7
    5      3/4,2/5,4/3,1/9
    6      4/4,3/5,2/6,5/3,1/12

Too much granularity on the CMC? My white costs are an attempt to also show that white has it easiest making creatures with low P, high T at the top end of the scale. Also, the difference between 1/9 and 1/10 is MUCH smaller than 9/1 and 10/1, for instance. Other colours to come. --CH
While this will be useful, I'm not convinced it's the best place to start. I might be inclined to try to initially get sorceries/instants coming out with halfway sensible costs; then move on to artifacts and enchantments; and only then get to creatures. I think the core challenge of adding appropriate costs can be most cleanly addressed in the sorcery/instant case. Each of the other two steps have their challenges, but I'm more confident that those steps are doable :) and it'd be nice to get some proof-of-concept without having to go through the whole P/T or activated-ability cost-balancing rigmaroles just yet. --AC
Probably wise, although in some respects creatures have the easiest parts (keyword "specific" abilities). I'm just getting carried away, methinks. Suspect the correct way to go about this is to create abilsManaCost? and abilsManaCostFrac? at the stage of initflags, and then bubble down through the nest of effects working out at what stage we need to modify costs. I'm not clear whether they'd be better in decimal or unary - I think decimal, although it makes subtraction of arbitrary amounts tricky. We probably survive but not having arbitrary amounts, but defining X_minus_Y for X and Y up to, say 10 fills me with foreboding.
I may not have any time to do anything with this over the weekend, but I may be able to roll up my sleeves come next week. If you get there before me, I still strongly recommend outputting what you're doing to the mana cost when you do it, as it will make it much easier to spot oddities and places where we're modifying costs incorrectly. That's a NoteToSelf? as well. --CH

As for make it easier for green to harm flyers than pump them, how about we replace "general" with "positive" or "negative"? And actually, you know, I think that would make a lot of sense generally. Rather than trying to qualify effects as positive or negative, make it generate either positive or negative effects. 99% of activated abilities and 80-90% of triggered and static abilities should be positive. But then if we're generating a positive activated ability, say, that can take the form of either positiveeffect to positivecolourtarget (which won't be "tgt creature an opponent controls"), or negativeeffect to negativecolourtarget (which won't be "tgt creature you control"). Then green's positivecolourtargets can include "green creatures", "Elves", etc, while its negativecolourtargets include flyers, and perhaps Wizards or Zombies. --AC
That, I think, has a lot of merit. It does rather remove some of the weirdness of the generator - but in what is almost certainly a good direction: firming the feel of each colour. And you're right that it should make costs easier to do - Black should find it easy to pump Zombies and weaken Green creatures, for instance; but hard to do that the other way around. I like it.

We also need - and I don't know whether the current implementation has - the distinction between "Target opponent" as a subject (as in MTG: Cruel Edict) and as an object (as in MTG: Searing Flesh). In the former case, we need to undergo a cost increase-decrease reversal (as it should cost you to have your opponent sacrifice a creature, but give you a discount if you're forced to yourself). In the latter case, it's just a targetting restriction, and not a particularly harsh one. Determining when it is harsh and when it isn't is another case for postive and negative (it's a harsh restriction if the effect is positive, etc.). Thankfully "Target player" is easy - that should always be costed as a "positive" effect - something you want to do - since you can choose to whom you're doing it.
Agree to all of this. There isn't currently a distinction between subject and object: they're all cases of "effectspecifiedplayer", "permspecifiedplayergroup" and so on - and that section (under "=== Player words =", line 641) could use a refactoring anyway. Going through replacing all calls to effectspecifiedsingleplayer etc with singleplayersubject (and so on) sounds like a good thing to do. You mention what to do in cases of "Target opponent" and "Target player": other possible values are "You" (probably no effect on costs, as a reverse of "target opponent"), and "Each player" (probably decrease cost, as it means you're either giving opponents benefits or yourself penalties). --AC
Yes, all sounds good. Beware of MTG: Balance, though - we can't decrease costs too much for "Each player"! Possibly even just a "fractional-under". --CH

The next step, as I see it, is to try to characterise cheap or expensive abilities. We're a little helped by the way that (amongst mono-coloured cards), certain colours may only get a given type of effect, but all colours that do get it get it for about the same price, it seems. (e.g. G and W are both about equally good at lifegaining; W and B get charged about the same price for [the same] [effect]; etc. But it's still going to be quite, quite mad. For example, we'll need to distinguish between:
I've had a go at making the costing of damageeffects more specific. The vanilla or nearly-vanilla burn spells recently suggest that dealing N damage to a "target creature or player" costs N-and-under for an Instant, and N-1-and-under for a Sorcery, with a few cards being over and a few cards being under:
N damage for N-1 as instant / N-2 as sorc: Shock, Magma Jet (since scry is 1), Searing Wind
N damage for N-and-under as instant / N-1-and-under as sorc: Lava Dart, Firebolt, Scorching Lava, Yamabushi's Flame, Barbed Lightning (after correction for false modality), Carbonize, Singe, Beacon of Destruction
N damage for N as instant / N-1 as sorc: Zap, Lightning Blast, Pyromatics
More expensive: Pinpoint Avalanche, Ember Shot, Spark Spray, Lava Axe
(assuming a more expensive Flashback cost only adds 0.5 to the mana cost rather than the 1 we have below)
If the N is an X, that adds 1 mana (Blaze / Volcanic Geyser). It seems that restricting to either only target creature or target player gives a discount of 1 (Flames of the Blood Hand, Heat Ray). We can probably cost more specific restrictions as per the standard reductions for qualifiedcreature etc. Applying to all creatures may or may not cost 1 more (Inferno, Pyroclasm, Starstorm, Savage Twister), but applying to all creatures and players doesn't have this extra cost. Also applying to all flyers (Hurricane etc) or all nonflyers (Earthquake etc) cost the same as above. --AC

Yes, indeed. We should be able to do it in chunks, thankfully, since this is essentially a debug page.

What state will we need to carry about with us, in order to work out how qualifiers and restrictions should be costed? At the very least, I think we need:
Note that currently qualifiedcreature etc are making reductions to the cost independent of this effect. i.e. the transition from "Destroy target creature" to "Destroy target Elf" earns the same discount as "Bounce target creature" -> "Bounce target Elf".

This might be enough. However, we may also find it useful to carry a record of:

Add more stuff as we think of it. --CH

The complete list of effects needing costing is:

selfmodeffect | countereffect | copyspelleffect | carddraweffect | destroyeffect | destroyeffect | bounceeffect | ptmodeffect | lifechangeeffect | damageeffect | damageeffect | damageeffect | recurseeffect | modifycreatureeffect | modifypermanenteffect | regenerateeffect | manaeffect | landsearcheffect | taporuntapeffect | replacementeffect | counterseffect | tutoreffect | cardmoveeffect | controlchangeeffect | sacrificeeffect | textmodeffect | numberedeffect | attacheffect | revealcardseffect | tokencreationeffect | pipereffect

These can probably be divided into:


Other ToDo items for oneoffs:
One possible approach would be to decide up-front whether a card contains an X in the cost. Then if it does, ensure all modes (and "instead" clauses from Hellbent or Kicker) contain precisely one X. Something like a special value for "Xvar" as well as some special "XvarRequired?" flag that gets checked by dynamicinteger, as well as at the end of every mode.

Mis-costings to fix:

Musing about the next challenge: Artifacts and enchantments. There are two challenges in adapting the work on oneoffs we've already done into artifacts and enchantments:
(1) For activated abilities (eg MTG: Planar Portal or MTG: Treasure Trove), not only will the costs need to be reworked to take into account repeatability (except in self-sac costs), but also the costs of the activation and the spell need to be balanced.
(2) Dealing with static and triggered abilities.
Focusing on (1) for the moment, I think we need to research the costs for two or three of the currently implemented oneoff effects, to see how different they are as activated abilities on permanents. (Preferably artifacts or enchantments for this initial stage, as P/T just muddy the waters.) But it'd also be interesting to see how the costs and triggers compare for those that come up as triggered abilities also. --AC

BNF changes that might become permanent

option ::= include = AlexChurchill/MagicCardGenerator

// restrict to oneoffs and creatures for the moment
generatecard ::= initflagsoneoff generateoneoff | initflagsperm generatepermanent | initflagsperm generatepermanent
generatepermanent ::= initialisecosts zeromanacost <myType::=ctr> <mySrc::=ctr> <<myText::=permanenttextbox##permcategory>> showtype cardprefixes myText cardsuffixes

generateoneoff ::= choosenewoneofftype <<myText::=spelltemplate>> showtypeandcost cardprefixes myText cardsuffixes debugshowcosts
choosenewoneofftype ::= choosesorcorinst <myType::=unknown> <mySrc::=unknown> initialisecosts getoneoffbasemanacost
choosesorcorinst ::= <mySpd::=inst> | <mySpd::=sorc>
initialisecosts ::= <Xsinmanacost::=nothing> <reqdcoloursymbols_white::=0> <reqdcoloursymbols_blue::=0> <reqdcoloursymbols_black::=0> <reqdcoloursymbols_red::=0> <reqdcoloursymbols_green::=0> <reqdcoloursymbols##myColour::=1>
getoneoffbasemanacost ::= getoneoffbasemanacost##mySpd goldCostReduction?##myNumColours?
getoneoffbasemanacost_inst ::= <manacost::=1> <fracmanacost::=none>
getoneoffbasemanacost_sorc ::= zeromanacost
zeromanacost ::= <manacost::=0> <fracmanacost::=none>

showtypeandcost ::= Spelltype##mySpd space showmanacost "
Spelltype_inst ::= Spelltype_unknown
Spelltype_sorc ::= Spelltype_unknown

// To generate a mana cost: for each colour, add one of that coloured mana symbol and subtract (1) from colourless cost.
// Then, if "under" and colourless cost is >=2, subtract 2 and add a coloured mana symbol.
// If "over" and colourless cost is >=1, subtract 1 and add a coloured mana symbol.
showmanacost ::= <<colouredmanacost::=nothing>> showmanacost##permcategory

// for lands, we don't need to show any mana cost
showmanacost_land ::= nothing
showmanacost_normal ::= showmanacost##myColour
showmanacost_planeswalker ::= showmanacost##myColour
showmanacost_white ::= showcolouredmanacost
showmanacost_blue ::= showcolouredmanacost
showmanacost_black ::= showcolouredmanacost
showmanacost_red ::= showcolouredmanacost
showmanacost_green ::= showcolouredmanacost

// for artifacts, we can't tweak amount of coloured mana: currently just discard whatever over/under factor there is
showmanacost_artifact ::= showwholemanacost

// We'll be enforcing one coloured mana symbol for each colour the card has, so subtract that many
// from the mana cost to obtain a first approximation to the colourless mana cost
showcolouredmanacost ::= subcolfromCMC <<colouredmanacost::=cc_addallcolouredmanasymbols>> tweakmanacost##fracmanacost showwholemanacost
subcolfromCMC ::= subcolfromCMC_white subcolfromCMC_blue subcolfromCMC_black subcolfromCMC_red subcolfromCMC_green
subcolfromCMC_white ::= <minus_op1::=manacost> <minus_op2::=reqdcoloursymbols_white> _minus <manacost::=minus_output>
subcolfromCMC_blue ::= <minus_op1::=manacost> <minus_op2::=reqdcoloursymbols_blue> _minus <manacost::=minus_output>
subcolfromCMC_black ::= <minus_op1::=manacost> <minus_op2::=reqdcoloursymbols_black> _minus <manacost::=minus_output>
subcolfromCMC_red ::= <minus_op1::=manacost> <minus_op2::=reqdcoloursymbols_red> _minus <manacost::=minus_output>
subcolfromCMC_green ::= <minus_op1::=manacost> <minus_op2::=reqdcoloursymbols_green> _minus <manacost::=minus_output>

cc_addallcolouredmanasymbols ::= colouredmanacost colouredmanasymbols##amicoloured_white##amicoloured_blue##amicoloured_black##amicoloured_red##amicoloured_green

cc_addmanasymbol ::= leftmanasymbol colouredmanacost | colouredmanacost rightmanasymbol

tweakmanacost_none ::= nothing
tweakmanacost_under ::= <gt_op1::=manacost> <gt_op2::=1> _greaterthan tweakmanacost_under##gt_output
// if there is (2) to subtract, turn it into one coloured mana symbol
tweakmanacost_under_true ::= <minus_op1::=manacost> <minus_op2::=2> _minus <manacost::=minus_output> <<colouredmanacost::=cc_addmanasymbol>>
// If there isn't (2) to subtract, either just put up with it, or subtract (1) if there is
tweakmanacost_under_0 ::= nothing | subtracthalfamana
tweakmanacost_under_false ::= nothing

tweakmanacost_over ::= <gt_op1::=manacost> <gt_op2::=0> _greaterthan tweakmanacost_over##gt_output
// If there is (1) to subtract, turn it into one coloured mana symbol
tweakmanacost_over_true ::= <minus_op1::=manacost> <minus_op2::=1> _minus <manacost::=minus_output> <<colouredmanacost::=cc_addmanasymbol>>
// If there isn't (1) to subtract, either just put up with it, or add (1) to manacost
tweakmanacost_over_0 ::= nothing | addhalfamana
tweakmanacost_over_false ::= nothing | addhalfamana

showwholemanacost ::= Xsinmanacost <tmp::=sign##manacost> displaymanacostifpositive##tmp colouredmanacost

displaymanacostifpositive_negative ::= nothing
displaymanacostifpositive_0 ::= displaymanacostifartifact##myColour
displaymanacostifpositive_positive ::= manacost
displaymanacostifartifact_white ::= nothing
displaymanacostifartifact_blue ::= nothing
displaymanacostifartifact_black ::= nothing
displaymanacostifartifact_red ::= nothing
displaymanacostifartifact_green ::= nothing
displaymanacostifartifact_artifact ::= manacost

// Ick.  There MUST be a better way. And yet I can't think of it.
colouredmanasymbols_false_false_false_false_false ::= nothing <leftmanasymbol::=1> <rightmanasymbol::=1>
colouredmanasymbols_false_false_false_false_true  ::= showreqd_green      <leftmanasymbol::=G> <rightmanasymbol::=G>
colouredmanasymbols_false_false_false_true_false  ::= showreqd_red      <leftmanasymbol::=R> <rightmanasymbol::=R>
colouredmanasymbols_false_false_false_true_true  ::= showreqd_red  showreqd_green    <leftmanasymbol::=R> <rightmanasymbol::=G>
colouredmanasymbols_false_false_true_false_false  ::= showreqd_black      <leftmanasymbol::=B> <rightmanasymbol::=B>
colouredmanasymbols_false_false_true_false_true  ::= showreqd_black showreqd_green    <leftmanasymbol::=B> <rightmanasymbol::=G>
colouredmanasymbols_false_false_true_true_false  ::= showreqd_black showreqd_red    <leftmanasymbol::=B> <rightmanasymbol::=R>
colouredmanasymbols_false_false_true_true_true    ::= showreqd_black showreqd_red showreqd_green    <leftmanasymbol::=B> <rightmanasymbol::=G>
colouredmanasymbols_false_true_false_false_false  ::= showreqd_blue      <leftmanasymbol::=U> <rightmanasymbol::=U>
colouredmanasymbols_false_true_false_false_true  ::= showreqd_green showreqd_blue    <leftmanasymbol::=G> <rightmanasymbol::=U>
colouredmanasymbols_false_true_false_true_false  ::= showreqd_blue  showreqd_red    <leftmanasymbol::=U> <rightmanasymbol::=R>
colouredmanasymbols_false_true_false_true_true    ::= showreqd_blue showreqd_red showreqd_green    <leftmanasymbol::=U> <rightmanasymbol::=G>
colouredmanasymbols_false_true_true_false_false  ::= showreqd_blue showreqd_black    <leftmanasymbol::=U> <rightmanasymbol::=B>
colouredmanasymbols_false_true_true_false_true    ::= showreqd_green showreqd_blue showreqd_black    <leftmanasymbol::=G> <rightmanasymbol::=B>
colouredmanasymbols_false_true_true_true_false    ::= showreqd_blue showreqd_black showreqd_red    <leftmanasymbol::=U> <rightmanasymbol::=R>
colouredmanasymbols_false_true_true_true_true    ::= showreqd_blue showreqd_black showreqd_red showreqd_green  <leftmanasymbol::=U> <rightmanasymbol::=G>
colouredmanasymbols_true_false_false_false_false  ::= showreqd_white      <leftmanasymbol::=W> <rightmanasymbol::=W>
colouredmanasymbols_true_false_false_false_true  ::= showreqd_green showreqd_white    <leftmanasymbol::=G> <rightmanasymbol::=W>
colouredmanasymbols_true_false_false_true_false  ::= showreqd_red showreqd_white    <leftmanasymbol::=R> <rightmanasymbol::=W>
colouredmanasymbols_true_false_false_true_true    ::= showreqd_red showreqd_green showreqd_white    <leftmanasymbol::=R> <rightmanasymbol::=W>
colouredmanasymbols_true_false_true_false_false  ::= showreqd_white showreqd_black    <leftmanasymbol::=W> <rightmanasymbol::=B>
colouredmanasymbols_true_false_true_false_true    ::= showreqd_black showreqd_green showreqd_white    <leftmanasymbol::=B> <rightmanasymbol::=W>
colouredmanasymbols_true_false_true_true_false    ::= showreqd_white showreqd_black showreqd_red    <leftmanasymbol::=W> <rightmanasymbol::=R>
colouredmanasymbols_true_false_true_true_true    ::= showreqd_black showreqd_red showreqd_green showreqd_white  <leftmanasymbol::=B> <rightmanasymbol::=W>
colouredmanasymbols_true_true_false_false_false  ::= showreqd_white showreqd_blue    <leftmanasymbol::=W> <rightmanasymbol::=U>
colouredmanasymbols_true_true_false_false_true    ::= showreqd_green showreqd_white showreqd_blue    <leftmanasymbol::=G> <rightmanasymbol::=U>
colouredmanasymbols_true_true_false_true_false    ::= showreqd_red showreqd_white showreqd_blue    <leftmanasymbol::=R> <rightmanasymbol::=U>
colouredmanasymbols_true_true_false_true_true    ::= showreqd_red showreqd_green showreqd_white showreqd_blue  <leftmanasymbol::=R> <rightmanasymbol::=U>
colouredmanasymbols_true_true_true_false_false    ::= showreqd_white showreqd_blue showreqd_black    <leftmanasymbol::=W> <rightmanasymbol::=B>
colouredmanasymbols_true_true_true_false_true    ::= showreqd_green showreqd_white showreqd_blue showreqd_black  <leftmanasymbol::=G> <rightmanasymbol::=B>
colouredmanasymbols_true_true_true_true_false    ::= showreqd_white showreqd_blue showreqd_black showreqd_red  <leftmanasymbol::=W> <rightmanasymbol::=R>
colouredmanasymbols_true_true_true_true_true      ::= showreqd_white showreqd_blue showreqd_black showreqd_red showreqd_green  <leftmanasymbol::=W> <rightmanasymbol::=G>

showreqd_white ::= W <minus_op1::=reqdcoloursymbols_white> <minus_op2::=1> _minus <reqdcoloursymbols_white::=minus_output> <showmore##reqdcoloursymbols_white::=showreqd_white> <showmore_0::=nothing> showmore##reqdcoloursymbols_white
showreqd_blue ::= U <minus_op1::=reqdcoloursymbols_blue> <minus_op2::=1> _minus <reqdcoloursymbols_blue::=minus_output> <showmore##reqdcoloursymbols_blue::=showreqd_blue> <showmore_0::=nothing> showmore##reqdcoloursymbols_blue
showreqd_black ::= B <minus_op1::=reqdcoloursymbols_black> <minus_op2::=1> _minus <reqdcoloursymbols_black::=minus_output> <showmore##reqdcoloursymbols_black::=showreqd_black> <showmore_0::=nothing> showmore##reqdcoloursymbols_black
showreqd_red ::= R <minus_op1::=reqdcoloursymbols_red> <minus_op2::=1> _minus <reqdcoloursymbols_red::=minus_output> <showmore##reqdcoloursymbols_red::=showreqd_red> <showmore_0::=nothing> showmore##reqdcoloursymbols_red
showreqd_green ::= G <minus_op1::=reqdcoloursymbols_green> <minus_op2::=1> _minus <reqdcoloursymbols_green::=minus_output> <showmore##reqdcoloursymbols_green::=showreqd_green> <showmore_0::=nothing> showmore##reqdcoloursymbols_green

// ----- Modifying it during card generation -----
updatemanacost ::= modifyfractionalcost##fractionalcostmod <tmp::=sign##manacostmod> modifymanacost##tmp debugshowcosts

modifyfractionalcost_none ::= nothing
modifyfractionalcost_over ::= incfractionalcost##fracmanacost
modifyfractionalcost_under ::= decfractionalcost##fracmanacost
incfractionalcost_under ::= <fracmanacost::=none>
incfractionalcost_none ::= <fracmanacost::=over>
incfractionalcost_over ::= <fracmanacost::=none> <<manacostmod::=succ##manacostmod>>
decfractionalcost_under ::= <fracmanacost::=none> <<manacostmod::=predec##manacostmod>>
decfractionalcost_none ::= <fracmanacost::=under>
decfractionalcost_over ::= <fracmanacost::=none>

modifymanacost_0 ::= nothing
modifymanacost_positive ::= <plus_op1::=manacost> <plus_op2::=manacostmod> _plus <manacost::=plus_output> <manacostmod::=0>
modifymanacost_negative ::= <minus_op1::=manacost> <minus_op2::=abs##manacostmod> _minus <manacost::=minus_output> <manacostmod::=0>

pushmanacost ::= <stack##stacklevel::=manacost> push <stack##stacklevel::=fracmanacost> push zeromanacost
popmanacost ::= pop <fracmanacost::=stack##stacklevel> pop <manacost::=stack##stacklevel>

// ensured mana symbols count 1-to-1 in a converted mana cost.  That is, Cancel (inst, 1UU) should be represented
// as manacost 2, +1 for instant, with reqdcoloursymbols_blue at 2.
// Extra coloured symbols can still be "tweaked" to allow for half-mana considerations.
ensureatleast ::= <gt_op1::=atleast> <gt_op2::=reqdcoloursymbols##myColour> _greaterthan ensureatleast##gt_output
ensureatleast_false ::= nothing
ensureatleast_0 ::= nothing
ensureatleast_true ::= <reqdcoloursymbols##myColour::=atleast>

// quick macros for common cost mods
addhalfamana ::= <manacostmod::=0> <fractionalcostmod::=over> updatemanacost
add1mana ::= <manacostmod::=1> <fractionalcostmod::=none> updatemanacost
add2mana ::= <manacostmod::=2> <fractionalcostmod::=none> updatemanacost
add3mana ::= <manacostmod::=3> <fractionalcostmod::=none> updatemanacost
add4mana ::= <manacostmod::=4> <fractionalcostmod::=none> updatemanacost
add5mana ::= <manacostmod::=5> <fractionalcostmod::=none> updatemanacost
add6mana ::= <manacostmod::=6> <fractionalcostmod::=none> updatemanacost

subtracthalfamana ::= <manacostmod::=0> <fractionalcostmod::=under> updatemanacost
subtract1mana ::= <manacostmod::=-_1> <fractionalcostmod::=none> updatemanacost
subtract2mana ::= <manacostmod::=-_2> <fractionalcostmod::=none> updatemanacost
subtract4mana ::= <manacostmod::=-_4> <fractionalcostmod::=none> updatemanacost

gold[CostReduction 0]? ::= nothing
gold[CostReduction 1]? ::= nothing
gold[CostReduction 2]? ::= subtracthalfamana
gold[CostReduction 3]? ::= subtracthalfamana
gold[CostReduction 4]? ::= subtract1mana
gold[CostReduction 5]? ::= subtract2mana

//-- New versions of existing BNF rules --
add[ExtraColour yes]? ::= <prevNumColours?::=myNumColours?> <myNumColours?::=succ##myNumColours?> findNewUnusedColour? <myColour##myNumColours?::=newColour> <prevColour::=myColour> <nextColour::=colourswap##prevColour> <colourswap##newColour::=colourswap##prevColour> <colourswap##prevColour::=newColour> <amicoloured##newColour::=true> <myColour::=newColour> <atleast::=1> ensureatleast
selectSingleColour? ::= <myColour::=justcolourword> <colourswap##myColour::=myColour> <myNumColours?::=1> <myColour_1::=myColour> <amicoloured_white::=false> <amicoloured_blue::=false> <amicoloured_black::=false> <amicoloured_red::=false> <amicoloured_green::=false> <amicoloured##myColour::=true>

spelltemplate ::= normalspell | normalspell | normalspell | normalspell | normalspell | normalspell | modalspell | colourspecificspell##myColour
colourspecificspell_white ::= normalspell
colourspecificspell_blue ::= normalspell
colourspecificspell_black ::= hellbentspell
colourspecificspell_red ::= hellbentspell
colourspecificspell_green ::= normalspell

// costs for spell keyword abilities
spellkeywordabilityprefix_white ::= buybackability | flashbackability | affinityability | convokeability | kickerability
spellkeywordabilityprefix_blue ::= buybackability | flashbackability | affinityability
spellkeywordabilityprefix_black ::= buybackability | flashbackability | affinityability | kickerability
spellkeywordabilityprefix_red ::= buybackability | flashbackability | affinityability | kickerability
spellkeywordabilityprefix_green ::= buybackability | flashbackability | affinityability | convokeability | kickerability

spellkeywordabilitysuffix_white ::= stormability | cyclingability | scryability | spliceability | madnessability | hauntability_spell | forecastability_specific | cantripability
spellkeywordabilitysuffix_blue ::= stormability | cyclingability | scryability | spliceability | madnessability | transmuteability | replicateability | forecastability_specific | cantripability
spellkeywordabilitysuffix_black ::= stormability | cyclingability | scryability | spliceability | madnessability | transmuteability | hauntability_spell | cantripability
spellkeywordabilitysuffix_red ::= stormability | cyclingability | scryability | spliceability | madnessability | replicateability | cantripability
spellkeywordabilitysuffix_green ::= stormability | cyclingability | scryability | spliceability | madnessability | cantripability

maybeentwine ::= nothing | nothing | nothing | nothing | nothing | nothing | nothing | nothing | entwineability

buybackability ::= add1mana "Buyback " nocardprobablymanacost
flashbackability ::= add1mana "Flashback " nocardprobablymanacost
affinityability ::= add2mana "Affinity for " qualifiedpermanents
convokeability ::= add2mana Convoke
kickerability ::= addhalfamana kickercost notekickercost newline "If you paid the " nextkickercost " kicker cost, " effecttext

cyclingability ::= add1mana "Cycling " nocardprobablymanacost
spliceability ::= addhalfamana "Splice onto " spelltypeorsubtype ": " nocardprobablymanacost
stormability ::= add2mana Storm
scryability ::= add1mana "Scry " dynamicinteger showsuffixes
madnessability ::= addhalfamana "Madness " nocardprobablymanacost
transmuteability ::= addhalfamana "Transmute " nocardprobablymanacost
replicateability ::= add1mana "Replicate " nocardprobablymanacost
cantripability ::= add2mana "Draw a card."
entwineability ::= add1mana newline "Entwine " nocardprobablymanacost

hauntability_spell ::= add1mana "Haunt" newline "When the creature this haunts is put into a graveyard from play, " lastspelleffecttext

Spells with templates that do special things to costs

// Modal spells should take the max of their effects' costs, and then add 1/2 for each extra possible mode.
// The first two effects generated will have their costs stored in manacost 1 and 2, and then we
// sort manacosts 1 and 2 so that 2 is the larger.
// Each time we generate another mode, we stores its costs in manacost 1 (overwriting any previous manacost 1),
// and sort so that 2 is the larged, in order that we end up with the largest cost at the end.
// We also use pushmanacost and popmanacost to add half a mana extra per mode.
modalspell ::= addhalfamana "Choose one: " pushmanacost effecttext <manacost1::=manacost> <fraccost1::=fracmanacost> "; or " zeromanacost resetflags effecttext <manacost2::=manacost> <fraccost2::=fracmanacost> popmanacost sortmcs1and2 optionalfurthermodes addmc2tomanacost maybeentwine
optionalfurthermodes ::= nothing | nothing | nothing | nothing | addhalfamana pushmanacost "; or " resetflags effecttext <manacost1::=manacost> <fraccost1::=fracmanacost> popmanacost sortmcs1and2 optionalfurthermodes

// Hellbent spells should ideally generate two effects and make the better of them the hellbent one, and cost somewhere between the two. We arrange them so that #1 is normal, #2 is hellbent.
hellbentspell ::= pushmanacost <effecttype::=effecttext> <<effect1::=effecttype>> <manacost1::=manacost> <fraccost1::=fracmanacost> zeromanacost <<effect2::=effecttype>> <manacost2::=manacost> <fraccost2::=fracmanacost> popmanacost sortmcs1and2 displayhellbentspell

// If CMC1 > CMC2, then swap them.
sortmcs1and2 ::= <gt_op1::=manacost1> <gt_op2::=manacost2> _greaterthan sortmcs1and2##gt_output
sortmcs1and2_true ::= swapcosts1and2
sortmcs1and2_false ::= nothing
// If integer parts are equal, compare fractional parts.
// If #1 is "under", do nothing. If "#1" is "over", swap. If #1 is "none", do nothing unless #2 is under.
sortmcs1and2_0 ::= sortmcs1and2_f1##fraccost1
sortmcs1and2_f1_under ::= nothing
sortmcs1and2_f1_none ::= <tmp##fraccost2::=nothing> <tmp_under::=swapcosts1and2> tmp##fraccost2
sortmcs1and2_f1_over ::= swapcosts1and2

swapcosts1and2 ::= <tmp::=effect2> <effect2::=effect1> <effect1::=tmp> <tmp::=manacost2> <manacost2::=manacost1> <manacost1::=tmp> <tmp::=fraccost2> <fraccost2::=fraccost1> <fraccost1::=fraccost2>

addmc2tomanacost ::= <manacostmod::=manacost2> <fractionalcostmod::=fraccost2> updatemanacost

// For "A. Hellbent - instead B", cost is A + half(B-A) = half(A+B)
// For "A. Hellbent - B", cost is A + half(B)
// "(3manaeffect) Hellbent-instead(5manaeffect)" costs 4 mana (Cackling Flames)
// "(3manaeffect) Hellbent-(5manaeffect)" costs 5-mana-and-over: 3 + half of 5
// "(-2 manaeffect) Hellbent-(1manaeffect)" costs -1.5, i.e. -1-and-under: -2 + half of 1
// "(X manaeffect) Hellbent-(1manaeffect)" costs X-and-over (Demonfire)

displayhellbentspell ::= effect1 ". Hellbent - If you have no cards in hand, " maybeinstead{hellbentinstead} effect2 calculatehellbentcost##hellbentinstead
calculatehellbentcost_nothing ::= <plus_op1::=manacost1> <plus_op2::=half##manacost2> _plus <plus_op1::=plus_output> <plus_op2::=manacost> _plus <manacost::=plus_output>
calculatehellbentcost_insteadspace ::= <plus_op1::=manacost1> <plus_op2::=manacost2> _plus <plus_op1::=half##plus_output> <plus_op2::=manacost> _plus <manacost::=plus_output>

// Forecast is an activated ability, and really needs to wait until we have activated abilities working
//forecastability ::=...

maybeinstead ::= nothing | insteadspace
insteadspace ::= "instead "

// -- Destroy effect costing --
// never restrict destruction by controller
destroyeffect ::= destroyorrfg##myColour space pushsuffixes somenumberoftarget{numberDestroyed} space pushsuffixes <myControlFlag?::=used> destroyable##myColour <myControlFlag?::=nothing> <myPluralSuffix?::=nothing> popshowsuffixes popshowsuffixes
somenumberoftarget ::= "target" | "target" | "target" | "target" | "target" | "target" | "target" | "target" | alltargets | alltargets | twotarget | uptoNtarget
alltargets ::= add2mana <myPluralSuffix?::=s> "all" <damageRecipSpecification?::=inclusive>
twotarget ::= add1mana <myPluralSuffix?::=s> "two target" <damageRecipSpecification?::=exclusive>
// "up to 1" costs no more than "1". "up to 2" costs 2 more. All other "up to N"s cost 3 more.
uptoNtarget ::= "up to " dynamicinteger " target" <damageRecipSpecification?::=exclusive> <tmp##lastDynamicInt?::=add3mana> <tmp##1::=nothing> <tmp##2::=add2mana> tmp##lastDynamicInt? <myPluralSuffix?::=s>

destroyorrfg_white ::= "destroy" | "destroy" | "destroy" | addhalfamana "remove " <suffixes::=fromthegame>
destroyorrfg_black ::= "destroy"
destroyorrfg_red ::= "destroy"
destroyorrfg_green ::= "destroy"
destroyorrfg_artifact ::= "destroy"
fromthegame ::= " from the game"

oneormoretypeofdestroyable ::= destroyable##myColour | destroyable##myColour | destroyable##myColour | destroyable##myColour | destroyable##myColour | destroyable##myColour{tmpdest1} " or " differenttypeofdestroyable
differenttypeofdestroyable ::= <tmpdest2::=destroyable##myColour> <tmp##tmpdest2::=tmpdest2> <tmp##tmpdest1::=differenttypeofdestroyable> tmp##tmpdest2

// White has the most complicated destroyable, because it needs to take into account whether it's destroying "all" of them
destroyable_white ::= add0mana optionallyqualified_enchantment | add1mana optionallyqualified_artifact | add2mana destroyablecreature_white | maybewrathable
maybewrathable ::= <tmp##numberDestroyed::=destroyable_white> <tmp_alltargets::=wrathable> tmp##numberDestroyed
// wrathable / geddonable creatures/lands can be qualified (eg Winds of Rath)
// I've already added 2 mana for the "all", so add 2 further to get up to the 4 mana for wrath/geddon
wrathable ::= add2mana optionallyqualified_creature | add2mana optionallyqualified_land

// Other colours' destroyables are simpler
destroyable_black ::= add2mana destroyablecreature_black | add2mana destroyablecreature_black | add2mana destroyablecreature_black | add3mana addhalfamana optionallyqualified_land
destroyable_red ::= add1mana optionallyqualified_artifact | add3mana optionallyqualified_land
destroyable_green ::= add0mana optionallyqualified_artifact | add1mana optionallyqualified_enchantment | add3mana addhalfamana optionallyqualified_land | add3mana destroyablecreature_green
destroyable_artifact ::= add4mana destroyablecreature_artifact | add4mana optionallyqualified_land

destroyablecreature_white ::= <combatantsrc::=destroyablecreature_white> combatant | <combatantsrc::=destroyablecreature_white> combatant | <combatantsrc::=destroyablecreature_white> combatant | <combatantsrc::=destroyablecreature_white> combatant | blackorred space optionallynoncolourqualifiedcreature | nonptqualifiedcreature " with power greater than " dynamicinteger showsuffixes
destroyablecreature_black ::= addhalfamana optionallyqualified_creature | "nonblack creature" myPluralSuffix? | "nonblack " optionallynoncolourqualifiedcreature | unusualblackdestroyable
unusualblackdestroyable ::= non choosesinglecommoncreaturetype_black " creature" myPluralSuffix? | subtract1mana whiteorgreencreaturetype##myPluralSuffix?
destroyablecreature_green ::= optionallyqualified_creature " with flying"
destroyablecreature_artifact ::= optionallyqualified_creature | qualifiedcreature

combatant ::= combatant##mySpd
combatant_inst ::= "attacking or blocking " optionallyqualified_creature setTargetCreature?##myPluralSuffix?
combatant_sorc ::= combatantsrc
combatant_phase ::= combatantsrc

// -- Attach effect costing --
// Attach effects are free, with a one mana surcharge for gaining control permanently, and a half mana for gaining control until eot
chooseattacheecontrolandspecialtargets ::= "Gain control of " setTargetOnePermanent? thatattachee{myTarget} space duration{myDuration} addattachdurationcost##myDuration | "Gain control of " thatattachee space duration{myDuration} addattachdurationcost##myDuration setTargetOneCreature? | "(Control of " setTargetOnePermanent? thatattachee{myTarget} " doesn't change.)" add0mana | "(Control of " thatattachee " doesn't change.)" setTargetOneCreature? add0mana

addattachdurationcost_ueot ::= addhalfamana
addattachdurationcost_doesntend ::= add1mana

// -- Regenerate effect costing --
// Regenerate effects are free, at least on Instants. We'll need to expand this for self-regen'ing creatures.
regenerateeffect ::= add0mana "regenerate " somenumberoftargetqualifiedcreatures showsuffixes

// -- Text mod effect costing --
textmodeffect ::= add0mana "change the text of target " textmodtarget##mySpd " by replacing all instances of one " modifiablephrase " with another. (This effect doesn't end at end of turn.)"
textmodtarget_inst ::= optionallyqualified_spellorpermanent
textmodtarget_sorc ::= optionallyqualified_permanent setTargetOnePermanent?
textmodtarget_phase ::= optionallyqualified_permanent setTargetOnePermanent?
optionallyqualified_spellorpermanent ::= optionallyqualified_spell | optionallyqualified_permanent setTargetOnePermanent? | "spell or permanent" | subtract1mana spellandpermanentadjective " spell or permanent"

optionallyqualified_permanent ::= permanent myPluralSuffix? | permanent myPluralSuffix? | permanent myPluralSuffix? | qualifiedpermanent subtract1mana
optionallyqualified_spell ::= spell myPluralSuffix? | spell myPluralSuffix? | spell myPluralSuffix? | qualifiedspell subtract1mana

// -- Copy effect costing --
// After adjusting for instant-speed, copying an "instant or sorcery" costs 1.5, "activated ability" 0, "spell or ability" 2
copyspelleffect_inst ::= "copy target " qualifiedoneoffspellorability{tmp_qoosoa} addcopycost##tmp_qoosoa " and choose new targets for the copy"
addcopycost_oneoffspell ::= addoneoffcopycost##lastoneoff
addcopycost_storedqualifiedoneoffspell ::= addoneoffcopycost##lastoneoff addqualifiedcopycost##lastqualifiedoneoff
addcopycost_optionallyqualifiedactivatedability ::= subtract1mana
addcopycost_spelloractivatedability ::= add1mana

addoneoffcopycost_spellsubtype ::= add0mana
addoneoffcopycost_sorcery ::= addhalfamana
addoneoffcopycost_instant ::= addhalfamana
addoneoffcopycost__instantorsorcery ::= add1mana addhalfamana

addqualifiedcopycost_colouredoneoffspell ::= subtract1mana
addqualifiedcopycost_spellsubtypespell ::= subtract1mana
addqualifiedcopycost_maybemanaqualifiedoneoffspell ::= subtract1mana
// qualifying by manacost would like better resolution than this: "<2" is harder than "<7", but ">2" is easier than ">7"

// -- Damage effect costing --
damageeffect_inst ::= "~this~ deals " dynamicinteger adddamagecost pushsuffixes " damage to " somenumberoftargetdamagerecipients <myPluralSuffix?::=nothing> pushparams showsuffixes popparams popsuffixes pushparams showsuffixes popparams optionaldamagemodifier
// Split by whether the last dynamic integer was an X or a known number
adddamagecost ::= <tmp##lastDynamicInt?::=adddamagecost_integer> <tmp##X::=adddamagecost_variable> <tmp##Y::=adddamagecost_variable> <tmp##Z::=adddamagecost_variable> tmp##lastDynamicInt?
// If we're dealing a known amount N of damage, cost as (N-1.5)
adddamagecost_integer ::= subtract1mana subtracthalfamana <manacostmod::=lastDynamicInt?> <fractionalcostmod::=none> updatemanacost
// If we're dealing a variable amount Xvar of damage, normally that means we want Xvar in the mana cost, or possible an additional cost.
// Very occasionally, we want to allow an Xvar to be defined in the card text, like MTG: Tribal Flames, MTG: Citadel of Pain, MTG: Jovial Evil, MTG: Sparksmith etc; so we add 2 mana in those cases
adddamagecost_variable ::= putXinmanacostnotsuffixes | putXinmanacostnotsuffixes | putXinmanacostnotsuffixes | putXinmanacostnotsuffixes | putXinmanacostnotsuffixes | putXinmanacostnotsuffixes | putXinadditionalcostnotsuffixes | add2mana
adddamagecost_Y ::= adddamagecost_X
adddamagecost_Z ::= adddamagecost_X

putXinmanacostnotsuffixes ::= addXvartomanacost <suffixes::=nothing>
putXinadditionalcostnotsuffixes ::= addXvaradditionalcost <suffixes::=nothing>

somenumberoftargetdamagerecipients ::= somenumberoftarget space <damageRecipSpecification?::=exclusive> pushsuffixes damagerecipient popsuffixes

damagemodifier ::= dmgmod_nopreventredirect addhalfamana optionaldamagemodifier | dmgmod_noregen addhalfamana optionaldamagemodifier | dmgmod_rfg addhalfamana | dmgmod_steal add1mana

damageeffect_flyer ::= damageeffect_inst
damagerecipient_green ::= flyer
flyer ::= creature myPluralSuffix? " with flying"

// -- Tutor effect costing --
tutoreffect ::= oneormoreplayersincludingyou{myPlr} " may search " possessive##myPlr " library for a " pushplayer <revealornot::=revealit> tutorablecolourtargetcard <<thismoveittozone::=moveittozone##tutordest>> popplayer revealornot premoveshuffle##tutordest " and " thismoveittozone postmoveshuffle##tutordest tutorplayersdiscount##myPlr

tutorabletargetcard_white ::= artifact add4mana intohandorplay | enchantment add4mana intohandorplay | Aura add2mana intohandorplay | Equipment add1mana intohandorplay
tutorabletargetcard_blue ::= instant add2mana notintoplay | instantorsorcery add3mana notintoplay | artifact add3mana intohandorplay
tutorabletargetcard_black ::= notutorqualification add4mana notintoplay | notutorqualification add4mana notintoplay | notutorqualification add4mana notintoplay | nothingorcreature add1mana intograveyard
tutorabletargetcard_red ::= sorcery add2mana notintoplay | sorcery add2mana notintoplay | sorcery add2mana notintoplay | Equipment add1mana intohandorplay
tutorabletargetcard_green ::= creature add3mana intohandorplay | creature add3mana intohandorplay | slightlyqualifiedcreature add3mana intohandorplay | land add2mana intohandorplay
// slightlyqualifiedcreature will deduct mana for the qualification it applies if necessary
tutorabletargetcard_artifact ::= nothing add6mana notintoplay | artifact add4mana intohandorplay

notintoplay ::= intohand | intohand | intohand | ontopoflibrary
intohandorplay ::= intohand | intohand | intoplay | ontopoflibrary
intoplay ::= <tutordest::=play> <revealornot::=nothing> add2mana
intohand ::= <tutordest::=hand>
intograveyard ::= <tutordest::=graveyard> <revealornot::=nothing>
ontopoflibrary ::= <tutordest::=library> subtract2mana

nothingorcreature ::= notutorqualification | "creature" subtract1mana
notutorqualification ::= nothing <revealornot::=nothing>
revealit ::= revealit2
revealit2 ::= ", reveal it,"

oneormoreplayersincludingyou ::= playeryou | playeryou | playeryou | playereachplr | playertgtplr
tutorplayersdiscount_playeryou ::= nothing
tutorplayersdiscount_playertgtplr ::= nothing
tutorplayersdiscount_playereachplr ::= subtract1mana subtracthalfamana

moveittozone_play ::= "put it into play under " possessive##myPlr " control" setTargetOnePermanent?
moveittozone_hand ::= "put it into " possessive##myPlr " hand"
moveittozone_graveyard ::= "put it into " possessive##myPlr " graveyard"
moveittozone_library ::= "put it on top of " possessive##myPlr " library"

premoveshuffle_play ::= nothing
premoveshuffle_hand ::= nothing
premoveshuffle_graveyard ::= nothing
premoveshuffle_library ::= premoveshuffle##revealornot
premoveshuffle_revealit2 ::= " shuffle that library,"
premoveshuffle_nothing2 ::= ", shuffle that library,"

postmoveshuffle_play ::= ". If " playerSecondRef? space doverb##myPlr " so, shuffle that library afterwards."
postmoveshuffle_hand ::= ". If " playerSecondRef? space doverb##myPlr " so, shuffle that library afterwards."
postmoveshuffle_graveyard ::= ". If " playerSecondRef? space doverb##myPlr " so, shuffle that library afterwards."
postmoveshuffle_library ::= nothing

// -- Counter effect costing --
countereffect_inst ::= <atleast::=1> "counter target " optionallyqualifiedspellorability{myCounterTarget?} addcountercost##myCounterTarget? optionalpreventativeconditionsuffix ensureatleast

optionallyqualifiedspellorability ::= spell_ps | spell_ps | spell_ps | qualifiedspell | optionallysourcedactivatedability | spellorability
spell_ps ::= "spell" mySpellPluralSuffix?
optionallysourcedactivatedability ::= activatedability##mySpellPluralSuffix? optionalabilitysource
spellorability ::= spellorability##mySpellPluralSuffix?
optionalabilitysource ::= nothing | nothing | nothing | nothing | nothing | " from a " qualifiedpermanent " source" subtract1mana

qualifiedspell ::= spelltype mySpellPluralSuffix? | slightlyqualifiedcreature " spell" mySpellPluralSuffix? | colourphrase " spell" mySpellPluralSuffix? | nonlandpermanenttype " spell" mySpellPluralSuffix? | instantorsorcery " spell" mySpellPluralSuffix? | maybemanaqualifiedspell | spellsubtype " spell" mySpellPluralSuffix?

spelltype ::= "creature spell" | "artifact spell" | "enchantment spell" | "sorcery spell" | "instant spell" | spellsubtype " spell"

// Since this is a counterspell, it must be an instant and therefore already has a CMC of 1.
// Unconditional counterspelling costs an additional 2, and requires UU
// Qualified counterspelling costs an additional 1
// Countering activated abilities is essentially free
// Countering spell or ability costs an additional 3, and requires UU
// We can't call ensureatleast here, because if there's a preventative condition we don't require UU
addcountercost_spell_ps ::= add2mana <atleast::=2>
addcountercost_qualifiedspell ::= add1mana
addcountercost_optionallysourcedactivatedability ::= subtract1mana
addcountercost_spellorability ::= add3mana <atleast::=2>

paysextracost ::= <atleast::=1> _paysextracost
_paysextracost ::= "pays " opponentpayablemanacost subtract4p5minusCMC | "pays " opponentpayablemanacost subtract4p5minusCMC | "discards a " discardablecard subtract1mana subtracthalfamana | "sacrifices a " noncontrolqualifiedpermanent subtract1mana subtracthalfamana | "pays " dynamicinteger " life" showsuffixes <CMC::=lastDynamicInt?> subtract4p5minusCMC
subtract4p5minusCMC ::= <manacostmod::=CMC> <fractionalcostmod::=none> updatemanacost subtract4mana subtracthalfamana

// -- Lifechangeeffect costing --
// Gaining N life costs (N-2)/2.
// Losing N life costs the same as dealing N damage: N-1.5.
// Draining N life costs N + (N>3 ? 1 : 0).
lifegaineffect ::= effectspecifiedplayer " gain" playerVerbSuffix space dynamicinteger addlifegaincost " life" showsuffixes
lifelosseffect ::= effectspecifiedplayer " lose" playerVerbSuffix space dynamicinteger adddamagecost " life" showsuffixes
lifedraineffect ::= playerlifedrain | playerlifedrain | creaturelifedrain | creaturelifedrain | creatureorplayerlifedrain

addlifegaincost ::= <tmp##lastDynamicInt?::=addlifegaincost_integer> <tmp##X::=addlifegaincost_variable> <tmp##Y::=addlifegaincost_variable> <tmp##Z::=addlifegaincost_variable> tmp##lastDynamicInt?
// Gaining N life costs (N-2)/2, but gaining X costs X or X+1.
addlifegaincost_integer ::= <manacostmod::=half##lastDynamicInt?> <fractionalcostmod::=none> updatemanacost subtract1mana
// If we're gaining a variable amount Xvar of life, normally that means we want Xvar in the mana cost, or possibly an additional cost.
// Sometimes we want to allow an Xvar to be defined in the card text, like MTG: Gerrard's Wisdom, MTG: Joyous Respite etc; so we add 4 mana in those cases
addlifegaincost_variable ::= putXinmanacostnotsuffixes | putXinmanacostnotsuffixes | putXinmanacostnotsuffixes | putXinadditionalcostnotsuffixes | add4mana

playerlifedrain ::= nonyouspecifiedplayers " lose" playerVerbSuffix space dynamicinteger addlifedraincost " life" showsuffixes " and you gain that much life"
creaturelifedrain ::= "~this~ deals " dynamicinteger addlifedraincost " damage to target " pushsuffixes optionallyqualified_creature popshowsuffixes " and you gain that much life"
creatureorplayerlifedrain ::= add1mana "~this~ deals " dynamicinteger addlifedraincost " damage to target creature or player" showsuffixes " and you gain that much life"
addlifedraincost ::= <tmp##lastDynamicInt?::=addlifedraincost_integer> <tmp##X::=addlifedraincost_variable> <tmp##Y::=addlifedraincost_variable> <tmp##Z::=addlifedraincost_variable> tmp##lastDynamicInt?
// Draining N life costs N+1, unless N is <=2 in which case it only costs N.
addlifedraincost_integer ::= <manacostmod::=lastDynamicInt?> <fractionalcostmod::=none> updatemanacost <gt_op1::=manacost> <gt_op2::=2> _greaterthan tweakdraincost##gt_output
tweakdraincost_true ::= add1mana
tweakdraincost_0 ::= nothing
tweakdraincost_false ::= nothing
// If we're draining a variable amount Xvar of life, normally that means we want Xvar in the mana cost, or possibly an additional cost.
// Sometimes we want to allow an Xvar to be defined in the card text, like MTG: Gerrard's Wisdom, MTG: Joyous Respite etc; so we add 4 mana in those cases
addlifedraincost_variable ::= putXinmanacostnotsuffixes add2mana | putXinmanacostnotsuffixes add2mana | putXinmanacostnotsuffixes add2mana | putXinadditionalcostnotsuffixes add2mana | add4mana

// -- Carddraweffect costong --
// For Blue:
// -  drawing 1 is free.
// -  N cards costs N+1
// -  If M cards are also discarded, that's a discount of M
// For Black
// -  N cards costs N+1 and N life
// -  If M creatures are sacrificed, that's a discount of 2M life
// -  2 cards is a special case, costing 2 (and 2 life)

carddraweffect_blue ::= "draw a card" maybediscardafterdraw | genericdraw add1mana <manacostmod::=lastDynamicInt?> <fractionalcostmod::=none> updatemanacost maybediscardafterdraw

maybediscardafterdraw ::= nothing | nothing | ", then discard " smallpositiveinteger{N} " card" pluralsuffix##N <manacostmod::=-##N> <fractionalcostmod::=none> updatemanacost

carddraweffect_black ::= <<lastdrawtext::=genericdraw>> blackdrawmanacost splitblackadditionalcosts lastdrawtext

blackdrawmanacost ::= <bdrawmanacost##lastDynamicInt?::=bdrawnormalcost> <bdrawmanacost_2::=bdraw2cost> bdrawmanacost##lastDynamicInt?
bdrawnormalcost ::= add1mana <manacostmod::=lastDynamicInt?> <fractionalcostmod::=none> updatemanacost
bdraw2cost ::= add2mana

genericdraw ::= "draw " dynamicnon1integer " card" pluralsuffix##lastDynamicInt? showsuffixes
splitblackadditionalcosts ::= <lifepay::=lastDynamicInt?> <ctrpay::=0> enoughlifetoshift <andneeded::=no> showblackadditionalcosts
enoughlifetoshift ::= <enough##lifepay::=maybeshiftlifecost> <enough_1::=nothing> <enough_0::=nothing> enough##lifepay
maybeshiftlifecost ::= nothing | <minus_op1::=lifepay> <minus_op2::=2> _minus <lifepay::=minus_output> <<ctrpay::=succ##ctrpay>> enoughlifetoshift
showblackadditionalcosts ::= "As an additional cost to play ~this~, " showlifecost showctrcost "." newline
showlifecost ::= <showlifecost##lifepay::=shownonzerolifecost> <showlifecost_0::=nothing> showlifecost##lifepay
shownonzerolifecost ::= <andneeded::=yes> "pay " lifepay " life"
showctrcost ::= <showctrcost##ctrpay::=shownonzeroctrcost> <showctrcost_0::=nothing> showctrcost##ctrpay
shownonzeroctrcost ::= <showand_yes::=showand> <showand_no::=nothing> showand##andneeded "sacrifice " ctrpay " creature" pluralsuffix##ctrpay
showand ::= " and "

Vanilla creatures

cardabilities ::= choosevanilla choosefrenchabilities
choosevanilla ::= choosevanilla##myColour
choosevanilla_white ::= 11for1butbetter | bear | 13for2 | winddrake | 24for4 | hillgiant
choosevanilla_blue ::= 11for1butbetter | 21for1 | 13for2 | winddrake | 14for3 | hillgiant
choosevanilla_black ::= 11for1butbetter | 21for1 | greyogre | 31for3 | 42for4 | 53for5
choosevanilla_red ::= 11for1butbetter | 21for1 | 32for3 | 42for4 | hillgiant
choosevanilla_green ::= 11for1butbetter | bear | 33for3 | 43for4 | 44for5 | 55for6
choosevanilla_artifact ::= 11for1 | 21for1 | greyogre | hillgiant

11for1 ::= <mypower::=1> <mytoughness::=1> addhalfamana <creaturesize::=small>
11for1butbetter ::= <mypower::=1> <mytoughness::=1> add1mana <creaturesize::=small>
21for1 ::= <mypower::=2> <mytoughness::=1> add2mana <creaturesize::=small>
bear ::= <mypower::=2> <mytoughness::=2> add2mana <creaturesize::=small>
greyogre ::= <mypower::=2> <mytoughness::=2> add3mana <creaturesize::=small>
winddrake ::= <mypower::=2> <mytoughness::=2> add3mana <creaturesize::=small> "Flying" newline
13for2 ::= <mypower::=1> <mytoughness::=3> add2mana <creaturesize::=small>
31for3 ::= <mypower::=3> <mytoughness::=1> add3mana <creaturesize::=large>
32for3 ::= <mypower::=3> <mytoughness::=2> add3mana <creaturesize::=large>
33for3 ::= <mypower::=3> <mytoughness::=3> add3mana <creaturesize::=large>
14for3 ::= <mypower::=1> <mytoughness::=4> add3mana <creaturesize::=small>
24for4 ::= <mypower::=2> <mytoughness::=4> add4mana <creaturesize::=small>
42for4 ::= <mypower::=4> <mytoughness::=2> add4mana <creaturesize::=large>
43for4 ::= <mypower::=4> <mytoughness::=3> add4mana <creaturesize::=large>
hillgiant ::= <mypower::=3> <mytoughness::=3> add4mana <creaturesize::=large>
44for5 ::= <mypower::=4> <mytoughness::=4> add5mana <creaturesize::=large>
53for5 ::= <mypower::=5> <mytoughness::=3> add5mana <creaturesize::=large>
55for6 ::= <mypower::=5> <mytoughness::=5> add6mana <creaturesize::=large>

choosefrenchabilities ::= 1frenchability | 2frenchabilities
1frenchability ::= frenchability##myColour##creaturesize addcost##frenchcost
  1. For 2 French abilities, we add the costs, unless they're both free in which case we add half a mana instead

2frenchabilities ::= frenchability##myColour##creaturesize{{ability1}} <cost1::=frenchcost> newline differentfrenchability <cost2::=frenchcost> <add2frenchcosts##cost1##cost2::=add2frenchcosts> <add2frenchcosts##free##free::=addhalfamana> add2frenchcosts##cost1##cost2
differentfrenchability ::= <<ability2::=frenchability##myColour##creaturesize>> <tmp##ability1##ability2::=ability2> <tmp##ability1##ability1::=differentfrenchability> tmp##ability1##ability2

add1frenchcost ::= addcost##frenchcost
add2frenchcosts  ::= addcost##cost1 addcost##cost2
addcost_free ::= add0mana
addcost_halfamana ::= addhalfamana
addcost_1mana ::= add1mana
addcost_2mana ::= add2mana
addcost_3mana ::= add3mana
addcost_4mana ::= add4mana
addcost_5mana ::= add5mana
addcost_6mana ::= add6mana

Spelltype_ctr ::= artifact##myColour "Creature - " myFullCtrType? " (" mypower slash mytoughness ", " showMyColour? ")" space showmanacost

frenchability_white_small ::= flying <frenchcost::=free> | first space strike <frenchcost::=free> | vigilance  <frenchcost::=free> | protectionability <frenchcost::=halfamana> | double space strike <frenchcost::=1mana>
frenchability_white_large::= flying <frenchcost::=free> | first space strike <frenchcost::=free> | vigilance  <frenchcost::=free> | protectionability <frenchcost::=halfamana> | double space strike <frenchcost::=2mana>

frenchability_blue_small ::= flying <frenchcost::=halfamana> | unblockability <frenchcost::=halfamana>
frenchability_blue_large::= flying <frenchcost::=free> | unblockability <frenchcost::=1mana>

frenchability_black_small ::= fear <frenchcost::=halfamana> | selfregenerateability <frenchcost::=1mana> | flying <frenchcost::=halfamana> | deathtouch <frenchcost::=1mana>
frenchability_black_large::= fear <frenchcost::=1mana> | selfregenerateability <frenchcost::=1mana> | flying <frenchcost::=1mana> | deathtouch <frenchcost::=halfamana>

frenchability_red_small ::= haste <frenchcost::=halfamana> | first space strike <frenchcost::=free> | double space strike <frenchcost::=1mana>
frenchability_red_large::= haste <frenchcost::=halfamana> | first space strike <frenchcost::=free> | double space strike <frenchcost::=2mana>

frenchability_green_small ::= reach <frenchcost::=free> | trample <frenchcost::=halfamana> | deathtouch <frenchcost::=1mana> | selfregenerateability <frenchcost::=1mana>
frenchability_green_large::= reach <frenchcost::=free> | trample <frenchcost::=halfamana> | deathtouch <frenchcost::=halfamana> | selfregenerateability <frenchcost::=1mana>

frenchability_artifact_small ::= flying <frenchcost::=1mana> | first space strike <frenchcost::=1mana> | unblockability <frenchcost::=2mana>
frenchability_artifact_large::= flying <frenchcost::=1mana> | first space strike <frenchcost::=1mana> | unblockability <frenchcost::=2mana>

unblockability ::= newline "~this~ is unblockable." newline
selfregenerateability ::= newline manasymbol##myColour ": Regenerate ~this~." newline | newline subtracthalfamana "1" manasymbol##myColour ": Regenerate ~this~." newline
protectionability ::= protection_specific

// -- Costs of costs --
costinmana ::= <CMC::=0> colouredmanacost | smallpositiveinteger{CMC} | smallpositiveinteger{CMC} colouredmanacost
colouredmanacost ::= singlecolouredcost | singlecolouredcost | singlecolouredcost | singlecolouredcost | singlecolouredcost | singlecolouredcost | multicolouredcost
multicolouredcost ::= twocolouredcost | twocolouredcost | twocolouredcost | twocolouredcost | threecolouredcost | fivecolouredcost

singlecolouredcost ::= manasymbol##myColour <CMC::=succ##CMC> | manasymbol##myColour{M} <CMC::=succ##CMC> optionalmanasymbol
// manasymbol | manasymbol{M} optionalmanasymbol
optionalmanasymbol ::= nothing | M <CMC::=succ##CMC> | M <CMC::=succ##CMC> optionalmanasymbol
twocolouredcost ::= alliedmanacost | alliedmanacost | alliedmanacost | alliedmanacost | enemymanacost
alliedmanacost ::= add2toCMC manasymbol##myColour{M} manasuccessor##M | add2toCMC manasymbol##myColour{M} unlikelymanasymbol manasuccessor##M{M} unlikelymanasymbol | add2toCMC <M::=manasymbol##myColour> manapredecessor##M M | add2toCMC <M::=manasymbol##myColour> manapredecessor##M{M} unlikelymanasymbol manasuccessor##M{M} unlikelymanasymbol
// an allied activation cost on e.g. a blue card will be either patterned UB, WU, UUBBB or WWWU
// manasymbol{M} manasuccessor##M | manasymbol{M} unlikelymanasymbol manasuccessor##M{M} unlikelymanasymbol
enemymanacost ::= add2toCMC <M::=manasymbol##myColour> manapredecessor##M <M::=manasuccessor##M> M | add2toCMC <M::=manasymbol##myColour> manapredecessor##M{M} unlikelymanasymbol <M::=manasuccessor##M> manasuccessor##M{M} unlikelymanasymbol
// an enemy activation cost on e.g. a green card will be either RW or RRRWW
// manasymbol{M} <M::=manasuccessor##M> manasuccessor##M | manasymbol{M} unlikelymanasymbol <M::=manasuccessor##M> manasuccessor##M{M} unlikelymanasymbol
unlikelymanasymbol ::= nothing | nothing | M <CMC::=succ##CMC> unlikelymanasymbol
threecolouredcost ::= <M::=manasymbol##myColour> manapredecessor##M M manasuccessor##M <CMC::=succ##CMC> <CMC::=succ##CMC> <CMC::=succ##CMC>
fivecolouredcost ::= WUBRG <CMC::=succ##CMC> <CMC::=succ##CMC> <CMC::=succ##CMC> <CMC::=succ##CMC> <CMC::=succ##CMC>
add2toCMC ::= <CMC::=succ##CMC> <CMC::=succ##CMC>

opponentpayablemanacost ::= smallpositiveinteger{CMC} | smallpositiveinteger{CMC} | smallpositiveinteger{CMC} | smallpositiveinteger{CMC} | smallpositiveinteger{CMC} | smallpositiveinteger{CMC} | smallpositiveinteger{CMC} | smallpositiveinteger{CMC} | smallpositiveinteger{CMC} | costinmana

duration ::= ueot | ueot | ueot | ueot | ueot | doesntend
ueot ::= "until end of turn"
doesntend ::= "(This effect doesn't end at end of turn)"

blackorred ::= "black" | "red" | "black" | "red" | "black or red"

_maybetapstatusperm_nothing2 ::= subtracthalfamana <tapStatus::=untapped> "untapped " tapstatussrc | subtracthalfamana <tapStatus::=tapped> "tapped " tapstatussrc

newqualifiedcreature ::= "creature" myPluralSuffix? | "creature" myPluralSuffix? | subtract1mana subtracthalfamana creaturetype | colourphrase " creature" myPluralSuffix? | maybeptqualifiedcreature | subtract1mana subtracthalfamana creaturetype | colourphrase " creature" myPluralSuffix? | "creature" myPluralSuffix? " with " ptexpression space inequality space dynamicinteger showsuffixes | slightlyqualifiedcreature | maybeunusualcreatureadjectivecreature | "creature" myPluralSuffix? " with " creaturekeywordabilitygeneral | maybecombatadjectivecreature | <tapstatussrc::=newqualifiedcreature> maybetapstatusperm
slightlyqualifiedcreature ::= subtract1mana subtracthalfamana creaturetype | colourphrase " creature" myPluralSuffix?

colourphrase ::= rarelynon subtract1mana subtracthalfamana colourword

rarelynon ::= nothing | nothing | nothing | nothing | nothing | add1mana "non"

qualifiedoneoffspellorability ::= oneoffspell | storedqualifiedoneoffspell | optionallyqualifiedactivatedability | spelloractivatedability
storedqualifiedoneoffspell ::= qualifiedoneoffspell{lastqualifiedoneoff}

optionallyqualifiedactivatedability ::= activatedability##mySpellPluralSuffix? optionalabilitysource
optionalabilitysource ::= nothing | nothing | nothing | nothing | " from a " qualifiedpermanent " source" subtract1mana

oneoffspell ::= spelltypeorsubtype{lastoneoff} " spell" mySpellPluralSuffix? | instantorsorcery{lastoneoff} " spell" mySpellPluralSuffix?
qualifiedoneoffspell ::= colouredoneoffspell | spellsubtypespell | maybemanaqualifiedoneoffspell

_maybemanaqualifiedoneoffspell_nothing2 ::= subtract1mana <myManaQual?::=used> qualifiedoneoffspell space manacostphrase <myManaQual?::=nothing>
spelltypeorsubtype ::= spellsubtype | spellsubtype | sorcery | instant
colouredoneoffspell ::= colourphrase space oneoffspell
spellsubtypespell ::= spellsubtype2{lastoneoff} " spell" mySpellPluralSuffix?
spellsubtype2 ::= spellsubtype

instantorsorcery ::= instant | sorcery | _instantorsorcery
_instantorsorcery ::= "instant or sorcery"
spelloractivatedability ::= spelloractivatedability##mySpellPluralSuffix?
spelloractivatedability_nothing2 ::= "spell or activated ability"
spelloractivatedability_s ::= "spells or activated abilities"

useXvariable ::= usenewx | maybeoldx | maybeaddxcost
maybeaddxcost ::= <tmp##Xvar::=useXvariable> <tmp##X::=addxcost> tmp##Xvar
addxcost ::= Xvar{lastDynamicInt?} addXvartomanacost | Xvar{lastDynamicInt?} addXvaradditionalcost

addXvartomanacost ::= <<Xsinmanacost::=XsinmanacostfollowedbyXvar?>>
addXvaradditionalcost ::= <cardprefixes##prefixnum::=additionalXvarcost> nextprefixnum
additionalXvarcost ::= "As an additional cost to play ~this~, pay " Xvar " life." newline | "As an additional cost to play ~, discard " Xvar " cards." newline
XsinmanacostfollowedbyXvar? ::= Xsinmanacost Xvar

dynamicnon1integer ::= <<dummy::=dynamicinteger>> <tmp##lastDynamicInt?::=lastDynamicInt?> <tmp_1::=dynamicnon1integer> tmp##lastDynamicInt?

BNF templates that can be obsoleted

kickerspell ::= NO LONGER USED

BNF changes that are temporary for testing/debugging

// disallow planeswalkers (!)
selectMyPermCategory? ::= <permcategory::=normal>
// disallow land
selectLand ::= selectMyPermColour?

// restrict to effects we've implemented
commoneffect_white ::= destroyeffect | regenerateeffect | damageeffect | damageeffect | lifechangeeffect
//... | selfmodeffect##thisStillInPlay? | selfmodeffect##thisStillInPlay? | ptmodeffect | recurseeffect | modifycreatureeffect | modifypermanenteffect | landsearcheffect | taporuntapeffect | targetobtainingeffect " and " maybeToggleMyColour? specialtargeteffect
commoneffect_blue ::= copyspelleffect##mySpd | countereffect##mySpd | carddraweffect_blue
//... | selfmodeffect##thisStillInPlay? | selfmodeffect##thisStillInPlay? | ptmodeffect | bounceeffect | modifycreatureeffect | modifypermanenteffect | taporuntapeffect | replacementeffect | targetobtainingeffect " and " maybeToggleMyColour? specialtargeteffect
commoneffect_black ::= destroyeffect | destroyeffect | destroyeffect | regenerateeffect | damageeffect | lifechangeeffect | carddraweffect_black
//... | selfmodeffect##thisStillInPlay? | selfmodeffect##thisStillInPlay? | ptmodeffect | ptmodeffect | recurseeffect | recurseeffect | modifycreatureeffect | modifypermanenteffect | targetobtainingeffect " and " maybeToggleMyColour? specialtargeteffect
commoneffect_red ::= destroyeffect | destroyeffect | damageeffect | damageeffect | damageeffect
//...selfmodeffect##thisStillInPlay? | selfmodeffect##thisStillInPlay? | ptmodeffect | ptmodeffect | modifycreatureeffect | modifypermanenteffect | manaeffect | targetobtainingeffect " and " maybeToggleMyColour? specialtargeteffect
commoneffect_green ::= destroyeffect | destroyeffect | regenerateeffect | lifechangeeffect
//...selfmodeffect##thisStillInPlay? | selfmodeffect##thisStillInPlay? | carddraweffect | ptmodeffect | ptmodeffect | recurseeffect | modifycreatureeffect | modifypermanenteffect | manaeffect | manaeffect | landsearcheffect | landsearcheffect | taporuntapeffect | targetobtainingeffect " and " maybeToggleMyColour? specialtargeteffect
commoneffect_artifact ::= damageeffect | lifechangeeffect
//... selfmodeffect##thisStillInPlay? | selfmodeffect##thisStillInPlay? | carddraweffect | ptmodeffect | damageeffect | modifycreatureeffect | modifypermanenteffect | targetobtainingeffect " and " maybeToggleMyColour? specialtargeteffect

rareeffect_white ::= attacheffect | tutoreffect
//... | effecttext " and " toggleMyColour? typeofeffect | <numberedeffect_no::=typeofeffect> maybenumberedeffect | revealcardseffect | tokencreationeffect
rareeffect_blue ::= attacheffect | tutoreffect | textmodeffect
//... | effecttext " and " toggleMyColour? typeofeffect | controlchangeeffect | controlchangeeffect | <numberedeffect_no::=typeofeffect> maybenumberedeffect | revealcardseffect | tokencreationeffect | pipereffect
rareeffect_black ::= tutoreffect
//... counterseffect | controlchangeeffect | sacrificeeffect | <numberedeffect_no::=typeofeffect> maybenumberedeffect | revealcardseffect | tokencreationeffect | effecttext " and " toggleMyColour? typeofeffect
rareeffect_red ::= attacheffect | tutoreffect | copyspelleffect##mySpd
// | effecttext " and " toggleMyColour? typeofeffect
//... controlchangeeffect | <numberedeffect_no::=typeofeffect> maybenumberedeffect | revealcardseffect | tokencreationeffect |
rareeffect_green ::= tutoreffect | damageeffect
//... counterseffect | <numberedeffect_no::=typeofeffect> maybenumberedeffect | revealcardseffect | tokencreationeffect | tokencreationeffect | pipereffect | effecttext " and " toggleMyColour? typeofeffect
rareeffect_artifact ::= attacheffect | tutoreffect
//... counterseffect | <numberedeffect_no::=typeofeffect> maybenumberedeffect | effecttext " and " toggleMyColour? typeofeffect

add0mana ::= <manacostmod::=0> <fractionalcostmod::=none> updatemanacost

debugshowcosts ::= ""
// " (cost " <numtodisplay::=manacost> displaynum "-and-" fracmanacost ") "

// have lots of keywords, as that's what we're testing
maybespellkeywordabilityprefix ::= nothing | nothing | nothing | nothing | nothing | spellkeywordabilityprefix##myColour newline maybespellkeywordabilityprefix
maybespellkeywordabilitysuffix ::= nothing | nothing | nothing | nothing | nothing | newline spellkeywordabilitysuffix##myColour maybespellkeywordabilitysuffix

ec2-3-230-154-90.compute-1.amazonaws.com | ToothyWiki | ChrisHowlett | RecentChanges | Login | Webcomic
Edit this page | View other revisions | Recently used referrers
Last edited November 22, 2020 6:52 pm (viewing revision 144, which is the newest) (diff)