mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
- Updated CharmAi to use new canPlay()
This commit is contained in:
@@ -18,40 +18,10 @@ import java.util.Random;
|
|||||||
|
|
||||||
public class CharmAi extends SpellAbilityAi {
|
public class CharmAi extends SpellAbilityAi {
|
||||||
@Override
|
@Override
|
||||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
protected boolean checkAiLogic(final Player ai, final SpellAbility sa, final String aiLogic) {
|
||||||
final Random r = MyRandom.getRandom();
|
if (aiLogic.equals("Triskaidekaphobia")) {
|
||||||
|
List<AbilitySub> choices = CharmEffect.makePossibleOptions(sa);
|
||||||
final int num = Integer.parseInt(sa.hasParam("CharmNum") ? sa.getParam("CharmNum") : "1");
|
List<AbilitySub> chosenList = new ArrayList<AbilitySub>();
|
||||||
final int min = sa.hasParam("MinCharmNum") ? Integer.parseInt(sa.getParam("MinCharmNum")) : num;
|
|
||||||
boolean timingRight = sa.isTrigger(); //is there a reason to play the charm now?
|
|
||||||
|
|
||||||
// reset the chosen list. Otherwise it will be locked in forever
|
|
||||||
sa.setChosenList(null);
|
|
||||||
List<AbilitySub> chosenList = min > 1 ? chooseMultipleOptionsAi(sa, ai, min) : chooseOptionsAi(sa, ai, timingRight, num, min, sa.hasParam("CanRepeatModes"), false);
|
|
||||||
|
|
||||||
if (chosenList.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
sa.setChosenList(chosenList);
|
|
||||||
}
|
|
||||||
|
|
||||||
// prevent run-away activations - first time will always return true
|
|
||||||
return r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<AbilitySub> chooseOptionsAi(SpellAbility sa, final Player ai, boolean playNow, int num, int min, boolean allowRepeat, boolean opponentChoser) {
|
|
||||||
if (sa.getChosenList() != null) {
|
|
||||||
return sa.getChosenList();
|
|
||||||
}
|
|
||||||
List<AbilitySub> choices = CharmEffect.makePossibleOptions(sa);
|
|
||||||
List<AbilitySub> chosenList = new ArrayList<AbilitySub>();
|
|
||||||
|
|
||||||
if (opponentChoser) {
|
|
||||||
// This branch is for "An Opponent chooses" Charm spells from Alliances
|
|
||||||
// Current just choose the first available spell, which seem generally less disastrous for the AI.
|
|
||||||
//return choices.subList(0, 1);
|
|
||||||
return choices.subList(1, choices.size());
|
|
||||||
} else if ("Triskaidekaphobia".equals(sa.getHostCard().getName())) {
|
|
||||||
AbilitySub gain = choices.get(0);
|
AbilitySub gain = choices.get(0);
|
||||||
AbilitySub lose = choices.get(1);
|
AbilitySub lose = choices.get(1);
|
||||||
FCollection<Player> opponents = ai.getOpponents();
|
FCollection<Player> opponents = ai.getOpponents();
|
||||||
@@ -118,21 +88,50 @@ public class CharmAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
chosenList.add(aiLife == 12 || oppCritical ? lose : gain);
|
chosenList.add(aiLife == 12 || oppCritical ? lose : gain);
|
||||||
} else {
|
} else {
|
||||||
// normal logic, try to gain life if its critical
|
// For cases not handled by the above, try to kill everyone
|
||||||
boolean oppCritical = false;
|
chosenList.add(lose);
|
||||||
// an oppoent is Critical = 12, and can gain life, try to gain life instead
|
|
||||||
// but only if ai doesn't kill itself with that.
|
|
||||||
if (aiLife != 12) {
|
|
||||||
for (Player p : opponents) {
|
|
||||||
if (p.getLife() == 12 && p.canGainLife()) {
|
|
||||||
oppCritical = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chosenList.add(aiLife == 14 || aiLife <= 10 || oppCritical ? gain : lose);
|
|
||||||
}
|
}
|
||||||
return chosenList;
|
sa.setChosenList(chosenList);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean checkApiLogic(Player ai, SpellAbility sa) {
|
||||||
|
final Random r = MyRandom.getRandom();
|
||||||
|
|
||||||
|
final int num = Integer.parseInt(sa.hasParam("CharmNum") ? sa.getParam("CharmNum") : "1");
|
||||||
|
final int min = sa.hasParam("MinCharmNum") ? Integer.parseInt(sa.getParam("MinCharmNum")) : num;
|
||||||
|
boolean timingRight = sa.isTrigger(); //is there a reason to play the charm now?
|
||||||
|
|
||||||
|
// reset the chosen list. Otherwise it will be locked in forever
|
||||||
|
sa.setChosenList(null);
|
||||||
|
List<AbilitySub> chosenList = min > 1 ? chooseMultipleOptionsAi(CharmEffect.makePossibleOptions(sa), ai, min)
|
||||||
|
: chooseOptionsAi(sa, ai, timingRight, num, min, sa.hasParam("CanRepeatModes"), false);
|
||||||
|
|
||||||
|
if (chosenList.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
sa.setChosenList(chosenList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// prevent run-away activations - first time will always return true
|
||||||
|
return r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<AbilitySub> chooseOptionsAi(SpellAbility sa, final Player ai, boolean playNow, int num, int min,
|
||||||
|
boolean allowRepeat, boolean opponentChoser) {
|
||||||
|
if (sa.getChosenList() != null) {
|
||||||
|
return sa.getChosenList();
|
||||||
|
}
|
||||||
|
List<AbilitySub> choices = CharmEffect.makePossibleOptions(sa);
|
||||||
|
List<AbilitySub> chosenList = new ArrayList<AbilitySub>();
|
||||||
|
|
||||||
|
if (opponentChoser) {
|
||||||
|
// This branch is for "An Opponent chooses" Charm spells from Alliances
|
||||||
|
// Current just choose the first available spell, which seem generally less disastrous for the AI.
|
||||||
|
//return choices.subList(0, 1);
|
||||||
|
return choices.subList(1, choices.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
AiController aic = ((PlayerControllerAi) ai.getController()).getAi();
|
AiController aic = ((PlayerControllerAi) ai.getController()).getAi();
|
||||||
@@ -175,31 +174,29 @@ public class CharmAi extends SpellAbilityAi {
|
|||||||
return chosenList;
|
return chosenList;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Extension of chooseOptionsAi specific to multi-option charms (eg. Cryptic Command, DTK commands)
|
// Choice selection for charms that require multiple choices (eg. Cryptic Command, DTK commands)
|
||||||
private List<AbilitySub> chooseMultipleOptionsAi(SpellAbility sa, final Player ai, int min) {
|
private List<AbilitySub> chooseMultipleOptionsAi(List<AbilitySub> choices, final Player ai, int min) {
|
||||||
if (sa.getChosenList() != null) {
|
|
||||||
return sa.getChosenList();
|
|
||||||
}
|
|
||||||
List<AbilitySub> choices = CharmEffect.makePossibleOptions(sa);
|
|
||||||
AbilitySub goodChoice = null;
|
AbilitySub goodChoice = null;
|
||||||
List<AbilitySub> chosenList = new ArrayList<AbilitySub>();
|
List<AbilitySub> chosenList = new ArrayList<AbilitySub>();
|
||||||
// select first n playable options
|
|
||||||
AiController aic = ((PlayerControllerAi) ai.getController()).getAi();
|
AiController aic = ((PlayerControllerAi) ai.getController()).getAi();
|
||||||
for (AbilitySub sub : choices) {
|
for (AbilitySub sub : choices) {
|
||||||
sub.setActivatingPlayer(ai);
|
sub.setActivatingPlayer(ai);
|
||||||
|
// Assign generic good choice to fill up choices if necessary
|
||||||
if ("Good".equals(sub.getParam("AILogic")) && aic.doTrigger(sub, false)) {
|
if ("Good".equals(sub.getParam("AILogic")) && aic.doTrigger(sub, false)) {
|
||||||
goodChoice = sub;
|
goodChoice = sub;
|
||||||
} else {
|
} else {
|
||||||
|
// Standard canPlayAi()
|
||||||
if (AiPlayDecision.WillPlay == aic.canPlaySa(sub)) {
|
if (AiPlayDecision.WillPlay == aic.canPlaySa(sub)) {
|
||||||
chosenList.add(sub);
|
chosenList.add(sub);
|
||||||
if (chosenList.size() == min) {
|
if (chosenList.size() == min) {
|
||||||
break;
|
break; // enough choices
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Add generic good choice if one more choice is needed
|
||||||
if (chosenList.size() == min - 1 && goodChoice != null) {
|
if (chosenList.size() == min - 1 && goodChoice != null) {
|
||||||
chosenList.add(0, goodChoice); //hack to make Dromoka's Charm fight targets work
|
chosenList.add(0, goodChoice); // hack to make Dromoka's Command fight targets work
|
||||||
return chosenList;
|
return chosenList;
|
||||||
}
|
}
|
||||||
if (chosenList.size() != min) {
|
if (chosenList.size() != min) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Name:Triskaidekaphobia
|
|||||||
ManaCost:3 B
|
ManaCost:3 B
|
||||||
Types:Enchantment
|
Types:Enchantment
|
||||||
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigCharm | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, choose one - Each player with exactly 13 life loses the game, then each player gains 1 life; Each player with exactly 13 life loses the game, then each player loses 1 life.
|
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigCharm | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, choose one - Each player with exactly 13 life loses the game, then each player gains 1 life; Each player with exactly 13 life loses the game, then each player loses 1 life.
|
||||||
SVar:TrigCharm:AB$ Charm | Cost$ 0 | Choices$ DBLoseGame1,DBLoseGame2 | CharmNum$ 1
|
SVar:TrigCharm:AB$ Charm | Cost$ 0 | AILogic$ Triskaidekaphobia | Choices$ DBLoseGame1,DBLoseGame2 | CharmNum$ 1
|
||||||
SVar:DBLoseGame1:DB$ LosesGame | Cost$ 0 | Defined$ Player.LifeEquals_13 | SubAbility$ DBGainLife | SpellDescription$ Each player with exactly 13 life loses the game, then each player gains 1 life.
|
SVar:DBLoseGame1:DB$ LosesGame | Cost$ 0 | Defined$ Player.LifeEquals_13 | SubAbility$ DBGainLife | SpellDescription$ Each player with exactly 13 life loses the game, then each player gains 1 life.
|
||||||
SVar:DBGainLife:DB$ GainLife | Defined$ Player | LifeAmount$ 1
|
SVar:DBGainLife:DB$ GainLife | Defined$ Player | LifeAmount$ 1
|
||||||
SVar:DBLoseGame2:DB$ LosesGame | Cost$ 0 | Defined$ Player.LifeEquals_13 | SubAbility$ DBLoseLife | SpellDescription$ Each player with exactly 13 life loses the game, then each player loses 1 life.
|
SVar:DBLoseGame2:DB$ LosesGame | Cost$ 0 | Defined$ Player.LifeEquals_13 | SubAbility$ DBLoseLife | SpellDescription$ Each player with exactly 13 life loses the game, then each player loses 1 life.
|
||||||
|
|||||||
Reference in New Issue
Block a user