mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +00:00
- Unbreak some AI logic parts
This commit is contained in:
committed by
Hans Mackowiak
parent
fb7a212597
commit
c27fa18ed7
@@ -137,8 +137,9 @@ public class ComputerUtilCost {
|
|||||||
* the source
|
* the source
|
||||||
* @return true, if successful
|
* @return true, if successful
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public static boolean checkDiscardCost(final Player ai, final Cost cost, final Card source, SpellAbility sa) {
|
public static boolean checkDiscardCost(final Player ai, final Cost cost, final Card source, SpellAbility sa) {
|
||||||
if (cost == null) {
|
if (cost == null || source.hasSVar("AISkipDiscardCostCheck") /* FIXME: should not be needed! */ ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,28 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
} else if (aiLogic.equals("BestCard")) {
|
||||||
|
CardCollectionView choices = ai.getGame().getCardsIn(ZoneType.listValueOf(sa.getParam("Origin")));
|
||||||
|
choices = CardLists.getValidCards(choices, sa.getParam("ChangeType"), host.getController(), host, sa);
|
||||||
|
if (!choices.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (aiLogic.startsWith("DiscardAllAndRetExiled")) {
|
||||||
|
int numExiledWithSrc = CardLists.filter(ai.getCardsIn(ZoneType.Exile), CardPredicates.isExiledWith(host)).size();
|
||||||
|
int curHandSize = ai.getCardsIn(ZoneType.Hand).size();
|
||||||
|
|
||||||
|
// minimum card advantage unless the hand will be fully reloaded
|
||||||
|
int minAdv = aiLogic.contains(".minAdv") ? Integer.parseInt(aiLogic.substring(aiLogic.indexOf(".minAdv") + 7)) : 0;
|
||||||
|
|
||||||
|
if (numExiledWithSrc > curHandSize) {
|
||||||
|
if (ComputerUtil.predictThreatenedObjects(ai, sa, true).contains(host)) {
|
||||||
|
// Try to gain some card advantage if the card will die anyway
|
||||||
|
// TODO: ideally, should evaluate the hand value and not discard good hands to it
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (curHandSize + minAdv - 1 < numExiledWithSrc) || (numExiledWithSrc >= ai.getMaxHandSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.checkAiLogic(ai, sa, aiLogic);
|
return super.checkAiLogic(ai, sa, aiLogic);
|
||||||
@@ -177,8 +199,13 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
return sa.isTargetNumberValid(); // Pre-targeted in checkAiLogic
|
return sa.isTargetNumberValid(); // Pre-targeted in checkAiLogic
|
||||||
} else if (aiLogic.equals("Ashiok")) {
|
} else if (aiLogic.equals("Ashiok")) {
|
||||||
return true; // If checkAiLogic returns true, then we should be good to go
|
return true; // If checkAiLogic returns true, then we should be good to go
|
||||||
|
} else if (aiLogic.equals("BestCard")) {
|
||||||
|
return true; // If checkAiLogic returns true, then we should be good to go
|
||||||
|
} else if (aiLogic.startsWith("DiscardAllAndRetExiled")) {
|
||||||
|
return true; // If checkAiLogic returns true, then we should be good to go
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isHidden(sa)) {
|
if (isHidden(sa)) {
|
||||||
return hiddenOriginCanPlayAI(aiPlayer, sa);
|
return hiddenOriginCanPlayAI(aiPlayer, sa);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -245,25 +245,8 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
&& !ComputerUtil.isPlayingReanimator(ai);
|
&& !ComputerUtil.isPlayingReanimator(ai);
|
||||||
}
|
}
|
||||||
} else if (origin.equals(ZoneType.Exile)) {
|
} else if (origin.equals(ZoneType.Exile)) {
|
||||||
String logic = sa.getParam("AILogic");
|
// TODO: nothing to do here at the moment
|
||||||
|
return false;
|
||||||
if (logic != null && logic.startsWith("DiscardAllAndRetExiled")) {
|
|
||||||
int numExiledWithSrc = CardLists.filter(ai.getCardsIn(ZoneType.Exile), CardPredicates.isExiledWith(source)).size();
|
|
||||||
int curHandSize = ai.getCardsIn(ZoneType.Hand).size();
|
|
||||||
|
|
||||||
// minimum card advantage unless the hand will be fully reloaded
|
|
||||||
int minAdv = logic.contains(".minAdv") ? Integer.parseInt(logic.substring(logic.indexOf(".minAdv") + 7)) : 0;
|
|
||||||
|
|
||||||
if (numExiledWithSrc > curHandSize) {
|
|
||||||
if (ComputerUtil.predictThreatenedObjects(ai, sa, true).contains(source)) {
|
|
||||||
// Try to gain some card advantage if the card will die anyway
|
|
||||||
// TODO: ideally, should evaluate the hand value and not discard good hands to it
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (curHandSize + minAdv - 1 < numExiledWithSrc) || (numExiledWithSrc >= ai.getMaxHandSize());
|
|
||||||
}
|
|
||||||
} else if (origin.equals(ZoneType.Stack)) {
|
} else if (origin.equals(ZoneType.Stack)) {
|
||||||
// time stop can do something like this:
|
// time stop can do something like this:
|
||||||
// Origin$ Stack | Destination$ Exile | SubAbility$ DBSkip
|
// Origin$ Stack | Destination$ Exile | SubAbility$ DBSkip
|
||||||
|
|||||||
@@ -7,5 +7,6 @@ T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigExile | TriggerZones$ Batt
|
|||||||
SVar:TrigExile:DB$ Dig | Defined$ You | DigNum$ 1 | ChangeNum$ All | DestinationZone$ Exile | ExileFaceDown$ True | NoReveal$ True
|
SVar:TrigExile:DB$ Dig | Defined$ You | DigNum$ 1 | ChangeNum$ All | DestinationZone$ Exile | ExileFaceDown$ True | NoReveal$ True
|
||||||
A:AB$ ChangeZone | Cost$ R Discard<1/Hand> Sac<1/CARDNAME> | Defined$ ExiledWith | Origin$ Exile | Destination$ Hand | AILogic$ DiscardAllAndRetExiled.minAdv2 | SpellDescription$ Put all cards exiled with CARDNAME into their owners' hands.
|
A:AB$ ChangeZone | Cost$ R Discard<1/Hand> Sac<1/CARDNAME> | Defined$ ExiledWith | Origin$ Exile | Destination$ Hand | AILogic$ DiscardAllAndRetExiled.minAdv2 | SpellDescription$ Put all cards exiled with CARDNAME into their owners' hands.
|
||||||
DeckNeeds:Color$Red
|
DeckNeeds:Color$Red
|
||||||
|
SVar:AISkipDiscardCostCheck:TRUE
|
||||||
AI:RemoveDeck:Random
|
AI:RemoveDeck:Random
|
||||||
Oracle:Haste\nWhenever Bomat Courier attacks, exile the top card of your library face down. (You can't look at it.)\n{R}, Discard your hand, Sacrifice Bomat Courier: Put all cards exiled with Bomat Courier into their owners' hands.
|
Oracle:Haste\nWhenever Bomat Courier attacks, exile the top card of your library face down. (You can't look at it.)\n{R}, Discard your hand, Sacrifice Bomat Courier: Put all cards exiled with Bomat Courier into their owners' hands.
|
||||||
|
|||||||
@@ -5,5 +5,6 @@ T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigKyrenExile | Tri
|
|||||||
SVar:TrigKyrenExile:DB$ ChangeZone | Defined$ TopOfLibrary | Origin$ Library | Destination$ Exile | ExileFaceDown$ True
|
SVar:TrigKyrenExile:DB$ ChangeZone | Defined$ TopOfLibrary | Origin$ Library | Destination$ Exile | ExileFaceDown$ True
|
||||||
A:AB$ ChangeZone | Cost$ 5 Discard<1/Hand> Sac<1/CARDNAME> | Defined$ ExiledWith | Origin$ Exile | Destination$ Hand | AILogic$ DiscardAllAndRetExiled.minAdv2 | SpellDescription$ Put all cards exiled with CARDNAME into their owners' hands.
|
A:AB$ ChangeZone | Cost$ 5 Discard<1/Hand> Sac<1/CARDNAME> | Defined$ ExiledWith | Origin$ Exile | Destination$ Hand | AILogic$ DiscardAllAndRetExiled.minAdv2 | SpellDescription$ Put all cards exiled with CARDNAME into their owners' hands.
|
||||||
SVar:AIPreference:DiscardCost$Card
|
SVar:AIPreference:DiscardCost$Card
|
||||||
|
SVar:AISkipDiscardCostCheck:TRUE
|
||||||
AI:RemoveDeck:Random
|
AI:RemoveDeck:Random
|
||||||
Oracle:At the beginning of your upkeep, you may exile the top card of your library face down.\n{5}, Discard your hand, Sacrifice Kyren Archive: Put all cards exiled with Kyren Archive into their owner's hand.
|
Oracle:At the beginning of your upkeep, you may exile the top card of your library face down.\n{5}, Discard your hand, Sacrifice Kyren Archive: Put all cards exiled with Kyren Archive into their owner's hand.
|
||||||
|
|||||||
@@ -12,5 +12,5 @@ Name:Tomb of the Dusk Rose
|
|||||||
ManaCost:no cost
|
ManaCost:no cost
|
||||||
Types:Legendary Land
|
Types:Legendary Land
|
||||||
A:AB$ Mana | Cost$ T | Produced$ Any | Amount$ 1 | SpellDescription$ Add one mana of any color.
|
A:AB$ Mana | Cost$ T | Produced$ Any | Amount$ 1 | SpellDescription$ Add one mana of any color.
|
||||||
A:AB$ ChangeZone | Cost$ 2 W B T | Hidden$ True | Origin$ Exile | Destination$ Battlefield | ChangeType$ Creature.ExiledWithSource | ChangeNum$ 1 | GainControl$ True | Mandatory$ True | StackDescription$ SpellDescription | SpellDescription$ Put a creature card exiled with this permanent onto the battlefield under your control.
|
A:AB$ ChangeZone | Cost$ 2 W B T | Hidden$ True | Origin$ Exile | Destination$ Battlefield | ChangeType$ Creature.ExiledWithSource | ChangeNum$ 1 | GainControl$ True | Mandatory$ True | AILogic$ BestCard | StackDescription$ SpellDescription | SpellDescription$ Put a creature card exiled with CARDNAME onto the battlefield under your control.
|
||||||
Oracle:(Transforms from Profane Procession.)\n{T}: Add one mana of any color.\n{2}{W}{B}, {T}: Put a creature card exiled with this permanent onto the battlefield under your control.
|
Oracle:(Transforms from Profane Procession.)\n{T}: Add one mana of any color.\n{2}{W}{B},{T}: Put a creature card exiled with this permanent onto the battlefield under your control.
|
||||||
|
|||||||
Reference in New Issue
Block a user