mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-14 01:38:13 +00:00
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:
@@ -943,6 +943,12 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,33 +17,20 @@
|
||||
*/
|
||||
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.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.ability.AnimateAi;
|
||||
import forge.card.ColorSet;
|
||||
import forge.card.MagicColor;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GameType;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
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.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.CostPart;
|
||||
@@ -64,6 +51,11 @@ import forge.util.MyRandom;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.maps.LinkedHashMapToAmount;
|
||||
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
|
||||
@@ -610,35 +602,31 @@ public class SpecialCardAi {
|
||||
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
|
||||
List<SpellAbility> best = Lists.newArrayList();
|
||||
List<SpellAbility> possible = Lists.newArrayList();
|
||||
List<String> possible = Lists.newArrayList();
|
||||
Card tgtCard = sa.getTargetCard();
|
||||
if (tgtCard != null) {
|
||||
for (SpellAbility sp : spells) {
|
||||
if (SpellApiToAi.Converter.get(sp.getApi()).canPlayAIWithSubs(ai, sp)) {
|
||||
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 ("Indestructible".equals(kw) && ai.getOpponents().getCreaturesInPlay().isEmpty()) {
|
||||
CardCollection oppUntappedCreatures = CardLists.filter(ai.getOpponents().getCreaturesInPlay(), CardPredicates.Presets.UNTAPPED);
|
||||
for (String kw : options) {
|
||||
if (!tgtCard.hasKeyword(kw)) {
|
||||
if ("Indestructible".equals(kw)) {
|
||||
if (oppUntappedCreatures.isEmpty()) {
|
||||
continue; // nothing to damage or kill the creature with
|
||||
} else {
|
||||
possible.clear();
|
||||
possible.add(kw); // prefer Indestructible above all else
|
||||
break;
|
||||
}
|
||||
possible.add(sp); // these SAs at least don't duplicate a keyword on the card
|
||||
break;
|
||||
}
|
||||
possible.add(kw); // these SAs at least don't duplicate a keyword on the card
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!best.isEmpty()) {
|
||||
return Aggregates.random(best);
|
||||
} else if (!possible.isEmpty()) {
|
||||
if (!possible.isEmpty()) {
|
||||
return Aggregates.random(possible);
|
||||
} 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,16 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.SpellApiToAi;
|
||||
import forge.card.MagicColor;
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.keyword.Keyword;
|
||||
@@ -32,6 +23,9 @@ import forge.game.zone.ZoneType;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.collect.FCollection;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class ChooseGenericEffectAi extends SpellAbilityAi {
|
||||
|
||||
@@ -47,8 +41,6 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if ("GideonBlackblade".equals(aiLogic)) {
|
||||
return SpecialCardAi.GideonBlackblade.consider(ai, sa);
|
||||
} else if ("AtOppEOT".equals(aiLogic)) {
|
||||
PhaseHandler ph = ai.getGame().getPhaseHandler();
|
||||
return ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn() == ai;
|
||||
@@ -99,8 +91,6 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
|
||||
return spells.get(0);
|
||||
} else if ("Random".equals(logic)) {
|
||||
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
|
||||
List<SpellAbility> filtered = Lists.newArrayList(Iterables.filter(spells, new Predicate<SpellAbility>() {
|
||||
@Override
|
||||
|
||||
@@ -143,6 +143,8 @@ public class PumpAi extends PumpAiBase {
|
||||
return SpecialCardAi.ElectrostaticPummeler.consider(ai, sa);
|
||||
} else if (aiLogic.startsWith("AristocratCounters")) {
|
||||
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)) {
|
||||
final SpellAbility moveSA = sa.findSubAbilityByType(ApiType.MoveCounter);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user