CountersAi: skip for only one against Vorinclex

This commit is contained in:
tool4EvEr
2021-10-10 18:49:29 +02:00
parent e773868f18
commit f0a3d19d38
5 changed files with 26 additions and 19 deletions

View File

@@ -22,13 +22,17 @@ import java.util.List;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import forge.ai.ComputerUtilCard; import forge.ai.ComputerUtilCard;
import forge.ai.SpellAbilityAi;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView; import forge.game.card.CardCollectionView;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CounterEnumType; import forge.game.card.CounterEnumType;
import forge.game.card.CounterType; import forge.game.card.CounterType;
import forge.game.keyword.Keyword; import forge.game.keyword.Keyword;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.util.Aggregates; import forge.util.Aggregates;
@@ -40,7 +44,7 @@ import forge.util.Aggregates;
* @author Forge * @author Forge
* @version $Id$ * @version $Id$
*/ */
public abstract class CountersAi { public abstract class CountersAi extends SpellAbilityAi {
// An AbilityFactory subclass for Putting or Removing Counters on Cards. // An AbilityFactory subclass for Putting or Removing Counters on Cards.
/** /**
@@ -54,10 +58,16 @@ public abstract class CountersAi {
* a {@link java.lang.String} object. * a {@link java.lang.String} object.
* @param amount * @param amount
* a int. * a int.
* @param newParam TODO
* @return a {@link forge.game.card.Card} object. * @return a {@link forge.game.card.Card} object.
*/ */
public static Card chooseCursedTarget(final CardCollectionView list, final String type, final int amount) { public static Card chooseCursedTarget(final CardCollectionView list, final String type, final int amount, final Player ai) {
Card choice; Card choice;
if (amount == 1 && !CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Vorinclex, Monstrous Raider")).isEmpty()) {
return null;
}
if (type.equals("M1M1")) { if (type.equals("M1M1")) {
// try to kill the best killable creature, or reduce the best one // try to kill the best killable creature, or reduce the best one
// but try not to target a Undying Creature // but try not to target a Undying Creature
@@ -87,6 +97,7 @@ public abstract class CountersAi {
*/ */
public static Card chooseBoonTarget(final CardCollectionView list, final String type) { public static Card chooseBoonTarget(final CardCollectionView list, final String type) {
Card choice = null; Card choice = null;
if (type.equals("P1P1")) { if (type.equals("P1P1")) {
choice = ComputerUtilCard.getBestCreatureAI(list); choice = ComputerUtilCard.getBestCreatureAI(list);

View File

@@ -49,7 +49,6 @@ public class CountersMultiplyAi extends SpellAbilityAi {
if (!c.canReceiveCounters(counterType)) { if (!c.canReceiveCounters(counterType)) {
return false; return false;
} }
} else { } else {
for (Map.Entry<CounterType, Integer> e : c.getCounters().entrySet()) { for (Map.Entry<CounterType, Integer> e : c.getCounters().entrySet()) {
// has negative counter it would double // has negative counter it would double
@@ -146,7 +145,7 @@ public class CountersMultiplyAi extends SpellAbilityAi {
CardCollection aiList = CardLists.filterControlledBy(list, ai); CardCollection aiList = CardLists.filterControlledBy(list, ai);
if (!aiList.isEmpty()) { if (!aiList.isEmpty()) {
// counter type list to check // counter type list to check
// first loyalty, then P1P!, then Charge Counter // first loyalty, then P1P1, then Charge Counter
List<CounterEnumType> typeList = Lists.newArrayList(CounterEnumType.LOYALTY, CounterEnumType.P1P1, CounterEnumType.CHARGE); List<CounterEnumType> typeList = Lists.newArrayList(CounterEnumType.LOYALTY, CounterEnumType.P1P1, CounterEnumType.CHARGE);
for (CounterEnumType type : typeList) { for (CounterEnumType type : typeList) {
// enough targets // enough targets
@@ -182,7 +181,6 @@ public class CountersMultiplyAi extends SpellAbilityAi {
private void addTargetsByCounterType(final Player ai, final SpellAbility sa, final CardCollection list, private void addTargetsByCounterType(final Player ai, final SpellAbility sa, final CardCollection list,
final CounterType type) { final CounterType type) {
CardCollection newList = CardLists.filter(list, CardPredicates.hasCounter(type)); CardCollection newList = CardLists.filter(list, CardPredicates.hasCounter(type));
if (newList.isEmpty()) { if (newList.isEmpty()) {
return; return;

View File

@@ -53,7 +53,7 @@ import forge.game.zone.ZoneType;
import forge.util.Aggregates; import forge.util.Aggregates;
import forge.util.MyRandom; import forge.util.MyRandom;
public class CountersPutAi extends SpellAbilityAi { public class CountersPutAi extends CountersAi {
/* /*
* (non-Javadoc) * (non-Javadoc)
@@ -179,7 +179,7 @@ public class CountersPutAi extends SpellAbilityAi {
if (abTgt.canTgtCreature()) { if (abTgt.canTgtCreature()) {
// try to kill creature with -1/-1 counters if it can // try to kill creature with -1/-1 counters if it can
// receive counters, execpt it has undying // receive counters, except it has undying
CardCollection oppCreat = CardLists.getTargetableCards(ai.getOpponents().getCreaturesInPlay(), sa); CardCollection oppCreat = CardLists.getTargetableCards(ai.getOpponents().getCreaturesInPlay(), sa);
CardCollection oppCreatM1 = CardLists.filter(oppCreat, CardPredicates.hasCounter(CounterEnumType.M1M1)); CardCollection oppCreatM1 = CardLists.filter(oppCreat, CardPredicates.hasCounter(CounterEnumType.M1M1));
oppCreatM1 = CardLists.getNotKeyword(oppCreatM1, Keyword.UNDYING); oppCreatM1 = CardLists.getNotKeyword(oppCreatM1, Keyword.UNDYING);
@@ -549,7 +549,7 @@ public class CountersPutAi extends SpellAbilityAi {
} }
if (sa.isCurse()) { if (sa.isCurse()) {
choice = CountersAi.chooseCursedTarget(list, type, amount); choice = chooseCursedTarget(list, type, amount, ai);
} else { } else {
if (type.equals("P1P1") && !SpellAbilityAi.isSorcerySpeed(sa)) { if (type.equals("P1P1") && !SpellAbilityAi.isSorcerySpeed(sa)) {
for (Card c : list) { for (Card c : list) {
@@ -564,15 +564,15 @@ public class CountersPutAi extends SpellAbilityAi {
if (abCost == null if (abCost == null
|| (ph.is(PhaseType.END_OF_TURN) && ph.getPlayerTurn().isOpponentOf(ai))) { || (ph.is(PhaseType.END_OF_TURN) && ph.getPlayerTurn().isOpponentOf(ai))) {
// only use at opponent EOT unless it is free // only use at opponent EOT unless it is free
choice = CountersAi.chooseBoonTarget(list, type); choice = chooseBoonTarget(list, type);
} }
} }
} }
if (ComputerUtilAbility.getAbilitySourceName(sa).equals("Dromoka's Command")) { if (ComputerUtilAbility.getAbilitySourceName(sa).equals("Dromoka's Command")) {
choice = CountersAi.chooseBoonTarget(list, type); choice = chooseBoonTarget(list, type);
} }
} else { } else {
choice = CountersAi.chooseBoonTarget(list, type); choice = chooseBoonTarget(list, type);
} }
} }
@@ -681,7 +681,6 @@ public class CountersPutAi extends SpellAbilityAi {
sa.resetTargets(); sa.resetTargets();
// target loop // target loop
while (sa.canAddMoreTarget()) { while (sa.canAddMoreTarget()) {
if (list.isEmpty()) { if (list.isEmpty()) {
if (!sa.isTargetNumberValid() if (!sa.isTargetNumberValid()
|| sa.getTargets().size() == 0) { || sa.getTargets().size() == 0) {
@@ -693,7 +692,7 @@ public class CountersPutAi extends SpellAbilityAi {
} }
if (sa.isCurse()) { if (sa.isCurse()) {
choice = CountersAi.chooseCursedTarget(list, type, amount); choice = chooseCursedTarget(list, type, amount, ai);
} else { } else {
CardCollection lands = CardLists.filter(list, CardPredicates.Presets.LANDS); CardCollection lands = CardLists.filter(list, CardPredicates.Presets.LANDS);
SpellAbility animate = sa.findSubAbilityByType(ApiType.Animate); SpellAbility animate = sa.findSubAbilityByType(ApiType.Animate);
@@ -702,7 +701,7 @@ public class CountersPutAi extends SpellAbilityAi {
} else if ("BoonCounterOnOppCreature".equals(logic)) { } else if ("BoonCounterOnOppCreature".equals(logic)) {
choice = ComputerUtilCard.getWorstCreatureAI(list); choice = ComputerUtilCard.getWorstCreatureAI(list);
} else { } else {
choice = CountersAi.chooseBoonTarget(list, type); choice = chooseBoonTarget(list, type);
} }
} }
@@ -838,7 +837,7 @@ public class CountersPutAi extends SpellAbilityAi {
// Choose targets here: // Choose targets here:
if (sa.isCurse()) { if (sa.isCurse()) {
if (preferred) { if (preferred) {
choice = CountersAi.chooseCursedTarget(list, type, amount); choice = chooseCursedTarget(list, type, amount, ai);
if (choice == null && mandatory) { if (choice == null && mandatory) {
choice = Aggregates.random(list); choice = Aggregates.random(list);
} }
@@ -852,7 +851,7 @@ public class CountersPutAi extends SpellAbilityAi {
} else { } else {
if (preferred) { if (preferred) {
list = ComputerUtil.getSafeTargets(ai, sa, list); list = ComputerUtil.getSafeTargets(ai, sa, list);
choice = CountersAi.chooseBoonTarget(list, type); choice = chooseBoonTarget(list, type);
if (choice == null && mandatory) { if (choice == null && mandatory) {
choice = Aggregates.random(list); choice = Aggregates.random(list);
} }

View File

@@ -104,7 +104,7 @@ public class PoisonAi extends SpellAbilityAi {
if (!betterTgts.isEmpty()) { if (!betterTgts.isEmpty()) {
tgts = betterTgts; tgts = betterTgts;
} else if (mandatory) { } else if (mandatory) {
// no better choice but better than hiting himself // no better choice but better than hitting himself
sa.getTargets().add(tgts.getFirst()); sa.getTargets().add(tgts.getFirst());
return true; return true;
} }
@@ -121,7 +121,7 @@ public class PoisonAi extends SpellAbilityAi {
// need to target something, try to target allies // need to target something, try to target allies
PlayerCollection allies = ai.getAllies().filter(PlayerPredicates.isTargetableBy(sa)); PlayerCollection allies = ai.getAllies().filter(PlayerPredicates.isTargetableBy(sa));
if (!allies.isEmpty()) { if (!allies.isEmpty()) {
// some ally would be uneffected // some ally would be unaffected
PlayerCollection betterAllies = allies.filter(new Predicate<Player>() { PlayerCollection betterAllies = allies.filter(new Predicate<Player>() {
@Override @Override
public boolean apply(Player input) { public boolean apply(Player input) {

View File

@@ -145,7 +145,6 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
} }
public boolean requirementsCheck(Game game, Map<String,String> params) { public boolean requirementsCheck(Game game, Map<String,String> params) {
if (this.isSuppressed()) { if (this.isSuppressed()) {
return false; // Effect removed by effect return false; // Effect removed by effect
} }