diff --git a/.gitignore b/.gitignore
index 093b530a5..9d459d7de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,4 +18,5 @@ logs/*
.idea/
*.iml
remote-sync
-replay
\ No newline at end of file
+replay
+!replay/.placeholder
diff --git a/database/.placeholder b/database/.placeholder
new file mode 100644
index 000000000..e69de29bb
diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/errata/set01-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/errata/set01-errata.json
index a79f3a3c9..dbc6aa7ee 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/errata/set01-errata.json
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/errata/set01-errata.json
@@ -48,7 +48,252 @@
}
]
},
-
+ "51_45": {
+ "title": "*Galadriel",
+ "subtitle": "Lady of Light",
+ "culture": "elven",
+ "cost": 3,
+ "type": "ally",
+ "allyHome": "fellowship,6",
+ "race": "elf",
+ "strength": 3,
+ "vitality": 3,
+ "effects": [
+ {
+ "type": "trigger",
+ "trigger": {
+ "type": "startOfTurn"
+ },
+ "effect": {
+ "type": "heal",
+ "filter": "choose(ally,allyHome(fellowship,6))",
+ "count": "0-3"
+ }
+ },
+ {
+ "type": "activated",
+ "phase": "fellowship",
+ "cost": {
+ "type": "exert",
+ "filter": "self",
+ "times": 1
+ },
+ "effect": {
+ "type": "play",
+ "filter": "choose(elf)",
+ "cost": -1
+ }
+ }
+ ]
+ },
+ "51_80": {
+ "title": "*Ottar",
+ "subtitle": "Man of Laketown",
+ "culture": "gandalf",
+ "cost": 1,
+ "type": "ally",
+ "allyHome": "fellowship,3",
+ "race": "man",
+ "strength": 2,
+ "vitality": 2,
+ "condition": {
+ "type": "canSpot",
+ "filter": "name(Gandalf)"
+ },
+ "effects": {
+ "type": "activated",
+ "phase": "fellowship",
+ "cost": [
+ {
+ "type": "exert",
+ "filter": "self"
+ },
+ {
+ "type": "discardFromHand",
+ "forced": false
+ }
+ ],
+ "effect": {
+ "type": "drawCards"
+ }
+ }
+ },
+ "51_108": {
+ "title": "*No Stranger to the Shadows",
+ "culture": "gondor",
+ "cost": 0,
+ "type": "condition",
+ "keyword": [
+ "stealth"
+ ],
+ "target": "ranger",
+ "effects": {
+ "type": "modifier",
+ "modifier": {
+ "type": "modifyCost",
+ "filter": "site",
+ "amount": -1
+ }
+ }
+ },
+ "51_138": {
+ "title": "Saruman's Snows",
+ "culture": "isengard",
+ "cost": 2,
+ "type": "condition",
+ "keyword": [
+ "spell",
+ "weather"
+ ],
+ "target": "site",
+ "effects": [
+ {
+ "type": "extraCost",
+ "cost": {
+ "type": "exert",
+ "filter": "choose(culture(isengard),minion)"
+ }
+ },
+ {
+ "type": "modifier",
+ "modifier": {
+ "type": "cantPlayPhaseEventsOrPhaseSpecialAbilities",
+ "condition": [
+ {
+ "type": "location",
+ "filter": "hasAttached(self)"
+ },
+ {
+ "type": "canSpot",
+ "filter": "culture(isengard),minion,inSkirmish"
+ }
+ ],
+ "phase": "skirmish"
+ }
+ },
+ {
+ "type": "trigger",
+ "trigger": {
+ "type": "endOfTurn"
+ },
+ "effect": {
+ "type": "discard",
+ "filter": "self"
+ }
+ }
+ ]
+ },
+ "51_139": {
+ "title": "Savagery To Match Their Numbers",
+ "culture": "isengard",
+ "cost": 1,
+ "type": "event",
+ "keyword": "skirmish",
+ "effects": {
+ "type": "event",
+ "effect": [
+ {
+ "type": "modifyStrength",
+ "filter": "choose(uruk-hai)",
+ "memorize": "chosenUrukHai",
+ "amount": 2
+ },
+ {
+ "type": "conditional",
+ "condition": {
+ "type": "canSpot",
+ "count": 5,
+ "filter": "companion"
+ },
+ "effect": [
+ {
+ "type": "addKeyword",
+ "filter": "memory(chosenUrukHai)",
+ "keyword": "fierce",
+ "until": "start(regroup)"
+ }
+ ]
+ }
+ ]
+
+ }
+ },
+ "51_195": {
+ "title": "*Relics of Moria",
+ "culture": "moria",
+ "cost": 1,
+ "type": "condition",
+ "keyword": "support area",
+ "effects": {
+ "type": "activated",
+ "phase": "shadow",
+ "cost": {
+ "type": "removeTwilight",
+ "amount": 2
+ },
+ "effect": {
+ "type": "playCardFromDiscard",
+ "removedTwilight": 2,
+ "filter": "choose(culture(moria),possession)"
+ }
+ }
+ },
+ "51_234": {
+ "title": "*Úlairë Nertëa",
+ "subtitle": "Messenger of Dol Guldur",
+ "culture": "wraith",
+ "cost": 4,
+ "type": "minion",
+ "race": "nazgul",
+ "strength": 9,
+ "vitality": 2,
+ "site": 3,
+ "effects": {
+ "type": "trigger",
+ "trigger": {
+ "type": "played",
+ "filter": "self"
+ },
+ "effect": {
+ "type": "duplicate",
+ "amount": {
+ "type": "forEachYouCanSpot",
+ "filter": "companion",
+ "over": 4
+ },
+ "effect": {
+ "type": "optional",
+ "text": "Would you like to play a wraith minion from your discard?",
+ "effect": {
+ "type": "playCardFromDiscard",
+ "filter": "choose(culture(wraith),minion)"
+ }
+ }
+ }
+ }
+ },
+ "51_248": {
+ "title": "Forces of Mordor",
+ "culture": "sauron",
+ "cost": 0,
+ "type": "event",
+ "keyword": "shadow",
+ "effects": {
+ "type": "event",
+ "cost": {
+ "type": "exert",
+ "filter": "choose(culture(sauron),minion)"
+ },
+ "effect": {
+ "type": "addTwilight",
+ "amount": {
+ "type": "forEachYouCanSpot",
+ "filter": "culture(sauron),orc",
+ "limit": 3
+ }
+ }
+ }
+ },
"51_311": {
"title": "*Sam",
"subtitle": "Son of Hamfast",
@@ -67,13 +312,11 @@
"cost": [
{
"type": "exert",
- "filter": "self",
- "times": 1
+ "filter": "self"
},
{
"type": "exert",
- "filter": "choose(another,companion)",
- "times": 1
+ "filter": "choose(another,companion)"
}
],
"effect": {
@@ -94,10 +337,64 @@
}
]
},
-
-
-
-
-
-
-}
\ No newline at end of file
+ "51_313": {
+ "title": "*Sting",
+ "culture": "shire",
+ "cost": 1,
+ "type": "possession",
+ "possession": "hand weapon",
+ "strength": 2,
+ "target": "name(Frodo)",
+ "effects": {
+ "type": "activated",
+ "phase": [
+ "fellowship",
+ "regroup"
+ ],
+ "cost": {
+ "type": "exert",
+ "filter": "bearer"
+ },
+ "effect": [
+ {
+ "type": "revealrandomcardsfromhand",
+ "hand": "shadowPlayer",
+ "forced": true,
+ "memorize": "revealedCards",
+ "count": 4
+ },
+ {
+ "type": "removeTwilight",
+ "amount": {
+ "type": "cardPhaseLimit",
+ "limit": 2,
+ "amount": {
+ "type": "forEachMatchingInMemory",
+ "memory": "revealedCards",
+ "filter": "orc",
+ "limit": 2
+ }
+ }
+ }
+ ]
+ }
+ },
+ "51_316": {
+ "title": "A Talent for Not Being Seen",
+ "culture": "shire",
+ "cost": 0,
+ "type": "condition",
+ "target": "or(name(Merry),name(Pippin)),not(hasAttached(name(A Talent for Not Being Seen)))",
+ "keyword": [
+ "stealth"
+ ],
+ "effects": {
+ "type": "modifier",
+ "modifier": {
+ "type": "modifyCost",
+ "filter": "site",
+ "amount": -1
+ }
+ }
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/errata/set02-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/errata/set02-errata.json
index 60fa17d6c..47c99486e 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/errata/set02-errata.json
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/errata/set02-errata.json
@@ -1,7 +1,7 @@
{
- "52_32": {
+ "52_32": {
"side": "free_people",
- "cost": 0,
+ "cost": 1,
"strength": 1,
"culture": "Gondor",
"possession": "Hand Weapon",
@@ -17,7 +17,7 @@
"phase": "skirmish",
"condition": {
"type": "canSpot",
- "filter": "bearer,inSkirmishAgainst(Nazgul)",
+ "filter": "bearer,inSkirmishAgainst(Nazgul)"
},
"cost": [
{
@@ -30,7 +30,7 @@
"filter": "self"
}
],
- "effect":[
+ "effect": [
{
"type": "modifyStrength",
"filter": "memory(bearer)",
@@ -42,9 +42,163 @@
"keyword": "damage+1"
}
]
- },
+ }
]
},
-
-
-}
\ No newline at end of file
+ "52_75": {
+ "title": "*Bill Ferny",
+ "subtitle": "Swarthy Sneering Fellow",
+ "culture": "wraith",
+ "cost": 2,
+ "type": "minion",
+ "race": "man",
+ "strength": 4,
+ "vitality": 1,
+ "site": 2,
+ "effects": [
+ {
+ "type": "modifier",
+ "modifier": {
+ "type": "removeKeyword",
+ "filter": "nazgul",
+ "keyword": "roaming"
+ }
+ },
+ {
+ "type": "modifier",
+ "modifier": {
+ "type": "cantBeAssignedToSkirmishAgainst",
+ "condition": {
+ "type": "canSpot",
+ "filter": "hobbit"
+ },
+ "minion": "self",
+ "fpCharacter": "any",
+ "side": "free people"
+ }
+ },
+ {
+ "type": "trigger",
+ "trigger": {
+ "type": "condition",
+ "condition": {
+ "type": "location",
+ "filter": "underground"
+ }
+ },
+ "effect": {
+ "type": "discard",
+ "filter": "self"
+ }
+ }
+ ]
+ },
+ "52_101": {
+ "title": "*Filibert Bolger",
+ "subtitle": "Wily Rascal",
+ "culture": "shire",
+ "cost": 1,
+ "type": "ally",
+ "allyHome": "fellowship,1",
+ "race": "hobbit",
+ "strength": 1,
+ "vitality": 2,
+ "effects": {
+ "type": "activated",
+ "phase": "skirmish",
+ "cost": [
+ {
+ "type": "exert",
+ "filter": "choose(hobbit,companion,not(ring bearer))",
+ "times": 2,
+ "memorize": "exertedHobbit"
+ }
+ ],
+ "effect": {
+ "type": "cancelSkirmish",
+ "filter": "memory(exertedHobbit),infierceskirmish"
+ }
+ }
+ },
+ "52_108": {
+ "title": "*O Elbereth! Gilthoniel!",
+ "culture": "shire",
+ "cost": 1,
+ "type": "condition",
+ "strength": 1,
+ "keyword": "tale",
+ "target": "ring bearer",
+ "effects": {
+ "type": "activated",
+ "phase": "skirmish",
+ "cost": [
+ {
+ "type": "memorize",
+ "filter": "bearer",
+ "memory": "bearer"
+ },
+ {
+ "type": "discard",
+ "filter": "self"
+ }
+ ],
+ "effect": {
+ "type": "choice",
+ "texts": [
+ "Make the Ring-bearer strength +3 if skirmishing a Nazgul",
+ "Take off The One Ring"
+ ],
+ "effects": [
+ {
+ "type": "addmodifier",
+ "modifier": {
+ "type": "modifyStrength",
+ "filter": "memory(bearer),inSkirmishAgainst(nazgul)",
+
+ "amount": 3
+ },
+
+ },
+ {
+ "type": "takeOffRing"
+ }
+ ]
+ }
+ }
+ },
+ "52_121": {
+ "title": "*Gimli",
+ "subtitle": "Dwarf of the Mountain-race",
+ "culture": "dwarven",
+ "cost": 2,
+ "type": "companion",
+ "race": "dwarf",
+ "strength": 6,
+ "vitality": 3,
+ "resistance": 6,
+ "signet": "frodo",
+ "keyword": "damage+1",
+ "effects": [
+ {
+ "type": "modifier",
+ "modifier": {
+ "type": "modifyCost",
+ "filter": "underground,site",
+ "amount": -1
+ }
+ },
+ {
+ "type": "modifier",
+ "modifier": {
+ "type": "modifyStrength",
+ "amount": 1,
+ "condition": {
+ "type": "location",
+ "filter": "underground"
+ },
+ "filter": "self"
+ }
+ }
+ ]
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/errata/set03-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/errata/set03-errata.json
index 0ef29e212..280bcb074 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/errata/set03-errata.json
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/errata/set03-errata.json
@@ -1,7 +1,73 @@
{
- "53_42": {
+ "53_17": {
+ "title": "*Galadriel",
+ "subtitle": "Lady of the Golden Wood",
+ "culture": "elven",
+ "cost": 3,
+ "type": "ally",
+ "allyHome": "fellowship,6",
+ "race": "elf",
+ "strength": 3,
+ "vitality": 3,
+ "effects": [
+ {
+ "type": "trigger",
+ "optional": true,
+ "trigger": {
+ "type": "startOfTurn"
+ },
+ "effect": {
+ "type": "heal",
+ "filter": "choose(another,elf)"
+ }
+ },
+ {
+ "type": "activated",
+ "phase": "fellowship",
+ "cost": {
+ "type": "exert",
+ "filter": "self",
+ "times": 2
+ },
+ "effect": {
+ "type": "playNextSite",
+ "filter": "forest"
+ }
+ }
+ ]
+ },
+ "53_38": {
+ "title": "*Aragorn",
+ "subtitle": "Heir to the White City",
+ "culture": "Gondor",
+ "type": "companion",
+ "race": "Man",
+ "cost": 4,
+ "strength": 8,
+ "vitality": 4,
+ "resistance": 6,
+ "signet": "frodo",
+ "keyword": [
+ "Ranger"
+ ],
+ "effects": {
+ "type": "trigger",
+ "trigger": {
+ "type": "moves"
+ },
+ "condition": {
+ "type": "phase",
+ "phase": "fellowship"
+ },
+ "effect": {
+ "type": "removeTwilight",
+ "amount": 1
+ }
+ }
+ },
+ "53_42": {
"side": "free_people",
- "cost": 0,
+ "cost": 1,
"culture": "Gondor",
"title": "*Horn of Boromir",
"type": "possession",
@@ -12,26 +78,76 @@
"cost": [
{
"type": "exert",
- "filter": "bearer",
- "times": 1
+ "filter": "bearer"
},
{
- "type": "exert",
- "filter": "choose(ally)",
- "memorize": "summonedAlly",
- "times": 1
- }
+ "type": "discard",
+ "filter": "self"
+ }
],
- "effect":[
+ "effect": [
+ {
+ "type": "spot",
+ "filter": "choose(ally)",
+ "memorize": "chosenAlly"
+ },
+ {
+ "type": "addModifier",
+ "modifier": {
+ "type": "modifyStrength",
+ "filter": "memory(chosenAlly)",
+ "amount": 3,
+ },
+ "until": "start(regroup)"
+ },
{
"type": "allyCanParticipateInArcheryFireAndSkirmishes",
- "filter": "memory(summonedAlly)",
+ "filter": "memory(chosenAlly)",
"until": "start(regroup)"
}
]
}
},
-
+ "53_67": {
+ "title": "*The Palantir of Orthanc",
+ "culture": "isengard",
+ "cost": 0,
+ "type": "artifact",
+ "possession": "palantir",
+ "keyword": "support area",
+ "condition": {
+ "type": "canSpot",
+ "filter": "culture(isengard),minion"
+ },
+ "effects": {
+ "type": "activated",
+ "phase": "shadow",
+ "cost": [
+ {
+ "type": "removeTwilight",
+ "amount": 2
+ }
+ ],
+ "condition": {
+ "type": "canSpot",
+ "filter": "culture(isengard),minion",
+ "count": 2,
+ },
+ "effect": [
+ {
+ "type": "revealRandomCardsFromHand",
+ "forced": true,
+ "hand": "fp",
+ "count": 1,
+ "memorize": "revealedCard"
+ },
+ {
+ "type": "putCardsFromHandOnTopOfDeck",
+ "filter": "choose(memory(revealedCard))"
+ }
+ ]
+ }
+ },
"53_68": {
"side": "shadow",
"site": 4,
@@ -44,13 +160,6 @@
"title": "*Saruman",
"type": "minion",
"effects": [
- {
- "type": "modifier",
- "modifier": {
- "type": "cantbeassignedtoskirmish",
- "filter": "self"
- }
- },
{
"type": "modifier",
"modifier": {
@@ -62,6 +171,27 @@
}
}
},
+ {
+ "type": "modifier",
+ "modifier": {
+ "type": "cantbeassignedtoskirmish",
+ "filter": "self"
+ }
+ },
+ {
+ "type": "activated",
+ "phase": "maneuver",
+ "cost": {
+ "type": "exert",
+ "filter": "self"
+ },
+ "effect": {
+ "type": "addKeyword",
+ "filter": "choose(uruk-hai)",
+ "keyword": "fierce",
+ "until": "start(regroup)"
+ }
+ },
{
"type": "activatedTrigger",
"trigger": {
@@ -70,30 +200,105 @@
},
"cost": {
"type": "exert",
- "filter": "self",
- "times": 1
+ "filter": "self"
},
"effect":
{
"type": "preventWound",
"filter": "choose(uruk-hai)"
}
- },
- {
- "type": "activated",
- "phase": "maneuver",
- "cost": {
- "type": "exert",
- "filter": "self",
- "times": 1
- },
- "effect": {
- "type": "addKeyword",
- "filter": "choose(uruk-hai)",
- "keyword": "fierce"
- }
- },
+ }
]
},
-
-}
\ No newline at end of file
+ "53_106": {
+ "title": "*Bill the Pony",
+ "culture": "Shire",
+ "side": "free_people",
+ "cost": 0,
+ "type": "possession",
+ "keyword": [
+ "stealth"
+ ],
+ "target": "name(Sam)",
+ "effects": [
+ {
+ "type": "modifier",
+ "modifier": {
+ "type": "modifyCost",
+ "filter": "site",
+ "amount": -1
+ }
+ },
+ {
+ "type": "trigger",
+ "trigger": {
+ "type": "condition",
+ "condition": {
+ "type": "location",
+ "filter": "underground"
+ }
+ },
+ "effect": {
+ "type": "discard",
+ "filter": "self"
+ }
+ }
+ ]
+ },
+ "53_108": {
+ "title": "Frying Pan",
+ "culture": "Shire",
+ "cost": 1,
+ "type": "possession",
+ "possession": "hand weapon",
+ "strength": 1,
+ "target": "hobbit",
+ "effects": {
+ "type": "activated",
+ "phase": "skirmish",
+ "cost": {
+ "type": "exert",
+ "filter": "bearer"
+ },
+ "effect": {
+ "type": "wound",
+ "filter": "choose(orc,inSkirmishAgainst(bearer))"
+ }
+ }
+ },
+ "53_113": {
+ "title": "*The Shire Countryside",
+ "culture": "shire",
+ "cost": 1,
+ "type": "condition",
+ "keyword": "support area",
+ "condition": {
+ "type": "canSpot",
+ "count": 2,
+ "filter": "culture(shire),companion"
+ },
+ "effects": {
+ "type": "trigger",
+ "optional": true,
+ "trigger": {
+ "type": "removesBurden",
+ "filter": "not(hobbit)"
+ },
+ "condition": {
+ "type": "perPhaseLimit",
+ "limit": 1
+ },
+ "effect": [
+ {
+ "type": "incrementPerPhaseLimit",
+ "limit": 1
+ },
+ {
+ "type": "heal",
+ "count": "0-2",
+ "filter": "choose(companion)"
+ }
+ ]
+ }
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json
new file mode 100644
index 000000000..516757063
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json
@@ -0,0 +1,431 @@
+{
+ "101_1": {
+ "side": "free_people",
+ "culture": "Gondor",
+ "title": "*The Lords of Gondor Have Returned",
+ "type": "condition",
+ "cost": 2,
+ "keyword": "support area",
+ "effects": [
+ {
+ "type": "activated",
+ "phase": "skirmish",
+ "condition": {
+ "type": "canSpot",
+ "filter": "bearer,inSkirmishAgainst(Nazgul)",
+ },
+ "cost": [
+ {
+ "type": "memorize",
+ "filter": "bearer",
+ "memory": "bearer"
+ },
+ {
+ "type": "discard",
+ "filter": "self"
+ }
+ ],
+ "effect":[
+ {
+ "type": "modifyStrength",
+ "filter": "memory(bearer)",
+ "amount": 3
+ },
+ {
+ "type": "addKeyword",
+ "filter": "memory(bearer)",
+ "keyword": "damage+1"
+ }
+ ]
+ },
+ ]
+ },
+
+ "101_2": {
+ "side": "free_people",
+ "culture": "Gondor",
+ "title": "*I Will Not Let the White City Fall",
+ "type": "condition",
+ "cost": 2,
+ "keyword": "support area",
+ "effects": [
+ {
+ "type": "trigger",
+ "trigger": {
+ "type": "losesSkirmish",
+ "filter": "name(Boromir)"
+ },
+ "effect": {
+ "type": "modifyStrength",
+ "filter": "choose(name(Aragorn))",
+ "amount": 2,
+ "until": "start(regroup)"
+ },
+ },
+ {
+ "type": "trigger",
+ "trigger": {
+ "type": "losesSkirmish",
+ "filter": "name(Aragorn)"
+ },
+ "effect": {
+ "type": "modifyStrength",
+ "filter": "choose(name(Boromir))",
+ "amount": 2,
+ "until": "start(regroup)"
+ },
+ }
+ ]
+ },
+
+ "101_3": {
+ "side": "free_people",
+ "culture": "Gondor",
+ "title": "*Boromir",
+ "subtitle": "The Redeemed",
+ "type": "companion",
+ "cost": 3,
+ "race": "man",
+ "strength": 7,
+ "vitality": 3,
+ "resistance": 6,
+ "signet": "aragorn",
+ "effects": [
+ {
+ "type": "modifier",
+ "modifier": {
+ "type": "addKeyword",
+ "filter": "self",
+ "keyword": "defender+1",
+ "condition": {
+ "type": "canSpot",
+ "filter": "companion,culture(shire)",
+ "count": 2
+ }
+ }
+ },
+ {
+ "type": "modifier",
+ "modifier": {
+ "type": "modifyStrength",
+ "filter": "self",
+ "amount": 2,
+ "condition": {
+ "type": "canSpot",
+ "filter": "companion,culture(shire)",
+ "count": 4
+ }
+ }
+ },
+ {
+ "type": "modifier",
+ "modifier": {
+ "type": "addKeyword",
+ "filter": "self",
+ "keyword": "damage+1",
+ "condition": {
+ "type": "canSpot",
+ "filter": "companion,culture(shire)",
+ "count": 4
+ }
+ }
+ },
+
+ ]
+ },
+
+ "101_4": {
+ "side": "free_people",
+ "culture": "Gondor",
+ "title": "*Loud and Clear It Sounds",
+ "type": "condition",
+ "cost": 1,
+ "keyword": "support area",
+ "effects": [
+ {
+ "type": "trigger",
+ "optional": true,
+ "trigger": {
+ "type": "assignedToSkirmish",
+ "filter": "companion,culture(shire)",
+ "side": "shadow",
+ "memorizeAssigned": "assignedHobbit",
+ "memorizeAgainst": "assignedMinion"
+ },
+ "cost": [
+ {
+ "type": "exert",
+ "count": 1,
+ "filter": "choose(companion,culture(gondor))",
+ "memorize": "newAssignee"
+ },
+ {
+ "type": "discard",
+ "filter": "self"
+ }
+ ],
+ "effect": {
+ "type": "replaceInAssignment",
+ "filter": "memory(assignedHobbit)",
+ "with": "memory(newAssignee)"
+ }
+ }
+ ]
+ },
+
+ "101_5": {
+ "side": "free_people",
+ "culture": "Gondor",
+ "title": "Remnant of Numenor",
+ "type": "condition",
+ "cost": 1,
+ "keyword": "support area",
+ "condition": {
+ "type": "canSpot",
+ "filter": "companion,culture(gondor)"
+ },
+ "effects": {
+ "type": "trigger",
+ "optional": true,
+ "trigger": {
+ "type": "discardFromHand",
+ "filter": "any",
+ "player": "shadowPlayer"
+ },
+ "cost": {
+ "type": "addTwilight",
+ "amount": 1
+ },
+ "effect": {
+ "type": "shuffleCardsFromDiscardIntoDrawDeck",
+ "filter": "choose(culture(gondor))",
+ "count": 1
+ }
+ }
+ },
+
+ "101_6": {
+ "side": "shadow",
+ "culture": "Sauron",
+ "title": "*Great Wolf Chief",
+ "type": "minion",
+ "cost": 5,
+ "race": "warg",
+ "strength": 10,
+ "vitality": 3,
+ "site": 6,
+ "keyword": [
+ "tracker",
+ "fierce"
+ ],
+ "effects": [
+ {
+ "type": "modifier",
+ "modifier": {
+ "type": "ModifySiteNumber",
+ "filter": "self",
+ "amount": {
+ "type": "forEachYouCanSpot",
+ "filter": "stealth",
+ "multiplier": -1
+ }
+ }
+ },
+
+ {
+ "type": "trigger",
+ "optional": true,
+ "trigger": {
+ "type": "played",
+ "filter": "another,culture(sauron),warg"
+ },
+ "effect": {
+ "type": "exert",
+ "player": "fp",
+ "filter": "choose(companion)",
+ "count": 1
+ }
+ }
+ ]
+ },
+
+ "101_7": {
+ "side": "shadow",
+ "culture": "Sauron",
+ "title": "Hollin Snarler",
+ "type": "minion",
+ "cost": 3,
+ "race": "warg",
+ "strength": 4,
+ "vitality": 3,
+ "site": 6,
+ "keyword": [
+ "tracker",
+ "fierce"
+ ],
+ "effects": [
+ {
+ "type": "modifier",
+ "modifier": {
+ "type": "ModifySiteNumber",
+ "filter": "self",
+ "amount": {
+ "type": "forEachYouCanSpot",
+ "filter": "stealth",
+ "multiplier": -1
+ }
+ }
+ },
+
+ {
+ "type": "modifier",
+ "modifier": {
+ "type": "ModifyStrength",
+ "filter": "self",
+ "amount": {
+ "type": "forEachYouCanSpot",
+ "filter": "or(stealth,and(companion,wounded))",
+
+ }
+ }
+ },
+
+ ]
+ },
+
+ "101_8": {
+ "side": "shadow",
+ "culture": "Sauron",
+ "title": "Hound of Sauron",
+ "type": "minion",
+ "cost": 2,
+ "race": "warg",
+ "strength": 6,
+ "vitality": 2,
+ "site": 6,
+ "keyword": [
+ "tracker",
+ "fierce"
+ ],
+ "effects": [
+ {
+ "type": "activated",
+ "phase": "skirmish",
+ "condition": {
+ "type": "canSpot",
+ "filter": "bearer,inSkirmishAgainst(Nazgul)",
+ },
+ "cost": [
+ {
+ "type": "memorize",
+ "filter": "bearer",
+ "memory": "bearer"
+ },
+ {
+ "type": "discard",
+ "filter": "self"
+ }
+ ],
+ "effect":[
+ {
+ "type": "modifyStrength",
+ "filter": "memory(bearer)",
+ "amount": 3
+ },
+ {
+ "type": "addKeyword",
+ "filter": "memory(bearer)",
+ "keyword": "damage+1"
+ }
+ ]
+ },
+ ]
+ },
+
+ "101_9": {
+ "side": "shadow",
+ "culture": "Sauron",
+ "title": "*The Hunt is Up!",
+ "type": "condition",
+ "cost": 1,
+ "keyword": "support area",
+ "effects": [
+ {
+ "type": "activated",
+ "phase": "skirmish",
+ "condition": {
+ "type": "canSpot",
+ "filter": "bearer,inSkirmishAgainst(Nazgul)",
+ },
+ "cost": [
+ {
+ "type": "memorize",
+ "filter": "bearer",
+ "memory": "bearer"
+ },
+ {
+ "type": "discard",
+ "filter": "self"
+ }
+ ],
+ "effect":[
+ {
+ "type": "modifyStrength",
+ "filter": "memory(bearer)",
+ "amount": 3
+ },
+ {
+ "type": "addKeyword",
+ "filter": "memory(bearer)",
+ "keyword": "damage+1"
+ }
+ ]
+ },
+ ]
+ },
+
+ "101_10": {
+ "side": "shadow",
+ "culture": "Sauron",
+ "title": "I See You",
+ "type": "event",
+ "cost": 1,
+ "keyword": "assignment",
+ "effects": [
+ {
+ "type": "activated",
+ "phase": "skirmish",
+ "condition": {
+ "type": "canSpot",
+ "filter": "bearer,inSkirmishAgainst(Nazgul)",
+ },
+ "cost": [
+ {
+ "type": "memorize",
+ "filter": "bearer",
+ "memory": "bearer"
+ },
+ {
+ "type": "discard",
+ "filter": "self"
+ }
+ ],
+ "effect":[
+ {
+ "type": "modifyStrength",
+ "filter": "memory(bearer)",
+ "amount": 3
+ },
+ {
+ "type": "addKeyword",
+ "filter": "memory(bearer)",
+ "keyword": "damage+1"
+ }
+ ]
+ },
+ ]
+ },
+
+
+
+}
\ No newline at end of file
diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js.inc b/gemp-lotr/gemp-lotr-async/src/main/web/js.inc
index caca3b4a3..ea0607081 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/web/js.inc
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/js.inc
@@ -22,6 +22,7 @@
+
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 9501123bf..a82ec0cf3 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
@@ -114,4 +114,5 @@ var PCCards = {
'83_188': 'https://i.lotrtcgpc.net/errata/xlist/63_188.jpg',
'85_64': 'https://i.lotrtcgpc.net/errata/xlist/65_064.jpg',
-}
\ No newline at end of file
+}
+}
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/set101-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/set101-rarity.txt
index e69de29bb..743e3b02c 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/set101-rarity.txt
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/set101-rarity.txt
@@ -0,0 +1,47 @@
+101S1
+101S2
+101S3
+101S4
+101S5
+101S6
+101S7
+101S8
+101S9
+101S10
+101S11
+101S12
+101S13
+101S14
+101S15
+101S16
+101S17
+101S18
+101S19
+101S20
+101S21
+101S22
+101S23
+101S24
+101S25
+101S26
+101S27
+101S28
+101S29
+101S30
+101S31
+101S32
+101S33
+101S34
+101S35
+101S36
+101S37
+101S38
+101S39
+101S40
+101S41
+101S42
+101S43
+101S44
+101S45
+101S46
+101S47
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java
index 8a17b3b19..3e02e103e 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java
@@ -29,6 +29,7 @@ public class EffectAppenderFactory {
effectAppenderProducers.put("wound", new Wound());
effectAppenderProducers.put("heal", new Heal());
effectAppenderProducers.put("replaceinskirmish", new ReplaceInSkirmish());
+ effectAppenderProducers.put("replaceinassignment", new ReplaceInAssignment());
effectAppenderProducers.put("canttakemorewoundsthan", new CantTakeMoreWoundsThan());
effectAppenderProducers.put("canttakewounds", new CantTakeWounds());
effectAppenderProducers.put("choice", new Choice());
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayNextSite.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayNextSite.java
index 295da5510..0829dda5b 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayNextSite.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayNextSite.java
@@ -2,10 +2,14 @@ package com.gempukku.lotro.cards.build.field.effect.appender;
import com.gempukku.lotro.cards.build.ActionContext;
import com.gempukku.lotro.cards.build.CardGenerationEnvironment;
+import com.gempukku.lotro.cards.build.FilterableSource;
import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
import com.gempukku.lotro.cards.build.field.FieldUtils;
import com.gempukku.lotro.cards.build.field.effect.EffectAppender;
import com.gempukku.lotro.cards.build.field.effect.EffectAppenderProducer;
+import com.gempukku.lotro.common.Filterable;
+import com.gempukku.lotro.filters.Filter;
+import com.gempukku.lotro.filters.Filters;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.game.state.LotroGame;
import com.gempukku.lotro.logic.actions.CostToEffectAction;
@@ -16,23 +20,44 @@ import org.json.simple.JSONObject;
public class PlayNextSite implements EffectAppenderProducer {
@Override
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
- FieldUtils.validateAllowedFields(effectObject, "memorize");
-
+ FieldUtils.validateAllowedFields(effectObject, "filter", "memorize");
+ final String filter = FieldUtils.getString(effectObject.get("filter"), "filter", "any");
final String memorize = FieldUtils.getString(effectObject.get("memorize"), "memorize");
+ final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
+
return new DelayedAppender() {
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
final LotroGame game = actionContext.getGame();
- final int currentSiteNumber = game.getGameState().getCurrentSiteNumber();
- final PhysicalCard nextSite = game.getGameState().getSite(currentSiteNumber + 1);
- return currentSiteNumber < 9
- && (nextSite == null || game.getModifiersQuerying().canReplaceSite(game, actionContext.getPerformingPlayer(), nextSite));
+ final int nextSiteNumber = game.getGameState().getCurrentSiteNumber() + 1;
+ final PhysicalCard nextSite = game.getGameState().getSite(nextSiteNumber);
+ final Filterable filterable = filterableSource.getFilterable(actionContext);
+ final String playerId = actionContext.getPerformingPlayer();
+
+ if (nextSiteNumber > 9 || nextSiteNumber < 1)
+ return false;
+
+ if (nextSite != null && !game.getModifiersQuerying().canReplaceSite(game, actionContext.getPerformingPlayer(), nextSite))
+ return false;
+
+ if (game.getFormat().isOrderedSites()) {
+ Filter printedSiteNumber = new Filter() {
+ @Override
+ public boolean accepts(LotroGame game, PhysicalCard physicalCard) {
+ return physicalCard.getBlueprint().getSiteNumber() == nextSiteNumber;
+ }
+ };
+ return Filters.filter(game.getGameState().getAdventureDeck(playerId), game, Filters.and(filterable, printedSiteNumber)).size() > 0;
+ } else {
+ return Filters.filter(game.getGameState().getAdventureDeck(playerId), game, filterable).size() > 0;
+ }
}
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
- return new PlayNextSiteEffect(action, actionContext.getPerformingPlayer()) {
+ final Filterable filterable = filterableSource.getFilterable(actionContext);
+ return new PlayNextSiteEffect(action, actionContext.getPerformingPlayer(), filterable) {
@Override
protected void sitePlayedCallback(PhysicalCard site) {
if (memorize != null) {
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/ReplaceInAssignment.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/ReplaceInAssignment.java
new file mode 100644
index 000000000..858fef97e
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/ReplaceInAssignment.java
@@ -0,0 +1,47 @@
+package com.gempukku.lotro.cards.build.field.effect.appender;
+
+import com.gempukku.lotro.cards.build.ActionContext;
+import com.gempukku.lotro.cards.build.CardGenerationEnvironment;
+import com.gempukku.lotro.cards.build.FilterableSource;
+import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
+import com.gempukku.lotro.cards.build.field.FieldUtils;
+import com.gempukku.lotro.cards.build.field.effect.EffectAppender;
+import com.gempukku.lotro.cards.build.field.effect.EffectAppenderProducer;
+import com.gempukku.lotro.cards.build.field.effect.appender.resolver.CardResolver;
+import com.gempukku.lotro.game.PhysicalCard;
+import com.gempukku.lotro.logic.actions.CostToEffectAction;
+import com.gempukku.lotro.logic.effects.ReplaceFpCharacterInAssignmentEffect;
+import com.gempukku.lotro.logic.timing.DoNothingEffect;
+import com.gempukku.lotro.logic.timing.Effect;
+import org.json.simple.JSONObject;
+
+public class ReplaceInAssignment implements EffectAppenderProducer {
+ @Override
+ public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
+ FieldUtils.validateAllowedFields(effectObject, "filter", "with");
+
+ final String filter = FieldUtils.getString(effectObject.get("filter"), "filter");
+ final String with = FieldUtils.getString(effectObject.get("with"), "with");
+
+ MultiEffectAppender result = new MultiEffectAppender();
+ result.addEffectAppender(
+ CardResolver.resolveCard(filter, "_oldAssignee", "you", "Choose assigned character to replace", environment));
+ result.addEffectAppender(
+ CardResolver.resolveCard(with, "_newAssignee", "you", "Choose character to replace with in assignment", environment));
+ result.addEffectAppender(
+ new DelayedAppender() {
+ @Override
+ protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
+ final PhysicalCard oldCard = actionContext.getCardFromMemory("_oldAssignee");
+ final PhysicalCard newCard = actionContext.getCardFromMemory("_newAssignee");
+ if (oldCard != null && newCard != null)
+ return new ReplaceFpCharacterInAssignmentEffect(newCard, oldCard);
+ else
+ return new DoNothingEffect();
+ }
+ });
+
+ return result;
+ }
+
+}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java
index 851190fb0..291c95543 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java
@@ -41,6 +41,7 @@ public class FilterFactory {
simpleFilters.put("unwounded", (actionContext) -> Filters.unwounded);
simpleFilters.put("exhausted", (actionContext) -> Filters.exhausted);
simpleFilters.put("inskirmish", (actionContext) -> Filters.inSkirmish);
+ simpleFilters.put("infierceskirmish", (actionContext) -> Filters.inFierceSkirmish);
simpleFilters.put("inplay", (actionContext) -> Filters.inPlay);
simpleFilters.put("notassignedtoskirmish",
(actionContext) -> Filters.notAssignedToSkirmish);
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java
index 076147941..dc6529c9f 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java
@@ -4,6 +4,7 @@ import com.gempukku.lotro.cards.build.CardGenerationEnvironment;
import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
import com.gempukku.lotro.cards.build.ModifierSource;
import com.gempukku.lotro.cards.build.field.FieldUtils;
+import com.gempukku.lotro.logic.modifiers.FreePeoplePlayerMayNotAssignCharacterModifier;
import org.json.simple.JSONObject;
import java.util.HashMap;
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/DiscardFromHand.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/DiscardFromHand.java
index c5189bd66..5cf299eb5 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/DiscardFromHand.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/DiscardFromHand.java
@@ -1,22 +1,23 @@
package com.gempukku.lotro.cards.build.field.effect.trigger;
-import com.gempukku.lotro.cards.build.ActionContext;
-import com.gempukku.lotro.cards.build.CardGenerationEnvironment;
-import com.gempukku.lotro.cards.build.FilterableSource;
-import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
+import com.gempukku.lotro.cards.build.*;
import com.gempukku.lotro.cards.build.field.FieldUtils;
+import com.gempukku.lotro.cards.build.field.effect.appender.resolver.PlayerResolver;
import com.gempukku.lotro.logic.timing.TriggerConditions;
import com.gempukku.lotro.logic.timing.results.DiscardCardFromHandResult;
+import com.gempukku.lotro.logic.timing.results.DiscardCardsFromPlayResult;
import org.json.simple.JSONObject;
public class DiscardFromHand implements TriggerCheckerProducer {
@Override
public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
- FieldUtils.validateAllowedFields(value, "filter", "memorize");
+ FieldUtils.validateAllowedFields(value, "filter", "memorize", "player");
final String filter = FieldUtils.getString(value.get("filter"), "filter", "any");
final String memorize = FieldUtils.getString(value.get("memorize"), "memorize");
+ final String player = FieldUtils.getString(value.get("player"), "player");
+ PlayerSource playerSource = (player != null) ? PlayerResolver.resolvePlayer(player, environment) : null;
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
return new TriggerChecker() {
@@ -27,8 +28,14 @@ public class DiscardFromHand implements TriggerCheckerProducer {
@Override
public boolean accepts(ActionContext actionContext) {
- final boolean result = TriggerConditions.forEachDiscardedFromHand(actionContext.getGame(), actionContext.getEffectResult(),
+ boolean result = TriggerConditions.forEachDiscardedFromHand(actionContext.getGame(), actionContext.getEffectResult(),
filterableSource.getFilterable(actionContext));
+ if (result && playerSource != null) {
+ // Need to check if it was that player discarding the card
+ final String performingPlayer = ((DiscardCardFromHandResult) actionContext.getEffectResult()).getSource().getOwner();
+ if (performingPlayer == null || !performingPlayer.equals(playerSource.getPlayer(actionContext)))
+ result = false;
+ }
if (result && memorize != null) {
actionContext.setCardMemory(memorize, ((DiscardCardFromHandResult) actionContext.getEffectResult()).getDiscardedCard());
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RemovesBurden.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RemovesBurden.java
new file mode 100644
index 000000000..37a425982
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RemovesBurden.java
@@ -0,0 +1,33 @@
+package com.gempukku.lotro.cards.build.field.effect.trigger;
+
+import com.gempukku.lotro.cards.build.ActionContext;
+import com.gempukku.lotro.cards.build.CardGenerationEnvironment;
+import com.gempukku.lotro.cards.build.FilterableSource;
+import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
+import com.gempukku.lotro.cards.build.field.FieldUtils;
+import com.gempukku.lotro.logic.timing.TriggerConditions;
+import org.json.simple.JSONObject;
+
+public class RemovesBurden implements TriggerCheckerProducer {
+ @Override
+ public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
+ FieldUtils.validateAllowedFields(value, "filter");
+
+ String filter = FieldUtils.getString(value.get("filter"), "filter", "any");
+
+ final FilterableSource sourceFilter = environment.getFilterFactory().generateFilter(filter, environment);
+
+ return new TriggerChecker() {
+ @Override
+ public boolean accepts(ActionContext actionContext) {
+ return TriggerConditions.removedBurden(actionContext.getGame(), actionContext.getEffectResult(),
+ sourceFilter.getFilterable(actionContext));
+ }
+
+ @Override
+ public boolean isBefore() {
+ return false;
+ }
+ };
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java
index ba8cf0962..eb7a61b36 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java
@@ -39,6 +39,7 @@ public class TriggerCheckerFactory {
triggerCheckers.put("discardfromhand", new DiscardFromHand());
triggerCheckers.put("putsonring", new PutsOnRing());
triggerCheckers.put("addsburden", new AddsBurden());
+ triggerCheckers.put("removesburden", new RemovesBurden());
triggerCheckers.put("addsthreat", new AddsThreat());
triggerCheckers.put("transferred", new Transferred());
triggerCheckers.put("killed", new Killed());
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java
index 6513aa6cb..55deea50c 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java
@@ -431,6 +431,18 @@ public class Filters {
}
};
+ public static final Filter inFierceSkirmish = new Filter() {
+ @Override
+ public boolean accepts(LotroGame game, PhysicalCard physicalCard) {
+ Skirmish skirmish = game.getGameState().getSkirmish();
+ if (skirmish != null && game.getGameState().isFierceSkirmishes()) {
+ return (skirmish.getFellowshipCharacter() == physicalCard)
+ || skirmish.getShadowCharacters().contains(physicalCard);
+ }
+ return false;
+ }
+ };
+
public static final Filter inPlay = new Filter() {
@Override
public boolean accepts(LotroGame game, PhysicalCard physicalCard) {
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/PlayNextSiteEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/PlayNextSiteEffect.java
index b792bb307..c8ad311a9 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/PlayNextSiteEffect.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/PlayNextSiteEffect.java
@@ -1,5 +1,6 @@
package com.gempukku.lotro.logic.effects;
+import com.gempukku.lotro.common.Filterable;
import com.gempukku.lotro.game.state.LotroGame;
import com.gempukku.lotro.logic.timing.Action;
@@ -8,6 +9,10 @@ public class PlayNextSiteEffect extends PlaySiteEffect {
super(action, playerId, null, 0);
}
+ public PlayNextSiteEffect(Action action, String playerId, Filterable... extraSiteFilters) {
+ super(action, playerId, null, 0, extraSiteFilters);
+ }
+
@Override
protected int getSiteNumberToPlay(LotroGame game) {
return game.getGameState().getCurrentSiteNumber() + 1;
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java
index d7c45f41e..a89701c00 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java
@@ -108,6 +108,14 @@ public class TriggerConditions {
return false;
}
+ public static boolean removedBurden(LotroGame game, EffectResult effectResult, Filterable... sourceFilters) {
+ if (effectResult.getType() == EffectResult.Type.REMOVE_BURDEN) {
+ RemoveBurdenResult burdenResult = (RemoveBurdenResult) effectResult;
+ return (Filters.and(sourceFilters).accepts(game, burdenResult.getSource()));
+ }
+ return false;
+ }
+
public static boolean addedThreat(LotroGame game, EffectResult effectResult, Filterable... sourceFilters) {
if (effectResult.getType() == EffectResult.Type.ADD_THREAT) {
AddThreatResult burdenResult = (AddThreatResult) effectResult;
diff --git a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json
index da5ea02b7..ef78a1674 100644
--- a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json
+++ b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json
@@ -1,4 +1,11 @@
[
+ {
+ "name": "Debug",
+ "code":"debug_hall",
+ "sites": "SPECIAL",
+ "maximumSameName":100,
+ "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 51, 52, 53, 101]
+ },
{
"name":"Fellowship block",
"code":"fotr_block",
@@ -11,7 +18,6 @@
"code":"pc_fotr_block",
"sites":"FELLOWSHIP",
"cancelRingBearerSkirmish":true,
- "hall":false,
"set":[1, 2, 3, 51, 52, 53, 101],
"banned":["1_40","1_311","2_32","3_42","3_68",]
},
@@ -62,7 +68,8 @@
"code":"ttt_block",
"sites":"TWO_TOWERS",
"cancelRingBearerSkirmish":true,
- "set":[4, 5, 6]
+ "set":[4, 5, 6],
+ "hall":false
},
{
"name":"Towers block - Set 4",
@@ -86,14 +93,16 @@
"sites":"TWO_TOWERS",
"cancelRingBearerSkirmish":true,
"banned":["1_40", "1_45", "1_80", "1_108", "1_139", "1_234", "1_248", "1_313", "2_32", "2_101", "2_108", "3_38", "3_42", "3_68", "4_192"],
- "set":[1, 2, 3, 4, 5, 6]
+ "set":[1, 2, 3, 4, 5, 6],
+ "hall":false
},
{
"name": "Anything goes",
"code":"rev_tow_sta",
"sites": "SPECIAL",
"cancelRingBearerSkirmish":true,
- "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
+ "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21],
+ "hall":false
},
{
"name":"Towers standard - Sets 1-4",
@@ -137,7 +146,8 @@
"sites":"KING",
"cancelRingBearerSkirmish":true,
"banned":["1_40", "1_45","1_80", "1_108", "1_139", "1_195", "1_234", "1_248", "1_313", "2_32", "2_101", "2_108", "3_38", "3_42", "3_67", "3_68", "3_106", "3_108"],
- "set":[1, 2, 3, 4, 5, 6, 7]
+ "set":[1, 2, 3, 4, 5, 6, 7],
+ "hall":false
},
{
"name":"King block",
@@ -145,7 +155,8 @@
"sites":"KING",
"cancelRingBearerSkirmish":true,
"restricted":["7_49"],
- "set":[7, 8, 10]
+ "set":[7, 8, 10],
+ "hall":false
},
{
"name":"King block - Set 7",
@@ -169,14 +180,13 @@
"name":"Movie block",
"code":"movie",
"sites":"KING",
- "banned":["8_1", "3_38", "3_106", "1_40", "2_32", "1_248", "3_108", "1_45", "7_96", "3_42", "10_2", "10_91", "1_108", "1_80", "3_67", "1_195", "3_68", "1_139", "7_49", "1_313", "1_234"],
+ "banned":["1_40", "1_45", "1_80", "1_108", "1_139", "1_195", "1_234", "1_248", "1_313", "2_32", "3_106", "3_108", "3_38", "3_42", "3_67", "3_68", "7_49", "7_96", "8_1", "10_2", "10_91"],
"set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
},
{
"name":"PC-Movie",
"code":"pc_movie",
"sites":"KING",
- "hall":false,
"set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 51, 52, 53, 101],
"banned":["1_40","1_311","2_32","3_42","3_68", "1_45", "1_80", "1_108", "1_139", "1_195", "1_234", "1_248", "1_313", "3_106", "3_108", "3_38", "3_67", "7_49", "7_96", "8_1", "10_2", "10_91"],
},
@@ -218,34 +228,39 @@
"code":"war_block",
"sites":"SHADOWS",
"restricted":["11_132", "11_100"],
- "set":[11, 12, 13]
+ "set":[11, 12, 13],
+ "hall":false
},
{
"name":"Hunter block",
"code":"hunter_block",
"sites":"SHADOWS",
- "set":[15, 17, 18]
+ "set":[15, 17, 18],
+ "hall":false
},
{
"name":"War of the Ring standard",
"code":"war_standard",
"sites":"SHADOWS",
"banned":["4_73", "4_276", "4_304", "7_49", "8_1", "10_2", "10_11", "10_91", "11_31", "11_100", "11_132"],
- "set":[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
+ "set":[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
+ "hall":false
},
{
"name":"Standard",
"code":"standard",
"sites":"SHADOWS",
"banned":["0_1-19", "0_21", "0_22", "0_30-47", "0_62-67", "8_1", "13_188", "11_114", "11_31", "10_11", "15_64", "10_2", "10_91", "11_132", "7_49", "11_100"],
- "set":[0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
+ "set":[0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
+ "hall":false
},
{
"name":"Open",
"code":"open",
"sites":"SHADOWS",
"restricted":["1_248", "7_49", "10_2", "10_91", "11_100", "11_132"],
- "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
+ "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
+ "hall":false
},
{
"name":"Expanded",
@@ -259,7 +274,6 @@
"name":"PC-Expanded",
"code":"pc_expanded",
"sites":"SHADOWS",
- "hall":false,
"banned":["1_40","1_311","2_32","3_42","3_68","1_45", "1_138", "1_234", "1_313", "1_316", "2_121", "3_17", "3_38", "3_67", "3_108", "3_113", "4_73", "7_49", "8_1", "10_2", "10_11", "10_91", "11_31", "11_100", "11_132"],
"restricted":["1_80", "1_108", "1_139", "1_195", "1_248", "2_75", "3_106", "4_276", "4_304"],
"set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 51, 52, 53, 101]
@@ -296,7 +310,8 @@
"banned":["1_138", "1_311", "1_316", "1_331", "1_338", "1_354", "1_355", "1_360", "2_14", "2_75", "3_1", "3_113", "4_73", "4_338", "4_355", "4_357", "7_190", "8_20", "10_11",
"8_1", "8_3", "3_38", "3_106", "1_40", "2_32", "1_248", "3_108", "1_45", "7_96", "3_42", "10_2", "10_91", "1_108", "1_80", "3_67", "1_195", "3_68", "1_139", "7_49", "1_313", "1_234", "7_156"],
"valid":["0_56-60"],
- "set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ "set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+ "hall":false
},
{
"name":"Movie block, no GLR (10R11)",
@@ -330,7 +345,7 @@
"limit3":[],
"set":[30, 31],
"restrictedName":["Gandalf", "Bilbo"],
- "hall":true
+ "hall":false
},
{
"name": "Hobbit: The Clouds Burst",
@@ -342,7 +357,7 @@
"limit3": [],
"set": [30, 32],
"restrictedName": ["Gandalf", "Bilbo"],
- "hall": true
+ "hall":false
},
{
"name": "Hobbit: Fire and Water",
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 2131b58ac..f2a88f690 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
@@ -168,8 +168,8 @@ public class GenericCardTestHelper extends AbstractAtTest {
public List FreepsGetADParamAsList(String paramName) { return GetADParamAsList(P1, paramName); }
public List ShadowGetADParamAsList(String paramName) { return GetADParamAsList(P2, paramName); }
public List GetADParamAsList(String playerID, String paramName) { return Arrays.asList(GetAwaitingDecisionParam(playerID, paramName)); }
- public Object FreepsGetADParam(String paramName) { return GetAwaitingDecisionParam(P1, paramName); }
- public Object ShadowGetADParam(String paramName) { return GetAwaitingDecisionParam(P2, paramName); }
+ public String[] FreepsGetADParam(String paramName) { return GetAwaitingDecisionParam(P1, paramName); }
+ public String[] ShadowGetADParam(String paramName) { return GetAwaitingDecisionParam(P2, paramName); }
public String[] GetAwaitingDecisionParam(String playerID, String paramName) {
AwaitingDecision decision = _userFeedback.getAwaitingDecision(playerID);
return decision.getDecisionParameters().get(paramName);
@@ -180,6 +180,8 @@ public class GenericCardTestHelper extends AbstractAtTest {
return decision.getDecisionParameters();
}
+ //public boolean HasItemIn
+
public void FreepsUseCardAction(String name) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, name)); }
public void FreepsUseCardAction(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, "Use " + GameUtils.getFullName(card))); }
public void ShadowUseCardAction(String name) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, name)); }
@@ -268,6 +270,15 @@ public class GenericCardTestHelper extends AbstractAtTest {
Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.SUPPORT));
}
+ public void FreepsMoveCardToDiscard(String cardName) { FreepsMoveCardToSupportArea(GetFreepsCard(cardName)); }
+ public void FreepsMoveCardToDiscard(PhysicalCardImpl...cards) {
+ Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.DISCARD));
+ }
+ public void ShadowMoveCardToDiscard(String cardName) { ShadowMoveCardToSupportArea(GetShadowCard(cardName)); }
+ public void ShadowMoveCardToDiscard(PhysicalCardImpl...cards) {
+ Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.DISCARD));
+ }
+
public void MoveCardToZone(String player, PhysicalCardImpl card, Zone zone) {
if(card.getZone() != null)
{
@@ -326,11 +337,21 @@ public class GenericCardTestHelper extends AbstractAtTest {
}
- public void FreepsAssignToMinion(String name, String target) throws DecisionResultInvalidException { FreepsAssignToMinion(GetFreepsCard(name), GetShadowCard(target)); }
- public void FreepsAssignToMinion(PhysicalCardImpl comp, PhysicalCardImpl minion) throws DecisionResultInvalidException {
- playerDecided(P1, comp.getCardId() + " " + minion.getCardId());
+ public void FreepsAssignToMinions(PhysicalCardImpl comp, PhysicalCardImpl...minions) throws DecisionResultInvalidException { AssignToMinions(P1, comp, minions); }
+ public void ShadowAssignToMinions(PhysicalCardImpl comp, PhysicalCardImpl...minions) throws DecisionResultInvalidException { AssignToMinions(P2, comp, minions); }
+ public void AssignToMinions(String player, PhysicalCardImpl comp, PhysicalCardImpl...minions) throws DecisionResultInvalidException {
+ String result = comp.getCardId() + "";
+
+ for (PhysicalCardImpl minion : minions) {
+ result += " " + minion.getCardId();
+ }
+
+ playerDecided(player, result);
}
- public void FreepsAssignToMinions(PhysicalCardImpl[]... groups) throws DecisionResultInvalidException {
+
+ public void FreepsAssignToMinions(PhysicalCardImpl[]...groups) throws DecisionResultInvalidException { AssignToMinions(P1, groups); }
+ public void ShadowAssignToMinions(PhysicalCardImpl[]...groups) throws DecisionResultInvalidException { AssignToMinions(P2, groups); }
+ public void AssignToMinions(String player, PhysicalCardImpl[]...groups) throws DecisionResultInvalidException {
String result = "";
for (PhysicalCardImpl[] group : groups) {
@@ -342,9 +363,10 @@ public class GenericCardTestHelper extends AbstractAtTest {
result += ",";
}
- playerDecided(P1, result);
+ playerDecided(player, result);
}
+
public List FreepsGetAttachedCards(String name) { return GetAttachedCards(GetFreepsCard(name)); }
public List GetAttachedCards(PhysicalCardImpl card) {
return (List)(List>)_game.getGameState().getAttachedCards(card);
@@ -384,6 +406,11 @@ public class GenericCardTestHelper extends AbstractAtTest {
{
return _game.getModifiersQuerying().getStrength(_game, card);
}
+ public int GetVitality(PhysicalCardImpl card)
+ {
+ return _game.getModifiersQuerying().getVitality(_game, card);
+ }
+ public int GetSiteNumber(PhysicalCardImpl card) { return _game.getModifiersQuerying().getMinionSiteNumber(_game, card); }
public boolean HasKeyword(PhysicalCardImpl card, Keyword keyword)
{
@@ -396,9 +423,15 @@ public class GenericCardTestHelper extends AbstractAtTest {
_game.getModifiersEnvironment().addUntilEndOfTurnModifier(mod);
}
+ public void FreepsChoose(String choice) throws DecisionResultInvalidException { playerDecided(P1, choice); }
+ public void ShadowChoose(String choice) throws DecisionResultInvalidException { playerDecided(P2, choice); }
+
public void FreepsChooseToMove() throws DecisionResultInvalidException { playerDecided(P1, "0"); }
public void FreepsChooseToStay() throws DecisionResultInvalidException { playerDecided(P1, "1"); }
+ public boolean FreepsHasOptionalTriggerAvailable() throws DecisionResultInvalidException { return FreepsDecisionAvailable("Optional Response"); }
+ public boolean ShadowHasOptionalTriggerAvailable() throws DecisionResultInvalidException { return ShadowDecisionAvailable("Optional Response"); }
+
public void FreepsAcceptOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P1, "0"); }
public void FreepsDeclineOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P1, "1"); }
public void ShadowAcceptOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, "0"); }
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set1/Card1_011Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set1/Card1_011Tests.java
new file mode 100644
index 000000000..fd28da7c3
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set1/Card1_011Tests.java
@@ -0,0 +1,55 @@
+package com.gempukku.lotro.cards.official.set1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+
+// Tidings of Erebor
+public class Card1_011Tests
+{
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("farin", "1_11");
+
+ put("goblin", "1_178");
+ }}
+ );
+ }
+
+ @Test
+ public void FarinStrengthBoostWhileSkirmishingOrc() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl farin = scn.GetFreepsCard("farin");
+ scn.FreepsMoveCharToTable(farin);
+
+ PhysicalCardImpl goblin = scn.GetShadowCard("goblin");
+ scn.ShadowMoveCharToTable(goblin);
+
+ scn.StartGame();
+ scn.FreepsSkipCurrentPhaseAction();
+
+ scn.SkipToPhase(Phase.ASSIGNMENT);
+
+ scn.SkipCurrentPhaseActions();
+
+ scn.FreepsAssignToMinions(farin, goblin);
+ scn.FreepsResolveSkirmish(farin);
+
+ assertEquals(7, scn.GetStrength(farin));
+
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java
new file mode 100644
index 000000000..2b57ef072
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java
@@ -0,0 +1,198 @@
+package com.gempukku.lotro.cards.unofficial.pc.errata.set1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+import java.util.*;
+
+import static junit.framework.Assert.assertEquals;
+
+public class Elrond_LoRErrataTests
+{
+
+ protected GenericCardTestHelper GetSimpleDeckScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("elrond", "51_40");
+ put("randomcard", "1_3");
+ }}
+ );
+ }
+
+ protected GenericCardTestHelper GetSimpleSpotScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("elrond", "51_40");
+ put("gandalf", "1_72");
+ put("arwen", "1_30");
+ }}
+ );
+ }
+
+ protected GenericCardTestHelper GetHome3AllyScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("elrond", "51_40");
+ put("allyHome3_1", "1_60");
+ put("allyHome3_2", "1_27"); // tharin
+ put("allyHome6_1", "1_56");
+ put("allyHome6_2", "1_57");
+ }}
+ );
+ }
+
+ @Test
+ public void ElrondStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 1E
+ * Title: *Elrond
+ * Subtitle: Lord of Rivendell
+ * Side: Free Peoples
+ * Culture: Elven
+ * Twilight Cost: 4
+ * Type: Ally
+ * Subtype: Elf
+ * Home: 3
+ * Strength: 8
+ * Vitality: 4
+ * Errata Game Text: To play, spot Gandalf or an Elf.
+ * At the start of each of your turns, heal up to 3 allies whose home is site 3.
+ * Fellowship: Exert Elrond twice (or once if you can spot 2 other [elven] allies) to draw a card.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetSimpleDeckScenario();
+
+ PhysicalCardImpl elrond = scn.GetFreepsCard("elrond");
+
+ assertTrue(elrond.getBlueprint().isUnique());
+ assertEquals(4, elrond.getBlueprint().getTwilightCost());
+
+ assertEquals(8, elrond.getBlueprint().getStrength());
+ assertEquals(4, elrond.getBlueprint().getVitality());
+ assertEquals(3, Arrays.stream(elrond.getBlueprint().getAllyHomeSiteNumbers()).findFirst().getAsInt());
+ }
+
+ @Test
+ public void FellowshipActionExertsTwiceToDrawACardIfNoAllies() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetSimpleDeckScenario();
+ PhysicalCardImpl elrond = scn.GetFreepsCard("elrond");
+
+ scn.FreepsMoveCharToTable(elrond);
+
+ scn.StartGame();
+
+ assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase());
+ assertTrue(scn.FreepsCardActionAvailable(elrond));
+
+ assertEquals(0, scn.GetWoundsOn(elrond));
+ assertEquals(0, scn.GetFreepsHandCount());
+ assertEquals(1, scn.GetFreepsDeckCount());
+
+ scn.FreepsUseCardAction(elrond);
+
+ assertEquals(2, scn.GetWoundsOn(elrond));
+ assertEquals(1, scn.GetFreepsHandCount());
+ assertEquals(0, scn.GetFreepsDeckCount());
+ }
+
+ @Test
+ public void FellowshipActionExertsOnceToDrawACardIf2Allies() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetHome3AllyScenario();
+ PhysicalCardImpl elrond = scn.GetFreepsCard("elrond");
+ scn.FreepsMoveCharToTable("allyHome3_1");
+ scn.FreepsMoveCharToTable("allyHome6_1");
+
+ scn.FreepsMoveCharToTable(elrond);
+
+ scn.StartGame();
+
+ assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase());
+ assertTrue(scn.FreepsCardActionAvailable(elrond));
+
+ assertEquals(0, scn.GetWoundsOn(elrond));
+ assertEquals(0, scn.GetFreepsHandCount());
+ //assertEquals(2, scn.GetFreepsDeckCount());
+
+ scn.FreepsUseCardAction(elrond);
+
+ assertEquals(1, scn.GetWoundsOn(elrond));
+ assertEquals(1, scn.GetFreepsHandCount());
+ //assertEquals(1, scn.GetFreepsDeckCount());
+ }
+
+ @Test
+ public void CardCanPlayIfGandalfInPlay() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetSimpleSpotScenario();
+ PhysicalCardImpl elrond = scn.GetFreepsCard("elrond");
+ PhysicalCardImpl gandalf = scn.GetFreepsCard("gandalf");
+
+ scn.FreepsMoveCardToHand(elrond);
+ scn.FreepsMoveCardToHand(gandalf);
+
+ scn.StartGame();
+
+ assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase());
+ assertFalse(scn.FreepsCardPlayAvailable(elrond));
+
+ scn.FreepsPlayCard(gandalf);
+ assertTrue(scn.FreepsCardPlayAvailable(elrond));
+ }
+
+ @Test
+ public void CardCanPlayIfElfInPlay() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetSimpleSpotScenario();
+ PhysicalCardImpl elrond = scn.GetFreepsCard("elrond");
+ PhysicalCardImpl arwen = scn.GetFreepsCard("arwen");
+
+ scn.FreepsMoveCardToHand(elrond);
+ scn.FreepsMoveCardToHand(arwen);
+
+ scn.StartGame();
+
+ assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase());
+ assertFalse(scn.FreepsCardPlayAvailable(elrond));
+
+ scn.FreepsPlayCard(arwen);
+ assertTrue(scn.FreepsCardPlayAvailable(elrond));
+ }
+
+ @Test
+ public void AllyHealsCappedAt3() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetHome3AllyScenario();
+ scn.FreepsMoveCharToTable("elrond");
+ scn.FreepsMoveCharToTable("allyHome3_1");
+ scn.FreepsMoveCharToTable("allyHome3_2");
+ scn.FreepsMoveCharToTable("allyHome6_1");
+ scn.FreepsMoveCharToTable("allyHome6_2");
+
+ scn.FreepsAddWoundsToChar("elrond", 1);
+ scn.FreepsAddWoundsToChar("allyHome3_1", 1);
+ scn.FreepsAddWoundsToChar("allyHome3_2", 1);
+ scn.FreepsAddWoundsToChar("allyHome6_1", 1);
+ scn.FreepsAddWoundsToChar("allyHome6_2", 1);
+
+ scn.StartGame();
+
+ assertEquals(Phase.BETWEEN_TURNS, scn.GetCurrentPhase());
+
+ assertEquals(3, scn.FreepsGetADParamAsList("cardId").size());
+ assertEquals("0", scn.FreepsGetADParam("min")[0]);
+ assertEquals("3", scn.FreepsGetADParam("max")[0]);
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java
new file mode 100644
index 000000000..20ee8d921
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java
@@ -0,0 +1,124 @@
+package com.gempukku.lotro.cards.unofficial.pc.errata.set1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+public class Galadriel_LoLErrataTests
+{
+ protected GenericCardTestHelper GetSimplePlayScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("galadriel", "51_45");
+ put("elrond", "1_40");
+ }}
+ );
+ }
+
+ protected GenericCardTestHelper GetHome6AllyScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("galadriel", "51_45");
+ put("allyHome3_1", "1_60");
+ put("allyHome6_1", "1_56");
+ put("allyHome6_2", "1_57");
+ put("allyHome6_3", "1_34");
+ }}
+ );
+ }
+
+ @Test
+ public void GaladrielStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 1E
+ * Title: *Galadriel
+ * Subtitle: Lady of Light
+ * Side: Free Peoples
+ * Culture: Elven
+ * Twilight Cost: 3
+ * Type: Ally
+ * Subtype: Elf
+ * Home: 6
+ * Strength: 3
+ * Vitality: 3
+ * Errata Game Text: At the start of each of your turns, heal up to 3 allies whose home is site 6.
+ * Fellowship: Exert Galadriel to play an Elf; that Elf's twilight cost is -1.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetSimplePlayScenario();
+
+ PhysicalCardImpl galadriel = scn.GetFreepsCard("galadriel");
+
+ assertTrue(galadriel.getBlueprint().isUnique());
+ assertEquals(3, galadriel.getBlueprint().getTwilightCost());
+
+ assertEquals(3, galadriel.getBlueprint().getStrength());
+ assertEquals(3, galadriel.getBlueprint().getVitality());
+ assertEquals(6, Arrays.stream(galadriel.getBlueprint().getAllyHomeSiteNumbers()).findFirst().getAsInt());
+ }
+
+ @Test
+ public void FellowshipActionExertsToDiscountAnElf() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetSimplePlayScenario();
+
+ PhysicalCardImpl galadriel = scn.GetFreepsCard("galadriel");
+ scn.FreepsMoveCharToTable(galadriel);
+ scn.FreepsMoveCardToHand("elrond");
+
+ scn.StartGame();
+
+ assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase());
+ assertTrue(scn.FreepsCardActionAvailable(galadriel));
+
+ assertEquals(0, scn.GetWoundsOn(galadriel));
+ assertEquals(1, scn.GetFreepsHandCount());
+ assertEquals(0, scn.GetTwilight());
+
+ scn.FreepsUseCardAction(galadriel);
+
+ assertEquals(1, scn.GetWoundsOn(galadriel));
+ assertEquals(0, scn.GetFreepsHandCount());
+ assertEquals(3, scn.GetTwilight());
+ }
+
+
+ @Test
+ public void AllyHealsCappedAt3() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetHome6AllyScenario();
+ scn.FreepsMoveCharToTable("galadriel");
+ scn.FreepsMoveCharToTable("allyHome3_1");
+ scn.FreepsMoveCharToTable("allyHome6_1");
+ scn.FreepsMoveCharToTable("allyHome6_2");
+ scn.FreepsMoveCharToTable("allyHome6_3");
+
+ scn.FreepsAddWoundsToChar("galadriel", 1);
+ scn.FreepsAddWoundsToChar("allyHome3_1", 1);
+ scn.FreepsAddWoundsToChar("allyHome6_1", 1);
+ scn.FreepsAddWoundsToChar("allyHome6_2", 1);
+ scn.FreepsAddWoundsToChar("allyHome6_3", 1);
+
+ scn.StartGame();
+
+ assertEquals(Phase.BETWEEN_TURNS, scn.GetCurrentPhase());
+
+ //There are 5 total elf allies in play: 1 is home 3. The rest should be eligible.
+ assertEquals(4, scn.FreepsGetADParamAsList("cardId").size());
+ assertEquals("0", scn.FreepsGetADParam("min")[0]);
+ assertEquals("3", scn.FreepsGetADParam("max")[0]);
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java
new file mode 100644
index 000000000..61ac53d78
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java
@@ -0,0 +1,104 @@
+package com.gempukku.lotro.cards.unofficial.pc.errata.set1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class NoStrangerErrataTests
+{
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("aragorn", "1_89");
+ put("arwen", "1_30");
+ put("boromir", "1_97");
+ put("nostranger", "51_108");
+ put("nostranger2", "51_108");
+ }}
+ );
+ }
+
+
+ @Test
+ public void NoStrangerStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 1E
+ * Title: *No Stranger to the Shadows
+ * Side: Free Peoples
+ * Culture: Gondor
+ * Twilight Cost: 0
+ * Type: Condition
+ * Errata Game Text: At the start of each of your turns, heal up to 3 allies whose home is site 6.
+ * Fellowship: Exert Galadriel to play an Elf; that Elf's twilight cost is -1.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger");
+
+ assertTrue(nostranger.getBlueprint().isUnique());
+ assertEquals(0, nostranger.getBlueprint().getTwilightCost());
+ assertTrue(scn.HasKeyword(nostranger, Keyword.STEALTH));
+ }
+
+ @Test
+ public void NoStrangerCanOnlyPlayOnRanger() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+ PhysicalCardImpl arwen = scn.GetFreepsCard("arwen");
+ PhysicalCardImpl boromir = scn.GetFreepsCard("boromir");
+ PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger");
+
+ scn.FreepsMoveCharToTable(aragorn);
+ scn.FreepsMoveCharToTable(arwen);
+ scn.FreepsMoveCharToTable(boromir);
+ scn.FreepsMoveCardToHand(nostranger);
+
+ scn.StartGame();
+
+ assertTrue(scn.FreepsCardPlayAvailable(nostranger));
+
+ scn.FreepsPlayCard(nostranger);
+
+ //There are 3 companions in play, but only 2 rangers, so we should only see 2 options
+ assertEquals(2, scn.FreepsGetADParamAsList("cardId").size());
+ }
+
+
+ @Test
+ public void NoStrangerReducesTwilight() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+ PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger");
+
+ scn.FreepsMoveCharToTable(aragorn);
+ scn.FreepsMoveCardToHand(nostranger);
+
+ scn.StartGame();
+
+ scn.FreepsPlayCard(nostranger);
+
+ scn.FreepsSkipCurrentPhaseAction();
+
+ // 2 for Frodo/Aragorn, 1 for the site, -1 for No Stranger
+ assertEquals(2, scn.GetTwilight());
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java
new file mode 100644
index 000000000..6116365b8
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java
@@ -0,0 +1,107 @@
+package com.gempukku.lotro.cards.unofficial.pc.errata.set1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.common.Signet;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+public class Sam_SoHErrataTests
+{
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("sam", "51_311");
+
+ put("orc", "1_272");
+ }}
+ );
+ }
+
+ @Test
+ public void SamStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 1E
+ * Title: *Sam
+ * Subtitle: Son of Hamfast
+ * Side: Free Peoples
+ * Culture: Shire
+ * Twilight Cost: 2
+ * Type: Companion
+ * Subtype: Hobbit
+ * Strength: 3
+ * Vitality: 4
+ * Signet: Aragorn
+ * Errata Game Text: Fellowship: Exert Sam and another companion to remove a burden.
+ * Response: If Frodo dies, make Sam the Ring-bearer (resistance 5).
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl sam = scn.GetFreepsCard("sam");
+
+ assertTrue(sam.getBlueprint().isUnique());
+ assertEquals(2, sam.getBlueprint().getTwilightCost());
+
+ assertEquals(3, sam.getBlueprint().getStrength());
+ assertEquals(4, sam.getBlueprint().getVitality());
+ assertEquals(Signet.ARAGORN, sam.getBlueprint().getSignet());
+
+ }
+
+ @Test
+ public void FellowshipActionExertsTwiceToRemoveABurden() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl sam = scn.GetFreepsCard("sam");
+ scn.FreepsMoveCharToTable(sam);
+
+ scn.StartGame();
+
+ assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase());
+ assertTrue(scn.FreepsCardActionAvailable(sam));
+
+ assertEquals(0, scn.GetWoundsOn(sam));
+ assertEquals(0, scn.GetWoundsOn(frodo));
+ assertEquals(1, scn.GetBurdens());
+
+ scn.FreepsUseCardAction(sam);
+
+ assertEquals(1, scn.GetWoundsOn(sam));
+ assertEquals(1, scn.GetWoundsOn(frodo));
+ assertEquals(0, scn.GetBurdens());
+ }
+
+
+ @Test
+ public void RBDeathMakesSamTheRB() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl sam = scn.GetFreepsCard("sam");
+ PhysicalCardImpl orc = scn.GetShadowCard("orc");
+ scn.FreepsMoveCharToTable(sam);
+
+ scn.StartGame();
+
+ assertNotSame(scn.GetRingBearer(), sam);
+ scn.AddWoundsToChar(frodo, 4);
+
+ scn.SkipCurrentPhaseActions();
+
+ assertTrue(scn.FreepsActionAvailable("Optional Trigger"));
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java
new file mode 100644
index 000000000..f9537d39d
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java
@@ -0,0 +1,173 @@
+package com.gempukku.lotro.cards.unofficial.pc.errata.set1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.common.Zone;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import junit.framework.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class StingErrataTests
+{
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("sting", "51_313");
+ put("sam", "1_311");
+ put("merry", "1_302");
+
+ put("orc1", "1_178");
+ put("orc2", "1_178");
+ put("orc3", "1_178");
+ put("scimitar1", "1_180");
+ put("scimitar2", "1_180");
+ put("scimitar3", "1_180");
+ }}
+ );
+ }
+
+ @Test
+ public void StingStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 1E
+ * Title: *Sting
+ * Side: Free Peoples
+ * Culture: Shire
+ * Twilight Cost: 1
+ * Strength: +2
+ * Type: Possession
+ * Subtype: Hand Weapon
+ * Errata Game Text: Bearer must be Frodo.
+ * Fellowship or Regroup: Exert Frodo to reveal 4 cards at random from an opponent's hand. Remove (1) for each Orc revealed (limit (2)).
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl sting = scn.GetFreepsCard("sting");
+
+ assertTrue(sting.getBlueprint().isUnique());
+ assertEquals(1, sting.getBlueprint().getTwilightCost());
+ assertEquals(2, sting.getBlueprint().getStrength());
+ }
+
+
+ @Test
+ public void StingCanOnlyBeBorneByFrodo() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl sam = scn.GetFreepsCard("sam");
+ PhysicalCardImpl sting = scn.GetFreepsCard("sting");
+
+ scn.FreepsMoveCharToTable(sam);
+ scn.FreepsMoveCardToHand(sting);
+
+ scn.StartGame();
+
+ scn.FreepsPlayCard(sting);
+
+ //should have automatically gone to frodo as the only valid target
+ Assert.assertEquals(Zone.ATTACHED, sting.getZone());
+ Assert.assertEquals(frodo, sting.getAttachedTo());
+ }
+
+ @Test
+ public void StingAbilityAvailableInBothFellowshipAndRegroup() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl sting = scn.GetFreepsCard("sting");
+
+ scn.AttachCard(sting, frodo);
+
+ scn.StartGame();
+
+ assertTrue(scn.FreepsCardActionAvailable(sting));
+
+ scn.SkipToPhase(Phase.REGROUP);
+
+ assertTrue(scn.FreepsCardActionAvailable(sting));
+ }
+
+ @Test
+ public void StingAbilityExertsFrodoAndRevealsFourCards() throws DecisionResultInvalidException, CardNotFoundException {
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl sting = scn.GetFreepsCard("sting");
+
+ PhysicalCardImpl orc1 = scn.GetShadowCard("orc1");
+ PhysicalCardImpl orc2 = scn.GetShadowCard("orc2");
+ PhysicalCardImpl orc3 = scn.GetShadowCard("orc3");
+ PhysicalCardImpl scimitar1 = scn.GetShadowCard("scimitar1");
+
+ scn.AttachCard(sting, frodo);
+
+ scn.ShadowMoveCardToHand(orc1, orc2, orc3, scimitar1);
+
+ scn.StartGame();
+
+ scn.FreepsUseCardAction(sting);
+
+ //Reveals 2 cards
+ assertEquals(4, scn.FreepsGetADParamAsList("blueprintId").size());
+ assertEquals(1, scn.GetWoundsOn(frodo));
+ }
+
+ @Test
+ public void StingAbilityRemovesTwilight() throws DecisionResultInvalidException, CardNotFoundException {
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl sting = scn.GetFreepsCard("sting");
+ PhysicalCardImpl sam = scn.GetFreepsCard("sam");
+ PhysicalCardImpl merry = scn.GetFreepsCard("merry");
+
+ PhysicalCardImpl orc1 = scn.GetShadowCard("orc1");
+
+ scn.FreepsMoveCharToTable(sam, merry);
+ scn.AttachCard(sting, frodo);
+
+ scn.ShadowMoveCardToHand(orc1);
+
+ scn.StartGame();
+
+ scn.SetTwilight(10);
+
+ scn.FreepsUseCardAction(sting);
+ //Both players need to dismiss the card reveal dialog.
+ scn.FreepsSkipCurrentPhaseAction();
+ scn.ShadowSkipCurrentPhaseAction();
+
+ // 10 twilight - 1 orc in the hand = 9 twilight
+ assertEquals(9, scn.GetTwilight());
+
+ scn.FreepsUseCardAction(sting);
+ scn.FreepsSkipCurrentPhaseAction();
+ scn.ShadowSkipCurrentPhaseAction();
+ // 9 twilight - 1 orc in the hand = 8 twilight
+ assertEquals(8, scn.GetTwilight());
+
+ scn.FreepsUseCardAction(sting);
+ scn.FreepsSkipCurrentPhaseAction();
+ scn.ShadowSkipCurrentPhaseAction();
+ // limit of 2 should have been hit, so no twilight should be removed
+ assertEquals(8, scn.GetTwilight());
+
+ }
+
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java
new file mode 100644
index 000000000..9f6a8ad6f
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java
@@ -0,0 +1,108 @@
+package com.gempukku.lotro.cards.unofficial.pc.errata.set1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.common.Zone;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import junit.framework.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class TalentForNBSErrataTests
+{
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("talent", "51_316");
+ put("sam", "1_311");
+ put("merry", "1_302");
+ put("pippin", "1_307");
+ put("boromir", "1_97");
+ }}
+ );
+ }
+
+ @Test
+ public void TalentStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 1E
+ * Title: A Talent for Not Being Seen
+ * Side: Free Peoples
+ * Culture: Shire
+ * Twilight Cost: 0
+ * Type: Condition
+ * Errata Game Text: Stealth. Bearer must be Merry or Pippin. Limit 1 per character.
+ * Each site's Shadow number is -1.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl talent = scn.GetFreepsCard("talent");
+
+ assertFalse(talent.getBlueprint().isUnique());
+ assertEquals(0, talent.getBlueprint().getTwilightCost());
+
+ assertTrue(scn.HasKeyword(talent, Keyword.STEALTH));
+ }
+
+ @Test
+ public void TalentOnlyPlaysOnMerryOrPippin() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl sam = scn.GetFreepsCard("sam");
+ PhysicalCardImpl merry = scn.GetFreepsCard("merry");
+ PhysicalCardImpl pippin = scn.GetFreepsCard("pippin");
+ PhysicalCardImpl talent = scn.GetFreepsCard("talent");
+
+ scn.FreepsMoveCharToTable(sam);
+ scn.FreepsMoveCharToTable(merry);
+ scn.FreepsMoveCharToTable(pippin);
+ scn.FreepsMoveCardToHand(talent);
+
+ scn.StartGame();
+
+ scn.FreepsPlayCard(talent);
+
+ //There are 4 companions in play, but only 2 valid targets
+ assertEquals(2, scn.FreepsGetADParamAsList("cardId").size());
+ }
+
+
+ @Test
+ public void TalentReducesTwilightIfOnlyHobbits() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl merry = scn.GetFreepsCard("merry");
+ PhysicalCardImpl talent = scn.GetFreepsCard("talent");
+
+ scn.FreepsMoveCharToTable(merry);
+ scn.FreepsMoveCardToHand(talent);
+
+ scn.StartGame();
+
+ scn.FreepsPlayCard(talent);
+ scn.FreepsSkipCurrentPhaseAction();
+
+ // 2 for Frodo/Merry, 1 for the site, -1 for Talent
+ assertEquals(2, scn.GetTwilight());
+
+ }
+
+
+
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java
new file mode 100644
index 000000000..5dec844d3
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java
@@ -0,0 +1,161 @@
+package com.gempukku.lotro.cards.unofficial.pc.errata.set2;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.*;
+
+public class FlamingBrandErrataTests
+{
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("brand", "52_32");
+ put("brand2", "52_32");
+ put("arwen", "1_30");
+ put("boromir", "1_97");
+ put("aragorn", "1_89");
+
+ put("nazgul", "1_229");
+ put("runner", "1_178");
+ }}
+ );
+ }
+
+ @Test
+ public void BrandStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 1E
+ * Title: Flaming Brand
+ * Side: Free Peoples
+ * Culture: Gondor
+ * Twilight Cost: 1
+ * 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.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl brand = scn.GetFreepsCard("brand");
+
+ assertFalse(brand.getBlueprint().isUnique());
+ assertEquals(1, brand.getBlueprint().getTwilightCost());
+ assertEquals(1, brand.getBlueprint().getStrength());
+ }
+
+ @Test
+ public void CanBeBorneByRangers() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl arwen = scn.GetFreepsCard("arwen");
+ PhysicalCardImpl boromir = scn.GetFreepsCard("boromir");
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+ PhysicalCardImpl brand = scn.GetFreepsCard("brand");
+
+ scn.FreepsMoveCharToTable(arwen);
+ scn.FreepsMoveCharToTable(boromir);
+ scn.FreepsMoveCharToTable(aragorn);
+ scn.FreepsMoveCardToHand(brand);
+
+ scn.StartGame();
+
+
+ assertTrue(scn.FreepsCardPlayAvailable(brand));
+
+ scn.FreepsPlayCard(brand);
+
+ //There are 3 companions in play, but only 2 rangers, so we should only see 2 options
+ assertEquals(2, scn.FreepsGetADParamAsList("cardId").size());
+ scn.FreepsChooseCard(aragorn);
+ assertTrue(scn.IsAttachedTo(brand, aragorn));
+
+ }
+
+ @Test
+ public void CanBeBorneTwice() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+ PhysicalCardImpl brand = scn.GetFreepsCard("brand");
+ PhysicalCardImpl brand2 = scn.GetFreepsCard("brand2");
+
+ scn.FreepsMoveCharToTable(aragorn);
+ scn.FreepsMoveCardToHand(brand);
+ scn.FreepsMoveCardToHand(brand2);
+
+ scn.StartGame();
+
+ scn.FreepsPlayCard(brand);
+ assertTrue(scn.FreepsCardPlayAvailable(brand2));
+ scn.FreepsPlayCard(brand2);
+
+ assertEquals(2, scn.GetAttachedCards(aragorn).size());
+ }
+
+ @Test
+ public void SkirmishAbilityAvailableWhenSkirmishingNazgul() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+ PhysicalCardImpl brand = scn.GetFreepsCard("brand");
+ PhysicalCardImpl runner = scn.GetShadowCard("runner");
+ PhysicalCardImpl nazgul = scn.GetShadowCard("nazgul");
+
+ scn.FreepsMoveCharToTable(aragorn);
+ scn.FreepsMoveCardToHand(brand);
+
+ scn.ShadowMoveCharToTable(runner);
+ scn.ShadowMoveCharToTable(nazgul);
+
+ scn.StartGame();
+
+ assertEquals(8, scn.GetStrength(aragorn));
+ scn.FreepsPlayCard(brand);
+ assertEquals(9, scn.GetStrength(aragorn));
+
+ scn.SkipToPhase(Phase.ASSIGNMENT);
+ scn.SkipCurrentPhaseActions();
+ scn.FreepsAssignToMinions(aragorn, runner);
+ //skip assigning the nazgul
+ scn.SkipCurrentPhaseActions();
+
+ //start goblin skirmish
+ scn.FreepsResolveSkirmish(aragorn);
+
+ //goblin shouldn't trigger Flaming Brand's action
+ assertEquals(0, scn.FreepsGetAvailableActions().size());
+ scn.SkipCurrentPhaseActions();
+
+ //assignment for fierce skirmish
+ scn.SkipCurrentPhaseActions();
+ scn.FreepsAssignToMinions(aragorn, nazgul);
+ scn.FreepsResolveSkirmish(aragorn);
+
+ assertEquals(1, scn.FreepsGetAvailableActions().size());
+ assertTrue(scn.FreepsCardActionAvailable(brand));
+
+ assertFalse(scn.HasKeyword(aragorn, Keyword.DAMAGE));
+ scn.FreepsUseCardAction(brand);
+ assertEquals(11, scn.GetStrength(aragorn));
+ assertTrue(scn.HasKeyword(aragorn, Keyword.DAMAGE));
+
+ //Brand is discarded
+ assertFalse(scn.IsAttachedTo(brand, aragorn));
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java
new file mode 100644
index 000000000..f7feea04f
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java
@@ -0,0 +1,100 @@
+package com.gempukku.lotro.cards.unofficial.pc.errata.set2;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.common.Signet;
+import com.gempukku.lotro.filters.Filters;
+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.KeywordModifier;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class Gimli_DotMrErrataTests
+{
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("gimli", "52_121");
+ }}
+ );
+ }
+
+ @Test
+ public void GimliStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 1E
+ * Title: *Gimli
+ * Subtitle: Dwarf of the Mountain-race
+ * Side: Free Peoples
+ * Culture: Dwarven
+ * Twilight Cost: 2
+ * Type: Companion
+ * Subtype: Dwarf
+ * Strength: 6
+ * Vitality: 3
+ * Signet: Frodo
+ * Errata Game Text: Damage +1. Each underground site's Shadow number is -1. While the fellowship is at an underground site, Gimli is strength +1.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl gimli = scn.GetFreepsCard("gimli");
+
+ assertTrue(gimli.getBlueprint().isUnique());
+ assertEquals(2, gimli.getBlueprint().getTwilightCost());
+
+ assertEquals(6, gimli.getBlueprint().getStrength());
+ assertEquals(3, gimli.getBlueprint().getVitality());
+ assertEquals(Signet.FRODO, gimli.getBlueprint().getSignet());
+
+ assertTrue(scn.HasKeyword(gimli, Keyword.DAMAGE));
+ }
+
+
+ @Test
+ public void GimliRemovesTwilightWhenUnderground() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl gimli = scn.GetFreepsCard("gimli");
+ scn.FreepsMoveCharToTable(gimli);
+
+ scn.StartGame();
+
+ scn.InsertAdHocModifier(new KeywordModifier(null, Filters.siteNumber(2), Keyword.UNDERGROUND));
+
+ scn.FreepsSkipCurrentPhaseAction();
+
+ // 2 for Frodo/Gimli, 1 for the site, -1 for Gimli's text
+ assertEquals(2, scn.GetTwilight());
+ }
+
+ @Test
+ public void GimliDoesNotRemoveTwilightWhenNotUnderground() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl gimli = scn.GetFreepsCard("gimli");
+ scn.FreepsMoveCharToTable(gimli);
+
+ scn.StartGame();
+
+ scn.FreepsSkipCurrentPhaseAction();
+
+ // 2 for Frodo/Gimli, 1 for the site
+ assertEquals(3, scn.GetTwilight());
+ }
+
+
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java
new file mode 100644
index 000000000..17aa95db5
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java
@@ -0,0 +1,126 @@
+package com.gempukku.lotro.cards.unofficial.pc.errata.set3;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.common.Signet;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class Aragorn_HttWCErrataTests
+{
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("aragorn", "53_38");
+ put("gimli", "1_13");
+
+ put("minion", "1_268");
+ put("tracker", "1_270");
+ }}
+ );
+ }
+
+ @Test
+ public void AragornHasRanger() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+
+
+ }
+
+ @Test
+ public void AragornStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 1E
+ * Title: *Aragorn
+ * Subtitle: Heir to the White City
+ * Side: Free Peoples
+ * Culture: Gondor
+ * Twilight Cost: 4
+ * Type: Companion
+ * Subtype: Man
+ * Strength: 8
+ * Vitality: 4
+ * Signet: Frodo
+ * Errata Game Text: Ranger. Each time the fellowship moves during the fellowship phase, remove (1).
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+
+ assertTrue(aragorn.getBlueprint().isUnique());
+ assertEquals(4, aragorn.getBlueprint().getTwilightCost());
+
+ assertEquals(8, aragorn.getBlueprint().getStrength());
+ assertEquals(4, aragorn.getBlueprint().getVitality());
+ assertEquals(Signet.FRODO, aragorn.getBlueprint().getSignet());
+
+ assertTrue(scn.HasKeyword(aragorn, Keyword.RANGER));
+ }
+
+
+ @Test
+ public void AragornAbilityOnlyWorksDuringFellowship() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+ scn.FreepsMoveCharToTable(aragorn);
+
+ scn.StartGame();
+ scn.SetTwilight(2);
+
+ scn.FreepsSkipCurrentPhaseAction();
+
+ // 2 for Frodo/Aragorn, 1 for the site, 2 in the pool, -1 for Aragorn's text
+ assertEquals(4, scn.GetTwilight());
+
+
+ scn.SkipToPhase(Phase.REGROUP);
+
+ scn.SkipCurrentPhaseActions();
+ scn.ShadowSkipCurrentPhaseAction();
+ assertEquals(4, scn.GetTwilight());
+ scn.FreepsChooseToMove();
+
+ // 2 for Frodo/Aragorn, 1 for the site, 4 in the pool, no removal from Aragorn
+ assertEquals(7, scn.GetTwilight());
+ }
+
+ @Test
+ public void AragornAbilityOnlyWorksIfTwilightInPool() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+ scn.FreepsMoveCharToTable(aragorn);
+
+ scn.StartGame();
+
+ scn.FreepsSkipCurrentPhaseAction();
+
+ // 2 for Frodo/Aragorn, 1 for the site, no removal since there was nothing in the pool before moving
+ assertEquals(3, scn.GetTwilight());
+
+ }
+
+
+
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java
new file mode 100644
index 000000000..ff577d784
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java
@@ -0,0 +1,123 @@
+package com.gempukku.lotro.cards.unofficial.pc.errata.set3;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Zone;
+import com.gempukku.lotro.filters.Filters;
+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.KeywordModifier;
+import junit.framework.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class BillThePonyErrataTests
+{
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("bill", "53_106");
+ put("sam", "1_311");
+ }}
+ );
+ }
+
+ @Test
+ public void BillStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 1E
+ * Title: *Bill the Pony
+ * Side: Free Peoples
+ * Culture: Shire
+ * Twilight Cost: 0
+ * Type: Possession
+ * Subtype: Pony
+ * Errata Game Text: Stealth. Bearer must be Sam.
+ * Each site's Shadow number is -1. Discard this possession when at an underground site.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl bill = scn.GetFreepsCard("bill");
+
+ assertTrue(bill.getBlueprint().isUnique());
+ assertEquals(0, bill.getBlueprint().getTwilightCost());
+
+ assertTrue(scn.HasKeyword(bill, Keyword.STEALTH));
+ }
+
+ @Test
+ public void BillCanBeBorneBySam() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl bill = scn.GetFreepsCard("bill");
+ PhysicalCardImpl sam = scn.GetFreepsCard("sam");
+
+ scn.FreepsMoveCardToHand(bill, sam);
+
+ scn.StartGame();
+
+
+ assertFalse(scn.FreepsCardPlayAvailable(bill));
+ scn.FreepsPlayCard(sam);
+ assertTrue(scn.FreepsCardPlayAvailable(bill));
+ scn.FreepsPlayCard(bill);
+
+ Assert.assertTrue(scn.IsAttachedTo(bill, sam));
+ }
+
+
+ @Test
+ public void BillReducesTwilight() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl bill = scn.GetFreepsCard("bill");
+ PhysicalCardImpl sam = scn.GetFreepsCard("sam");
+
+ scn.FreepsMoveCardToHand(bill, sam);
+
+ scn.StartGame();
+
+ scn.FreepsPlayCard(sam);
+ scn.FreepsPlayCard(bill);
+
+ // 2 for Frodo/Sam, 1 for the site, -1 for Bill
+ assertEquals(2, scn.GetTwilight());
+ }
+
+
+ @Test
+ public void BillDiscardedWhenMovingToUnderground() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl bill = scn.GetFreepsCard("bill");
+ PhysicalCardImpl sam = scn.GetFreepsCard("sam");
+
+ scn.FreepsMoveCardToHand(bill, sam);
+
+ scn.InsertAdHocModifier(new KeywordModifier(null, Filters.siteNumber(2), Keyword.UNDERGROUND));
+
+ scn.StartGame();
+
+ scn.FreepsPlayCard(sam);
+ scn.FreepsPlayCard(bill);
+
+ scn.FreepsSkipCurrentPhaseAction();
+
+ assertFalse(scn.IsAttachedTo(bill, sam));
+ assertEquals(Zone.DISCARD, bill.getZone());
+ }
+
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java
new file mode 100644
index 000000000..16fe9c1fb
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java
@@ -0,0 +1,140 @@
+package com.gempukku.lotro.cards.unofficial.pc.errata.set3;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import junit.framework.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.*;
+
+public class HornOfBoromirErrataTests
+{
+ protected GenericCardTestHelper GetFOTRScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("horn", "53_42");
+ put("elrond", "1_40");
+ put("boromir", "1_97");
+ put("aragorn", "1_89");
+
+ put("runner1", "1_178");
+ }},
+ GenericCardTestHelper.FellowshipSites,
+ GenericCardTestHelper.FOTRFrodo,
+ GenericCardTestHelper.FOTRRing
+ );
+ }
+
+ protected GenericCardTestHelper GetMovieScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("horn", "53_42");
+ put("elrond", "1_40");
+ put("boromir", "1_97");
+ put("aragorn", "1_89");
+
+ put("runner1", "1_178");
+ put("runner2", "1_178");
+ }}
+ );
+ }
+
+ @Test
+ public void HornStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 1E
+ * Title: *Horn of Boromir
+ * Side: Free Peoples
+ * Culture: Gondor
+ * Twilight Cost: 1
+ * Type: Possession
+ * Errata Game Text: Bearer must be Boromir.
+ * Maneuver: Exert Boromir and discard this possession to spot an ally. Until the regroup phase, that ally is strength +3 and participates in archery fire and skirmishes.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetFOTRScenario();
+
+ PhysicalCardImpl horn = scn.GetFreepsCard("horn");
+
+ assertTrue(horn.getBlueprint().isUnique());
+ assertEquals(1, horn.getBlueprint().getTwilightCost());
+ }
+
+ @Test
+ public void CanBeBorneByBoromir() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetFOTRScenario();
+
+ PhysicalCardImpl elrond = scn.GetFreepsCard("elrond");
+ PhysicalCardImpl boromir = scn.GetFreepsCard("boromir");
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+ PhysicalCardImpl horn = scn.GetFreepsCard("horn");
+
+ scn.FreepsMoveCharToTable(elrond);
+
+ scn.FreepsMoveCharToTable(aragorn);
+ scn.FreepsMoveCardToHand(horn);
+ scn.FreepsMoveCardToHand(boromir);
+
+ scn.StartGame();
+
+ assertFalse(scn.FreepsCardPlayAvailable(horn));
+ scn.FreepsPlayCard(boromir);
+ assertTrue(scn.FreepsCardPlayAvailable(horn));
+ scn.FreepsPlayCard(horn);
+
+ Assert.assertTrue(scn.IsAttachedTo(horn, boromir));
+ }
+
+ @Test
+ public void AbilityExertsAndDiscardsToPermitAllyToSkirmish() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetFOTRScenario();
+
+ PhysicalCardImpl elrond = scn.GetFreepsCard("elrond");
+ PhysicalCardImpl boromir = scn.GetFreepsCard("boromir");
+ PhysicalCardImpl horn = scn.GetFreepsCard("horn");
+ PhysicalCardImpl runner1 = scn.GetShadowCard("runner1");
+
+ scn.FreepsMoveCharToTable(elrond);
+ scn.FreepsMoveCharToTable(boromir);
+ scn.FreepsMoveCardToHand(horn);
+
+ scn.ShadowMoveCharToTable(runner1);
+
+ scn.StartGame();
+
+ scn.FreepsPlayCard(horn);
+
+ scn.SkipToPhase(Phase.MANEUVER);
+ assertTrue(scn.FreepsCardActionAvailable(horn));
+ scn.FreepsUseCardAction(horn);
+
+ //discards
+ assertFalse(scn.IsAttachedTo(horn, boromir));
+ assertEquals(1, scn.GetWoundsOn(boromir));
+ assertEquals(11, scn.GetStrength(elrond));
+
+ scn.SkipToPhase(Phase.ASSIGNMENT);
+
+ scn.SkipCurrentPhaseActions();
+
+ scn.FreepsAssignToMinions(elrond, runner1);
+ assertTrue(scn.IsCharAssigned(elrond));
+ assertEquals(11, scn.GetStrength(elrond));
+
+ }
+
+
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java
new file mode 100644
index 000000000..a1483984e
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java
@@ -0,0 +1,151 @@
+package com.gempukku.lotro.cards.unofficial.pc.errata.set3;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.common.Signet;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class Saruman_KoIErrataTests
+{
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("legolas", "1_50");
+ put("tale", "1_66");
+ put("doubleshot", "1_38");
+
+ put("saruman", "53_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
+ * Culture: Isengard
+ * Twilight Cost: 4
+ * 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.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl saruman = scn.GetFreepsCard("saruman");
+
+ assertTrue(saruman.getBlueprint().isUnique());
+ assertEquals(4, saruman.getBlueprint().getTwilightCost());
+
+ assertEquals(8, saruman.getBlueprint().getStrength());
+ assertEquals(4, saruman.getBlueprint().getVitality());
+ assertEquals(4, saruman.getBlueprint().getSiteNumber());
+
+ }
+
+ @Test
+ public void SarumanImmunityAndWoundBlock() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl legolas = scn.GetFreepsCard("legolas");
+
+ PhysicalCardImpl saruman = scn.GetShadowCard("saruman");
+ PhysicalCardImpl uruk1 = scn.GetShadowCard("uruk1");
+ PhysicalCardImpl uruk2 = scn.GetShadowCard("uruk2");
+
+
+ scn.FreepsMoveCharToTable(legolas);
+
+ scn.ShadowMoveCharToTable(saruman);
+ scn.ShadowMoveCharToTable(uruk1);
+ scn.ShadowMoveCharToTable(uruk2);
+
+ scn.StartGame();
+
+ scn.SkipToPhase(Phase.ARCHERY);
+
+ //can't hit saruman
+ scn.FreepsUseCardAction(legolas);
+ assertFalse(scn.FreepsCanChooseCharacter(saruman));
+
+ scn.FreepsChooseCard(uruk1);
+ assertTrue(scn.ShadowCardActionAvailable(saruman));
+
+ //saruman blocks the uruk hit
+ scn.ShadowUseCardAction(saruman);
+
+ assertEquals(0, scn.GetWoundsOn(uruk1));
+ assertEquals(1, scn.GetWoundsOn(saruman));
+ //Old version made them fierce, ensure that was removed
+ assertFalse(scn.HasKeyword(uruk1, Keyword.FIERCE));
+
+ //shadow has to skip archery actions
+ scn.ShadowSkipCurrentPhaseAction();
+
+
+ assertEquals(0, scn.GetWoundsOn(uruk1));
+ assertEquals(1, scn.GetWoundsOn(saruman));
+
+
+ scn.SkipToPhase(Phase.ASSIGNMENT);
+ scn.SkipCurrentPhaseActions();
+
+ //saruman is not on the list of assignable minions
+ assertEquals(2, scn.FreepsGetADParamAsList("minions").size());
+
+ }
+
+
+ @Test
+ public void SarumanAbilityGrantsFierce() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl saruman = scn.GetShadowCard("saruman");
+ PhysicalCardImpl uruk1 = scn.GetShadowCard("uruk1");
+
+ scn.ShadowMoveCharToTable(saruman);
+ scn.ShadowMoveCharToTable(uruk1);
+
+ scn.StartGame();
+
+ scn.SkipToPhase(Phase.MANEUVER);
+ scn.FreepsSkipCurrentPhaseAction();
+
+ assertTrue(scn.ShadowCardActionAvailable(saruman));
+
+ scn.ShadowUseCardAction(saruman);
+
+ assertTrue(scn.HasKeyword(uruk1, Keyword.FIERCE));
+
+ assertEquals(0, scn.GetWoundsOn(uruk1));
+ assertEquals(1, scn.GetWoundsOn(saruman));
+
+ scn.SkipToPhase(Phase.ASSIGNMENT);
+ assertTrue(scn.HasKeyword(uruk1, Keyword.FIERCE));
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java
new file mode 100644
index 000000000..8b603c12a
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java
@@ -0,0 +1,147 @@
+package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class Card_V1_001Tests
+{
+
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("aragorn", "1_89");
+ put("boromir", "1_97");
+ put("lords", "101_1");
+
+ put("runner1", "1_178");
+ put("runner2", "1_178");
+ }}
+ );
+ }
+
+
+ @Test
+ public void LordsStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: VSet1, VPack1
+ * Title: The Lords of Gondor Have Returned
+ * Side: Free Peoples
+ * Culture: Gondor
+ * Twilight Cost: 2
+ * Type: Condition
+ * Subtype: Support Area
+ * Game Text: While Boromir is assigned to skirmish more than one minion, Aragorn is strength +3.
+ * While Aragorn is assigned to skirmish more than one minion, Boromir is strength +3.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl lords = scn.GetFreepsCard("lords");
+
+ assertTrue(scn.HasKeyword(lords, Keyword.SUPPORT_AREA));
+ assertEquals(2, lords.getBlueprint().getTwilightCost());
+ assertTrue(lords.getBlueprint().isUnique());
+ }
+
+// @Test
+// public void OneIsBuffedWhenOtherAssignedMultiple() throws DecisionResultInvalidException, CardNotFoundException {
+// //Pre-game setup
+// GenericCardTestHelper scn = GetScenario();
+//
+// PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+// PhysicalCardImpl boromir = scn.GetFreepsCard("boromir");
+// PhysicalCardImpl lords = scn.GetFreepsCard("lords");
+//
+// scn.FreepsMoveCharToTable(aragorn);
+// scn.FreepsMoveCharToTable(boromir);
+// scn.FreepsMoveCardToHand(lords);
+//
+// PhysicalCardImpl runner1 = scn.GetShadowCard("runner1");
+// PhysicalCardImpl runner2 = scn.GetShadowCard("runner2");
+//
+// scn.ShadowMoveCharToTable(runner1);
+// scn.ShadowMoveCharToTable(runner2);
+//
+// scn.StartGame();
+// scn.FreepsPlayCard(lords);
+// scn.SkipToPhase(Phase.ASSIGNMENT);
+//
+// assertEquals(7, scn.GetStrength(boromir));
+// assertEquals(8, scn.GetStrength(aragorn));
+//
+// scn.FreepsSkipCurrentPhaseAction();
+// scn.ShadowSkipCurrentPhaseAction();
+//
+// //Let shadow assign so we don't have to worry about defender bonuses
+// scn.FreepsSkipCurrentPhaseAction();
+// scn.ShadowAssignToMinions(boromir, runner1, runner2);
+//
+// assertEquals(7, scn.GetStrength(boromir));
+// assertEquals(11, scn.GetStrength(aragorn));
+//
+// scn.FreepsResolveSkirmish(boromir);
+//
+// scn.SkipToPhase(Phase.REGROUP);
+// scn.SkipCurrentPhaseActions();
+// scn.ShadowSkipCurrentPhaseAction();
+// scn.FreepsChooseToMove();
+//
+// scn.SkipToPhase(Phase.ASSIGNMENT);
+//
+// //Let shadow assign so we don't have to worry about defender bonuses
+// scn.FreepsSkipCurrentPhaseAction();
+// scn.ShadowAssignToMinions(aragorn, runner1, runner2);
+//
+// assertEquals(10, scn.GetStrength(boromir));
+// assertEquals(8, scn.GetStrength(aragorn));
+// }
+
+
+ @Test
+ public void NoBuffsWhenAssignedSingle() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+ PhysicalCardImpl boromir = scn.GetFreepsCard("boromir");
+ PhysicalCardImpl lords = scn.GetFreepsCard("lords");
+
+ scn.FreepsMoveCharToTable(aragorn);
+ scn.FreepsMoveCharToTable(boromir);
+ scn.FreepsMoveCardToHand(lords);
+
+ PhysicalCardImpl runner1 = scn.GetShadowCard("runner1");
+ PhysicalCardImpl runner2 = scn.GetShadowCard("runner2");
+
+ scn.ShadowMoveCharToTable(runner1);
+ scn.ShadowMoveCharToTable(runner2);
+
+ scn.StartGame();
+ scn.FreepsPlayCard(lords);
+ scn.SkipToPhase(Phase.ASSIGNMENT);
+
+ assertEquals(7, scn.GetStrength(boromir));
+ assertEquals(8, scn.GetStrength(aragorn));
+
+ scn.SkipCurrentPhaseActions();
+
+ scn.FreepsAssignToMinions(new PhysicalCardImpl[]{ boromir, runner1 }, new PhysicalCardImpl[]{ aragorn, runner2 });
+
+ assertEquals(7, scn.GetStrength(boromir));
+ assertEquals(8, scn.GetStrength(aragorn));
+
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java
new file mode 100644
index 000000000..702475e33
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java
@@ -0,0 +1,125 @@
+package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class Card_V1_002Tests
+{
+
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("aragorn", "1_89");
+ put("boromir", "1_97");
+ put("whitecity", "101_2");
+
+ put("attea", "1_229");
+ put("cantea", "1_230");
+ }}
+ );
+ }
+
+
+ @Test
+ public void WhiteCityStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: VSet1, VPack1
+ * Title: *I Will Not Let the White City Fall
+ * Side: Free Peoples
+ * Culture: Gondor
+ * Twilight Cost: 2
+ * Type: Condition
+ * Subtype: Support Area
+ * Game Text: Each time Boromir loses a skirmish, make Aragorn strength +2 until the regroup phase.
+ * Each time Aragorn loses a skirmish, make Boromir strength +2 until the regroup phase.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl whitecity = scn.GetFreepsCard("whitecity");
+
+ assertTrue(scn.HasKeyword(whitecity, Keyword.SUPPORT_AREA));
+ assertEquals(2, whitecity.getBlueprint().getTwilightCost());
+ assertTrue(whitecity.getBlueprint().isUnique());
+ }
+
+ @Test
+ public void OneIsBuffedWhenOtherLosesSkirmish() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+ PhysicalCardImpl boromir = scn.GetFreepsCard("boromir");
+ PhysicalCardImpl whitecity = scn.GetFreepsCard("whitecity");
+
+ scn.FreepsMoveCharToTable(aragorn);
+ scn.FreepsMoveCharToTable(boromir);
+ scn.FreepsMoveCardToHand(whitecity);
+
+ PhysicalCardImpl cantea = scn.GetShadowCard("cantea");
+ PhysicalCardImpl attea = scn.GetShadowCard("attea");
+ scn.ShadowMoveCharToTable(cantea, attea);
+
+ scn.StartGame();
+ scn.FreepsPlayCard(whitecity);
+ scn.SkipToPhase(Phase.ASSIGNMENT);
+
+ assertEquals(7, scn.GetStrength(boromir));
+ assertEquals(8, scn.GetStrength(aragorn));
+
+ scn.SkipCurrentPhaseActions();
+
+ //Standard assignment
+ scn.FreepsAssignToMinions(new PhysicalCardImpl[] { aragorn, cantea}, new PhysicalCardImpl[] { boromir, attea});
+
+ scn.FreepsResolveSkirmish(aragorn);
+ scn.SkipCurrentPhaseActions();
+ scn.FreepsAcceptOptionalTrigger(); //Have to resolve the skirmish and the condition trigger
+ // 14 > 8, Aragorn lost, Boromir should be buffed
+ assertEquals(9, scn.GetStrength(boromir));
+ assertEquals(8, scn.GetStrength(aragorn));
+
+ scn.FreepsResolveSkirmish(boromir);
+ scn.SkipCurrentPhaseActions();
+ scn.FreepsAcceptOptionalTrigger(); //Have to resolve the skirmish and the condition trigger
+ // 12 > 9, Boromir lost, Aragorn should be buffed
+ assertEquals(9, scn.GetStrength(boromir));
+ assertEquals(10, scn.GetStrength(aragorn));
+
+ //Fierce assignment
+ scn.FreepsSkipCurrentPhaseAction();
+ scn.ShadowSkipCurrentPhaseAction();
+
+ scn.FreepsAssignToMinions(new PhysicalCardImpl[] { aragorn, cantea}, new PhysicalCardImpl[] { boromir, attea});
+ scn.FreepsResolveSkirmish(boromir);
+ scn.SkipCurrentPhaseActions();
+ scn.FreepsAcceptOptionalTrigger(); //Have to resolve the skirmish and the condition trigger
+ // 10 > 9, Boromir lost again, Aragorn should be buffed again
+ assertEquals(9, scn.GetStrength(boromir));
+ assertEquals(12, scn.GetStrength(aragorn));
+
+ scn.FreepsResolveSkirmish(aragorn);
+ //Aragorn now wins his skirmish, so there's no loss trigger to evaluate
+
+ scn.SkipToPhase(Phase.REGROUP);
+
+ //strength should be back to normal
+ assertEquals(7, scn.GetStrength(boromir));
+ assertEquals(8, scn.GetStrength(aragorn));
+ }
+
+
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java
new file mode 100644
index 000000000..b4b263a23
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java
@@ -0,0 +1,95 @@
+package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.common.Signet;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class Card_V1_003Tests
+{
+
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("boromir", "101_3");
+ put("sam", "1_311");
+ put("merry", "1_302");
+ put("pippin", "1_307");
+ }}
+ );
+ }
+
+
+ @Test
+ public void BoromirStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: VSet1, VPack1
+ * Title: *Boromir
+ * Subtitle: The Redeemed
+ * Side: Free Peoples
+ * Culture: Gondor
+ * Twilight Cost: 3
+ * Type: Companion
+ * Subtype: Man
+ * Strength: 7
+ * Vitality: 3
+ * Signet: Aragorn
+ * Game Text: While you can spot 2 [shire] companions, Boromir is defender +1.
+ * While you can spot 4 [shire] companions, Boromir is strength +2 and damage +1.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl boromir = scn.GetFreepsCard("boromir");
+
+ assertTrue(boromir.getBlueprint().isUnique());
+ assertEquals(3, boromir.getBlueprint().getTwilightCost());
+ assertEquals(7, boromir.getBlueprint().getStrength());
+ assertEquals(3, boromir.getBlueprint().getVitality());
+ assertEquals(Signet.ARAGORN, boromir.getBlueprint().getSignet());
+ }
+
+ @Test
+ public void TwoAndFourHobbitsTriggerBuffs() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl boromir = scn.GetFreepsCard("boromir");
+ PhysicalCardImpl sam = scn.GetFreepsCard("sam");
+ PhysicalCardImpl merry = scn.GetFreepsCard("merry");
+ PhysicalCardImpl pippin = scn.GetFreepsCard("pippin");
+
+ scn.FreepsMoveCardToHand(sam, merry, pippin);
+ scn.FreepsMoveCharToTable(boromir);
+
+ scn.StartGame();
+
+ assertFalse(scn.HasKeyword(boromir, Keyword.DEFENDER));
+ assertFalse(scn.HasKeyword(boromir, Keyword.DAMAGE));
+ assertEquals(7, scn.GetStrength(boromir));
+
+ scn.FreepsPlayCard(sam);
+ assertTrue(scn.HasKeyword(boromir, Keyword.DEFENDER));
+ assertEquals(7, scn.GetStrength(boromir));
+
+ scn.FreepsPlayCard(merry);
+ scn.FreepsPlayCard(pippin);
+ assertTrue(scn.HasKeyword(boromir, Keyword.DAMAGE));
+ assertEquals(9, scn.GetStrength(boromir));
+ }
+
+
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_004Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_004Tests.java
new file mode 100644
index 000000000..5a32b7a25
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_004Tests.java
@@ -0,0 +1,106 @@
+package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.common.Zone;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class Card_V1_004Tests
+{
+
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("aragorn", "1_89");
+ put("boromir", "1_97");
+ put("loud", "101_4");
+
+ put("attea", "1_229");
+ }}
+ );
+ }
+
+
+ @Test
+ public void LoudAndClearStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: VSet1, VPack1
+ * Title: *Loud and Clear It Sounds
+ * Side: Free Peoples
+ * Culture: Gondor
+ * Twilight Cost: 1
+ * Type: Condition
+ * Subtype: Support Area
+ * Game Text: Each time the Shadow player assigns as minion to a [shire] companion, you may exert a [gondor] companion and discard this condition to assign that minion to that [gondor] companion instead.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl loud = scn.GetFreepsCard("loud");
+
+ assertTrue(scn.HasKeyword(loud, Keyword.SUPPORT_AREA));
+ assertEquals(1, loud.getBlueprint().getTwilightCost());
+ assertTrue(loud.getBlueprint().isUnique());
+ }
+
+ @Test
+ public void LoudAndClearInterceptsShadowAssignment() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+ PhysicalCardImpl boromir = scn.GetFreepsCard("boromir");
+ PhysicalCardImpl loud = scn.GetFreepsCard("loud");
+
+ scn.FreepsMoveCharToTable(boromir, aragorn);
+ scn.FreepsMoveCardToSupportArea(loud);
+
+ PhysicalCardImpl attea = scn.GetShadowCard("attea");
+ scn.ShadowMoveCharToTable(attea);
+
+ scn.StartGame();
+ scn.SkipToPhase(Phase.ASSIGNMENT);
+
+ //Assignment actions
+ scn.SkipCurrentPhaseActions();
+
+ //Skip standard assignment so shadow assigns
+ scn.FreepsSkipCurrentPhaseAction();
+
+ scn.ShadowAssignToMinions(frodo, attea);
+
+ assertTrue(scn.FreepsHasOptionalTriggerAvailable());
+ scn.FreepsAcceptOptionalTrigger();
+ scn.FreepsChooseCard(boromir);
+
+ assertTrue(loud.getZone() == Zone.DISCARD);
+ assertTrue(scn.IsCharAssigned(boromir));
+ assertEquals(1, scn.GetWoundsOn(boromir));
+ assertFalse(scn.IsCharAssigned(frodo));
+
+ scn.FreepsResolveSkirmish(boromir);
+ scn.SkipCurrentPhaseActions();
+
+ //fierce skirmish
+ scn.SkipCurrentPhaseActions();
+ scn.FreepsAssignToMinions(frodo, attea);
+ //should only trigger if shadow assigns
+ assertFalse(scn.FreepsHasOptionalTriggerAvailable());
+ }
+
+
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_005Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_005Tests.java
new file mode 100644
index 000000000..2c1cd710f
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_005Tests.java
@@ -0,0 +1,126 @@
+package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Phase;
+import com.gempukku.lotro.common.Zone;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class Card_V1_005Tests
+{
+
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("aragorn", "1_89");
+ put("boromir", "1_97");
+ put("remnant", "101_5");
+
+ put("inquisitor", "1_268");
+ }}
+ );
+ }
+
+
+ @Test
+ public void RemnantStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: VSet1, VPack1
+ * Title: *Remnant of Numenor
+ * Side: Free Peoples
+ * Culture: Gondor
+ * Twilight Cost: 1
+ * Type: Condition
+ * Subtype: Support Area
+ * Game Text: To play, spot a [gondor] companion.
+ * Each time a card is discarded from your hand by a Shadow card, you may add (1) to shuffle a [gondor] card from your discard pile into your draw deck.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl remnant = scn.GetFreepsCard("remnant");
+
+ assertTrue(scn.HasKeyword(remnant, Keyword.SUPPORT_AREA));
+ assertEquals(1, remnant.getBlueprint().getTwilightCost());
+ }
+
+ @Test
+ public void RemnantSpotsAGondorCompanionToPlay() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+ PhysicalCardImpl remnant = scn.GetFreepsCard("remnant");
+
+ scn.FreepsMoveCardToHand(aragorn, remnant);
+
+ scn.StartGame();
+
+ assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase());
+ Assert.assertFalse(scn.FreepsCardPlayAvailable(remnant));
+
+ scn.FreepsPlayCard(aragorn);
+ assertTrue(scn.FreepsCardPlayAvailable(remnant));
+ }
+
+ @Test
+ public void RemnantTriggersOnShadowDiscardFromHand() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn");
+ PhysicalCardImpl boromir = scn.GetFreepsCard("boromir");
+ PhysicalCardImpl remnant = scn.GetFreepsCard("remnant");
+
+ scn.FreepsMoveCardToDiscard(boromir);
+ scn.FreepsMoveCardToHand(aragorn);
+ scn.FreepsMoveCardToSupportArea(remnant);
+
+ PhysicalCardImpl inquisitor = scn.GetShadowCard("inquisitor");
+ scn.ShadowMoveCardToHand(inquisitor);
+
+ scn.StartGame();
+
+ scn.SetTwilight(10);
+
+ scn.FreepsSkipCurrentPhaseAction();
+
+ assertEquals(1, scn.GetFreepsHandCount());
+ assertEquals(1, scn.GetFreepsDeckCount()); //the orc is also in the deck
+ assertEquals(1, scn.GetFreepsDiscardCount());
+
+ scn.ShadowPlayCard(inquisitor);
+ scn.ShadowAcceptOptionalTrigger();
+
+ assertTrue(scn.FreepsHasOptionalTriggerAvailable());
+ scn.FreepsAcceptOptionalTrigger();
+
+ //scn.FreepsGetADParamAsList()
+
+ scn.FreepsChoose("temp0");
+
+ //Card from hand was discarded, one of the two cards in the discard was shuffled in with the orc
+ assertEquals(0, scn.GetFreepsHandCount());
+ assertEquals(2, scn.GetFreepsDeckCount());
+ assertEquals(1, scn.GetFreepsDiscardCount());
+
+ // 10 starting + 2 for moving - 5 for the orc + 1 for Remnant triggering
+ assertEquals(8, scn.GetTwilight());
+
+ }
+
+
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_006Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_006Tests.java
new file mode 100644
index 000000000..c5518640f
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_006Tests.java
@@ -0,0 +1,113 @@
+package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Signet;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class Card_V1_006Tests
+{
+
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("stealth1", "2_106");
+ put("stealth2", "2_106");
+
+ put("chief", "101_6");
+ put("snarler", "101_7");
+
+ }}
+ );
+ }
+
+
+ @Test
+ public void ChiefStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: VSet1, VPack1
+ * Title: *Great Wolf Chief
+ * Side: Shadow
+ * Culture: Sauron
+ * Twilight Cost: 5
+ * Type: Minion
+ * Subtype: Warg
+ * Strength: 10
+ * Vitality: 3
+ * Home Site: 6
+ * Game Text: Tracker. Fierce. The site number of this minion is -1 for each stealth card you can spot.
+ * Each time you play another [sauron] Warg, you may make the Free Peoples player exert a companion.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl chief = scn.GetFreepsCard("chief");
+
+ assertTrue(chief.getBlueprint().isUnique());
+ assertEquals(5, chief.getBlueprint().getTwilightCost());
+ assertEquals(10, chief.getBlueprint().getStrength());
+ assertEquals(3, chief.getBlueprint().getVitality());
+ assertEquals(6, chief.getBlueprint().getSiteNumber());
+ assertTrue(scn.HasKeyword(chief, Keyword.TRACKER));
+ assertTrue(scn.HasKeyword(chief, Keyword.FIERCE));
+ }
+
+ @Test
+ public void ChiefSiteNumberReducedForEachStealthCard() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl stealth1 = scn.GetFreepsCard("stealth1");
+ PhysicalCardImpl stealth2 = scn.GetFreepsCard("stealth2");
+
+ scn.FreepsMoveCardToSupportArea(stealth1, stealth2);
+
+ PhysicalCardImpl chief = scn.GetShadowCard("chief");
+
+ scn.ShadowMoveCharToTable(chief);
+
+ scn.StartGame();
+
+ // 6 base, -2 for the 2 Nice Imitations on the table.
+ assertEquals(4, scn.GetSiteNumber(chief));
+ }
+
+ @Test
+ public void ChiefExertsACompanionWhenEachWargPlayed() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+
+ PhysicalCardImpl chief = scn.GetShadowCard("chief");
+ PhysicalCardImpl snarler = scn.GetShadowCard("snarler");
+
+ scn.ShadowMoveCharToTable(chief);
+ scn.ShadowMoveCardToHand(snarler);
+
+ scn.StartGame();
+
+ scn.SetTwilight(10);
+ scn.FreepsSkipCurrentPhaseAction();
+
+ scn.ShadowPlayCard(snarler);
+ assertTrue(scn.ShadowHasOptionalTriggerAvailable());
+ scn.ShadowAcceptOptionalTrigger();
+
+ assertEquals(1, scn.GetWoundsOn(frodo));
+ }
+
+
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_007Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_007Tests.java
new file mode 100644
index 000000000..c8017e1b9
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_007Tests.java
@@ -0,0 +1,110 @@
+package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.game.CardNotFoundException;
+import com.gempukku.lotro.game.PhysicalCardImpl;
+import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class Card_V1_007Tests
+{
+
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("stealth1", "2_106");
+ put("stealth2", "2_106");
+
+ put("snarler", "101_7");
+
+ }}
+ );
+ }
+
+
+ @Test
+ public void SnarlerStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: VSet1, VPack1
+ * Title: Hollin Snarler
+ * Side: Shadow
+ * Culture: Sauron
+ * Twilight Cost: 3
+ * Type: Minion
+ * Subtype: Warg
+ * Strength: 4
+ * Vitality: 2
+ * Home Site: 6
+ * Game Text: Tracker. Fierce. The site number of this minion is -1 for each stealth card you can spot.
+ * This minion is strength +1 for each wounded companion or stealth card you can spot.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl snarler = scn.GetFreepsCard("snarler");
+
+ assertFalse(snarler.getBlueprint().isUnique());
+ assertEquals(3, snarler.getBlueprint().getTwilightCost());
+ assertEquals(4, snarler.getBlueprint().getStrength());
+ assertEquals(3, snarler.getBlueprint().getVitality());
+ assertEquals(6, snarler.getBlueprint().getSiteNumber());
+ assertTrue(scn.HasKeyword(snarler, Keyword.TRACKER));
+ assertTrue(scn.HasKeyword(snarler, Keyword.FIERCE));
+ }
+
+ @Test
+ public void SnarlerSiteNumberReducedForEachStealthCard() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl stealth1 = scn.GetFreepsCard("stealth1");
+ PhysicalCardImpl stealth2 = scn.GetFreepsCard("stealth2");
+
+ scn.FreepsMoveCardToSupportArea(stealth1, stealth2);
+
+ PhysicalCardImpl snarler = scn.GetShadowCard("snarler");
+
+ scn.ShadowMoveCharToTable(snarler);
+
+ scn.StartGame();
+
+ // 6 base, -2 for the 2 Nice Imitations on the table.
+ assertEquals(4, scn.GetSiteNumber(snarler));
+ }
+
+ @Test
+ public void SnarlerStrengthIncreasesWithWoundedCompanionsAndStealth() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl stealth1 = scn.GetFreepsCard("stealth1");
+ PhysicalCardImpl stealth2 = scn.GetFreepsCard("stealth2");
+
+ scn.FreepsMoveCardToSupportArea(stealth1,stealth2);
+
+ PhysicalCardImpl snarler = scn.GetShadowCard("snarler");
+
+ scn.ShadowMoveCharToTable(snarler);
+
+ scn.StartGame();
+
+ scn.AddWoundsToChar(frodo, 1);
+ scn.FreepsSkipCurrentPhaseAction();
+
+ // Base of 4, +2 for stealth cards, +1 for wounded frodo
+ assertEquals(7, scn.GetStrength(snarler));
+ }
+
+
+}