MustBlockEffect: use Choose Card for Crashing Boars

This commit is contained in:
Hans Mackowiak
2020-03-01 10:30:45 +00:00
parent 40bb3d2750
commit 93f0ade107
3 changed files with 86 additions and 32 deletions

View File

@@ -1,7 +1,7 @@
package forge.ai.ability;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.ai.*;
import forge.game.Game;
@@ -12,11 +12,9 @@ import forge.game.card.CardPredicates;
import forge.game.combat.Combat;
import forge.game.combat.CombatUtil;
import forge.game.keyword.Keyword;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import java.util.List;
@@ -28,7 +26,6 @@ public class MustBlockAi extends SpellAbilityAi {
final Card source = sa.getHostCard();
final Game game = aiPlayer.getGame();
final Combat combat = game.getCombat();
final PhaseHandler ph = game.getPhaseHandler();
final boolean onlyLethal = !"AllowNonLethal".equals(sa.getParam("AILogic"));
if (combat == null || !combat.isAttacking(source)) {
@@ -39,7 +36,6 @@ public class MustBlockAi extends SpellAbilityAi {
return false;
}
final TargetRestrictions abTgt = sa.getTargetRestrictions();
final List<Card> list = determineGoodBlockers(source, aiPlayer, combat.getDefenderPlayerByAttacker(source), sa, onlyLethal,false);
if (!list.isEmpty()) {
@@ -69,7 +65,6 @@ public class MustBlockAi extends SpellAbilityAi {
@Override
protected boolean doTriggerAINoCost(final Player ai, SpellAbility sa, boolean mandatory) {
final Card source = sa.getHostCard();
final TargetRestrictions abTgt = sa.getTargetRestrictions();
// only use on creatures that can attack
if (!ai.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)) {
@@ -94,7 +89,7 @@ public class MustBlockAi extends SpellAbilityAi {
boolean chance = false;
if (abTgt != null) {
if (sa.usesTargeting()) {
final List<Card> list = determineGoodBlockers(definedAttacker, ai, ai.getWeakestOpponent(), sa, true,true);
if (list.isEmpty()) {
return false;
@@ -119,6 +114,9 @@ public class MustBlockAi extends SpellAbilityAi {
sa.getTargets().add(blocker);
chance = true;
} else if (sa.hasParam("Choices")) {
// currently choice is attacked player
return true;
} else {
return false;
}
@@ -126,16 +124,9 @@ public class MustBlockAi extends SpellAbilityAi {
return chance;
}
private List<Card> determineGoodBlockers(final Card attacker, final Player ai, Player defender, SpellAbility sa,
private List<Card> determineBlockerFromList(final Card attacker, final Player ai, Iterable<Card> options, SpellAbility sa,
final boolean onlyLethal, final boolean testTapped) {
final Card source = sa.getHostCard();
final TargetRestrictions abTgt = sa.getTargetRestrictions();
List<Card> list = Lists.newArrayList();
list = CardLists.filter(defender.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
list = CardLists.getTargetableCards(list, sa);
list = CardLists.getValidCards(list, abTgt.getValidTgts(), source.getController(), source, sa);
list = CardLists.filter(list, new Predicate<Card>() {
List<Card> list = CardLists.filter(options, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
boolean tapped = c.isTapped();
@@ -161,4 +152,40 @@ public class MustBlockAi extends SpellAbilityAi {
return list;
}
private List<Card> determineGoodBlockers(final Card attacker, final Player ai, Player defender, SpellAbility sa,
final boolean onlyLethal, final boolean testTapped) {
List<Card> list = Lists.newArrayList();
list = CardLists.filter(defender.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
if (sa.usesTargeting()) {
list = CardLists.getTargetableCards(list, sa);
}
return determineBlockerFromList(attacker, ai, list, sa, onlyLethal, testTapped);
}
@Override
protected Card chooseSingleCard(Player ai, SpellAbility sa, Iterable<Card> options, boolean isOptional,
Player targetedPlayer) {
final Card host = sa.getHostCard();
Card attacker = host;
if (sa.hasParam("DefinedAttacker")) {
List<Card> attackers = AbilityUtils.getDefinedCards(host, sa.getParam("DefinedAttacker"), sa);
attacker = Iterables.getFirst(attackers, null);
}
if (attacker == null) {
return Iterables.getFirst(options, null);
}
List<Card> better = determineBlockerFromList(attacker, ai, options, sa, false, false);
if (!better.isEmpty()) {
return Iterables.getFirst(options, null);
}
return Iterables.getFirst(options, null);
}
}

View File

@@ -1,34 +1,62 @@
package forge.game.ability.effects;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.Localizer;
import java.util.ArrayList;
import java.util.List;
import com.google.common.collect.Lists;
public class MustBlockEffect extends SpellAbilityEffect {
@Override
public void resolve(SpellAbility sa) {
final Card host = sa.getHostCard();
final Player activator = sa.getActivatingPlayer();
final Game game = activator.getGame();
List<Card> tgtCards = Lists.newArrayList();
if (sa.hasParam("Choices")) {
Player chooser = activator;
if (sa.hasParam("Chooser")) {
final String choose = sa.getParam("Chooser");
chooser = AbilityUtils.getDefinedPlayers(sa.getHostCard(), choose, sa).get(0);
}
CardCollectionView choices = game.getCardsIn(ZoneType.Battlefield);
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, host);
if (!choices.isEmpty()) {
String title = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : Localizer.getInstance().getMessage("lblChooseaCard") +" ";
Card choosen = chooser.getController().chooseSingleEntityForEffect(choices, sa, title, false);
if (choosen != null) {
tgtCards.add(choosen);
}
}
} else {
tgtCards = getTargetCards(sa);
}
List<Card> tgtCards = getTargetCards(sa);
final TargetRestrictions tgt = sa.getTargetRestrictions();
final boolean mustBlockAll = sa.hasParam("BlockAllDefined");
List<Card> cards;
if (sa.hasParam("DefinedAttacker")) {
cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("DefinedAttacker"), sa);
} else {
cards = new ArrayList<>();
cards.add(host);
cards = Lists.newArrayList(host);
}
for (final Card c : tgtCards) {
if ((tgt == null) || c.canBeTargetedBy(sa)) {
if ((!sa.usesTargeting()) || c.canBeTargetedBy(sa)) {
if (mustBlockAll) {
c.addMustBlockCards(cards);
} else {
@@ -48,8 +76,6 @@ public class MustBlockEffect extends SpellAbilityEffect {
// end standard pre-
final List<Card> tgtCards = getTargetCards(sa);
String attacker = null;
if (sa.hasParam("DefinedAttacker")) {
final List<Card> cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("DefinedAttacker"), sa);
@@ -58,10 +84,13 @@ public class MustBlockEffect extends SpellAbilityEffect {
attacker = host.toString();
}
for (final Card c : tgtCards) {
sb.append(c).append(" must block ").append(attacker).append(" if able.");
if (sa.hasParam("Choices")) {
sb.append("Choosen creature ").append(" must block ").append(attacker).append(" if able.");
} else {
for (final Card c : getTargetCards(sa)) {
sb.append(c).append(" must block ").append(attacker).append(" if able.");
}
}
return sb.toString();
}

View File

@@ -2,8 +2,6 @@ Name:Crashing Boars
ManaCost:3 G G
Types:Creature Boar
PT:4/4
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigChoose | TriggerDescription$ Whenever CARDNAME attacks, defending player chooses an untapped creature they control. That creature blocks CARDNAME this turn if able.
SVar:TrigChoose:DB$ ChooseCard | Defined$ DefendingPlayer | Amount$ 1 | Choices$ Creature.untapped+DefenderCtrl | Mandatory$ True | SubAbility$ DBMustBlock
SVar:DBMustBlock:DB$ MustBlock | Defined$ ChosenCard
SVar:Picture:http://www.wizards.com/global/images/magic/general/crashing_boars.jpg
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ DBMustBlock | TriggerDescription$ Whenever CARDNAME attacks, defending player chooses an untapped creature they control. That creature blocks CARDNAME this turn if able.
SVar:DBMustBlock:DB$ MustBlock | Choices$ Creature.untapped+DefenderCtrl | Chooser$ DefendingPlayer
Oracle:Whenever Crashing Boars attacks, defending player chooses an untapped creature they control. That creature blocks Crashing Boars this turn if able.