diff --git a/.gitattributes b/.gitattributes index c082b9d5179..8b4bde811f1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -92,6 +92,7 @@ res/cardsfolder/a/adun_oakenshield.txt svneol=native#text/plain res/cardsfolder/a/advance_scout.txt svneol=native#text/plain res/cardsfolder/a/advanced_hoverguard.txt svneol=native#text/plain res/cardsfolder/a/advent_of_the_wurm.txt -text +res/cardsfolder/a/adventurers_guildhouse.txt -text res/cardsfolder/a/adventuring_gear.txt svneol=native#text/plain res/cardsfolder/a/advice_from_the_fae.txt -text res/cardsfolder/a/aegis_angel.txt -text @@ -1591,6 +1592,7 @@ res/cardsfolder/c/caterwauling_boggart.txt -text res/cardsfolder/c/cathars_crusade.txt -text res/cardsfolder/c/cathartic_adept.txt svneol=native#text/plain res/cardsfolder/c/cathedral_membrane.txt -text +res/cardsfolder/c/cathedral_of_serra.txt -text res/cardsfolder/c/cathedral_of_war.txt -text res/cardsfolder/c/cathedral_sanctifier.txt -text res/cardsfolder/c/cathodion.txt svneol=native#text/plain @@ -6674,6 +6676,7 @@ res/cardsfolder/m/master_healer.txt svneol=native#text/plain res/cardsfolder/m/master_of_arms.txt -text res/cardsfolder/m/master_of_cruelties.txt -text res/cardsfolder/m/master_of_etherium.txt svneol=native#text/plain +res/cardsfolder/m/master_of_the_hunt.txt -text res/cardsfolder/m/master_of_the_pearl_trident.txt -text res/cardsfolder/m/master_of_the_veil.txt -text res/cardsfolder/m/master_of_the_wild_hunt.txt svneol=native#text/plain @@ -7140,6 +7143,7 @@ res/cardsfolder/m/mothrider_samurai.txt svneol=native#text/plain res/cardsfolder/m/mountain.txt svneol=native#text/plain res/cardsfolder/m/mountain_bandit.txt svneol=native#text/plain res/cardsfolder/m/mountain_goat.txt svneol=native#text/plain +res/cardsfolder/m/mountain_stronghold.txt -text res/cardsfolder/m/mountain_titan.txt -text svneol=unset#text/plain res/cardsfolder/m/mountain_valley.txt svneol=native#text/plain res/cardsfolder/m/mountain_yeti.txt svneol=native#text/plain @@ -9485,6 +9489,7 @@ res/cardsfolder/s/sea_snidd.txt -text res/cardsfolder/s/sea_spirit.txt svneol=native#text/plain res/cardsfolder/s/sea_sprite.txt svneol=native#text/plain res/cardsfolder/s/seachrome_coast.txt svneol=native#text/plain +res/cardsfolder/s/seafarers_quay.txt -text res/cardsfolder/s/seafloor_debris.txt svneol=native#text/plain res/cardsfolder/s/seahunter.txt svneol=native#text/plain res/cardsfolder/s/seal_of_cleansing.txt svneol=native#text/plain @@ -9721,6 +9726,7 @@ res/cardsfolder/s/shatterskull_giant.txt svneol=native#text/plain res/cardsfolder/s/shatterstorm.txt svneol=native#text/plain res/cardsfolder/s/shauku_endbringer.txt svneol=native#text/plain res/cardsfolder/s/shaukus_minion.txt svneol=native#text/plain +res/cardsfolder/s/shelkin_brownie.txt -text res/cardsfolder/s/shell_of_the_last_kappa.txt -text res/cardsfolder/s/shell_skulkin.txt svneol=native#text/plain res/cardsfolder/s/shelldock_isle.txt -text @@ -11450,6 +11456,7 @@ res/cardsfolder/t/tobias_andrion.txt svneol=native#text/plain res/cardsfolder/t/toil_to_renown.txt svneol=native#text/plain res/cardsfolder/t/toil_trouble.txt -text res/cardsfolder/t/toils_of_night_and_day.txt svneol=native#text/plain +res/cardsfolder/t/tolaria.txt -text res/cardsfolder/t/tolaria_west.txt svneol=native#text/plain res/cardsfolder/t/tolarian_academy.txt svneol=native#text/plain res/cardsfolder/t/tolarian_drake.txt -text @@ -11805,6 +11812,7 @@ res/cardsfolder/u/unforge.txt -text res/cardsfolder/u/unfulfilled_desires.txt svneol=native#text/plain res/cardsfolder/u/unhallowed_pact.txt -text res/cardsfolder/u/unhinge.txt svneol=native#text/plain +res/cardsfolder/u/unholy_citadel.txt -text res/cardsfolder/u/unholy_grotto.txt svneol=native#text/plain res/cardsfolder/u/unholy_strength.txt svneol=native#text/plain res/cardsfolder/u/unified_strike.txt -text diff --git a/res/cardsfolder/a/adventurers_guildhouse.txt b/res/cardsfolder/a/adventurers_guildhouse.txt new file mode 100644 index 00000000000..ef7097c30fc --- /dev/null +++ b/res/cardsfolder/a/adventurers_guildhouse.txt @@ -0,0 +1,7 @@ +Name:Adventurers' Guildhouse +ManaCost:no cost +Types:Land +S:Mode$ Continuous | Affected$ Creature.Green+Legendary | AddKeyword$ Bands with Other Legendary Creatures | Description$ Green legendary creatures you control have "bands with other legendary creatures." (Any legendary creatures can attack in a band as long as at least one has "bands with other legendary creatures." Bands are blocked as a group. If at least two legendary creatures you control, one of which has "bands with other legendary creatures," are blocking or being blocked by the same creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking.) +SVar:RemAIDeck:True +SVar:Picture:http://www.wizards.com/global/images/magic/general/adventurers_guildhouse.jpg +Oracle:Green legendary creatures you control have "bands with other legendary creatures." (Any legendary creatures can attack in a band as long as at least one has "bands with other legendary creatures." Bands are blocked as a group. If at least two legendary creatures you control, one of which has "bands with other legendary creatures," are blocking or being blocked by the same creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking.) diff --git a/res/cardsfolder/c/cathedral_of_serra.txt b/res/cardsfolder/c/cathedral_of_serra.txt new file mode 100644 index 00000000000..bd8e4f374e7 --- /dev/null +++ b/res/cardsfolder/c/cathedral_of_serra.txt @@ -0,0 +1,7 @@ +Name:Cathedral of Serra +ManaCost:no cost +Types:Land +S:Mode$ Continuous | Affected$ Creature.White+Legendary | AddKeyword$ Bands with Other Legendary Creatures | Description$ White legendary creatures you control have "bands with other legendary creatures." (Any legendary creatures can attack in a band as long as at least one has "bands with other legendary creatures." Bands are blocked as a group. If at least two legendary creatures you control, one of which has "bands with other legendary creatures," are blocking or being blocked by the same creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking.) +SVar:RemAIDeck:True +SVar:Picture:http://www.wizards.com/global/images/magic/general/cathedral_of_serra.jpg +Oracle:White legendary creatures you control have "bands with other legendary creatures." (Any legendary creatures can attack in a band as long as at least one has "bands with other legendary creatures." Bands are blocked as a group. If at least two legendary creatures you control, one of which has "bands with other legendary creatures," are blocking or being blocked by the same creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking.) diff --git a/res/cardsfolder/m/master_of_the_hunt.txt b/res/cardsfolder/m/master_of_the_hunt.txt new file mode 100644 index 00000000000..4a3109b6c77 --- /dev/null +++ b/res/cardsfolder/m/master_of_the_hunt.txt @@ -0,0 +1,7 @@ +Name:Master of the Hunt +ManaCost:2 G G +Types:Creature Human +PT:2/2 +A:AB$ Token | Cost$ 2 G G | TokenAmount$ 1 | TokenTypes$ Creature,Wolf | TokenName$ Wolves of the Hunt | TokenOwner$ You | TokenColors$ Green | TokenPower$ 1 | TokenToughness$ 1 | TokenKeywords$ Bands with Other Creatures named Wolves of the Hunt | SpellDescription$ Put a 1/1 green Wolf creature token named Wolves of the Hunt onto the battlefield. It has "bands with other creatures named Wolves of the Hunt." +SVar:Picture:http://www.wizards.com/global/images/magic/general/master_of_the_hunt.jpg +Oracle:{2}{G}{G}: Put a 1/1 green Wolf creature token named Wolves of the Hunt onto the battlefield. It has "bands with other creatures named Wolves of the Hunt." (Any creatures named Wolves of the Hunt can attack in a band as long as at least one has "bands with other creatures named Wolves of the Hunt." Bands are blocked as a group. If at least two creatures named Wolves of the Hunt you control, one of which has "bands with other creatures named Wolves of the Hunt," are blocking or being blocked by the same creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking.) diff --git a/res/cardsfolder/m/mountain_stronghold.txt b/res/cardsfolder/m/mountain_stronghold.txt new file mode 100644 index 00000000000..4c9dd16f519 --- /dev/null +++ b/res/cardsfolder/m/mountain_stronghold.txt @@ -0,0 +1,7 @@ +Name:Mountain Stronghold +ManaCost:no cost +Types:Land +S:Mode$ Continuous | Affected$ Creature.Red+Legendary | AddKeyword$ Bands with Other Legendary Creatures | Description$ Red legendary creatures you control have "bands with other legendary creatures." (Any legendary creatures can attack in a band as long as at least one has "bands with other legendary creatures." Bands are blocked as a group. If at least two legendary creatures you control, one of which has "bands with other legendary creatures," are blocking or being blocked by the same creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking.) +SVar:RemAIDeck:True +SVar:Picture:http://www.wizards.com/global/images/magic/general/mountain_stronghold.jpg +Oracle:Red legendary creatures you control have "bands with other legendary creatures." (Any legendary creatures can attack in a band as long as at least one has "bands with other legendary creatures." Bands are blocked as a group. If at least two legendary creatures you control, one of which has "bands with other legendary creatures," are blocking or being blocked by the same creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking.) diff --git a/res/cardsfolder/s/seafarers_quay.txt b/res/cardsfolder/s/seafarers_quay.txt new file mode 100644 index 00000000000..434f9ce696b --- /dev/null +++ b/res/cardsfolder/s/seafarers_quay.txt @@ -0,0 +1,7 @@ +Name:Seafarer's Quay +ManaCost:no cost +Types:Land +S:Mode$ Continuous | Affected$ Creature.Blue+Legendary | AddKeyword$ Bands with Other Legendary Creatures | Description$ Blue legendary creatures you control have "bands with other legendary creatures." (Any legendary creatures can attack in a band as long as at least one has "bands with other legendary creatures." Bands are blocked as a group. If at least two legendary creatures you control, one of which has "bands with other legendary creatures," are blocking or being blocked by the same creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking.) +SVar:RemAIDeck:True +SVar:Picture:http://www.wizards.com/global/images/magic/general/seafarers_quay.jpg +Oracle:Blue legendary creatures you control have "bands with other legendary creatures." (Any legendary creatures can attack in a band as long as at least one has "bands with other legendary creatures." Bands are blocked as a group. If at least two legendary creatures you control, one of which has "bands with other legendary creatures," are blocking or being blocked by the same creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking.) diff --git a/res/cardsfolder/s/shelkin_brownie.txt b/res/cardsfolder/s/shelkin_brownie.txt new file mode 100644 index 00000000000..47bcee8a9fa --- /dev/null +++ b/res/cardsfolder/s/shelkin_brownie.txt @@ -0,0 +1,8 @@ +Name:Shelkin Brownie +ManaCost:1 G +Types:Creature Ouphe +PT:1/1 +A:AB$ Debuff | Cost$ T | ValidTgts$ Creature | TgtPrompt$ Select target creature | Keywords$ Bands with Other Creatures named Wolves of the Hunt & Bands with Other Legendary Creatures | SpellDescription$ Target creature loses all "bands with other" abilities until end of turn. | StackDescription$ SpellDescription +SVar:RemAIDeck:True +SVar:Picture:http://www.wizards.com/global/images/magic/general/shelkin_brownie.jpg +Oracle:{T}: Target creature loses all "bands with other" abilities until end of turn. diff --git a/res/cardsfolder/t/tolaria.txt b/res/cardsfolder/t/tolaria.txt new file mode 100644 index 00000000000..3c1335d6afe --- /dev/null +++ b/res/cardsfolder/t/tolaria.txt @@ -0,0 +1,8 @@ +Name:Tolaria +ManaCost:no cost +Types:Legendary Land +A:AB$ Mana | Cost$ T | Produced$ U | SpellDescription$ Add U to your mana pool. +A:AB$ Debuff | Cost$ T | ValidTgts$ Creature | TgtPrompt$ Select target creature | Keywords$ Banding & Bands with Other Creatures named Wolves of the Hunt & Bands with Other Legendary Creatures | ActivationPhases$ Upkeep | SpellDescription$ Target creature loses banding and all "bands with other" abilities until end of turn. Activate this ability only during any upkeep step. | StackDescription$ SpellDescription +SVar:RemAIDeck:True +SVar:Picture:http://www.wizards.com/global/images/magic/general/tolaria.jpg +Oracle:{T}: Add {U} to your mana pool.\n{T}: Target creature loses banding and all "bands with other" abilities until end of turn. Activate this ability only during any upkeep step. diff --git a/res/cardsfolder/u/unholy_citadel.txt b/res/cardsfolder/u/unholy_citadel.txt new file mode 100644 index 00000000000..eda4172ce0c --- /dev/null +++ b/res/cardsfolder/u/unholy_citadel.txt @@ -0,0 +1,7 @@ +Name:Unholy Citadel +ManaCost:no cost +Types:Land +S:Mode$ Continuous | Affected$ Creature.Black+Legendary | AddKeyword$ Bands with Other Legendary Creatures | Description$ Black legendary creatures you control have "bands with other legendary creatures." (Any legendary creatures can attack in a band as long as at least one has "bands with other legendary creatures." Bands are blocked as a group. If at least two legendary creatures you control, one of which has "bands with other legendary creatures," are blocking or being blocked by the same creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking.) +SVar:RemAIDeck:True +SVar:Picture:http://www.wizards.com/global/images/magic/general/unholy_citadel.jpg +Oracle:Black legendary creatures you control have "bands with other legendary creatures." (Any legendary creatures can attack in a band as long as at least one has "bands with other legendary creatures." Bands are blocked as a group. If at least two legendary creatures you control, one of which has "bands with other legendary creatures," are blocking or being blocked by the same creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking.) diff --git a/src/main/java/forge/game/combat/AttackingBand.java b/src/main/java/forge/game/combat/AttackingBand.java index 6a296c5b613..49667acad31 100644 --- a/src/main/java/forge/game/combat/AttackingBand.java +++ b/src/main/java/forge/game/combat/AttackingBand.java @@ -46,23 +46,52 @@ public class AttackingBand implements Comparable { public void calculateBlockedState() { this.blocked = !this.blockers.isEmpty(); } - public boolean canJoinBand(Card card) { - // If this card has banding it can definitely join - if (card.hasKeyword("Banding")) { + public static boolean isValidBand(List band, boolean shareDamage) { + if (band.isEmpty()) { + // An empty band is not a valid band + return false; + } + + int bandingCreatures = CardLists.getKeyword(band, "Banding").size(); + int neededBandingCreatures = shareDamage ? 1 : band.size() - 1; + if (neededBandingCreatures <= bandingCreatures) { + // For starting a band, only one can be non-Banding + // For sharing damage, only one needs to be Banding return true; } - // If all of the cards in the Band have banding, it can definitely join - if (attackers.size() == CardLists.getKeyword(attackers, "Banding").size()) { - return true; + // Legends lands, Master of the Hunt, Old Fogey (just in case) + // Since Bands With Other is a dead keyword, no major reason to make this more generic + // But if someone is super motivated, feel free to do it. Just make sure you update Tolaria and Shelkie Brownie + String[] bandsWithString = { "Bands with Other Legendary Creatures", "Bands with Other Creatures named Wolves of the Hunt", + "Bands with Other Dinosaurs" }; + String[] validString = { "Legendary.Creature", "Creature.namedWolves of the Hunt", "Dinosaur" }; + + Card source = band.get(0); + for(int i = 0; i < bandsWithString.length; i++) { + String keyword = bandsWithString[i]; + String valid = validString[i]; + + // Check if a bands with other keyword exists in band, and each creature in the band fits the valid quality + if (!CardLists.getKeyword(band, keyword).isEmpty() && + CardLists.getValidCards(band, valid, source.getController(), source).size() == band.size()) { + return true; + } } - - // TODO add checks for bands with other - //List bandsWithOther = CardLists.getKeyword(attackers, "Bands with Other"); - + return false; } + public boolean canJoinBand(Card card) { + // Trying to join an existing band, attackers should be non-empty and card should exist + List newBand = new ArrayList(attackers); + if (card != null) { + newBand.add(card); + } + + return isValidBand(newBand, false); + } + /* (non-Javadoc) * @see java.lang.Comparable#compareTo(java.lang.Object) */ diff --git a/src/main/java/forge/game/phase/Combat.java b/src/main/java/forge/game/phase/Combat.java index e16ee2e7333..e97d92b6cb1 100644 --- a/src/main/java/forge/game/phase/Combat.java +++ b/src/main/java/forge/game/phase/Combat.java @@ -446,7 +446,7 @@ public class Combat { if (ordered) { list = this.attackerDamageAssignmentOrder.containsKey(card) ? this.attackerDamageAssignmentOrder.get(card) : null; } else { - list = this.getBandByAttacker(card) != null ? this.getBandByAttacker(card).getBlockers() : null; + list = this.attackerToBandMap.containsKey(card) ? this.getBandByAttacker(card).getBlockers() : null; } if (list == null) { @@ -619,13 +619,8 @@ public class Combat { Player attackingPlayer = this.getAttackingPlayer(); Player assigningPlayer = blocker.getController(); - List bandingAttackers = CardLists.getKeyword(attackers, "Banding"); - if (!bandingAttackers.isEmpty()) { + if (AttackingBand.isValidBand(attackers, true)) { assigningPlayer = attackingPlayer; - } else { - // TODO Get each bands with other creature - // Check if any other valid creatures matches the bands with other - // assigningPlayer = blockingBand.get(0).getController(); } assignedDamage = true; @@ -677,13 +672,8 @@ public class Combat { if (defender instanceof Player && defender.hasKeyword("You assign combat damage of each creature attacking you.")) { assigningPlayer = (Player)defender; } else { - List blockingBand = CardLists.getKeyword(blockers, "Banding"); - if (!blockingBand.isEmpty()) { - assigningPlayer = blockingBand.get(0).getController(); - } else { - // TODO Get each bands with other creature - // Check if any other valid creatures matches the bands with other - // assigningPlayer = blockingBand.get(0).getController(); + if (AttackingBand.isValidBand(blockers, true)) { + assigningPlayer = blockers.get(0).getController(); } } diff --git a/src/main/java/forge/gui/input/InputAttack.java b/src/main/java/forge/gui/input/InputAttack.java index fe233ed3170..493d71903bf 100644 --- a/src/main/java/forge/gui/input/InputAttack.java +++ b/src/main/java/forge/gui/input/InputAttack.java @@ -123,8 +123,9 @@ public class InputAttack extends InputSyncronizedBase { combat.removeFromCombat(card); card.setUsedToPay(false); showCombat(); - // When removing an attacker should I clear the attacking band? - this.activateBand(this.activeBand); + // When removing an attacker clear the attacking band + this.activateBand(null); + return; } diff --git a/src/main/java/forge/gui/match/controllers/CCombat.java b/src/main/java/forge/gui/match/controllers/CCombat.java index 70900d9f2bd..65a65e291ae 100644 --- a/src/main/java/forge/gui/match/controllers/CCombat.java +++ b/src/main/java/forge/gui/match/controllers/CCombat.java @@ -88,11 +88,17 @@ public enum CCombat implements ICDoc { display.append(defender.getName()).append(" is attacked by:\n"); // Associate Bands, Attackers Blockers + boolean previousBand = false; for(AttackingBand band : bands) { + // Space out band blocks from non-band blocks + if (previousBand) { + display.append("\n"); + } + boolean isBand = band.getAttackers().size() > 1; if (isBand) { // Only print Band data if it's actually a band - display.append(" BAND"); + display.append(" > BAND"); if (band.getBlocked()) { display.append(" (blocked)"); } @@ -114,6 +120,7 @@ public enum CCombat implements ICDoc { for (final Card element : band.getBlockers()) { display.append(" < ").append(combatantToString(element)).append("\n"); } + previousBand = isBand; } } return display.toString().trim();