Keyword: add 'Bands with other' keyword (#5950)

This commit is contained in:
Hans Mackowiak
2024-08-19 06:32:44 +02:00
committed by GitHub
parent bb07351d4e
commit 492ff16c12
16 changed files with 40 additions and 43 deletions

View File

@@ -32,6 +32,7 @@ import forge.game.combat.CombatUtil;
import forge.game.combat.GlobalAttackRestrictions;
import forge.game.cost.Cost;
import forge.game.keyword.Keyword;
import forge.game.keyword.KeywordInterface;
import forge.game.player.Player;
import forge.game.player.PlayerCollection;
import forge.game.spellability.SpellAbility;
@@ -509,13 +510,9 @@ public class AiAttackController {
return;
}
List<String> bandsWithString = Arrays.asList("Bands with Other Legendary Creatures",
"Bands with Other Creatures named Wolves of the Hunt",
"Bands with Other Dinosaurs");
List<Card> bandingCreatures = null;
if (test == null) {
bandingCreatures = CardLists.filter(myList, card -> card.hasKeyword(Keyword.BANDING) || card.hasAnyKeyword(bandsWithString));
bandingCreatures = CardLists.filter(myList, card -> card.hasKeyword(Keyword.BANDING) || card.hasKeyword(Keyword.BANDSWITH));
// filter out anything that can't legally attack or is already declared as an attacker
bandingCreatures = CardLists.filter(bandingCreatures, card -> !combat.isAttacking(card) && CombatUtil.canAttack(card));
@@ -523,7 +520,7 @@ public class AiAttackController {
bandingCreatures = notNeededAsBlockers(attackers, bandingCreatures);
} else {
// Test a specific creature for Banding
if (test.hasKeyword(Keyword.BANDING) || test.hasAnyKeyword(bandsWithString)) {
if (test.hasKeyword(Keyword.BANDING) || test.hasKeyword(Keyword.BANDSWITH)) {
bandingCreatures = new CardCollection(test);
}
}
@@ -541,7 +538,7 @@ public class AiAttackController {
// TODO: Assign to band with the best attacker for now, but needs better logic.
for (Card c : bandingCreatures) {
Card bestBand;
Card bestBand = null;
if (c.getNetPower() <= 0) {
// Don't band a zero power creature if there's already a banding creature in a band
@@ -549,12 +546,16 @@ public class AiAttackController {
}
Card bestAttacker = ComputerUtilCard.getBestCreatureAI(attackers);
if (c.hasKeyword("Bands with Other Legendary Creatures")) {
bestBand = ComputerUtilCard.getBestCreatureAI(CardLists.getType(attackers, "Legendary"));
} else if (c.hasKeyword("Bands with Other Dinosaurs")) {
bestBand = ComputerUtilCard.getBestCreatureAI(CardLists.getType(attackers, "Dinosaur"));
} else if (c.hasKeyword("Bands with Other Creatures named Wolves of the Hunt")) {
bestBand = ComputerUtilCard.getBestCreatureAI(CardLists.filter(attackers, CardPredicates.nameEquals("Wolves of the Hunt")));
// TODO how should this work with multiple bands with other abilities?
if (c.hasKeyword(Keyword.BANDSWITH)) {
for (KeywordInterface kw : c.getKeywords(Keyword.BANDSWITH)) {
final String o = kw.getOriginal();
String m[] = o.split(":");
CardCollection bandPartner = CardLists.getValidCards(attackers, m[1], c.getController(), c, null);
bestBand = ComputerUtilCard.getBestCreatureAI(bandPartner);
break; // ?
}
} else if (!c.hasAnyKeyword(evasionKeywords) && bestAttacker != null && bestAttacker.hasAnyKeyword(evasionKeywords)) {
bestBand = ComputerUtilCard.getBestCreatureAI(CardLists.filter(attackers, card -> !card.hasAnyKeyword(evasionKeywords)));
} else {

View File

@@ -753,10 +753,6 @@ public class AiBlockController {
boolean needsMoreChumpBlockers = true;
// See if it's possible to tank up the damage with Banding
List<String> bandsWithString = Arrays.asList("Bands with Other Legendary Creatures",
"Bands with Other Creatures named Wolves of the Hunt",
"Bands with Other Dinosaurs");
if (AttackingBand.isValidBand(combat.getBlockers(attacker), true)) {
continue;
}
@@ -766,7 +762,7 @@ public class AiBlockController {
// See if there's a Banding blocker that can tank the damage
for (final Card blocker : chumpBlockers) {
if (blocker.hasKeyword(Keyword.BANDING) || blocker.hasAnyKeyword(bandsWithString)) {
if (blocker.hasKeyword(Keyword.BANDING) || blocker.hasKeyword(Keyword.BANDSWITH)) {
if (ComputerUtilCombat.getAttack(attacker) > ComputerUtilCombat.totalShieldDamage(attacker, combat.getBlockers(attacker))
&& ComputerUtilCombat.shieldDamage(attacker, blocker) > 0
&& CombatUtil.canBlock(attacker, blocker, combat) && ComputerUtilCombat.lifeInDanger(ai, combat)) {

View File

@@ -2479,6 +2479,10 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
sb.append("exile it haunting target creature.");
}
sb.append(")");
} else if (keyword.startsWith("Bands with other")) {
final String[] k = keyword.split(":");
String desc = k.length > 2 ? k[2] : CardType.getPluralType(k[1]);
sbLong.append(k[0]).append(" ").append(desc).append(" (").append(inst.getReminderText()).append(")");
} else if (keyword.equals("Convoke") || keyword.equals("Dethrone")|| keyword.equals("Fear")
|| keyword.equals("Melee") || keyword.equals("Improvise")|| keyword.equals("Shroud")
|| keyword.equals("Banding") || keyword.equals("Intimidate")|| keyword.equals("Evolve")

View File

@@ -60,6 +60,7 @@ public final class CardUtil {
"Fortify", "Transfigure", "Champion", "Evoke", "Prowl", "Freerunning",
"Reinforce", "Unearth", "Level up", "Miracle", "Overload", "Cleave",
"Scavenge", "Encore", "Bestow", "Outlast", "Dash", "Surge", "Emerge", "Hexproof:",
"Bands with other",
"etbCounter", "Reflect", "Ward").build();
/** List of keyword endings of keywords that could be modified by text changes. */
public static final ImmutableList<String> modifiableKeywordEndings = ImmutableList.<String>builder().add(

View File

@@ -5,6 +5,7 @@ import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.keyword.Keyword;
import forge.game.keyword.KeywordInterface;
import java.util.List;
@@ -39,24 +40,16 @@ public class AttackingBand {
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" };
for (Card c : CardLists.getKeyword(band, Keyword.BANDSWITH)) {
for (KeywordInterface kw : c.getKeywords(Keyword.BANDSWITH)) {
String o = kw.getOriginal();
String m[] = o.split(":");
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, null).size() == band.size()) {
if (CardLists.getValidCards(band, m[1], c.getController(), c, null).size() == band.size()) {
return true;
}
}
}
return false;
}

View File

@@ -22,6 +22,7 @@ public enum Keyword {
AWAKEN("Awaken", KeywordWithCostAndAmount.class, false, "If you cast this spell for %s, also put {%d:+1/+1 counter} on target land you control and it becomes a 0/0 Elemental creature with haste. It's still a land."),
BACKUP("Backup", KeywordWithAmount.class, false, "When this creature enters, put {%1$d:+1/+1 counter} on target creature. If that's another creature, it gains the following ability until end of turn."),
BANDING("Banding", SimpleKeyword.class, true, "Any creatures with banding, and up to one without, can attack in a band. Bands are blocked as a group. If any creatures with banding you control are blocking or being blocked by a creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking."),
BANDSWITH("Bands with other", KeywordWithType.class, false, "can attack in a band with another %s"),
BARGAIN("Bargain", SimpleKeyword.class, false, "You may sacrifice an artifact, enchantment, or token as you cast this spell."),
BATTLE_CRY("Battle cry", SimpleKeyword.class, false, "Whenever this creature attacks, each other attacking creature gets +1/+0 until end of turn."),
BESTOW("Bestow", KeywordWithCost.class, false, "If you cast this card for its bestow cost, it's an Aura spell with enchant creature. It becomes a creature again if it's not attached to a creature."),

View File

@@ -20,6 +20,7 @@ public class KeywordWithType extends KeywordInstance<KeywordWithType> {
type = "artifact, legendary, and/or Saga permanent";
}
break;
case BANDSWITH:
case HEXPROOF:
case LANDWALK:
type = details.split(":")[1];

View File

@@ -1,7 +1,7 @@
Name:Adventurers' Guildhouse
ManaCost:no cost
Types:Land
S:Mode$ Continuous | Affected$ Creature.Green+Legendary+YouCtrl | 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.)
S:Mode$ Continuous | Affected$ Creature.Green+Legendary+YouCtrl | AddKeyword$ Bands with other:Creature.Legendary: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:NonStackingEffect:True
DeckNeeds:Color$Green & Type$Legendary
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.)

View File

@@ -1,7 +1,7 @@
Name:Cathedral of Serra
ManaCost:no cost
Types:Land
S:Mode$ Continuous | Affected$ Creature.White+Legendary+YouCtrl | 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.)
S:Mode$ Continuous | Affected$ Creature.White+Legendary+YouCtrl | AddKeyword$ Bands with other:Creature.Legendary: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:NonStackingEffect:True
DeckHas:Keyword$BandsWithOther
DeckNeeds:Type$Legendary & Color$White

View File

@@ -1,6 +1,6 @@
Name:Mountain Stronghold
ManaCost:no cost
Types:Land
S:Mode$ Continuous | Affected$ Creature.Red+Legendary+YouCtrl | 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.)
S:Mode$ Continuous | Affected$ Creature.Red+Legendary+YouCtrl | AddKeyword$ Bands with other:Creature.Legendary: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.)
DeckNeeds:Color$Red & Type$Legendary
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.)

View File

@@ -6,7 +6,7 @@ K:Phasing
K:Cumulative upkeep:1
K:Echo:G G
K:Fading:3
K:Bands with Other Dinosaurs
K:Bands with other:Dinosaur
K:Landwalk:Plains.Snow:Snow Plains
K:Protection:Homarid:Homarids
K:Flanking

View File

@@ -1,6 +1,6 @@
Name:Seafarer's Quay
ManaCost:no cost
Types:Land
S:Mode$ Continuous | Affected$ Creature.Blue+Legendary+YouCtrl | 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.)
S:Mode$ Continuous | Affected$ Creature.Blue+Legendary+YouCtrl | AddKeyword$ Bands with other:Creature.Legendary: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.)
DeckNeeds:Type$Legendary & Color$Blue
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.)

View File

@@ -2,5 +2,5 @@ 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
A:AB$ Debuff | Cost$ T | ValidTgts$ Creature | TgtPrompt$ Select target creature | Keywords$ Bands with other | SpellDescription$ Target creature loses all "bands with other" abilities until end of turn. | StackDescription$ SpellDescription
Oracle:{T}: Target creature loses all "bands with other" abilities until end of turn.

View File

@@ -2,5 +2,5 @@ Name:Tolaria
ManaCost:no cost
Types:Legendary Land
A:AB$ Mana | Cost$ T | Produced$ U | SpellDescription$ Add {U}.
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 only during any upkeep step. | StackDescription$ SpellDescription
A:AB$ Debuff | Cost$ T | ValidTgts$ Creature | TgtPrompt$ Select target creature | Keywords$ Banding & Bands with other | ActivationPhases$ Upkeep | SpellDescription$ Target creature loses banding and all "bands with other" abilities until end of turn. Activate only during any upkeep step. | StackDescription$ SpellDescription
Oracle:{T}: Add {U}.\n{T}: Target creature loses banding and all "bands with other" abilities until end of turn. Activate only during any upkeep step.

View File

@@ -1,7 +1,7 @@
Name:Unholy Citadel
ManaCost:no cost
Types:Land
S:Mode$ Continuous | Affected$ Creature.Black+Legendary+YouCtrl | 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.)
S:Mode$ Continuous | Affected$ Creature.Black+Legendary+YouCtrl | AddKeyword$ Bands with other:Creature.Legendary: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:NonStackingEffect:True
DeckNeeds:Type$Legendary & Color$Black
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.)

View File

@@ -3,5 +3,5 @@ ManaCost:no cost
Colors:green
Types:Creature Wolf
PT:1/1
K:Bands with Other Creatures named Wolves of the Hunt
K:Bands with other:Creature.namedWolves of the Hunt:Creatures named Wolves of the Hunt
Oracle:Bands with other creatures named Wolves of the Hunt.