Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
FAQ v12 card errata (#3852)
Browse files Browse the repository at this point in the history
* FAQ v12 card errata

* Change then: to use sequential

* Update BayushiKachiko.js

* Cleaned up test cases, fixed some bugs in implementation.

Not sure why you changed Prepare for War.  It doesn't use "then".

* Fix prepare for war test with new "then"

Co-authored-by: Tom Nys <50174301+The-Outcast@users.noreply.github.com>
  • Loading branch information
jeremylarner and The-Outcast committed Dec 30, 2019
1 parent 0df25f4 commit 6d7d782
Show file tree
Hide file tree
Showing 51 changed files with 354 additions and 332 deletions.
3 changes: 2 additions & 1 deletion server/game/cards/01-Core/AgainstTheWaves.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const DrawCard = require('../../drawcard.js');
const { CardTypes } = require('../../Constants');
const { CardTypes, Players } = require('../../Constants');
const AbilityDsl = require('../../abilitydsl.js');

class AgainstTheWaves extends DrawCard {
Expand All @@ -9,6 +9,7 @@ class AgainstTheWaves extends DrawCard {
target: {
cardType: CardTypes.Character,
cardCondition: card => card.hasTrait('shugenja'),
controller: Players.Self,
gameAction: [AbilityDsl.actions.bow(), AbilityDsl.actions.ready()]
}
});
Expand Down
44 changes: 22 additions & 22 deletions server/game/cards/01-Core/YogoHiroue.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,35 @@ const AbilityDsl = require('../../abilitydsl');
const { CardTypes } = require('../../Constants');

class YogoHiroue extends DrawCard {
setupCardAbilities(ability) {
setupCardAbilities() {
this.action({
title: 'Move a character into the conflict',
condition: context => context.source.isParticipating(),
target: {
cardType: CardTypes.Character,
gameAction: ability.actions.moveToConflict()
},
then: context => ({
gameAction: AbilityDsl.actions.cardLastingEffect({
target: context.target,
effect: AbilityDsl.effects.delayedEffect({
when: {
afterConflict: event => event.conflict.winner === context.player
},
gameAction: AbilityDsl.actions.menuPrompt({
activePromptTitle: 'Dishonor ' + context.target.name + '?',
choices: ['Yes', 'No'],
choiceHandler: (choice, displayMessage) => {
if(displayMessage && choice === 'Yes') {
context.game.addMessage('{0} chooses to dishonor {1} due to {2}\'s delayed effect', context.player, context.target, context.source);
}
return { target: (choice === 'Yes' ? context.target : []) };
gameAction: AbilityDsl.actions.sequential([
AbilityDsl.actions.moveToConflict(),
AbilityDsl.actions.cardLastingEffect(context => ({
effect: AbilityDsl.effects.delayedEffect({
when: {
afterConflict: event => event.conflict.winner === context.player
},
gameAction: AbilityDsl.actions.dishonor()
gameAction: AbilityDsl.actions.menuPrompt({
activePromptTitle: 'Dishonor ' + context.target.name + '?',
choices: ['Yes', 'No'],
choiceHandler: (choice, displayMessage) => {
if(displayMessage && choice === 'Yes') {
context.game.addMessage('{0} chooses to dishonor {1} due to {2}\'s delayed effect', context.player, context.target, context.source);
}
return { target: (choice === 'Yes' ? context.target : []) };
},
gameAction: AbilityDsl.actions.dishonor()
})
})
})
})
})
}))
])
},
effect: 'move {0} into the conflict - they may choose to dishonor it if they win the conflict'
});
}
}
Expand Down
33 changes: 18 additions & 15 deletions server/game/cards/02.3-ItFC/BayushiKachiko.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
const DrawCard = require('../../drawcard.js');
const { TargetModes, CardTypes } = require('../../Constants');
const AbilityDsl = require('../../abilitydsl');
const { CardTypes } = require('../../Constants');

class BayushiKachiko extends DrawCard {
setupCardAbilities(ability) {
setupCardAbilities() {
this.action({
title: 'Send a character home',
condition: context => this.game.isDuringConflict('political') && context.source.isParticipating(),
target: {
cardType: CardTypes.Character,
cardCondition: (card, context) => card.politicalSkill < context.source.politicalSkill,
gameAction: ability.actions.sendHome()
},
then: context => ({
target: {
mode: TargetModes.Select,
activePromptTitle: 'Do you want to bow ' + context.target.name + '?',
choices: {
'Yes': ability.actions.bow({ target: context.target }),
'No': () => true
}
},
message: '{0} chooses to bow {2} due to {1}\'s ability'
})
gameAction: AbilityDsl.actions.sequential([
AbilityDsl.actions.sendHome(),
AbilityDsl.actions.menuPrompt(context => ({
activePromptTitle: 'Do you want to bow ' + context.target.name + '?',
choices: ['Yes', 'No'],
choiceHandler: (choice, displayMessage) => {
if(displayMessage && choice === 'Yes') {
context.game.addMessage('{0} chooses to bow {1} due to {2}\'s ability', context.player, context.target, context.source);
}
return { target: (choice === 'Yes' ? context.target : []) };
},
gameAction: AbilityDsl.actions.bow()
}))
])
}
});
}
}
Expand Down
14 changes: 7 additions & 7 deletions server/game/cards/02.3-ItFC/TestOfCourage.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
const DrawCard = require('../../drawcard.js');
const AbilityDsl = require('../../abilitydsl');
const { Players, CardTypes } = require('../../Constants');

class TestOfCourage extends DrawCard {
setupCardAbilities(ability) {
setupCardAbilities() {
this.action({
title: 'Move a character into conflict',
condition: context => context.player.opponent && context.player.showBid < context.player.opponent.showBid,
target: {
cardType: CardTypes.Character,
controller: Players.Self,
cardCondition: card => card.isFaction('lion'),
gameAction: ability.actions.moveToConflict()
gameAction: AbilityDsl.actions.sequential([
AbilityDsl.actions.moveToConflict(),
AbilityDsl.actions.honor()
])
},
then: context => ({
message: '{1} honors {3}',
messageArgs: context.target,
gameAction: ability.actions.honor({ target: context.target })
})
effect: 'move {0} to the conflict and honor it'
});
}
}
Expand Down
3 changes: 1 addition & 2 deletions server/game/cards/03-DotV/IsawaTadaka.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ class IsawaTadaka extends DrawCard {
setupCardAbilities(ability) {
this.persistentEffect({
targetController: Players.Opponent,
condition: context => context.game.currentConflict && context.game.currentConflict.hasElement('earth') ||
context.game.rings.earth.isConsideredClaimed(context.player),
condition: context => !context.game.rings.earth.isConsideredClaimed(context.player.opponent),
effect: ability.effects.playerCannot({
cannot: 'play',
restricts: 'copiesOfDiscardEvents'
Expand Down
5 changes: 4 additions & 1 deletion server/game/cards/03-DotV/KyudenIsawa.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ class KyudenIsawa extends StrongholdCard {
setupCardAbilities() {
this.action({
title: 'Play a spell event from discard',
cost: AbilityDsl.costs.bowSelf(),
cost: [
AbilityDsl.costs.bowSelf(),
AbilityDsl.costs.discardCard({ cardCondition: card => card.hasTrait('spell') })
],
condition: () => this.game.isDuringConflict(),
effect: 'play a spell event from discard',
gameAction: AbilityDsl.actions.selectCard(context => ({
Expand Down
20 changes: 11 additions & 9 deletions server/game/cards/04.2-TL/OracleOfStone.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
const DrawCard = require('../../drawcard.js');
const AbilityDsl = require('../../abilitydsl');

class OracleOfStone extends DrawCard {
setupCardAbilities(ability) {
setupCardAbilities() {
this.action({
title: 'Draw 2 cards, then discard 2 cards',
gameAction: ability.actions.draw(context => ({
target: context.game.getPlayers(),
amount: 2
})),
then: context => ({
gameAction: ability.actions.chosenDiscard({
gameAction: AbilityDsl.actions.sequential([
AbilityDsl.actions.draw(context => ({
target: context.game.getPlayers(),
amount: 2
})
})
})),
AbilityDsl.actions.chosenDiscard(context => ({
target: context.game.getPlayers(),
amount: 2
}))
]),
effect: 'make both players draw 2 cards, then discard 2 cards'
});
}
}
Expand Down
17 changes: 9 additions & 8 deletions server/game/cards/04.3-TFW/InvocationOfAsh.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
const DrawCard = require('../../drawcard.js');
const AbilityDsl = require('../../abilitydsl');
const { Players, CardTypes } = require('../../Constants');

class InvocationOfAsh extends DrawCard {
setupCardAbilities(ability) {
setupCardAbilities() {
this.action({
title: 'Move to another character',
cost: ability.costs.payHonor(1),
cost: AbilityDsl.costs.payHonor(1),
target: {
cardType: CardTypes.Character,
controller: Players.Self,
gameAction: ability.actions.attach(context => ({ attachment: context.source }))
gameAction: AbilityDsl.actions.sequential([
AbilityDsl.actions.attach(context => ({ attachment: context.source })),
AbilityDsl.actions.removeFate()
])
},
then: context => ({
message: '{1} removes one fate from {3}',
messageArgs: context.target,
gameAction: ability.actions.removeFate({ target: context.target })
})
effect: 'move {1} to {0}, then remove a fate from {0}',
effectArgs: context => context.source
});
}
}
Expand Down
8 changes: 4 additions & 4 deletions server/game/cards/04.4-TEaF/IkebanaArtisan.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ class IkebanaArtisan extends DrawCard {
},
limit: AbilityDsl.limit.unlimitedPerConflict(),
effect: 'lose 1 fate rather than 1 honor for not defending the conflict',
gameAction: AbilityDsl.actions.cancel(),
then: {
gameAction: AbilityDsl.actions.loseFate(context => ({ target: context.player }))
}
gameAction: AbilityDsl.actions.sequential([
AbilityDsl.actions.cancel(),
AbilityDsl.actions.loseFate(context => ({ target: context.player }))
])
});
}
}
Expand Down
12 changes: 7 additions & 5 deletions server/game/cards/04.4-TEaF/SoulBeyondReproach.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
const DrawCard = require('../../drawcard.js');
const AbilityDsl = require('../../abilitydsl');
const { Players, CardTypes } = require('../../Constants');

class SoulBeyondReproach extends DrawCard {
setupCardAbilities(ability) {
setupCardAbilities() {
this.action({
title: 'Honor a character, then honor it again',
target: {
cardType: CardTypes.Character,
controller: Players.Self,
gameAction: ability.actions.honor()
gameAction: AbilityDsl.actions.sequential([
AbilityDsl.actions.honor(),
AbilityDsl.actions.honor()
])
},
then: context => ({
gameAction: ability.actions.honor({ target: context.target })
})
effect: 'honor {0}, then honor it again'
});
}
}
Expand Down
13 changes: 8 additions & 5 deletions server/game/cards/04.5-AaN/MarkOfShame.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
const DrawCard = require('../../drawcard.js');
const AbilityDsl = require('../../abilitydsl');

class MarkOfShame extends DrawCard {
setupCardAbilities(ability) {
setupCardAbilities() {
this.reaction({
title: 'Dishonor attached character',
when: {
onCardPlayed: (event, context) => event.card === context.source
},
gameAction: ability.actions.dishonor(context => ({ target: context.source.parent })),
then: context => ({
gameAction: ability.actions.dishonor({ target: context.source.parent })
})
gameAction: AbilityDsl.actions.sequential([
AbilityDsl.actions.dishonor(context => ({ target: context.source.parent })),
AbilityDsl.actions.dishonor(context => ({ target: context.source.parent }))
]),
effect: 'dishonor {1}, then dishonor it again',
effectArgs: context => context.source.parent
});
}
}
Expand Down
29 changes: 16 additions & 13 deletions server/game/cards/05-UotE/BayushisWhisperers.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
const DrawCard = require('../../drawcard.js');
const AbilityDsl = require('../../abilitydsl');
const { Players } = require('../../Constants');

class BayushisWhisperers extends DrawCard {
setupCardAbilities(ability) {
setupCardAbilities() {
this.action({
title: 'Look at opponent\'s hand and name a card',
condition: context => context.player.opponent && this.game.isDuringConflict(),
effect: 'look at {1}\'s hand',
effect: 'look at {1}\'s hand, then name a card',
effectArgs: context => context.player.opponent,
gameAction: ability.actions.lookAt(context => ({ target: context.player.opponent.hand.sortBy(card => card.name), chatMessage: true })),
then: {
handler: context => this.game.promptWithMenu(context.player, this, {
context: context,
activePrompt: {
menuTitle: 'Name a card',
controls: [
{ type: 'card-name', command: 'menuButton', method: 'selectCardName', name: 'card-name' }
]
}
gameAction: AbilityDsl.actions.sequential([
AbilityDsl.actions.lookAt(context => ({ target: context.player.opponent.hand.sortBy(card => card.name), chatMessage: true })),
AbilityDsl.actions.handler({
handler: context => this.game.promptWithMenu(context.player, this, {
context: context,
activePrompt: {
menuTitle: 'Name a card',
controls: [
{ type: 'card-name', command: 'menuButton', method: 'selectCardName', name: 'card-name' }
]
}
})
})
}
])
});
}

Expand Down
10 changes: 5 additions & 5 deletions server/game/cards/05-UotE/Duty.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ class Duty extends DrawCard {
event.player === context.player && event.amount >= context.player.honor && event.context.stage === Stages.Effect
},
cannotBeMirrored: true,
effect: 'cancel their honor loss, and gain 1 honor',
gameAction: AbilityDsl.actions.cancel(),
then: {
gameAction: AbilityDsl.actions.gainHonor()
}
effect: 'cancel their honor loss, then gain 1 honor',
gameAction: AbilityDsl.actions.sequential([
AbilityDsl.actions.cancel(),
AbilityDsl.actions.gainHonor(context => ({ target: context.player }))
])
});
}
}
Expand Down
22 changes: 11 additions & 11 deletions server/game/cards/06-CotE/TranquilPhilosopher.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ class TranquilPhilosopher extends DrawCard {
mode: TargetModes.Ring,
activePromptTitle: 'Choose an unclaimed ring to move fate from',
ringCondition: ring => ring.isUnclaimed() && ring.fate > 0,
gameAction: AbilityDsl.actions.selectRing(context => ({
activePromptTitle: 'Choose an unclaimed ring to move fate to',
ringCondition: ring => ring.isUnclaimed() && ring !== context.ring,
message: '{0} moves a fate from {1} to {2}',
messageArgs: ring => [context.player, context.ring, ring],
gameAction: AbilityDsl.actions.placeFateOnRing({ origin: context.ring })
}))
gameAction: AbilityDsl.actions.sequential([
AbilityDsl.actions.selectRing(context => ({
activePromptTitle: 'Choose an unclaimed ring to move fate to',
ringCondition: ring => ring.isUnclaimed() && ring !== context.ring,
message: '{0} moves a fate from {1} to {2}',
messageArgs: ring => [context.player, context.ring, ring],
gameAction: AbilityDsl.actions.placeFateOnRing({ origin: context.ring })
})),
AbilityDsl.actions.gainHonor(context => ({ target: context.player }))
])
},
effect: 'move 1 fate from {0} to an unclaimed ring',
then: {
gameAction: AbilityDsl.actions.gainHonor()
}
effect: 'move 1 fate from {0} to an unclaimed ring, then gain 1 honor'
});
}
}
Expand Down
Loading

0 comments on commit 6d7d782

Please sign in to comment.