- Improve AI for Aether Vial, Ratchet Bomb.

This commit is contained in:
Agetian
2023-10-27 22:49:21 +03:00
parent 8cdcbc89d6
commit 1d77d79ec3
3 changed files with 49 additions and 3 deletions

View File

@@ -305,7 +305,11 @@ public class CountersPutAi extends CountersAi {
AiCardMemory.rememberCard(ai, source, AiCardMemory.MemorySet.HELD_MANA_SOURCES_FOR_MAIN2);
}
return willActivate;
}
} else if (logic.equals("ChargeToBestCMC")) {
return doChargeToCMCLogic(ai, sa);
} else if (logic.equals("ChargeToBestOppControlledCMC")) {
return doChargeToOppCtrlCMCLogic(ai, sa);
}
if (!sa.metConditions() && sa.getSubAbility() == null) {
return false;
@@ -740,6 +744,7 @@ public class CountersPutAi extends CountersAi {
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final SpellAbility root = sa.getRootAbility();
final Card source = sa.getHostCard();
final String aiLogic = sa.getParamOrDefault("AILogic", "");
// boolean chance = true;
boolean preferred = true;
CardCollection list;
@@ -747,6 +752,7 @@ public class CountersPutAi extends CountersAi {
final boolean divided = sa.isDividedAsYouChoose();
final int amount = AbilityUtils.calculateAmount(source, amountStr, sa);
int left = amount;
final String[] types;
String type = "";
if (sa.hasParam("CounterType")) {
@@ -759,6 +765,12 @@ public class CountersPutAi extends CountersAi {
type = types[0];
}
if ("ChargeToBestCMC".equals(aiLogic)) {
return doChargeToCMCLogic(ai, sa) || mandatory;
} else if ("ChargeToBestOppControlledCMC".equals(aiLogic)) {
return doChargeToOppCtrlCMCLogic(ai, sa) || mandatory;
}
if (!sa.usesTargeting()) {
// No target. So must be defined. (Unused at the moment)
// list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa);
@@ -1206,4 +1218,38 @@ public class CountersPutAi extends CountersAi {
return max;
}
private boolean doChargeToCMCLogic(Player ai, SpellAbility sa) {
Card source = sa.getHostCard();
CardCollectionView ownLib = CardLists.filter(ai.getCardsIn(ZoneType.Library), CardPredicates.isType("Creature"));
int numCtrs = source.getCounters(CounterEnumType.CHARGE);
int maxCMC = Aggregates.max(ownLib, CardPredicates.Accessors.fnGetCmc);
int optimalCMC = 0;
int curAmount = 0;
// Assume the AI knows its deck list and realizes what it has left in its library. Could be improved to make this less cheat-y.
for (int cmc = numCtrs; cmc <= maxCMC; cmc++) {
int numPerCMC = CardLists.filter(ownLib, CardPredicates.hasCMC(cmc)).size();
if (numPerCMC >= curAmount) {
curAmount = numPerCMC;
optimalCMC = cmc;
}
}
return numCtrs < optimalCMC;
}
private boolean doChargeToOppCtrlCMCLogic(Player ai, SpellAbility sa) {
Card source = sa.getHostCard();
CardCollectionView oppInPlay = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.NONLAND_PERMANENTS);
int numCtrs = source.getCounters(CounterEnumType.CHARGE);
int maxCMC = Aggregates.max(oppInPlay, CardPredicates.Accessors.fnGetCmc);
int optimalCMC = 0;
int curAmount = 0;
for (int cmc = numCtrs; cmc <= maxCMC; cmc++) {
int numPerCMC = CardLists.filter(oppInPlay, CardPredicates.hasCMC(cmc)).size();
if (numPerCMC >= curAmount) {
curAmount = numPerCMC;
optimalCMC = cmc;
}
}
return numCtrs < optimalCMC;
}
}

View File

@@ -3,6 +3,6 @@ ManaCost:1
Types:Artifact
A:AB$ ChangeZone | Cost$ T | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature.cmcEQX+YouCtrl | Optional$ You | SpellDescription$ You may put a creature card with mana value equal to the number of charge counters on CARDNAME from your hand onto the battlefield. | StackDescription$ SpellDescription
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ At the beginning of your upkeep, you may put a charge counter on CARDNAME.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ CHARGE | CounterNum$ 1
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ CHARGE | CounterNum$ 1 | AILogic$ ChargeToBestCMC
SVar:X:Count$CardCounters.CHARGE
Oracle:At the beginning of your upkeep, you may put a charge counter on Aether Vial.\n{T}: You may put a creature card with mana value equal to the number of charge counters on Aether Vial from your hand onto the battlefield.

View File

@@ -1,7 +1,7 @@
Name:Ratchet Bomb
ManaCost:2
Types:Artifact
A:AB$ PutCounter | Cost$ T | CounterType$ CHARGE | CounterNum$ 1 | SpellDescription$ Put a charge counter on CARDNAME.
A:AB$ PutCounter | Cost$ T | CounterType$ CHARGE | CounterNum$ 1 | AILogic$ ChargeToBestOppControlledCMC | SpellDescription$ Put a charge counter on CARDNAME.
A:AB$ DestroyAll | Cost$ T Sac<1/CARDNAME> | ValidCards$ Permanent.nonLand+cmcEQX | SpellDescription$ Destroy each nonland permanent with mana value equal to the number of charge counters on CARDNAME.
SVar:X:Count$CardCounters.CHARGE
Oracle:{T}: Put a charge counter on Ratchet Bomb.\n{T}, Sacrifice Ratchet Bomb: Destroy each nonland permanent with mana value equal to the number of charge counters on Ratchet Bomb.