mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 18:28:00 +00:00
- Improve AI logic for bouncing creatures, e.g. Restoration Angel.
This commit is contained in:
@@ -2,6 +2,8 @@ package forge.ai.ability;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import forge.game.card.*;
|
||||||
|
import forge.game.keyword.Keyword;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
@@ -32,14 +34,7 @@ import forge.game.GlobalRuleChange;
|
|||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardCollectionView;
|
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.card.CardPredicates;
|
|
||||||
import forge.game.card.CardPredicates.Presets;
|
import forge.game.card.CardPredicates.Presets;
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.card.CounterEnumType;
|
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.cost.CostDiscard;
|
import forge.game.cost.CostDiscard;
|
||||||
@@ -1397,6 +1392,42 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Reload Undying and Persist, get rid of -1/-1 counters, get rid of enemy auras if able
|
||||||
|
for (Card c : aiPermanents) {
|
||||||
|
if (c.isCreature()) {
|
||||||
|
boolean hasValuableAttachments = false;
|
||||||
|
boolean hasOppAttachments = false;
|
||||||
|
int numNegativeCounters = 0;
|
||||||
|
int numTotalCounters = 0;
|
||||||
|
for (Card attached : c.getAttachedCards()) {
|
||||||
|
if (attached.isAura()) {
|
||||||
|
if (attached.getController() == c.getController()) {
|
||||||
|
hasValuableAttachments = true;
|
||||||
|
} else if (attached.getController().isOpponentOf(c.getController())) {
|
||||||
|
hasOppAttachments = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Map<CounterType, Integer> counters = c.getCounters();
|
||||||
|
for (CounterType ct : counters.keySet()) {
|
||||||
|
int amount = counters.get(ct);
|
||||||
|
if (ComputerUtil.isNegativeCounter(ct, c)) {
|
||||||
|
numNegativeCounters += amount;
|
||||||
|
}
|
||||||
|
numTotalCounters += amount;
|
||||||
|
}
|
||||||
|
if (hasValuableAttachments || (ComputerUtilCard.isUselessCreature(ai, c) && !hasOppAttachments)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((c.hasKeyword(Keyword.PERSIST) || c.hasKeyword(Keyword.UNDYING))
|
||||||
|
&& !ComputerUtilCard.hasActiveUndyingOrPersist(c)) {
|
||||||
|
return c;
|
||||||
|
} else if (hasOppAttachments || (numTotalCounters > 0 && numNegativeCounters > numTotalCounters / 2)) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ PT:3/4
|
|||||||
K:Flash
|
K:Flash
|
||||||
K:Flying
|
K:Flying
|
||||||
T:Mode$ ChangesZone | ValidCard$ Creature.Self | Origin$ Any | Destination$ Battlefield | Execute$ RestorationExile | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may exile target non-Angel creature you control, then return that creature to the battlefield under your control.
|
T:Mode$ ChangesZone | ValidCard$ Creature.Self | Origin$ Any | Destination$ Battlefield | Execute$ RestorationExile | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may exile target non-Angel creature you control, then return that creature to the battlefield under your control.
|
||||||
SVar:RestorationExile:DB$ ChangeZone | ValidTgts$ Creature.nonAngel+YouCtrl | TgtPrompt$ Select target non-Angel creature you control | Origin$ Battlefield | Destination$ Exile | RememberTargets$ True | ForgetOtherTargets$ True | AILogic$ BounceOnce | SubAbility$ RestorationReturn
|
SVar:RestorationExile:DB$ ChangeZone | ValidTgts$ Creature.nonAngel+YouCtrl | TgtPrompt$ Select target non-Angel creature you control | Origin$ Battlefield | Destination$ Exile | RememberTargets$ True | ForgetOtherTargets$ True | SubAbility$ RestorationReturn
|
||||||
SVar:RestorationReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield | GainControl$ True
|
SVar:RestorationReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield | GainControl$ True
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/restoration_angel.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/restoration_angel.jpg
|
||||||
Oracle:Flash\nFlying\nWhen Restoration Angel enters the battlefield, you may exile target non-Angel creature you control, then return that card to the battlefield under your control.
|
Oracle:Flash\nFlying\nWhen Restoration Angel enters the battlefield, you may exile target non-Angel creature you control, then return that card to the battlefield under your control.
|
||||||
|
|||||||
Reference in New Issue
Block a user