Effects

Special effects on cards is a major contributor to cards in Chaos Cards (or in general for card games). The general philosophy in creating grammar rules for effects is to categorize and decompose what effects can possibly look like (as we would always need to do in designing a grammatical system). In general, an effect can be targeted or untargeted (i.e. whether the player needs to specify a target to trigger it), and it can be triggered by different events (e.g. battlecries and deathrattles are triggered when minions are played and destroyed respectively), or may require certain conditions (e.g. having leader’s health below 15), and there are different types of impacts an effect can have on the game state (e.g. deal damage, heal, buff). We summarize all these into our grammatical rules.

Effects

Effects :=

| justEffects(TargetedPlayEff, OtherEffs)

TargetedPlayEff :=

| noTargetedPlayEff()

| targetedBattlecryEff(TargetedEff)

| targetedCastEff(TargetedEff)

OtherEffs :=

| noOtherEffs()

| consOtherEffs(OtherEff, OtherEffs)

OtherEff :=

| untargetedBattlecryEff(UntargetedEff)

| untargetedCastEff(UntargetedEff)

| deathrattleEff(UntargetedEff)

| onDiscardEff(UntargetedEff)

| turnStartEff(UntargetedEff, AlleCond)

| turnEndEff(UntargetedEff, AlleCond)

In general, a card can have none or one or more effects. A spell card must have at least one effect, because spell cards does not have any active functionality beyond its effects. A set effects (possibly nothing for minion and leader cards) is summarized as and an Effects node, which is then divided into two parts, the targeted part (TargetedPlayEff) and the untargeted part (OtherEffs).

    • The targeted part can have zero or one effect, formulated with a rules set representing either no such effect, or a targeted battlecry effect (e.g. "deal 1 damage to a minion", only applicable to leaders and minions), or a targeted casting effect (almost the same as the battlecry version but only only applicable to spells). Targeted part is limited to at most one effect, due to that we only included in the design the targeted effects when playing a card (battlecries or spell casts) and that we formulate those with a form that requiring a constraint on what type of targets are valid (e.g. the Beast minion requirement in "deal 1 damage to a Beast minion") so we generally couldn't have two different requirements (unless we do a logical structure and guarantee the requirement is achievable).

    • The untargeted part can have zero or more effects, formulated with a recursive sequence representation rule set. Each untargeted effect can be triggered by a certain event (battlecry, cast, deathrattle etc.) and their difference from targeted effects are they don't require (which side(s)) the player to specify a target (e.g. "deal 1 damage to random minion"). Effects triggered at the start of turn and end of turn will also requires to with an AlleCond nonterminal (see the Conditions page) specifying the allegiance of the turns that the trigger is applicable (i.e. Who's turn start? It could be "at the start of your turns", or "at the start of your opponent turns", or "at start of both player's turns" depending on what that AlleCond node ends up to be.

    • There is a developer tunable upper limit on how many effects it can generate, and for spells, there is a lower limit of 1, i.e. at least one of the targeted part and untargeted part has to have some effect. These type of grammatical controls and constraints (as well as some others) are not directly visible in the grammar text here, but utilizes GIGL's feature in implementation.

TargetedEff & UntargetedEff

TargetedEff :=

| noCondTargetedEff(BaseTargetedEff, TargetCond)

| indeCondTargetedEff(BaseTargetedEff, TargetCond, IndeCond)

| srcCondTargetedEff(BaseTargetedEff, TargetCond, TargetCond)

UntargetedEff :=

| noCondUntargetedEff(BaseUntargetedEff)

| indeCondUntargetedEff(BaseUntargetedEff, IndeCond)

| srcCondUntargetedEff(BaseUntargetedEff, TargetCond)

Both targeted effects and untargeted effects can have some conditions, besides their impact (what they actually do). For example, in "if there is a Demon card on your hand, deal 1 damage to a Beast minion" is a targeted effect where "if there is a Demon card on your hand" and "Beast minion" are both conditions, and "deal 1 damage" is its impact.

    • For a targeted effect, one condition is required, more precisely defined as a target constraint, specifying what type of target is valid for the effect, such as the "Beast minion" in the example above. This is different from saying "select something, deal 1 damage if it is a Beast minion", because in this case you would be able do target something not a beast minion and do nothing, and this version would not be hard to implement but isn't quite meaningful unless we have multi-stage effects such as "deal 1 damage to a minion, if it is a Beast minion, deal 3 damage instead", which is excluded for simplicity.

    • Beyond targets constraints, there can also be conditions on the source card (called source conditions), i.e. the card where the triggered effect is, e.g. "if itself is a card with at most 5 mana cost". As there are effects that modifies stats on the cards, even abilities and minion types, such condition is meaningful.

    • Both the constraints on effect targets and conditions on effect source has the same internal form, i.e. they are requirements on particular characters/cards, thus being able to be represented by the same type of nonterminal, TargetCond. However, there are another type of conditions that are not associated with particular cards, such as "if there is a Demon card on your hand". We call this type of conditions independent conditions (card-independent), represented by IndeCond nodes. Conditions on leaders are also considered to be in this category, e.g. "if your leader has at most 10 health". Even though a leader is technically associated with a card, but referring to a leader is clear on which card it refers to, thus make it easier to just consider it as an independent condition.

  • For simplicity we do not allow source conditions and independent conditions to co-exist and we do not consider multiple source condition or independent conditions. Technically all these are valid but would need some thoughts on logical connections and how possible and meaningful they are for different cases.

  • For more details on TargetCond and IndeCond, please refer to the Conditions page.

BaseTargetEff & BaseUntargetedEff

BaseTargetedEff :=

| damageEff(int, DmgAbilities)

| healEff(int)

| resAtkTimesEff(int)

| costModEff(int)

| atkHpModEff(int, int)

| atkTimesModEff(int)

| destroyEff()

| discardEff()

| tranformEff(NewCardVariant)

| moveEff(Destination)

| copyEff(Destination)

| changeToBeastEff()

| changeToDragonEff()

| changeToDemonEff()

| giveChargeEff()

| giveTauntEff()

| giveStealthEff ()

| giveUntargetableEff()

| giveShieldEff()

| givePoisonousEff()

| giveLifestealEff()

| rmAbilitiesEff()

| setOverheatEff()

| decOhThresholdEff(int)

| resetStateEff()

| giveEffectsEff(Effects)

BaseUntargetedEff :=

| aoeEff(BaseTargetedEff, TargetCond)

| randEff(BaseTargetedEff, TargetCond)

| leaderEff(BaseTargetedEff, AlleCond)

| selfEff(BaseTargetedEff)

| drawCardEff(int, AlleCond)

| mpEff(int, AlleCond)

| maxMpEff(int, AlleCond)

| newEff(int, Destination, NewCardVariant)

| winGameEff(AlleCond)

The BaseTargetedEff and BaseUntargetedEff are the impacts parts for targeted and untargeted effects respectively. Between these two the targeted version is more basic as some type of untargeted effects (e.g. AoE effects) maybe based on targeted effects and contains certain condition parts inside. Here is some more detailed look on the sub-types for BaseTargetedEffs.

    • damageEff (damage), healEff (heal), and resAtkTimesEff (restore attack times) are effects that modify consumed stats on cards. Damaging and healing modifies consumed health (or current health value) and restoring attack times modifies the consumed attack times this turn (or remaining attack times this turn). Damaging may reduce the remaining health to zero or negative (negative is relevant to the source condition of deathrattles), in which case the character is destroyed. Healing and restoring attack times may not raise the corresponding stat beyond maximum (capped at the maximum). The range of magnitude is 1 ~ 10 for damaging and healing, and 1 ~ 5 for restoring attack times. Damage effect needs a DmgAbility field in addition to its magnitude, for the purpose adding Lifesteal or Poisonous ability. This is useful particularly for spells, as spells are set not to get these two ability in the main Abilities field from the Root, and is only possible to get these two attributes if there is some damaging effect on it. The abilities added here applies to the whole card, as well as those from the main Abilities field, and both kinds will combine in a disjunctive/additive way, i.e. as long as somewhere on the card is generated with a Lifesteal ability, the card has the ability and it applies to all damage from this card. A DmgAbility field is forced to not creating any actual ability if it is an effect nested under the giveEffectsEff (give effects to characters/cards) for simplicity, as there are ways to add abilities through effects.

    • costModEff (modify mana cost), atkHpMod (modify attack and max HP), and atkTimesMod (modify attack times) are effects that modify the stats on cards. Attack and max HP are commonly modified together (or they can be written together even only one of them is actually modified, as in Shadowverse, +2/+0 just means +2 attack). The range for modifying cost is -10 ~ +10 excluding zero; the range for modifying attack is -5 ~ +5 and the range for modifying max HP is 0 ~ +10 (note modifying attack and max HP are not allowed to be both zeros); the range for modifying attack times is 1~3. For the consumable resources, like health and attack times, here the difference from what's above is that this modifies the max amount. When modifying the max amount, the consumed amount does not change (so we don't allow decreasing max HP or attack times to save the problem of dealing with the situation that current consumed amount being larger than max).

    • destroyEff, discardEff, and transformEff are effects that change the existence of cards. Destroying applies to minions only, while discarding (we have some special semantics for discarding in Chaos Cards, see the game mechanism) and transforming applies to both minions and cards (note: none of the three can apply to a played leader). Transforming will require specifying what card it transform into, as the NewCardVariant node (see the Misc page). As transforming leads to a potentially recursive path (as it may involve generating a new complete card), the depth is constrained in the GIGL implementation.

    • moveEff, and copyEff are effects that involves card movements. Their difference is, intuitively, that copy effects will keep the source while move effects will not. Both effects needs a Destination node (see the Misc page) to be generated to specified the destination of the movement (e.g. "your hand", "the opponent's deck"). Note that the source of the movement would already be included in the condition/constraints for the applicable target cards outside the scope of a BaseTargetedEff node. Move effects are not allowed to move to the same location as where the card was and the destination must be a single destination (i.e. "both player's deck" is not allowed for a move effect), while all those are allowed for copy effects.

    • changeToBeastEff, changeToDragonEff, and changeToDemonEff are effects that modify the minion type of minions or minion cards. The minion type is exclusive so once a minion of one type it is no longer other types.

    • grantChargeEff, grantTauntEff, grantStealthEff, grantUntargetableEff, grantShieldEff, grantPoisonEff, and grantLifestealEff are effects that add abilities to characters or cards. Abilities can co-exist, so these effects do not remove other abilities.

    • removeAbilitiesEff effects remove all ability keywords from characters or cards.

    • setOverheatEff (set to overheat) and decOhThresholdEff (decrease overheat thresholds) are effects related to the advanced mechanism overheat in Chaos Cards. Setting to overheat sets effects on characters/cards to overheat which prevents them from being triggered until the end of their owner's end, serving like a temporary "silencing" (the "silencing" here isn't exactly the same as what's in Hearthstone as it only applies to the effects but not abilities or stat buffs). Decreasing overheat thresholds will apply the decrement on the threshold for overheat counters for all effects on the cards, serving like a permanent partial or complete silencing. The magnitude for decreasing overheat thresholds is in the range of 1 ~ 5. According to the overheat mechanism in Chaos Cards, both these two effects will apply repeatedly and shared over effects that are considered the same effect (duplicated cards/effects).

    • resetStateEff effects reset characters or cards to their original states when being generated. This applies to all the modifications from other effects, including clearing attached extra effects by the giveEffectsEff discussed below. If the target is a leader or minion, will also heal it to full HP. However, it does not apply to aspects that are naturally changed with general game mechanisms. It does not put the card back to the deck, and it does not reset the consumed attack times (as resets automatically at the start of the owner's turn), it does not reset the overheat counter (as resets automatically at the end of the owner's turn) and it does not revert the sleeping state (as it is automatically canceled at the subsequent turn after the turn the card is played).

    • giveEffectsEff effects attaches extra effects to characters or cards. An Effects node needs to be specified for what effects to attach. The attached effects can only be untargeted, to avoid the problem of having two targeted effects with conflicting target constraints. We used an Effects node (as opposed to an OtherEffs node for forcing untargeted effects) only for the convenience of managing certain data in implementation, and we passed a flag into the generator for the sub-tree following the Effects node so that it always selects noTargetedPlayEff rule to achieve forcing only untargeted effects. As this type of effect leads to a potentially recursive path, the depth is constrained in the GIGL implementation.

Here is some more detailed look on the sub-types for BaseUntargetedEffs.

  • aoeEff, randEff, leaderEff, and selfEff are effects that applies the impact of targeted effects to targets that are not specified by the player (thus being untargeted as a whole). AoE effects and random effects each need a TargetCond node (see the Conditions page) to specify the condition for applicable targets (i.e. target applicabilities), and AoE effects apply the impact to all applicable targets and random effects apply to a random one among them (well we could have a different version of random effects having an additional integer field saying apply it to random x among them but that would be a minor addition, and majority of such effects in existing games are single random targeted). A leader effect needs an AlleCond node (see the Conditions page) to specify who's leader(s) to apply the impact. A self effect applies the effect to minion/card where the effect is on (we do not generate self effects for played leaders as those can be covered by leader effects).

  • drawCardEff effects draw cards for sides ("you", "opponent" or "both sides) that are specified by the AlleCond node (see the Conditions page). The integer field indicates how many cards to drawn, generated in the range of 1~3, biased to smaller values.

  • mpEff (modify MP) and maxMpEff (modify max MP) effects modifies stats that are related to mana resources on some sides ("you", "opponent" or "both sides) that are specified by the AlleCond node (see the Conditions page). The difference between them is that modifying MP modifies the consumed (or remaining) MP, while modifying max MP modifies its maximum and keeps the consumed amount (i.e. will generally change the remaining MP at the same time). For any of this modifications, the remaining MP is always clamped betwen zero and max MP. The integer field indicates the change in the value, and is in the range of -10 ~ 10 excluding zeros for modifying MP and -5 ~ 5 excluding zeros for modifying max MP, both biased to small changes.

  • newEff effects spawn new minions/cards. Each such effect would need both a Destination node (see the Misc page) to specify the destination to spawn this card to and a NewCardVariant node (see the Misc page) to specify what new minion/cards to spawn. As it is not uncommon for minions/cards to be spawned with multiple copies (especially for minions), we also have an integer field to indicate how many copies to spawn. As this type of effect leads to a potentially recursive path (as it may involve generating a new complete card), the depth is constrained in the GIGL implementation. Note that a small nuance here, is that when dynamically randomized cards are spawned for both sides, both sides gets the same set of randomized cards (duplicate pairs).

    • winGameEff effects directly grant some side(s) of the match to win the game. A win game effect needs an AlleCond node (see the Conditions page) to specify who wins game ("you" or "the opponent"). When it says "both players win the game", that is equivalent to a draw. The type of effect is very drastic, so it is rarely generated.