Update Gideon Blackblade AI logic (#1630)

* - Update Gideon Blackblade AI logic.

* - Update imports.

* - Update imports.

* - Modify the method name to make more sense in the updated context.
This commit is contained in:
Agetian
2022-10-02 19:56:35 +03:00
committed by GitHub
parent 2f08524bf5
commit 614e067bc9
4 changed files with 33 additions and 47 deletions

View File

@@ -943,6 +943,12 @@ public class PlayerControllerAi extends PlayerController {
@Override @Override
public String chooseKeywordForPump(final List<String> options, final SpellAbility sa, final String prompt) { public String chooseKeywordForPump(final List<String> options, final SpellAbility sa, final String prompt) {
final String aiLogic = sa.getParamOrDefault("AILogic", "");
if (aiLogic.equals("GideonBlackblade")) {
return SpecialCardAi.GideonBlackblade.chooseKeyword(player, sa, options);
}
return Iterables.getFirst(options, null); return Iterables.getFirst(options, null);
} }

View File

@@ -17,33 +17,20 @@
*/ */
package forge.ai; package forge.ai;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import forge.game.GameEntity;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.ai.ability.AnimateAi; import forge.ai.ability.AnimateAi;
import forge.card.ColorSet; import forge.card.ColorSet;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.card.mana.ManaCost; import forge.card.mana.ManaCost;
import forge.game.Game; import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GameType; import forge.game.GameType;
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.*;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CardUtil;
import forge.game.card.CounterEnumType;
import forge.game.combat.Combat; import forge.game.combat.Combat;
import forge.game.combat.CombatUtil; import forge.game.combat.CombatUtil;
import forge.game.cost.CostPart; import forge.game.cost.CostPart;
@@ -64,6 +51,11 @@ import forge.util.MyRandom;
import forge.util.TextUtil; import forge.util.TextUtil;
import forge.util.maps.LinkedHashMapToAmount; import forge.util.maps.LinkedHashMapToAmount;
import forge.util.maps.MapToAmount; import forge.util.maps.MapToAmount;
import org.apache.commons.lang3.tuple.Pair;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/** /**
* Special logic for individual cards * Special logic for individual cards
@@ -610,35 +602,31 @@ public class SpecialCardAi {
return true; return true;
} }
public static SpellAbility chooseSpellAbility(final Player ai, final SpellAbility sa, final List<SpellAbility> spells) { public static String chooseKeyword(final Player ai, final SpellAbility sa, final List<String> options) {
// TODO: generalize and improve this so that it acts in a more reasonable way and can potentially be used for other cards too // TODO: generalize and improve this so that it acts in a more reasonable way and can potentially be used for other cards too
List<SpellAbility> best = Lists.newArrayList(); List<String> possible = Lists.newArrayList();
List<SpellAbility> possible = Lists.newArrayList();
Card tgtCard = sa.getTargetCard(); Card tgtCard = sa.getTargetCard();
if (tgtCard != null) { if (tgtCard != null) {
for (SpellAbility sp : spells) { CardCollection oppUntappedCreatures = CardLists.filter(ai.getOpponents().getCreaturesInPlay(), CardPredicates.Presets.UNTAPPED);
if (SpellApiToAi.Converter.get(sp.getApi()).canPlayAIWithSubs(ai, sp)) { for (String kw : options) {
best.add(sp); // these SAs are prioritized since the AI sees a reason to play them now
}
final List<String> keywords = sp.hasParam("KW") ? Arrays.asList(sp.getParam("KW").split(" & "))
: Lists.newArrayList();
for (String kw : keywords) {
if (!tgtCard.hasKeyword(kw)) { if (!tgtCard.hasKeyword(kw)) {
if ("Indestructible".equals(kw) && ai.getOpponents().getCreaturesInPlay().isEmpty()) { if ("Indestructible".equals(kw)) {
if (oppUntappedCreatures.isEmpty()) {
continue; // nothing to damage or kill the creature with continue; // nothing to damage or kill the creature with
} } else {
possible.add(sp); // these SAs at least don't duplicate a keyword on the card possible.clear();
possible.add(kw); // prefer Indestructible above all else
break; break;
} }
} }
possible.add(kw); // these SAs at least don't duplicate a keyword on the card
} }
} }
if (!best.isEmpty()) { }
return Aggregates.random(best); if (!possible.isEmpty()) {
} else if (!possible.isEmpty()) {
return Aggregates.random(possible); return Aggregates.random(possible);
} else { } else {
return Aggregates.random(spells); // if worst comes to worst, it's a PW +1 ability, so do at least something return Aggregates.random(options); // if worst comes to worst, it's a PW +1 ability, so do at least something
} }
} }
} }

View File

@@ -1,25 +1,16 @@
package forge.ai.ability; package forge.ai.ability;
import java.util.List;
import java.util.Map;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import forge.ai.ComputerUtilAbility; import forge.ai.ComputerUtilAbility;
import forge.ai.ComputerUtilCost; import forge.ai.ComputerUtilCost;
import forge.ai.SpecialCardAi;
import forge.ai.SpellAbilityAi; import forge.ai.SpellAbilityAi;
import forge.ai.SpellApiToAi; import forge.ai.SpellApiToAi;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.game.Game; import forge.game.Game;
import forge.game.card.Card; import forge.game.card.*;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
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.keyword.Keyword; import forge.game.keyword.Keyword;
@@ -32,6 +23,9 @@ import forge.game.zone.ZoneType;
import forge.util.Aggregates; import forge.util.Aggregates;
import forge.util.collect.FCollection; import forge.util.collect.FCollection;
import java.util.List;
import java.util.Map;
public class ChooseGenericEffectAi extends SpellAbilityAi { public class ChooseGenericEffectAi extends SpellAbilityAi {
@@ -47,8 +41,6 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
return true; return true;
} }
} }
} else if ("GideonBlackblade".equals(aiLogic)) {
return SpecialCardAi.GideonBlackblade.consider(ai, sa);
} else if ("AtOppEOT".equals(aiLogic)) { } else if ("AtOppEOT".equals(aiLogic)) {
PhaseHandler ph = ai.getGame().getPhaseHandler(); PhaseHandler ph = ai.getGame().getPhaseHandler();
return ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn() == ai; return ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn() == ai;
@@ -99,8 +91,6 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
return spells.get(0); return spells.get(0);
} else if ("Random".equals(logic)) { } else if ("Random".equals(logic)) {
return Aggregates.random(spells); return Aggregates.random(spells);
} else if ("GideonBlackblade".equals(logic)) {
return SpecialCardAi.GideonBlackblade.chooseSpellAbility(player, sa, spells);
} else if ("Phasing".equals(logic)) { // Teferi's Realm : keep aggressive } else if ("Phasing".equals(logic)) { // Teferi's Realm : keep aggressive
List<SpellAbility> filtered = Lists.newArrayList(Iterables.filter(spells, new Predicate<SpellAbility>() { List<SpellAbility> filtered = Lists.newArrayList(Iterables.filter(spells, new Predicate<SpellAbility>() {
@Override @Override

View File

@@ -143,6 +143,8 @@ public class PumpAi extends PumpAiBase {
return SpecialCardAi.ElectrostaticPummeler.consider(ai, sa); return SpecialCardAi.ElectrostaticPummeler.consider(ai, sa);
} else if (aiLogic.startsWith("AristocratCounters")) { } else if (aiLogic.startsWith("AristocratCounters")) {
return true; // the preconditions to this are already tested in checkAiLogic return true; // the preconditions to this are already tested in checkAiLogic
} else if ("GideonBlackblade".equals(aiLogic)) {
return SpecialCardAi.GideonBlackblade.consider(ai, sa);
} else if ("MoveCounter".equals(aiLogic)) { } else if ("MoveCounter".equals(aiLogic)) {
final SpellAbility moveSA = sa.findSubAbilityByType(ApiType.MoveCounter); final SpellAbility moveSA = sa.findSubAbilityByType(ApiType.MoveCounter);