- Improve the CostDiscard logic a little for cases where CARDNAME itself is discarded.

This commit is contained in:
Michael Kamensky
2021-08-15 09:29:55 +03:00
parent 16f7ac2949
commit 43c68ddfcb
3 changed files with 26 additions and 38 deletions

View File

@@ -1,47 +1,22 @@
package forge.ai;
import java.util.List;
import java.util.Set;
import forge.game.ability.ApiType;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import forge.ai.AiCardMemory.MemorySet;
import forge.ai.ability.AnimateAi;
import forge.card.ColorSet;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.ability.ApiType;
import forge.game.card.*;
import forge.game.card.CardPredicates.Presets;
import forge.game.card.CardUtil;
import forge.game.card.CounterEnumType;
import forge.game.card.CounterType;
import forge.game.combat.Combat;
import forge.game.cost.Cost;
import forge.game.cost.CostDamage;
import forge.game.cost.CostDiscard;
import forge.game.cost.CostPart;
import forge.game.cost.CostPayLife;
import forge.game.cost.CostPayment;
import forge.game.cost.CostPutCounter;
import forge.game.cost.CostRemoveAnyCounter;
import forge.game.cost.CostRemoveCounter;
import forge.game.cost.CostSacrifice;
import forge.game.cost.CostTapType;
import forge.game.cost.PaymentDecision;
import forge.game.cost.*;
import forge.game.keyword.Keyword;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.Spell;
import forge.game.spellability.SpellAbility;
@@ -49,6 +24,11 @@ import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import forge.util.TextUtil;
import forge.util.collect.FCollectionView;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Set;
public class ComputerUtilCost {
@@ -154,8 +134,14 @@ public class ComputerUtilCost {
final CostDiscard disc = (CostDiscard) part;
final String type = disc.getType();
if (type.equals("CARDNAME") && source.getAbilityText().contains("Bloodrush")) {
continue;
if (type.equals("CARDNAME")) {
if (source.getAbilityText().contains("Bloodrush")) {
continue;
} else if (ai.getGame().getPhaseHandler().is(PhaseType.END_OF_TURN, ai)
&& ai.getCardsIn(ZoneType.Hand).size() > ai.getMaxHandSize()) {
// Better do something than just discard stuff
return true;
}
}
final CardCollection typeList = CardLists.getValidCards(hand, type.split(","), source.getController(), source, sa);
if (typeList.size() > ai.getMaxHandSize()) {

View File

@@ -1,12 +1,7 @@
package forge.ai;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.card.CardStateName;
import forge.card.ICardFace;
import forge.card.mana.ManaCost;
@@ -24,8 +19,13 @@ import forge.game.player.PlayerController.BinaryChoiceType;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityCondition;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Base class for API-specific AI logic
* <p>
@@ -72,10 +72,12 @@ public abstract class SpellAbilityAi {
if (sa.hasParam("AILogic")) {
final String logic = sa.getParam("AILogic");
final boolean alwaysOnDiscard = "AlwaysOnDiscard".equals(logic) && ai.getGame().getPhaseHandler().is(PhaseType.END_OF_TURN, ai)
&& ai.getCardsIn(ZoneType.Hand).size() > ai.getMaxHandSize();
if (!checkAiLogic(ai, sa, logic)) {
return false;
}
if (!checkPhaseRestrictions(ai, sa, ai.getGame().getPhaseHandler(), logic)) {
if (!alwaysOnDiscard && !checkPhaseRestrictions(ai, sa, ai.getGame().getPhaseHandler(), logic)) {
return false;
}
} else {

View File

@@ -5,6 +5,6 @@ A:SP$ DealDamage | Cost$ 6 U R | ValidTgts$ Creature,Player,Planeswalker | TgtPr
SVar:DBTap:DB$ Tap | TargetMin$ 2 | TargetMax$ 2 | ValidTgts$ Permanent | TgtPrompt$ Select target permanent to tap | SubAbility$ DBToken
SVar:DBToken:DB$ Token | TokenScript$ ur_4_4_elemental | SubAbility$ DBDraw
SVar:DBDraw:DB$ Draw | NumCards$ 2
A:AB$ Token | Cost$ UR UR Discard<1/CARDNAME> | ActivationZone$ Hand | TokenScript$ c_a_treasure_sac | SpellDescription$ Create a Treasure token.
A:AB$ Token | Cost$ UR UR Discard<1/CARDNAME> | ActivationZone$ Hand | TokenScript$ c_a_treasure_sac | AILogic$ AlwaysOnDiscard | SpellDescription$ Create a Treasure token.
DeckHas:Ability$Token
Oracle:Magma Opus deals 4 damage divided as you choose among any number of targets. Tap two target permanents. Create a 4/4 blue and red Elemental creature token. Draw two cards.\n{U/R}{U/R}, Discard Magma Opus: Create a Treasure token.