From 632fd97049221b65f2e35b8caebfe951d55db630 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 30 Dec 2022 19:52:35 -0600 Subject: [PATCH] Various errata changes - Removed the rule-breaking convenience action from Decipher Realm of Dwarrowdelf - Added errata for all 3 self-discard dwarf cards: Beneath the Mountains, Realm of Dwarrowdelf, and Ever My Heart Rises - Greatest Kingdom nerfed to have a per-turn limit of 1 - Ancient Emnity changed to heal 1 elf, preventable by discarding 1 card from hand - Far-seeing Eyes changed to unique again - Savagery to Match Their Numbers reverted and changed to +4 in first skimrish, +2 afterwards, with a 2 twilight cost - Hunt Them Down reduced from 3 -> 2 twilight - Flaming Brand altered to self-discard in the regroup phase; strength and damage reduced to match the original version - Foul Things altered from "play a [moria] minion" to "play a [moria] card" - Saruman, Keeper of Isengard altered to permit exert or self-discard to prevent uruk wounds - His Cruelty and Malice reworked. Now discards a sauron minion to reveal top 2 cards of Freeps' draw deck; if either is Freeps a companion is exerted unless Freeps discards the revealed Freeps cards. - Galadriel's Silver Ewer not being playable fixed --- .../src/main/web/js/gemp-022/PC_Cards.js | 8 + .../cards/official/set02/set2-dwarven.hjson | 26 -- .../errata/set01/set01-Dwarven-errata.hjson | 14 +- .../pc/errata/set01/set01-Elven-errata.hjson | 23 +- .../errata/set01/set01-Isengard-errata.hjson | 141 ++++++++- .../errata/set02/set02-Dwarven-errata.hjson | 237 ++++++++++++++- .../pc/errata/set02/set02-Gondor-errata.hjson | 103 +++++++ .../pc/errata/set02/set02-Moria.hjson | 50 ++++ .../errata/set03/set03-Isengard-errata.hjson | 135 +++++++++ .../pc/errata/set03/set03-Sauron-errata.hjson | 68 +++-- .../errata/set04/set04-Dwarven-errata.hjson | 114 +++++++ .../pc/errata/set18/set18-Elven-errata.hjson | 2 +- .../lotro/cards/GenericCardTestHelper.java | 2 + .../errata/set01/Card_01_139_ErrataTests.java | 36 +-- .../errata/set02/Card_02_032_ErrataTests.java | 82 +++-- .../errata/set03/Card_03_068_ErrataTests.java | 40 ++- .../errata/set03/Card_03_091_ErrataTests.java | 283 +++++++++++++++++- 17 files changed, 1220 insertions(+), 144 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Moria.hjson create mode 100644 gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set04/set04-Dwarven-errata.hjson diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js index b26712e61..17b7c8510 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js @@ -321,6 +321,8 @@ var PCCards = { '71_43': 'https://i.lotrtcgpc.net/errata/LOTR-EN01E043.1_card.jpg', '71_68': 'https://i.lotrtcgpc.net/errata/LOTR-EN01E068.1_card.jpg', '71_80': 'https://i.lotrtcgpc.net/errata/LOTR-EN01E080.2_card.jpg', + '71_126': 'https://i.lotrtcgpc.net/errata/LOTR-EN01E126.1_card.jpg', + '71_139': 'https://i.lotrtcgpc.net/errata/LOTR-EN01E139.2_card.jpg', '71_150': 'https://i.lotrtcgpc.net/errata/LOTR-EN01E150.1_card.jpg', '71_154': 'https://i.lotrtcgpc.net/errata/LOTR-EN01E154.1_card.jpg', '71_160': 'https://i.lotrtcgpc.net/errata/LOTR-EN01E160.1_card.jpg', @@ -333,16 +335,21 @@ var PCCards = { '71_268': 'https://i.lotrtcgpc.net/errata/LOTR-EN01E268.1_card.jpg', '71_280': 'https://i.lotrtcgpc.net/errata/LOTR-EN01E280.1_card.jpg', '71_333': 'https://i.lotrtcgpc.net/errata/LOTR-EN01E333.1_card.jpg', + '72_1': 'https://i.lotrtcgpc.net/errata/LOTR-EN02E001.1_card.jpg', + '72_12': 'https://i.lotrtcgpc.net/errata/LOTR-EN02E012.1_card.jpg', '72_25': 'https://i.lotrtcgpc.net/errata/LOTR-EN02E025.1_card.jpg', '72_28': 'https://i.lotrtcgpc.net/errata/LOTR-EN02E028.1_card.jpg', + '72_32': 'https://i.lotrtcgpc.net/errata/LOTR-EN02E032.2_card.jpg', '72_43': 'https://i.lotrtcgpc.net/errata/LOTR-EN02E043.1_card.jpg', '72_44': 'https://i.lotrtcgpc.net/errata/LOTR-EN02E044.1_card.jpg', '72_45': 'https://i.lotrtcgpc.net/errata/LOTR-EN02E045.1_card.jpg', + '72_59': 'https://i.lotrtcgpc.net/errata/LOTR-EN02E059.1_card.jpg', '72_91': 'https://i.lotrtcgpc.net/errata/LOTR-EN02E091.1_card.jpg', '72_107': 'https://i.lotrtcgpc.net/errata/LOTR-EN02E107.1_card.jpg', '73_4': 'https://i.lotrtcgpc.net/errata/LOTR-EN03E004.1_card.jpg', '73_17': 'https://i.lotrtcgpc.net/errata/LOTR-EN03E017.2_card.jpg', '73_54': 'https://i.lotrtcgpc.net/errata/LOTR-EN03E054.1_card.jpg', + '73_68': 'https://i.lotrtcgpc.net/errata/LOTR-EN03E068.2_card.jpg', '73_79': 'https://i.lotrtcgpc.net/errata/LOTR-EN03E079.1_card.jpg', '73_82': 'https://i.lotrtcgpc.net/errata/LOTR-EN03E082.1_card.jpg', '73_87': 'https://i.lotrtcgpc.net/errata/LOTR-EN03E087.1_card.jpg', @@ -352,6 +359,7 @@ var PCCards = { '73_92': 'https://i.lotrtcgpc.net/errata/LOTR-EN03E092.1_card.jpg', '73_103': 'https://i.lotrtcgpc.net/errata/LOTR-EN03E103.1_card.jpg', '73_104': 'https://i.lotrtcgpc.net/errata/LOTR-EN03E104.1_card.jpg', + '74_46': 'https://i.lotrtcgpc.net/errata/LOTR-EN04E046.1_card.jpg', '74_146': 'https://i.lotrtcgpc.net/errata/LOTR-EN04E146.1_card.jpg', '75_8': 'https://i.lotrtcgpc.net/errata/LOTR-EN05E008.1_card.jpg', '75_57': 'https://i.lotrtcgpc.net/errata/LOTR-EN05E057.1_card.jpg', diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set02/set2-dwarven.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set02/set2-dwarven.hjson index 4abe9774a..24180ae03 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set02/set2-dwarven.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set02/set2-dwarven.hjson @@ -23,32 +23,6 @@ filter: choose(culture(dwarven),weapon) } } - { - type: activated - text: Discard cards from the top of your deck to no effect. - phase: fellowship - effect: [ - { - type: chooseANumber - from: 0 - to: 99 - text: Choose how many times to discard 3 cards from draw deck - memorize: chosenNumber - } - { - type: discardTopCardsFromDeck - forced: false - count: { - type: multiply - multiplier: 3 - source: { - type: fromMemory - memory: chosenNumber - } - } - } - ] - } ] } 2_2: { diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Dwarven-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Dwarven-errata.hjson index b26b49d1c..3f4f03428 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Dwarven-errata.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Dwarven-errata.hjson @@ -276,7 +276,7 @@ title: Greatest Kingdom of My People unique: true culture: dwarven - twilight: 0 + twilight: 1 type: condition keyword: [ tale @@ -297,11 +297,16 @@ filter: orc memorize: playedOrc } + requires: { + type: perTurnLimit + limit: 1 + } effect: [ { type: chooseCardsFromDiscard filter: choose(culture(dwarven)) memorize: chosenCard + count: 0-1 text: Choose a Dwarven card from your discard pile to take into hand } { @@ -317,13 +322,16 @@ effect: { type: putCardsFromDiscardIntoHand filter: memory(chosenCard) - count: 0-1 } } + { + type: IncrementPerTurnLimit + limit: 1 + } ] } ] - gametext: Tale. To play, exert a Dwarf. \Each time your opponent plays an Orc, you may take a [dwarven] card into hand from your discard pile. The Shadow player may discard the bottom card of their deck to prevent this. + gametext: Tale. To play, exert a Dwarf. \The first time your opponent plays an Orc each turn, you may take a [dwarven] card into hand from your discard pile. The Shadow player may discard the bottom 2 cards of their draw deck to prevent this. lore: "'With golden roof and silver floor / And runes of power upon the door.'" promotext: "" alts: { diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Elven-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Elven-errata.hjson index 1dfda17da..d7614d4b7 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Elven-errata.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Elven-errata.hjson @@ -48,17 +48,10 @@ effect: [ { type: chooseActiveCards - count: { - type: range - from: 0 - to: { - type: forEachYouCanSpot - filter: minion - } - } + count: 1 filter: choose(wounded,Elf) - memorize: chosenElves - text: Choose Elves to heal + memorize: chosenElf + text: Choose Elf to heal } { type: preventable @@ -67,20 +60,20 @@ type: DiscardFromHand player: ownerFromMemory(losingMinion) hand: ownerFromMemory(losingMinion) - count: 2 + count: 1 forced: false } - text: Discard 2 cards from hand to prevent healing {chosenElves} + text: Discard 1 card from hand to prevent healing {chosenElf} effect: { type: heal - filter: memory(chosenElves) + filter: memory(chosenElf) } } ] } ] } - gametext: Make an Elf strength +1. \If a minion loses this skirmish to that Elf, you may heal an Elf for each minion that you can spot; that minion’s owner may discard 2 cards at random from hand to prevent this. + gametext: Make an Elf strength +1. \If a minion loses this skirmish to that Elf, you may heal an Elf; that minion’s owner may discard a card from hand to prevent this. lore: Hard and bitter is the Elven hatred of Orcs, for they have lost many kinsmen to Orc savagery. promotext: "" alts: { @@ -305,7 +298,7 @@ style: Standard } title: Far-seeing Eyes - unique: false + unique: true culture: elven twilight: 2 type: condition diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Isengard-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Isengard-errata.hjson index f0f2427e3..84162faa8 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Isengard-errata.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Isengard-errata.hjson @@ -1,5 +1,55 @@ { - + 71_126: { + cardInfo: { + //Either a full URL, or a subpath for the PC image server + imagePath: errata/LOTR-EN01E126.1.jpg + //If this is true, then all gameplay-related info outside this cardInfo definition + // will be ignored and the java class loaded instead. + javaClass: false + //This instructs the blueprint generator to insert this card as an alt of the listed + // parent blueprint. Can of course be ommitted if not an errata or promo. + parent: 1_126 + //This is the tree path to use within the alts structure on the parent. + // Can of course be ommitted if parent is null. + parentPath: errata/pc + //Versioning differentiates releases within a particular alt path, such as PC errata + // version 1 vs version 2. PC version 2 will not conflict with, say, Decipher version 2. + //Top-level cards should always be version 0. + version: 1 + collInfo: 1C126 + rarity: U + setNum: "1" + cardNum: 126 + // Standard, Masterwork, Tengwar, FullArt, etc. Top-level cards are always Standard. + style: Standard + } + title: Hunt Them Down! + culture: isengard + twilight: 2 + type: event + keyword: maneuver + effects: { + type: event + effect: { + type: addKeyword + filter: choose(uruk-hai) + keyword: fierce + until: start(regroup) + } + } + gametext: Maneuver: Make an Uruk-hai fierce until the regroup phase. + lore: "'Do not stop until they are found!'" + promotext: "" + alts: { + //These are just CardInfo objects + promos: { + } + //These are full card definitions, with redundant info that is the same as the original card ommitted + errata: { + } + } + } + 51_138: { cardInfo: { //Either a full URL, or a subpath for the PC image server @@ -98,7 +148,7 @@ //Versioning differentiates releases within a particular alt path, such as PC errata // version 1 vs version 2. PC version 2 will not conflict with, say, Decipher version 2. //Top-level cards should always be version 0. - version: 1? + version: 1 collInfo: 1R139 rarity: R setNum: "1" @@ -163,6 +213,93 @@ } } + 71_139: { + cardInfo: { + //Either a full URL, or a subpath for the PC image server + imagePath: errata/LOTR-EN01E139.2.jpg + //If this is true, then all gameplay-related info outside this cardInfo definition + // will be ignored and the java class loaded instead. + javaClass: false + //This instructs the blueprint generator to insert this card as an alt of the listed + // parent blueprint. Can of course be ommitted if not an errata or promo. + parent: 1_139 + //This is the tree path to use within the alts structure on the parent. + // Can of course be ommitted if parent is null. + parentPath: errata/pc + //Versioning differentiates releases within a particular alt path, such as PC errata + // version 1 vs version 2. PC version 2 will not conflict with, say, Decipher version 2. + //Top-level cards should always be version 0. + version: 2 + collInfo: 1R139 + rarity: R + setNum: "1" + cardNum: 139 + // Standard, Masterwork, Tengwar, FullArt, etc. Top-level cards are always Standard. + style: Standard + } + title: Savagery To Match Their Numbers + culture: isengard + twilight: 2 + type: event + keyword: skirmish + effects: { + type: event + effect: { + type: choice + texts: [ + Make an Uruk-hai strength +2 + Make an Uruk-hai strength +2 (and +2 more and fierce until the regroup phase) + ] + effects: [ + { + type: modifyStrength + filter: choose(uruk-hai) + amount: 2 + } + { + type: conditional + requires: { + type: canSpot + count: 5 + filter: companion + } + effect: [ + { + type: modifyStrength + filter: choose(uruk-hai) + amount: 2 + memorize: chosenUrukHai + } + { + type: modifyStrength + filter: memory(chosenUrukHai) + amount: 2 + until: start(regroup) + } + { + type: addKeyword + filter: memory(chosenUrukHai) + keyword: fierce + until: start(regroup) + } + ] + } + ] + } + } + gametext: Skirmish: Make an Uruk-hai strength +2.\If you can spot 5 companions, also make it fierce and strength +2 more until the regroup phase). + lore: Uruk-hai match their enemies' strength with their own feral rage. + promotext: "" + alts: { + //These are just CardInfo objects + promos: { + } + //These are full card definitions, with redundant info that is the same as the original card ommitted + errata: { + } + } + } + 71_150: { cardInfo: { //Either a full URL, or a subpath for the PC image server diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Dwarven-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Dwarven-errata.hjson index 92234609d..808c2d2b6 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Dwarven-errata.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Dwarven-errata.hjson @@ -1,5 +1,240 @@ { - + 72_1: { + cardInfo: { + //Either a full URL, or a subpath for the PC image server + imagePath: errata/LOTR-EN02E001.1.jpg + //If this is true, then all gameplay-related info outside this cardInfo definition + // will be ignored and the java class loaded instead. + javaClass: false + //This instructs the blueprint generator to insert this card as an alt of the listed + // parent blueprint. Can of course be ommitted if not an errata or promo. + parent: 2_1 + //This is the tree path to use within the alts structure on the parent. + // Can of course be ommitted if parent is null. + parentPath: errata/pc + //Versioning differentiates releases within a particular alt path, such as PC errata + // version 1 vs version 2. PC version 2 will not conflict with, say, Decipher version 2. + //Top-level cards should always be version 0. + version: 1 + collInfo: 2R1 + rarity: R + setNum: "2" + cardNum: 1 + // Standard, Masterwork, Tengwar, FullArt, etc. Top-level cards are always Standard. + style: Standard + } + title: Beneath the Mountains + culture: dwarven + twilight: 1 + type: condition + keyword: [ + tale + support area + ] + effects: [ + { + type: activated + text: Discard 3 cards from the top of your draw deck to play a [dwarven] weapon from discard. + phase: fellowship + cost: { + type: discardTopCardsFromDeck + forced: false + count: 3 + } + effect: { + type: playCardFromDiscard + filter: choose(culture(dwarven),weapon) + } + } + { + type: activated + text: Discard 3 cards from the top of your deck to no effect. + phase: fellowship + effect: [ + { + type: chooseANumber + from: 0 + to: 99 + text: Choose how many times to discard 3 cards from draw deck + memorize: chosenNumber + } + { + type: discardTopCardsFromDeck + forced: false + count: { + type: multiply + multiplier: 3 + source: { + type: fromMemory + memory: chosenNumber + } + } + } + ] + } + ] + } + + 72_12: { + cardInfo: { + //Either a full URL, or a subpath for the PC image server + imagePath: errata/LOTR-EN02E012.1.jpg + //If this is true, then all gameplay-related info outside this cardInfo definition + // will be ignored and the java class loaded instead. + javaClass: false + //This instructs the blueprint generator to insert this card as an alt of the listed + // parent blueprint. Can of course be ommitted if not an errata or promo. + parent: 2_12 + //This is the tree path to use within the alts structure on the parent. + // Can of course be ommitted if parent is null. + parentPath: errata/pc + //Versioning differentiates releases within a particular alt path, such as PC errata + // version 1 vs version 2. PC version 2 will not conflict with, say, Decipher version 2. + //Top-level cards should always be version 0. + version: 1 + collInfo: 2R12 + rarity: R + setNum: "2" + cardNum: 12 + // Standard, Masterwork, Tengwar, FullArt, etc. Top-level cards are always Standard. + style: Standard + } + title: Realm of Dwarrowdelf + unique: true + culture: dwarven + twilight: 1 + type: condition + keyword: support area + effects: { + type: activated + phase: skirmish + cost: { + type: discardTopCardsFromDeck + count: 3 + forced: false + } + effect: [ + { + type: modifyStrength + filter: choose(dwarf) + memorize: chosenDwarf + amount: { + type: cardAffectedLimitPerPhase + prefix: str- + source: 1 + limit: 3 + } + } + { + type: conditional + requires: { + type: location + filter: underground + } + effect: { + type: addKeyword + filter: memory(chosenDwarf) + keyword: damage + amount: { + type: cardAffectedLimitPerPhase + prefix: dmg- + source: 1 + limit: 3 + } + } + } + { + type: chooseYesOrNo + player: you + text: Would you like to discard 3 cards from the top of your deck to no effect? + memorize: choice + } + { + type: conditional + requires: { + type: MemoryIs + memory: choice + value: yes + } + effect: { + type: discardTopCardsFromDeck + count: 3 + forced: false + } + } + { + type: Repeat + amount: 9 + effect: { + type: conditional + requires: { + type: MemoryIs + memory: choice + value: yes + } + effect: [ + { + type: chooseYesOrNo + player: you + text: Would you like to discard 3 more cards from the top of your deck to no effect? + memorize: choice + } + { + type: conditional + requires: { + type: MemoryIs + memory: choice + value: yes + } + effect: { + type: discardTopCardsFromDeck + count: 3 + forced: false + } + } + ] + } + } + { + type: optional + text: Discard cards from the top of your deck to no effect. + effect: [ + { + type: chooseANumber + from: 0 + to: 10 + text: Choose how many times to discard 3 cards from draw deck + memorize: chosenNumber + } + { + type: discardTopCardsFromDeck + forced: false + count: { + type: multiply + multiplier: 3 + source: { + type: fromMemory + memory: chosenNumber + } + } + } + ] + } + ] + } + gametext: Skirmish: Discard the top 3 cards from your draw deck to make a Dwarf strength +1 (limit +3) and, if underground, damage +1 (limit +3). You may then discard up to 30 cards from your draw deck 3 at a time. + lore: "'There must have been a mighty crowd of dwarves here... and every one of them busier than badgers....'" + promotext: "" + alts: { + //These are just CardInfo objects + promos: { + } + //These are full card definitions, with redundant info that is the same as the original card ommitted + errata: { + } + } + } + 52_6: { cardInfo: { //Either a full URL, or a subpath for the PC image server diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Gondor-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Gondor-errata.hjson index 3787d3246..b303e99c5 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Gondor-errata.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Gondor-errata.hjson @@ -80,4 +80,107 @@ } } } + + + 72_32: { + cardInfo: { + //Either a full URL, or a subpath for the PC image server + imagePath: errata/LOTR-EN02E032.2.jpg + //If this is true, then all gameplay-related info outside this cardInfo definition + // will be ignored and the java class loaded instead. + javaClass: false + //This instructs the blueprint generator to insert this card as an alt of the listed + // parent blueprint. Can of course be ommitted if not an errata or promo. + parent: 2_32 + //This is the tree path to use within the alts structure on the parent. + // Can of course be ommitted if parent is null. + parentPath: errata/pc + //Versioning differentiates releases within a particular alt path, such as PC errata + // version 1 vs version 2. PC version 2 will not conflict with, say, Decipher version 2. + //Top-level cards should always be version 0. + version: 2 + collInfo: 2R32 + rarity: R + setNum: "2" + cardNum: 32 + // Standard, Masterwork, Tengwar, FullArt, etc. Top-level cards are always Standard. + style: Standard + } + title: Flaming Brand + side: free_people + culture: Gondor + type: possession + itemclass: Hand Weapon + twilight: 1 + strength: 1 + target: ranger + effects: [ + { + type: extrapossessionclass + } + { + type: activated + phase: skirmish + requires: { + type: perTurnLimit + limit: 1 + } + effect: [ + { + type: addModifier + until: start(regroup) + modifier: { + type: ModifyStrength + filter: bearer + amount: 2 + requires: { + type: CanSpot + filter: bearer,InSkirmishAgainst(Nazgul) + } + } + } + { + type: addModifier + until: start(regroup) + modifier: { + type: AddKeyword + filter: bearer + keyword: damage+1 + requires: { + type: CanSpot + filter: bearer,InSkirmishAgainst(Nazgul) + } + } + } + { + type: addTrigger + until: end(Regroup) + trigger: { + type: StartOfPhase + phase: regroup + } + effect: { + type: Discard + filter: self + } + } + { + type: IncrementPerTurnLimit + limit: 1 + } + ] + } + ] + gametext: Bearer must be a ranger.
This weapon may be borne in addition to 1 other hand weapon.
Skirmish: If bearer is skirmishing a Nazgul, discard this possession to make bearer strength +3 and damage +2. + lore: "...a glimpse of Strider leaping out of the darkness with a flaming brand of wood in either hand." + promotext: "" + alts: { + //These are just CardInfo objects + promos: { + } + //These are full card definitions, with redundant info that is the same as the original card ommitted + errata: { + } + } + } } diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Moria.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Moria.hjson new file mode 100644 index 000000000..b69bbe03c --- /dev/null +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Moria.hjson @@ -0,0 +1,50 @@ +{ + 72_59: { + cardInfo: { + //Either a full URL, or a subpath for the PC image server + imagePath: errata/LOTR-EN02E059.1.jpg + //If this is true, then all gameplay-related info outside this cardInfo definition + // will be ignored and the java class loaded instead. + javaClass: false + //This instructs the blueprint generator to insert this card as an alt of the listed + // parent blueprint. Can of course be ommitted if not an errata or promo. + parent: 2_59 + //This is the tree path to use within the alts structure on the parent. + // Can of course be ommitted if parent is null. + parentPath: errata/pc + //Versioning differentiates releases within a particular alt path, such as PC errata + // version 1 vs version 2. PC version 2 will not conflict with, say, Decipher version 2. + //Top-level cards should always be version 0. + version: 1 + collInfo: 2U59 + rarity: U + setNum: "2" + cardNum: 59 + // Standard, Masterwork, Tengwar, FullArt, etc. Top-level cards are always Standard. + style: Standard + } + title: Foul Things + culture: moria + twilight: 2 + type: event + keyword: shadow + effects: { + type: event + effect: { + type: playCardFromDiscard + filter: choose(culture(moria)) + } + } + gametext: Shadow: Play a [Moria] card from your discard pile. + lore: "'Something has crept, or has been driven out of dark waters under the mountains.'" + promotext: "" + alts: { + //These are just CardInfo objects + promos: { + } + //These are full card definitions, with redundant info that is the same as the original card ommitted + errata: { + } + } + } +} diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set03/set03-Isengard-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set03/set03-Isengard-errata.hjson index 9ab7b344a..0dcd969d7 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set03/set03-Isengard-errata.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set03/set03-Isengard-errata.hjson @@ -184,6 +184,141 @@ } } } + + 73_68: { + cardInfo: { + //Either a full URL, or a subpath for the PC image server + imagePath: errata/LOTR-EN03E068.1.jpg + //If this is true, then all gameplay-related info outside this cardInfo definition + // will be ignored and the java class loaded instead. + javaClass: false + //This instructs the blueprint generator to insert this card as an alt of the listed + // parent blueprint. Can of course be ommitted if not an errata or promo. + parent: 3_68 + //This is the tree path to use within the alts structure on the parent. + // Can of course be ommitted if parent is null. + parentPath: errata/pc + //Versioning differentiates releases within a particular alt path, such as PC errata + // version 1 vs version 2. PC version 2 will not conflict with, say, Decipher version 2. + //Top-level cards should always be version 0. + version: 2 + collInfo: 3R68 + rarity: R + setNum: "3" + cardNum: 68 + // Standard, Masterwork, Tengwar, FullArt, etc. Top-level cards are always Standard. + style: Standard + } + title: Saruman + subtitle: Keeper of Isengard + unique: true + side: shadow + culture: Isengard + type: minion + race: Wizard + twilight: 4 + strength: 8 + vitality: 4 + site: 4 + effects: [ + { + type: modifier + modifier: { + type: cantTakeWounds + filter: self + requires: [ + { + type: phase + phase: archery + } + { + type: sarumanfirstsentenceactive + } + ] + } + } + { + type: modifier + modifier: { + type: cantbeassignedtoskirmish + filter: self + requires: { + type: sarumanfirstsentenceactive + } + } + } + { + type: activated + phase: maneuver + cost: { + type: exert + filter: self + } + effect: { + type: addKeyword + filter: choose(uruk-hai) + keyword: fierce + until: start(regroup) + memorize: chosenUruk + } + } + { + type: activatedTrigger + trigger: { + type: aboutToTakeWound + filter: uruk-hai + } + cost: { + type: choice + memorize: theChoice + texts: [ + Exert Saruman + Discard Saruman + ] + effects: [ + { + type: conditional + requires: { + type: canSpot + filter: self,not(exhausted) + } + effect: { + type: exert + filter: self + } + } + { + type: conditional + requires: { + type: canSpot + filter: self,exhausted + } + effect: { + type: discard + filter: self + } + } + ] + } + effect: + { + type: preventWound + filter: choose(uruk-hai) + } + } + ] + gametext: Saruman may not take wounds during the archery phase and may not be assigned to a skirmish.
Maneuver: Exert Saruman to make an Uruk-hai fierce until the regroup phase.
Response: If an Uruk-hai is about to take a wound, discard (or exert) Saruman to prevent that wound. + lore: "" + promotext: "" + alts: { + //These are just CardInfo objects + promos: { + } + //These are full card definitions, with redundant info that is the same as the original card ommitted + errata: { + } + } + } 53_67: { cardInfo: { diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set03/set03-Sauron-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set03/set03-Sauron-errata.hjson index a76f592ab..84ed7b3bd 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set03/set03-Sauron-errata.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set03/set03-Sauron-errata.hjson @@ -286,13 +286,48 @@ phase: regroup cost: [ { - type: chooseActiveCards + type: discard filter: choose(culture(sauron),minion) - memorize: chosenMinion - text: Choose a [Sauron] minion to exert or discard } ] effect: [ + { + type: RevealTopCardsOfDrawDeck + count: 2 + deck: freeps + memorize: cardsOnTop + } + { + type: conditional + requires: { + type: MemoryMatches + memory: cardsOnTop + filter: side(freeps) + } + effect: [ + { + type: chooseActiveCards + filter: choose(companion,not(exhausted),not(Ring-bearer)) + memorize: chosenComp + text: Choose a companion to exert (except the Ring-bearer) + } + { + type: preventable + player: freeps + cost: { + type: DiscardCardsFromDrawDeck + player: freeps + deck: freeps + filter: all(side(freeps),memory(cardsOnTop)) + } + text: Discard all revealed Free Peoples cards to prevent exerting {chosenComp}? + effect: { + type: exert + filter: memory(chosenComp) + } + } + ] + } { type: choice texts: [ @@ -306,34 +341,15 @@ } { type: discard - filter: memory(chosenMinion) + filter: choose(culture(sauron),minion) } ] } - { - type: chooseActiveCards - filter: choose(companion,not(exhausted)) - memorize: chosenComp - text: Choose a companion to exert - } - { - type: preventable - player: freeps - cost: { - type: discardTopCardsFromDeck - deck: freeps - count: 2 - forced: false - } - text: Discard the top 2 cards of your deck to prevent exerting {chosenComp} - effect: { - type: exert - filter: memory(chosenComp) - } - } + + ] } - gametext: Regroup: Exert or discard a [sauron] minion to exert a companion. The Free Peoples player may discard the top 2 cards from their draw deck to prevent this. + gametext: Regroup: Discard a [sauron] minion to reveal the top 2 cards of your opponent's draw deck. If at least 1 is a Free Peoples card, exert a companion (except the Ring-bearer). Your opponent may discard all revealed Free Peoples cards to prevent this. lore: "'Into this Ring he poured his cruelty, his malice, and his will to dominate all life.'" promotext: "" alts: { diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set04/set04-Dwarven-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set04/set04-Dwarven-errata.hjson new file mode 100644 index 000000000..b849ccd93 --- /dev/null +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set04/set04-Dwarven-errata.hjson @@ -0,0 +1,114 @@ +{ + 74_46: { + cardInfo: { + //Either a full URL, or a subpath for the PC image server + imagePath: errata/LOTR-EN04E046.1.jpg + //If this is true, then all gameplay-related info outside this cardInfo definition + // will be ignored and the java class loaded instead. + javaClass: false + //This instructs the blueprint generator to insert this card as an alt of the listed + // parent blueprint. Can of course be ommitted if not an errata or promo. + parent: 4_46 + //This is the tree path to use within the alts structure on the parent. + // Can of course be ommitted if parent is null. + parentPath: errata/pc + //Versioning differentiates releases within a particular alt path, such as PC errata + // version 1 vs version 2. PC version 2 will not conflict with, say, Decipher version 2. + //Top-level cards should always be version 0. + version: 1 + collInfo: 4R46 + rarity: R + setNum: "4" + cardNum: 46 + // Standard, Masterwork, Tengwar, FullArt, etc. Top-level cards are always Standard. + style: Standard + } + title: Ever My Heart Rises + unique: true + culture: Dwarven + twilight: 3 + type: condition + keyword: [ + Support Area + Tale + ] + effects: [ + { + type: trigger + trigger: { + type: played + filter: self + } + effect: { + type: stackTopCardsOfDrawDeck + count: 6 + where: self + } + } + { + type: activated + text: Discard 1 card from the top of your draw deck to take a Free Peoples card stacked here into hand. + phase: fellowship + requires: [ + { + type: canSpot + filter: dwarf + } + ] + cost: { + type: discardTopCardsFromDeck + count: 1 + forced: false + } + effect: { + type: putStackedCardsIntoHand + filter: choose(side(free people)) + on: self + } + } + { + type: activated + text: Discard cards from the top of your deck to no effect. + phase: fellowship + requires: [ + { + type: canSpot + filter: dwarf + } + ] + effect: [ + { + type: chooseANumber + from: 0 + to: 99 + text: Choose how many times to discard 5 cards from draw deck + memorize: chosenNumber + } + { + type: discardTopCardsFromDeck + forced: false + count: { + type: multiply + multiplier: 5 + source: { + type: fromMemory + memory: chosenNumber + } + } + } + ] + } + ] + gametext: Tale. When you play this condition, reveal the top 6 cards of your draw deck and stack them here.
Fellowship: Spot a Dwarf and discard the top card of your draw deck to take a Free Peoples card stacked here into hand.\Fellowship: Spot a Dwarf to discard the top 5 cards of your draw deck. + lore: "" + promotext: "" + alts: { + //These are just CardInfo objects + promos: { + } + //These are full card definitions, with redundant info that is the same as the original card ommitted + errata: { + } + } + } +} diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set18/set18-Elven-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set18/set18-Elven-errata.hjson index 14983016a..235d8c832 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set18/set18-Elven-errata.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set18/set18-Elven-errata.hjson @@ -31,7 +31,7 @@ keyword: support area requires: { type: canSpot - filter: title(or(Galadriel,Celeborn)) + filter: or(title(Galadriel),title(Celeborn)) } effects: [ { diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java index d42b5eae4..dc8623379 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java @@ -249,6 +249,8 @@ public class GenericCardTestHelper extends AbstractAtTest { public List FreepsGetCardChoices() { return GetADParamAsList(P1, "cardId"); } public List ShadowGetCardChoices() { return GetADParamAsList(P2, "cardId"); } + public List FreepsGetBPChoices() { return GetADParamAsList(P1, "blueprintId"); } + public List ShadowGetBPChoices() { return GetADParamAsList(P2, "blueprintId"); } public List FreepsGetMultipleChoices() { return GetADParamAsList(P1, "results"); } public List ShadowGetMultipleChoices() { return GetADParamAsList(P2, "results"); } public List FreepsGetADParamAsList(String paramName) { return GetADParamAsList(P1, paramName); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set01/Card_01_139_ErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set01/Card_01_139_ErrataTests.java index 56b3de98e..0118e6563 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set01/Card_01_139_ErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set01/Card_01_139_ErrataTests.java @@ -1,18 +1,16 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set01; import com.gempukku.lotro.cards.GenericCardTestHelper; -import com.gempukku.lotro.common.*; +import com.gempukku.lotro.common.CardType; +import com.gempukku.lotro.common.Culture; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Side; import com.gempukku.lotro.game.CardNotFoundException; -import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; -import com.gempukku.lotro.logic.modifiers.MoveLimitModifier; -import org.junit.Test; import java.util.HashMap; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; public class Card_01_139_ErrataTests { @@ -38,45 +36,47 @@ public class Card_01_139_ErrataTests /** * Set: 1 * Title: Savagery to Match\Their Numbers - * Side: Free Peoples + * Unique: False + * Side: FREE_PEOPLE * Culture: Isengard - * Twilight Cost: 0 + * Twilight Cost: 2 * Type: event * Subtype: - * Game Text: Skirmish: Make an Uruk-hai strength +2, or spot 5 companions to make an Uruk-hai strength +3 (and fierce until the regroup phase). + * Game Text: Skirmish: Make an Uruk-hai strength +2. + * If you can spot 5 companions, also make it fierce and strength +2 more until the regroup phase. */ //Pre-game setup - GenericCardTestHelper scn = GetScenario(); + var scn = GetScenario(); - PhysicalCardImpl card = scn.GetFreepsCard("card"); + var card = scn.GetFreepsCard("card"); assertFalse(card.getBlueprint().isUnique()); assertEquals(Side.FREE_PEOPLE, card.getBlueprint().getSide()); assertEquals(Culture.ISENGARD, card.getBlueprint().getCulture()); assertEquals(CardType.EVENT, card.getBlueprint().getCardType()); - //assertEquals(Race.CREATURE, card.getBlueprint().getRace()); + //assertEquals(Race., card.getBlueprint().getRace()); + //assertTrue(card.getBlueprint().getPossessionClasses().contains(PossessionClass.)); assertTrue(scn.HasKeyword(card, Keyword.SUPPORT_AREA)); - assertEquals(0, card.getBlueprint().getTwilightCost()); + assertEquals(2, card.getBlueprint().getTwilightCost()); //assertEquals(, card.getBlueprint().getStrength()); //assertEquals(, card.getBlueprint().getVitality()); //assertEquals(, card.getBlueprint().getResistance()); //assertEquals(Signet., card.getBlueprint().getSignet()); //assertEquals(, card.getBlueprint().getSiteNumber()); // Change this to getAllyHomeSiteNumbers for allies - } //@Test public void SavagerytoMatchTheirNumbersTest1() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTestHelper scn = GetScenario(); + var scn = GetScenario(); - PhysicalCardImpl card = scn.GetFreepsCard("card"); + var card = scn.GetFreepsCard("card"); scn.FreepsMoveCardToHand(card); scn.StartGame(); scn.FreepsPlayCard(card); - assertEquals(0, scn.GetTwilight()); + assertEquals(2, scn.GetTwilight()); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set02/Card_02_032_ErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set02/Card_02_032_ErrataTests.java index 060b6b1d9..a6fbddfe0 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set02/Card_02_032_ErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set02/Card_02_032_ErrataTests.java @@ -1,8 +1,7 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set02; import com.gempukku.lotro.cards.GenericCardTestHelper; -import com.gempukku.lotro.common.Keyword; -import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.*; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; @@ -17,8 +16,8 @@ public class Card_02_032_ErrataTests protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { return new GenericCardTestHelper( new HashMap<>() {{ - put("brand", "52_32"); - put("brand2", "52_32"); + put("brand", "72_32"); + put("brand2", "72_32"); put("arwen", "1_30"); put("boromir", "1_97"); put("aragorn", "1_89"); @@ -30,26 +29,32 @@ public class Card_02_032_ErrataTests } @Test - public void BrandStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + public void FlamingBrandStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { /** - * Set: 1E + * Set: 2 * Title: Flaming Brand - * Side: Free Peoples + * Unique: False + * Side: FREE_PEOPLE * Culture: Gondor * Twilight Cost: 1 - * Type: Possession + * Type: possession * Subtype: Hand Weapon - * Errata Game Text: Bearer must be a ranger. This weapon may be borne in addition to 1 other hand weapon. - * Skirmish: If bearer is skirmishing a Nazgul, discard this possession to make bearer strength +3 and damage +1. + * Strength: 1 + * Game Text: Bearer must be a ranger. This weapon may be borne in addition to 1 other hand weapon. + * Skirmish: Make bearer strength +2 and damage +1 while skirmishing a Nazgûl until the regroup phase (limit once per turn). Discard this possession at the start of the regroup phase. */ //Pre-game setup - GenericCardTestHelper scn = GetScenario(); + var scn = GetScenario(); - PhysicalCardImpl brand = scn.GetFreepsCard("brand"); + var brand = scn.GetFreepsCard("brand"); assertFalse(brand.getBlueprint().isUnique()); + assertEquals(Side.FREE_PEOPLE, brand.getBlueprint().getSide()); + assertEquals(Culture.GONDOR, brand.getBlueprint().getCulture()); + assertEquals(CardType.POSSESSION, brand.getBlueprint().getCardType()); + assertTrue(brand.getBlueprint().getPossessionClasses().contains(PossessionClass.HAND_WEAPON)); assertEquals(1, brand.getBlueprint().getTwilightCost()); assertEquals(1, brand.getBlueprint().getStrength()); } @@ -136,8 +141,6 @@ public class Card_02_032_ErrataTests //start goblin skirmish scn.FreepsResolveSkirmish(aragorn); - //goblin shouldn't trigger Flaming Brand's action - assertEquals(0, scn.FreepsGetAvailableActions().size()); scn.PassCurrentPhaseActions(); //assignment for fierce skirmish @@ -145,15 +148,60 @@ public class Card_02_032_ErrataTests scn.FreepsAssignToMinions(aragorn, nazgul); scn.FreepsResolveSkirmish(aragorn); - assertEquals(1, scn.FreepsGetAvailableActions().size()); + assertTrue(scn.FreepsAnyActionsAvailable()); assertTrue(scn.FreepsActionAvailable(brand)); assertFalse(scn.HasKeyword(aragorn, Keyword.DAMAGE)); scn.FreepsUseCardAction(brand); assertEquals(11, scn.GetStrength(aragorn)); assertTrue(scn.HasKeyword(aragorn, Keyword.DAMAGE)); + assertEquals(1, scn.GetKeywordCount(aragorn, Keyword.DAMAGE)); + } - //Brand is discarded - assertFalse(scn.IsAttachedTo(brand, aragorn)); + @Test + public void SkirmishAbilityLastsUntilRegroupAndSelfDiscards() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl brand = scn.GetFreepsCard("brand"); + PhysicalCardImpl nazgul = scn.GetShadowCard("nazgul"); + + scn.FreepsMoveCharToTable(aragorn); + scn.FreepsAttachCardsTo(aragorn, brand); + + scn.ShadowMoveCharToTable(nazgul); + + scn.StartGame(); + + scn.SkipToPhase(Phase.ASSIGNMENT); + scn.PassCurrentPhaseActions(); + scn.FreepsAssignToMinions(aragorn, nazgul); + + scn.FreepsResolveSkirmish(aragorn); + + assertTrue(scn.FreepsActionAvailable(brand)); + assertEquals(9, scn.GetStrength(aragorn)); + assertFalse(scn.HasKeyword(aragorn, Keyword.DAMAGE)); + scn.FreepsUseCardAction(brand); + assertEquals(11, scn.GetStrength(aragorn)); + assertTrue(scn.HasKeyword(aragorn, Keyword.DAMAGE)); + + scn.ShadowPassCurrentPhaseAction(); + scn.FreepsPassCurrentPhaseAction(); + + //assignment for fierce skirmish + scn.PassCurrentPhaseActions(); + + scn.FreepsAssignToMinions(aragorn, nazgul); + scn.FreepsResolveSkirmish(aragorn); + assertTrue(scn.IsAttachedTo(brand, aragorn)); + assertEquals(11, scn.GetStrength(aragorn)); + assertTrue(scn.HasKeyword(aragorn, Keyword.DAMAGE)); + + scn.PassCurrentPhaseActions(); + + assertEquals(Phase.REGROUP, scn.GetCurrentPhase()); + assertEquals(Zone.DISCARD, brand.getZone()); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_068_ErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_068_ErrataTests.java index 5aa74f667..374bd81df 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_068_ErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_068_ErrataTests.java @@ -1,8 +1,7 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set03; import com.gempukku.lotro.cards.GenericCardTestHelper; -import com.gempukku.lotro.common.Keyword; -import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.*; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; @@ -10,9 +9,7 @@ import org.junit.Test; import java.util.HashMap; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; public class Card_03_068_ErrataTests { @@ -23,45 +20,46 @@ public class Card_03_068_ErrataTests put("tale", "1_66"); put("doubleshot", "1_38"); - put("saruman", "53_68"); + put("saruman", "73_68"); put("uruk1", "1_151"); put("uruk2", "1_151"); }} ); } - @Test public void SarumanStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { /** - * Set: 1E - * Title: *Saruman - * Subtitle: Keeper of Isengard - * Side: Shadow + * Set: 3 + * Title: Saruman, Keeper of Isengard + * Unique: True + * Side: SHADOW * Culture: Isengard * Twilight Cost: 4 - * Type: Minion + * Type: minion * Subtype: Wizard * Strength: 8 * Vitality: 4 - * Home Site: 4 - * Errata Game Text: Saruman may not take wounds during the archery phase and may not be assigned to a skirmish. - * Maneuver: Exert Saruman to make an Uruk-hai fierce until the regroup phase. - * Response: If an Uruk-hai is about to take a wound, exert Saruman to prevent that wound. + * Site Number: 4 + * Game Text: Saruman may not take wounds during the archery phase and may not be assigned to a skirmish. + * Maneuver: Exert Saruman to make an Uruk-hai fierce until the regroup phase. + * Response: If an Uruk-hai is about to take a wound, discard (or exert) Saruman to prevent that wound. */ //Pre-game setup - GenericCardTestHelper scn = GetScenario(); + var scn = GetScenario(); - PhysicalCardImpl saruman = scn.GetFreepsCard("saruman"); + var saruman = scn.GetFreepsCard("saruman"); assertTrue(saruman.getBlueprint().isUnique()); + assertEquals(Side.SHADOW, saruman.getBlueprint().getSide()); + assertEquals(Culture.ISENGARD, saruman.getBlueprint().getCulture()); + assertEquals(CardType.MINION, saruman.getBlueprint().getCardType()); + assertEquals(Race.WIZARD, saruman.getBlueprint().getRace()); assertEquals(4, saruman.getBlueprint().getTwilightCost()); - assertEquals(8, saruman.getBlueprint().getStrength()); assertEquals(4, saruman.getBlueprint().getVitality()); - assertEquals(4, saruman.getBlueprint().getSiteNumber()); - + assertEquals(4, saruman.getBlueprint().getSiteNumber()); // Change this to getAllyHomeSiteNumbers for allies } @Test diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_091_ErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_091_ErrataTests.java index d1430372c..ce007eb33 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_091_ErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_091_ErrataTests.java @@ -20,6 +20,11 @@ public class Card_03_091_ErrataTests put("cruelty", "73_91"); put("soldier1", "1_271"); put("soldier2", "1_271"); + + put("sam", "1_310"); + put("freeps1", "2_1"); + put("freeps2", "2_2"); + put("freeps3", "2_3"); }}, GenericCardTestHelper.FellowshipSites, GenericCardTestHelper.FOTRFrodo, @@ -31,16 +36,16 @@ public class Card_03_091_ErrataTests public void HisCrueltyandMaliceStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { /** - * Set: 3 - * Title: His Cruelty and Malice - * Unique: False - * Side: SHADOW - * Culture: Sauron - * Twilight Cost: 1 - * Type: condition - * Subtype: Support Area - * Game Text: Regroup: Exert or discard a [sauron] minion to exert a companion. The Free Peoples player may discard the top 2 cards from their draw deck to prevent this. - */ + * Set: 3 + * Title: His Cruelty and Malice + * Unique: False + * Side: SHADOW + * Culture: Sauron + * Twilight Cost: 1 + * Type: condition + * Subtype: Support Area + * Game Text: Regroup: Discard a [sauron] minion to reveal the top 2 cards of your opponent's draw deck. If at least 1 is a Free Peoples cruelty, exert a companion (except the Ring-bearer). Your opponent may discard all revealed Free Peoples cards to prevent this. + */ //Pre-game setup var scn = GetScenario(); @@ -51,12 +56,11 @@ public class Card_03_091_ErrataTests assertEquals(Side.SHADOW, cruelty.getBlueprint().getSide()); assertEquals(Culture.SAURON, cruelty.getBlueprint().getCulture()); assertEquals(CardType.CONDITION, cruelty.getBlueprint().getCardType()); - assertTrue(scn.HasKeyword(cruelty, Keyword.SUPPORT_AREA)); assertEquals(1, cruelty.getBlueprint().getTwilightCost()); } @Test - public void HisCrueltyandMaliceGivesTheChoiceToExertOrDiscard() throws DecisionResultInvalidException, CardNotFoundException { + public void HisCrueltyandMaliceReveals2Cards() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup var scn = GetScenario(); @@ -65,7 +69,17 @@ public class Card_03_091_ErrataTests var soldier2 = scn.GetShadowCard("soldier2"); scn.ShadowMoveCardToSupportArea(cruelty); scn.ShadowMoveCharToTable(soldier1, soldier2); - scn.AddWoundsToChar(soldier1, 1); + + var sam = scn.GetFreepsCard("sam"); + var freeps1 = scn.GetFreepsCard("freeps1"); + var freeps2 = scn.GetFreepsCard("freeps2"); + var freeps3 = scn.GetFreepsCard("freeps3"); + var shadow1 = scn.GetFreepsCard("cruelty"); + var shadow2 = scn.GetFreepsCard("soldier1"); + var shadow3 = scn.GetFreepsCard("soldier2"); + + scn.FreepsMoveCharToTable(sam); + scn.FreepsMoveCardsToTopOfDeck(freeps1, freeps2); scn.StartGame(); @@ -82,6 +96,247 @@ public class Card_03_091_ErrataTests assertEquals(Zone.SHADOW_CHARACTERS, soldier1.getZone()); scn.ShadowChooseCard(soldier1); assertEquals(Zone.DISCARD, soldier1.getZone()); - assertTrue(scn.FreepsDecisionAvailable("Discard")); + assertTrue(scn.FreepsDecisionAvailable("revealed")); + assertEquals(2, scn.GetFreepsCardChoiceCount()); + } + + @Test + public void HisCrueltyRevealing2ShadowCardsDoesNothing() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var cruelty = scn.GetShadowCard("cruelty"); + var soldier1 = scn.GetShadowCard("soldier1"); + var soldier2 = scn.GetShadowCard("soldier2"); + scn.ShadowMoveCardToSupportArea(cruelty); + scn.ShadowMoveCharToTable(soldier1, soldier2); + + var sam = scn.GetFreepsCard("sam"); + var freeps1 = scn.GetFreepsCard("freeps1"); + var freeps2 = scn.GetFreepsCard("freeps2"); + var freeps3 = scn.GetFreepsCard("freeps3"); + var shadow1 = scn.GetFreepsCard("cruelty"); + var shadow2 = scn.GetFreepsCard("soldier1"); + var shadow3 = scn.GetFreepsCard("soldier2"); + + scn.FreepsMoveCharToTable(sam); + scn.FreepsMoveCardsToTopOfDeck(shadow1,shadow2); + + scn.StartGame(); + + scn.SkipToPhase(Phase.ASSIGNMENT); + scn.PassCurrentPhaseActions(); + scn.FreepsDeclineAssignments(); + scn.ShadowDeclineAssignments(); + + //Regroup phase + scn.FreepsPassCurrentPhaseAction(); + assertTrue(scn.ShadowActionAvailable(cruelty)); + scn.ShadowUseCardAction(cruelty); + scn.ShadowChooseCard(soldier1); + + var revealedCards = scn.FreepsGetBPChoices(); + assertTrue(revealedCards.contains(shadow1.getBlueprintId())); + assertTrue(revealedCards.contains(shadow2.getBlueprintId())); + scn.PassCurrentPhaseActions(); + assertFalse(scn.ShadowAnyDecisionsAvailable()); + } + + @Test + public void HisCrueltyRevealing1FreepsExerts() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var cruelty = scn.GetShadowCard("cruelty"); + var soldier1 = scn.GetShadowCard("soldier1"); + var soldier2 = scn.GetShadowCard("soldier2"); + scn.ShadowMoveCardToSupportArea(cruelty); + scn.ShadowMoveCharToTable(soldier1, soldier2); + + var sam = scn.GetFreepsCard("sam"); + var freeps1 = scn.GetFreepsCard("freeps1"); + var freeps2 = scn.GetFreepsCard("freeps2"); + var freeps3 = scn.GetFreepsCard("freeps3"); + var shadow1 = scn.GetFreepsCard("cruelty"); + var shadow2 = scn.GetFreepsCard("soldier1"); + var shadow3 = scn.GetFreepsCard("soldier2"); + + scn.FreepsMoveCharToTable(sam); + scn.FreepsMoveCardsToTopOfDeck(freeps1,shadow1); + + scn.StartGame(); + + scn.SkipToPhase(Phase.ASSIGNMENT); + scn.PassCurrentPhaseActions(); + scn.FreepsDeclineAssignments(); + scn.ShadowDeclineAssignments(); + + //Regroup phase + scn.FreepsPassCurrentPhaseAction(); + assertTrue(scn.ShadowActionAvailable(cruelty)); + scn.ShadowUseCardAction(cruelty); + scn.ShadowChooseCard(soldier1); + + var revealedCards = scn.FreepsGetBPChoices(); + assertTrue(revealedCards.contains(shadow1.getBlueprintId())); + assertTrue(revealedCards.contains(freeps1.getBlueprintId())); + + assertEquals(0, scn.GetWoundsOn(sam)); + scn.PassCurrentPhaseActions(); + + assertTrue(scn.FreepsDecisionAvailable("discard")); + scn.FreepsChooseNo(); + assertEquals(1, scn.GetWoundsOn(sam)); + } + + @Test + public void HisCrueltyRevealing2FreepsExerts() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var cruelty = scn.GetShadowCard("cruelty"); + var soldier1 = scn.GetShadowCard("soldier1"); + var soldier2 = scn.GetShadowCard("soldier2"); + scn.ShadowMoveCardToSupportArea(cruelty); + scn.ShadowMoveCharToTable(soldier1, soldier2); + + var sam = scn.GetFreepsCard("sam"); + var freeps1 = scn.GetFreepsCard("freeps1"); + var freeps2 = scn.GetFreepsCard("freeps2"); + var freeps3 = scn.GetFreepsCard("freeps3"); + var shadow1 = scn.GetFreepsCard("cruelty"); + var shadow2 = scn.GetFreepsCard("soldier1"); + var shadow3 = scn.GetFreepsCard("soldier2"); + + scn.FreepsMoveCharToTable(sam); + scn.FreepsMoveCardsToTopOfDeck(freeps1,freeps2); + + scn.StartGame(); + + scn.SkipToPhase(Phase.ASSIGNMENT); + scn.PassCurrentPhaseActions(); + scn.FreepsDeclineAssignments(); + scn.ShadowDeclineAssignments(); + + //Regroup phase + scn.FreepsPassCurrentPhaseAction(); + assertTrue(scn.ShadowActionAvailable(cruelty)); + scn.ShadowUseCardAction(cruelty); + scn.ShadowChooseCard(soldier1); + + var revealedCards = scn.FreepsGetBPChoices(); + assertTrue(revealedCards.contains(freeps2.getBlueprintId())); + assertTrue(revealedCards.contains(freeps1.getBlueprintId())); + + assertEquals(0, scn.GetWoundsOn(sam)); + scn.PassCurrentPhaseActions(); + + assertTrue(scn.FreepsDecisionAvailable("discard")); + scn.FreepsChooseNo(); + assertEquals(1, scn.GetWoundsOn(sam)); + } + + @Test + public void FreepsDiscarding1RevealedCardPreventsExert() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var cruelty = scn.GetShadowCard("cruelty"); + var soldier1 = scn.GetShadowCard("soldier1"); + var soldier2 = scn.GetShadowCard("soldier2"); + scn.ShadowMoveCardToSupportArea(cruelty); + scn.ShadowMoveCharToTable(soldier1, soldier2); + + var sam = scn.GetFreepsCard("sam"); + var freeps1 = scn.GetFreepsCard("freeps1"); + var freeps2 = scn.GetFreepsCard("freeps2"); + var freeps3 = scn.GetFreepsCard("freeps3"); + var shadow1 = scn.GetFreepsCard("cruelty"); + var shadow2 = scn.GetFreepsCard("soldier1"); + var shadow3 = scn.GetFreepsCard("soldier2"); + + scn.FreepsMoveCharToTable(sam); + scn.FreepsMoveCardsToTopOfDeck(freeps1,shadow1); + + scn.StartGame(); + + scn.SkipToPhase(Phase.ASSIGNMENT); + scn.PassCurrentPhaseActions(); + scn.FreepsDeclineAssignments(); + scn.ShadowDeclineAssignments(); + + //Regroup phase + scn.FreepsPassCurrentPhaseAction(); + assertTrue(scn.ShadowActionAvailable(cruelty)); + scn.ShadowUseCardAction(cruelty); + scn.ShadowChooseCard(soldier1); + + var revealedCards = scn.FreepsGetBPChoices(); + assertTrue(revealedCards.contains(shadow1.getBlueprintId())); + assertTrue(revealedCards.contains(freeps1.getBlueprintId())); + + assertEquals(0, scn.GetWoundsOn(sam)); + scn.PassCurrentPhaseActions(); + + assertTrue(scn.FreepsDecisionAvailable("discard")); + assertEquals(0, scn.GetFreepsDiscardCount()); + assertEquals(Zone.DECK, freeps1.getZone()); + scn.FreepsChooseYes(); + assertEquals(0, scn.GetWoundsOn(sam)); + assertEquals(1, scn.GetFreepsDiscardCount()); + assertEquals(Zone.DISCARD, freeps1.getZone()); + } + + @Test + public void FreepsDiscarding2RevealedCardPreventsExert() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var cruelty = scn.GetShadowCard("cruelty"); + var soldier1 = scn.GetShadowCard("soldier1"); + var soldier2 = scn.GetShadowCard("soldier2"); + scn.ShadowMoveCardToSupportArea(cruelty); + scn.ShadowMoveCharToTable(soldier1, soldier2); + + var sam = scn.GetFreepsCard("sam"); + var freeps1 = scn.GetFreepsCard("freeps1"); + var freeps2 = scn.GetFreepsCard("freeps2"); + var freeps3 = scn.GetFreepsCard("freeps3"); + var shadow1 = scn.GetFreepsCard("cruelty"); + var shadow2 = scn.GetFreepsCard("soldier1"); + var shadow3 = scn.GetFreepsCard("soldier2"); + + scn.FreepsMoveCharToTable(sam); + scn.FreepsMoveCardsToTopOfDeck(freeps1,freeps2); + + scn.StartGame(); + + scn.SkipToPhase(Phase.ASSIGNMENT); + scn.PassCurrentPhaseActions(); + scn.FreepsDeclineAssignments(); + scn.ShadowDeclineAssignments(); + + //Regroup phase + scn.FreepsPassCurrentPhaseAction(); + assertTrue(scn.ShadowActionAvailable(cruelty)); + scn.ShadowUseCardAction(cruelty); + scn.ShadowChooseCard(soldier1); + + var revealedCards = scn.FreepsGetBPChoices(); + assertTrue(revealedCards.contains(freeps2.getBlueprintId())); + assertTrue(revealedCards.contains(freeps1.getBlueprintId())); + + assertEquals(0, scn.GetWoundsOn(sam)); + scn.PassCurrentPhaseActions(); + + assertTrue(scn.FreepsDecisionAvailable("discard")); + assertEquals(0, scn.GetFreepsDiscardCount()); + assertEquals(Zone.DECK, freeps1.getZone()); + assertEquals(Zone.DECK, freeps2.getZone()); + scn.FreepsChooseYes(); + assertEquals(0, scn.GetWoundsOn(sam)); + assertEquals(2, scn.GetFreepsDiscardCount()); + assertEquals(Zone.DISCARD, freeps1.getZone()); + assertEquals(Zone.DISCARD, freeps2.getZone()); } }