mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
- Fixed accidental revert of PlayerControllerAi by r31697
This commit is contained in:
@@ -55,7 +55,8 @@ import org.apache.commons.lang3.tuple.Pair;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* A prototype for player controller class
|
||||
*
|
||||
* Handles phase skips for now.
|
||||
@@ -68,11 +69,11 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
brains = new AiController(p, game);
|
||||
}
|
||||
|
||||
public void allowCheatShuffle(boolean value) {
|
||||
|
||||
public void allowCheatShuffle(boolean value){
|
||||
brains.allowCheatShuffle(value);
|
||||
}
|
||||
|
||||
|
||||
public void setUseSimulation(boolean value) {
|
||||
brains.setUseSimulation(value);
|
||||
}
|
||||
@@ -80,7 +81,8 @@ public class PlayerControllerAi extends PlayerController {
|
||||
public SpellAbility getAbilityToPlay(Card hostCard, List<SpellAbility> abilities, ITriggerEvent triggerEvent) {
|
||||
if (abilities.size() == 0) {
|
||||
return null;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return abilities.get(0);
|
||||
}
|
||||
}
|
||||
@@ -101,60 +103,51 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Card, Integer> assignCombatDamage(Card attacker, CardCollectionView blockers, int damageDealt,
|
||||
GameEntity defender, boolean overrideOrder) {
|
||||
public Map<Card, Integer> assignCombatDamage(Card attacker, CardCollectionView blockers, int damageDealt, GameEntity defender, boolean overrideOrder) {
|
||||
return ComputerUtilCombat.distributeAIDamage(attacker, blockers, damageDealt, defender, overrideOrder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer announceRequirements(SpellAbility ability, String announce, boolean allowZero) {
|
||||
// For now, these "announcements" are made within the AI classes of the
|
||||
// appropriate SA effects
|
||||
// For now, these "announcements" are made within the AI classes of the appropriate SA effects
|
||||
if (ability.getApi() != null) {
|
||||
switch (ability.getApi()) {
|
||||
case ChooseNumber:
|
||||
return ability.getActivatingPlayer().isOpponentOf(player) ? 0
|
||||
: ComputerUtilMana.determineLeftoverMana(ability, player);
|
||||
case BidLife:
|
||||
return 0;
|
||||
default:
|
||||
return null;
|
||||
case ChooseNumber:
|
||||
return ability.getActivatingPlayer().isOpponentOf(player) ? 0 : ComputerUtilMana.determineLeftoverMana(ability, player);
|
||||
case BidLife:
|
||||
return 0;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null; // return incorrect value to indicate that
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardCollectionView choosePermanentsToSacrifice(SpellAbility sa, int min, int max,
|
||||
CardCollectionView validTargets, String message) {
|
||||
public CardCollectionView choosePermanentsToSacrifice(SpellAbility sa, int min, int max, CardCollectionView validTargets, String message) {
|
||||
return ComputerUtil.choosePermanentsToSacrifice(player, validTargets, max, sa, false, min == 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardCollectionView choosePermanentsToDestroy(SpellAbility sa, int min, int max,
|
||||
CardCollectionView validTargets, String message) {
|
||||
public CardCollectionView choosePermanentsToDestroy(SpellAbility sa, int min, int max, CardCollectionView validTargets, String message) {
|
||||
return ComputerUtil.choosePermanentsToSacrifice(player, validTargets, max, sa, true, min == 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardCollectionView chooseCardsForEffect(CardCollectionView sourceList, SpellAbility sa, String title,
|
||||
int min, int max, boolean isOptional) {
|
||||
public CardCollectionView chooseCardsForEffect(CardCollectionView sourceList, SpellAbility sa, String title, int min, int max, boolean isOptional) {
|
||||
return brains.chooseCardsForEffect(sourceList, sa, min, max, isOptional);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends GameEntity> T chooseSingleEntityForEffect(FCollectionView<T> optionList,
|
||||
DelayedReveal delayedReveal, SpellAbility sa, String title, boolean isOptional, Player targetedPlayer) {
|
||||
public <T extends GameEntity> T chooseSingleEntityForEffect(FCollectionView<T> optionList, DelayedReveal delayedReveal, SpellAbility sa, String title, boolean isOptional, Player targetedPlayer) {
|
||||
if (delayedReveal != null) {
|
||||
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(),
|
||||
delayedReveal.getMessagePrefix());
|
||||
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix());
|
||||
}
|
||||
ApiType api = sa.getApi();
|
||||
if (null == api) {
|
||||
throw new InvalidParameterException("SA is not api-based, this is not supported yet");
|
||||
}
|
||||
return SpellApiToAi.Converter.get(api).chooseSingleEntity(player, sa, (FCollection<T>) optionList, isOptional,
|
||||
targetedPlayer);
|
||||
return SpellApiToAi.Converter.get(api).chooseSingleEntity(player, sa, (FCollection<T>)optionList, isOptional, targetedPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -170,10 +163,10 @@ public class PlayerControllerAi extends PlayerController {
|
||||
public boolean confirmAction(SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
return getAi().confirmAction(sa, mode, message);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean confirmBidAction(SpellAbility sa, PlayerActionConfirmMode mode, String string, int bid,
|
||||
Player winner) {
|
||||
public boolean confirmBidAction(SpellAbility sa, PlayerActionConfirmMode mode, String string,
|
||||
int bid, Player winner) {
|
||||
return getAi().confirmBidAction(sa, mode, string, bid, winner);
|
||||
}
|
||||
|
||||
@@ -183,15 +176,13 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean confirmTrigger(SpellAbility sa, Trigger regtrig, Map<String, String> triggerParams,
|
||||
boolean isMandatory) {
|
||||
public boolean confirmTrigger(SpellAbility sa, Trigger regtrig, Map<String, String> triggerParams, boolean isMandatory) {
|
||||
if (sa.getHostCard().getName().equals("Deathmist Raptor")) {
|
||||
return true;
|
||||
}
|
||||
if (triggerParams.containsKey("DelayedTrigger") || isMandatory) {
|
||||
// TODO: The only card with an optional delayed trigger is Shirei,
|
||||
// Shizo's Caretaker,
|
||||
// needs to be expanded when a more difficult cards comes up
|
||||
//TODO: The only card with an optional delayed trigger is Shirei, Shizo's Caretaker,
|
||||
// needs to be expanded when a more difficult cards comes up
|
||||
return true;
|
||||
}
|
||||
// Store/replace target choices more properly to get this SA cleared.
|
||||
@@ -210,10 +201,8 @@ public class PlayerControllerAi extends PlayerController {
|
||||
subtc = sub.getTargets();
|
||||
sub.resetTargets();
|
||||
}
|
||||
// There is no way this doTrigger here will have the same target as
|
||||
// stored above
|
||||
// So it's possible it's making a different decision here than will
|
||||
// actually happen
|
||||
// There is no way this doTrigger here will have the same target as stored above
|
||||
// So it's possible it's making a different decision here than will actually happen
|
||||
if (!brains.doTrigger(sa, false)) {
|
||||
ret = false;
|
||||
}
|
||||
@@ -238,10 +227,10 @@ public class PlayerControllerAi extends PlayerController {
|
||||
public CardCollection orderBlockers(Card attacker, CardCollection blockers) {
|
||||
return AiBlockController.orderBlockers(attacker, blockers);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CardCollection orderBlocker(Card attacker, Card blocker, CardCollection oldBlockers) {
|
||||
return AiBlockController.orderBlocker(attacker, blocker, oldBlockers);
|
||||
return AiBlockController.orderBlocker(attacker, blocker, oldBlockers);
|
||||
};
|
||||
|
||||
@Override
|
||||
@@ -264,10 +253,11 @@ public class PlayerControllerAi extends PlayerController {
|
||||
CardCollection toBottom = new CardCollection();
|
||||
CardCollection toTop = new CardCollection();
|
||||
|
||||
for (Card c : topN) {
|
||||
for (Card c: topN) {
|
||||
if (ComputerUtil.scryWillMoveCardToBottomOfLibrary(player, c)) {
|
||||
toBottom.add(c);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
toTop.add(c);
|
||||
}
|
||||
}
|
||||
@@ -279,38 +269,37 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
@Override
|
||||
public boolean willPutCardOnTop(Card c) {
|
||||
return true; // AI does not know what will happen next (another clash or
|
||||
// that would become his topdeck)
|
||||
return true; // AI does not know what will happen next (another clash or that would become his topdeck)
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardCollectionView orderMoveToZoneList(CardCollectionView cards, ZoneType destinationZone) {
|
||||
// TODO Add logic for AI ordering here
|
||||
//TODO Add logic for AI ordering here
|
||||
return cards;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardCollection chooseCardsToDiscardFrom(Player p, SpellAbility sa, CardCollection validCards, int min,
|
||||
int max) {
|
||||
public CardCollection chooseCardsToDiscardFrom(Player p, SpellAbility sa, CardCollection validCards, int min, int max) {
|
||||
if (p == player) {
|
||||
return brains.getCardsToDiscard(min, max, validCards, sa);
|
||||
}
|
||||
|
||||
boolean isTargetFriendly = !p.isOpponentOf(player);
|
||||
|
||||
return isTargetFriendly ? ComputerUtil.getCardsToDiscardFromFriend(player, p, sa, validCards, min, max)
|
||||
: ComputerUtil.getCardsToDiscardFromOpponent(player, p, sa, validCards, min, max);
|
||||
return isTargetFriendly
|
||||
? ComputerUtil.getCardsToDiscardFromFriend(player, p, sa, validCards, min, max)
|
||||
: ComputerUtil.getCardsToDiscardFromOpponent(player, p, sa, validCards, min, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSpellAbilityForFree(SpellAbility copySA, boolean mayChooseNewTargets) {
|
||||
// Ai is known to set targets in doTrigger, so if it cannot choose new
|
||||
// targets, we won't call canPlays
|
||||
// Ai is known to set targets in doTrigger, so if it cannot choose new targets, we won't call canPlays
|
||||
if (mayChooseNewTargets) {
|
||||
if (copySA instanceof Spell) {
|
||||
Spell spell = (Spell) copySA;
|
||||
((PlayerControllerAi) player.getController()).getAi().canPlayFromEffectAI(spell, true, true);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
getAi().canPlaySa(copySA);
|
||||
}
|
||||
}
|
||||
@@ -320,9 +309,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
@Override
|
||||
public void playSpellAbilityNoStack(SpellAbility effectSA, boolean canSetupTargets) {
|
||||
if (canSetupTargets)
|
||||
brains.doTrigger(effectSA, true); // first parameter does not
|
||||
// matter, since return value
|
||||
// won't be used
|
||||
brains.doTrigger(effectSA, true); // first parameter does not matter, since return value won't be used
|
||||
ComputerUtil.playNoStack(player, effectSA, game);
|
||||
}
|
||||
|
||||
@@ -338,34 +325,33 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
@Override
|
||||
public TargetChoices chooseNewTargetsFor(SpellAbility ability) {
|
||||
// AI currently can't do this. But when it can it will need to be based
|
||||
// on Ability API
|
||||
// AI currently can't do this. But when it can it will need to be based on Ability API
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardCollectionView chooseCardsToDiscardUnlessType(int num, CardCollectionView hand, String uType,
|
||||
SpellAbility sa) {
|
||||
public CardCollectionView chooseCardsToDiscardUnlessType(int num, CardCollectionView hand, String uType, SpellAbility sa) {
|
||||
final CardCollectionView cardsOfType = CardLists.getType(hand, uType);
|
||||
if (!cardsOfType.isEmpty()) {
|
||||
Card toDiscard = Aggregates.itemWithMin(cardsOfType, CardPredicates.Accessors.fnGetCmc);
|
||||
return new CardCollection(toDiscard);
|
||||
}
|
||||
return getAi().getCardsToDiscard(num, (String[]) null, sa);
|
||||
return getAi().getCardsToDiscard(num, (String[])null, sa);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Mana chooseManaFromPool(List<Mana> manaChoices) {
|
||||
return manaChoices.get(0); // no brains used
|
||||
}
|
||||
|
||||
@Override
|
||||
public String chooseSomeType(String kindOfType, SpellAbility sa, List<String> validTypes, List<String> invalidTypes,
|
||||
boolean isOptional) {
|
||||
public String chooseSomeType(String kindOfType, SpellAbility sa, List<String> validTypes, List<String> invalidTypes, boolean isOptional) {
|
||||
String chosen = ComputerUtil.chooseSomeType(player, kindOfType, sa.getParam("AILogic"), invalidTypes);
|
||||
if (StringUtils.isBlank(chosen) && !validTypes.isEmpty()) {
|
||||
if (StringUtils.isBlank(chosen) && !validTypes.isEmpty())
|
||||
{
|
||||
chosen = validTypes.get(0);
|
||||
Log.warn("AI has no idea how to choose " + kindOfType + ", defaulting to 1st element: chosen");
|
||||
Log.warn("AI has no idea how to choose " + kindOfType +", defaulting to 1st element: chosen");
|
||||
}
|
||||
game.getAction().nofityOfValue(sa, null, "Computer picked: " + chosen, player);
|
||||
return chosen;
|
||||
@@ -377,13 +363,12 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA,
|
||||
String question) {
|
||||
public boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, String question) {
|
||||
return brains.aiShouldRun(replacementEffect, effectSA);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardCollectionView getCardsToMulligan(Player firstPlayer) {
|
||||
public CardCollectionView getCardsToMulligan(Player firstPlayer) {
|
||||
if (!ComputerUtil.wantMulligan(player)) {
|
||||
return null;
|
||||
}
|
||||
@@ -405,7 +390,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
public List<SpellAbility> chooseSpellAbilityToPlay() {
|
||||
return brains.chooseSpellAbilityToPlay();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void playChosenSpellAbility(SpellAbility sa) {
|
||||
// System.out.println("Playing sa: " + sa);
|
||||
@@ -414,26 +399,22 @@ public class PlayerControllerAi extends PlayerController {
|
||||
} else {
|
||||
ComputerUtil.handlePlayingSpellAbility(player, sa, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardCollection chooseCardsToDiscardToMaximumHandSize(int numDiscard) {
|
||||
return brains.getCardsToDiscard(numDiscard, (String[]) null, null);
|
||||
return brains.getCardsToDiscard(numDiscard, (String[])null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardCollection chooseCardsToRevealFromHand(int min, int max, CardCollectionView valid) {
|
||||
int numCardsToReveal = Math.min(max, valid.size());
|
||||
return numCardsToReveal == 0 ? new CardCollection() : (CardCollection) valid.subList(0, numCardsToReveal);
|
||||
return numCardsToReveal == 0 ? new CardCollection() : (CardCollection)valid.subList(0, numCardsToReveal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payManaOptional(Card c, Cost cost, SpellAbility sa, String prompt, ManaPaymentPurpose purpose) {
|
||||
final Ability ability = new AbilityStatic(c, cost, null) {
|
||||
@Override
|
||||
public void resolve() {
|
||||
}
|
||||
};
|
||||
final Ability ability = new AbilityStatic(c, cost, null) { @Override public void resolve() {} };
|
||||
ability.setActivatingPlayer(c.getController());
|
||||
|
||||
if (ComputerUtilCost.canPayCost(ability, c.getController())) {
|
||||
@@ -445,8 +426,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
@Override
|
||||
public List<SpellAbility> chooseSaToActivateFromOpeningHand(List<SpellAbility> usableFromOpeningHand) {
|
||||
// AI would play everything. But limits to one copy of (Leyline of
|
||||
// Singularity) and (Gemstone Caverns)
|
||||
// AI would play everything. But limits to one copy of (Leyline of Singularity) and (Gemstone Caverns)
|
||||
return brains.chooseSaToActivateFromOpeningHand(usableFromOpeningHand);
|
||||
}
|
||||
|
||||
@@ -454,16 +434,13 @@ public class PlayerControllerAi extends PlayerController {
|
||||
public int chooseNumber(SpellAbility sa, String title, int min, int max) {
|
||||
return brains.chooseNumber(sa, title, min, max);
|
||||
}
|
||||
|
||||
|
||||
public int chooseNumber(SpellAbility sa, String title, List<Integer> options, Player relatedPlayer) {
|
||||
return brains.chooseNumber(sa, title, options, relatedPlayer);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.game.player.PlayerController#chooseFlipResult(forge.Card,
|
||||
* forge.game.player.Player, java.lang.String[], boolean)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.player.PlayerController#chooseFlipResult(forge.Card, forge.game.player.Player, java.lang.String[], boolean)
|
||||
*/
|
||||
@Override
|
||||
public boolean chooseFlipResult(SpellAbility sa, Player flipper, boolean[] results, boolean call) {
|
||||
@@ -485,37 +462,31 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<SpellAbilityStackInstance, GameObject> chooseTarget(SpellAbility saSrc,
|
||||
List<Pair<SpellAbilityStackInstance, GameObject>> allTargets) {
|
||||
public Pair<SpellAbilityStackInstance, GameObject> chooseTarget(SpellAbility saSrc, List<Pair<SpellAbilityStackInstance, GameObject>> allTargets) {
|
||||
// TODO Teach AI how to use Spellskite
|
||||
return allTargets.get(0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void notifyOfValue(SpellAbility saSource, GameObject realtedTarget, String value) {
|
||||
// AI should take into consideration creature types, numbers and other
|
||||
// information (mostly choices) arriving through this channel
|
||||
// AI should take into consideration creature types, numbers and other information (mostly choices) arriving through this channel
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chooseBinary(SpellAbility sa, String question, BinaryChoiceType kindOfChoice, Boolean defaultVal) {
|
||||
switch (kindOfChoice) {
|
||||
case TapOrUntap:
|
||||
return true;
|
||||
case UntapOrLeaveTapped:
|
||||
return defaultVal != null && defaultVal.booleanValue();
|
||||
case UntapTimeVault:
|
||||
return false; // TODO Should AI skip his turn for time vault?
|
||||
case LeftOrRight:
|
||||
return brains.chooseDirection(sa);
|
||||
default:
|
||||
return MyRandom.getRandom().nextBoolean();
|
||||
switch(kindOfChoice) {
|
||||
case TapOrUntap: return true;
|
||||
case UntapOrLeaveTapped: return defaultVal != null && defaultVal.booleanValue();
|
||||
case UntapTimeVault: return false; // TODO Should AI skip his turn for time vault?
|
||||
case LeftOrRight: return brains.chooseDirection(sa);
|
||||
default:
|
||||
return MyRandom.getRandom().nextBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Card chooseProtectionShield(GameEntity entityBeingDamaged, List<String> options,
|
||||
Map<String, Card> choiceMap) {
|
||||
public Card chooseProtectionShield(GameEntity entityBeingDamaged, List<String> options, Map<String, Card> choiceMap) {
|
||||
int i = MyRandom.getRandom().nextInt(options.size());
|
||||
return choiceMap.get(options.get(i));
|
||||
}
|
||||
@@ -537,10 +508,9 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<CounterType, String> chooseAndRemoveOrPutCounter(Card cardWithCounter) {
|
||||
public Pair<CounterType,String> chooseAndRemoveOrPutCounter(Card cardWithCounter) {
|
||||
if (!cardWithCounter.hasCounters()) {
|
||||
System.out.println(
|
||||
"chooseCounterType was reached with a card with no counters on it. Consider filtering this card out earlier");
|
||||
System.out.println("chooseCounterType was reached with a card with no counters on it. Consider filtering this card out earlier");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -554,7 +524,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
for (final CounterType counter : cardWithCounter.getCounters().keySet()) {
|
||||
if ((!ComputerUtil.isNegativeCounter(counter, cardWithCounter) && allies.contains(controller))
|
||||
|| (ComputerUtil.isNegativeCounter(counter, cardWithCounter) && enemies.contains(controller))) {
|
||||
|| (ComputerUtil.isNegativeCounter(counter, cardWithCounter) && enemies.contains(controller))) {
|
||||
countersToIncrease.add(counter);
|
||||
} else {
|
||||
countersToDecrease.add(counter);
|
||||
@@ -563,18 +533,20 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
if (!countersToIncrease.isEmpty()) {
|
||||
int random = MyRandom.getRandom().nextInt(countersToIncrease.size());
|
||||
return new ImmutablePair<CounterType, String>(countersToIncrease.get(random), "Put");
|
||||
} else if (!countersToDecrease.isEmpty()) {
|
||||
return new ImmutablePair<CounterType,String>(countersToIncrease.get(random),"Put");
|
||||
}
|
||||
else if (!countersToDecrease.isEmpty()) {
|
||||
int random = MyRandom.getRandom().nextInt(countersToDecrease.size());
|
||||
return new ImmutablePair<CounterType, String>(countersToDecrease.get(random), "Remove");
|
||||
return new ImmutablePair<CounterType,String>(countersToDecrease.get(random),"Remove");
|
||||
}
|
||||
|
||||
// shouldn't reach here but just in case, remove random counter
|
||||
List<CounterType> countersOnCard = new ArrayList<CounterType>();
|
||||
int random = MyRandom.getRandom().nextInt(countersOnCard.size());
|
||||
return new ImmutablePair<CounterType, String>(countersOnCard.get(random), "Remove");
|
||||
return new ImmutablePair<CounterType,String>(countersOnCard.get(random),"Remove");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte chooseColorAllowColorless(String message, Card card, ColorSet colors) {
|
||||
final String c = ComputerUtilCard.getMostProminentColor(player.getCardsIn(ZoneType.Hand));
|
||||
@@ -582,7 +554,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
if ((colors.getColor() & chosenColorMask) != 0) {
|
||||
return chosenColorMask;
|
||||
} else {
|
||||
return Iterables.getFirst(colors, (byte) 0);
|
||||
return Iterables.getFirst(colors, (byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,20 +570,16 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
if ((colors.getColor() & chosenColorMask) != 0) {
|
||||
return chosenColorMask;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return Iterables.getFirst(colors, MagicColor.WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaperCard chooseSinglePaperCard(SpellAbility sa, String message, Predicate<PaperCard> cpp, String name) {
|
||||
throw new UnsupportedOperationException("Should not be called for AI"); // or
|
||||
// implement
|
||||
// it
|
||||
// if
|
||||
// you
|
||||
// know
|
||||
// how
|
||||
public PaperCard chooseSinglePaperCard(SpellAbility sa, String message,
|
||||
Predicate<PaperCard> cpp, String name) {
|
||||
throw new UnsupportedOperationException("Should not be called for AI"); // or implement it if you know how
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -621,8 +589,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
@Override
|
||||
public CounterType chooseCounterType(List<CounterType> options, SpellAbility sa, String prompt) {
|
||||
// may write a smarter AI if you need to (with calls to AI-clas for
|
||||
// given API ability)
|
||||
// may write a smarter AI if you need to (with calls to AI-clas for given API ability)
|
||||
|
||||
// TODO: ArsenalNut (06 Feb 12)computer needs
|
||||
// better logic to pick a counter type and probably
|
||||
@@ -633,15 +600,11 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
@Override
|
||||
public boolean confirmPayment(CostPart costPart, String prompt) {
|
||||
return brains.confirmPayment(costPart); // AI is expected to know what
|
||||
// it is paying for at the
|
||||
// moment (otherwise add another
|
||||
// parameter to this method)
|
||||
return brains.confirmPayment(costPart); // AI is expected to know what it is paying for at the moment (otherwise add another parameter to this method)
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReplacementEffect chooseSingleReplacementEffect(String prompt, List<ReplacementEffect> possibleReplacers,
|
||||
Map<String, Object> runParams) {
|
||||
public ReplacementEffect chooseSingleReplacementEffect(String prompt, List<ReplacementEffect> possibleReplacers, Map<String, Object> runParams) {
|
||||
// AI logic for choosing which replacement effect to apply
|
||||
// happens here.
|
||||
return possibleReplacers.get(0);
|
||||
@@ -650,7 +613,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
@Override
|
||||
public String chooseProtectionType(String string, SpellAbility sa, List<String> choices) {
|
||||
String choice = choices.get(0);
|
||||
SpellAbility hostsa = null; // for Protect sub-ability
|
||||
SpellAbility hostsa = null; //for Protect sub-ability
|
||||
if (game.stack.size() > 1) {
|
||||
for (SpellAbilityStackInstance si : game.getStack()) {
|
||||
SpellAbility spell = si.getSpellAbility(true);
|
||||
@@ -690,8 +653,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
}
|
||||
final PhaseHandler ph = game.getPhaseHandler();
|
||||
if (ph.getPlayerTurn() == sa.getActivatingPlayer() && ph.getPhase() == PhaseType.MAIN1
|
||||
&& sa.getTargetCard() != null) {
|
||||
if (ph.getPlayerTurn() == sa.getActivatingPlayer() && ph.getPhase() == PhaseType.MAIN1 && sa.getTargetCard() != null) {
|
||||
AiAttackController aiAtk = new AiAttackController(sa.getActivatingPlayer(), sa.getTargetCard());
|
||||
String s = aiAtk.toProtectAttacker(sa);
|
||||
if (s != null) {
|
||||
@@ -715,22 +677,12 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payCostToPreventEffect(Cost cost, SpellAbility sa, boolean alreadyPaid,
|
||||
FCollectionView<Player> allPayers) {
|
||||
public boolean payCostToPreventEffect(Cost cost, SpellAbility sa, boolean alreadyPaid, FCollectionView<Player> allPayers) {
|
||||
final Card source = sa.getHostCard();
|
||||
final Ability emptyAbility = new AbilityStatic(source, cost, sa.getTargetRestrictions()) {
|
||||
@Override
|
||||
public void resolve() {
|
||||
}
|
||||
};
|
||||
final Ability emptyAbility = new AbilityStatic(source, cost, sa.getTargetRestrictions()) { @Override public void resolve() { } };
|
||||
emptyAbility.setActivatingPlayer(player);
|
||||
if (ComputerUtilCost.willPayUnlessCost(sa, player, cost, alreadyPaid, allPayers)
|
||||
&& ComputerUtilCost.canPayCost(emptyAbility, player)) {
|
||||
ComputerUtil.playNoStack(player, emptyAbility, game); // AI needs
|
||||
// something
|
||||
// to resolve
|
||||
// to pay that
|
||||
// cost
|
||||
if (ComputerUtilCost.willPayUnlessCost(sa, player, cost, alreadyPaid, allPayers) && ComputerUtilCost.canPayCost(emptyAbility, player)) {
|
||||
ComputerUtil.playNoStack(player, emptyAbility, game); // AI needs something to resolve to pay that cost
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -739,12 +691,12 @@ public class PlayerControllerAi extends PlayerController {
|
||||
@Override
|
||||
public void orderAndPlaySimultaneousSa(List<SpellAbility> activePlayerSAs) {
|
||||
for (final SpellAbility sa : activePlayerSAs) {
|
||||
prepareSingleSa(sa.getHostCard(), sa, true);
|
||||
prepareSingleSa(sa.getHostCard(),sa,true);
|
||||
ComputerUtil.playStack(sa, player, game);
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareSingleSa(final Card host, final SpellAbility sa, boolean isMandatory) {
|
||||
|
||||
private void prepareSingleSa(final Card host, final SpellAbility sa, boolean isMandatory){
|
||||
if (sa.hasParam("TargetingPlayer")) {
|
||||
Player targetingPlayer = AbilityUtils.getDefinedPlayers(host, sa.getParam("TargetingPlayer"), sa).get(0);
|
||||
sa.setTargetingPlayer(targetingPlayer);
|
||||
@@ -772,7 +724,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
} else {
|
||||
ComputerUtil.playStack(tgtSA, player, game);
|
||||
}
|
||||
} else
|
||||
} else
|
||||
return false; // didn't play spell
|
||||
}
|
||||
return true;
|
||||
@@ -789,19 +741,15 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chooseCardsPile(SpellAbility sa, CardCollectionView pile1, CardCollectionView pile2,
|
||||
boolean faceUp) {
|
||||
public boolean chooseCardsPile(SpellAbility sa, CardCollectionView pile1, CardCollectionView pile2, boolean faceUp) {
|
||||
if (!faceUp) {
|
||||
// AI will choose the first pile if it is larger or the same
|
||||
// TODO Improve this to be slightly more random to not be so
|
||||
// predictable
|
||||
// TODO Improve this to be slightly more random to not be so predictable
|
||||
return pile1.size() >= pile2.size();
|
||||
} else {
|
||||
boolean allCreatures = Iterables.all(Iterables.concat(pile1, pile2), CardPredicates.Presets.CREATURES);
|
||||
int cmc1 = allCreatures ? ComputerUtilCard.evaluateCreatureList(pile1)
|
||||
: ComputerUtilCard.evaluatePermanentList(pile1);
|
||||
int cmc2 = allCreatures ? ComputerUtilCard.evaluateCreatureList(pile2)
|
||||
: ComputerUtilCard.evaluatePermanentList(pile2);
|
||||
int cmc1 = allCreatures ? ComputerUtilCard.evaluateCreatureList(pile1) : ComputerUtilCard.evaluatePermanentList(pile1);
|
||||
int cmc2 = allCreatures ? ComputerUtilCard.evaluateCreatureList(pile2) : ComputerUtilCard.evaluatePermanentList(pile2);
|
||||
System.out.println("value:" + cmc1 + " " + cmc2);
|
||||
|
||||
// for now, this assumes that the outcome will be bad
|
||||
@@ -815,7 +763,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
public void revealAnte(String message, Multimap<Player, PaperCard> removedAnteCards) {
|
||||
// Ai won't understand that anyway
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<? extends PaperCard> complainCardsCantPlayWell(Deck myDeck) {
|
||||
return brains.complainCardsCantPlayWell(myDeck);
|
||||
@@ -826,10 +774,10 @@ public class PlayerControllerAi extends PlayerController {
|
||||
return brains.getBooleanProperty(AiProps.CHEAT_WITH_MANA_ON_SHUFFLE) ? brains.cheatShuffle(list) : list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardShields chooseRegenerationShield(Card c) {
|
||||
return Iterables.getFirst(c.getShields(), null);
|
||||
}
|
||||
@Override
|
||||
public CardShields chooseRegenerationShield(Card c) {
|
||||
return Iterables.getFirst(c.getShields(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PaperCard> chooseCardsYouWonToAddToDeck(List<PaperCard> losses) {
|
||||
@@ -838,38 +786,35 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa,
|
||||
String prompt /* ai needs hints as well */, boolean isActivatedSa) {
|
||||
public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt /* ai needs hints as well */, boolean isActivatedSa) {
|
||||
// TODO Auto-generated method stub
|
||||
ManaCostBeingPaid cost = isActivatedSa ? ComputerUtilMana.calculateManaCost(sa, false, 0)
|
||||
: new ManaCostBeingPaid(toPay);
|
||||
ManaCostBeingPaid cost = isActivatedSa ? ComputerUtilMana.calculateManaCost(sa, false, 0) : new ManaCostBeingPaid(toPay);
|
||||
return ComputerUtilMana.payManaCost(cost, sa, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Card, ManaCostShard> chooseCardsForConvoke(SpellAbility sa, ManaCost manaCost,
|
||||
CardCollectionView untappedCreats0) {
|
||||
public Map<Card, ManaCostShard> chooseCardsForConvoke(SpellAbility sa, ManaCost manaCost, CardCollectionView untappedCreats0) {
|
||||
final Player ai = sa.getActivatingPlayer();
|
||||
final PhaseHandler ph = ai.getGame().getPhaseHandler();
|
||||
// Filter out mana sources that will interfere with payManaCost()
|
||||
//Filter out mana sources that will interfere with payManaCost()
|
||||
CardCollection untappedCreats = CardLists.filter(untappedCreats0, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return c.getManaAbilities().isEmpty();
|
||||
}
|
||||
});
|
||||
|
||||
// Only convoke after attackers have been declared
|
||||
|
||||
//Only convoke after attackers have been declared
|
||||
if (ph.isPlayerTurn(ai) && ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
|
||||
return new HashMap<Card, ManaCostShard>();
|
||||
}
|
||||
|
||||
// Do not convoke potential blockers until after opponent's attack
|
||||
|
||||
//Do not convoke potential blockers until after opponent's attack
|
||||
final CardCollectionView blockers = ComputerUtilCard.getLikelyBlockers(ai, null);
|
||||
if ((ph.isPlayerTurn(ai) && ph.getPhase().isAfter(PhaseType.COMBAT_BEGIN))
|
||||
|| (!ph.isPlayerTurn(ai) && ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS))) {
|
||||
untappedCreats.removeAll((List<?>) blockers);
|
||||
// Add threatened creatures
|
||||
if ((ph.isPlayerTurn(ai) && ph.getPhase().isAfter(PhaseType.COMBAT_BEGIN)) ||
|
||||
(!ph.isPlayerTurn(ai) && ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS))) {
|
||||
untappedCreats.removeAll((List<?>)blockers);
|
||||
//Add threatened creatures
|
||||
if (!ai.getGame().getStack().isEmpty()) {
|
||||
final List<GameObject> objects = ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), null);
|
||||
for (Card c : blockers) {
|
||||
@@ -891,16 +836,14 @@ public class PlayerControllerAi extends PlayerController {
|
||||
} else if (logic.equals("MostProminentInHumanDeck")) {
|
||||
return ComputerUtilCard.getMostProminentCardName(player.getOpponent().getCardsIn(ZoneType.Library));
|
||||
} else if (logic.equals("MostProminentCreatureInComputerDeck")) {
|
||||
CardCollectionView cards = CardLists.getValidCards(player.getCardsIn(ZoneType.Library), "Creature",
|
||||
player, sa.getHostCard());
|
||||
CardCollectionView cards = CardLists.getValidCards(player.getCardsIn(ZoneType.Library), "Creature", player, sa.getHostCard());
|
||||
return ComputerUtilCard.getMostProminentCardName(cards);
|
||||
} else if (logic.equals("BestCreatureInComputerDeck")) {
|
||||
return ComputerUtilCard.getBestCreatureAI(player.getCardsIn(ZoneType.Library)).getName();
|
||||
} else if (logic.equals("RandomInComputerDeck")) {
|
||||
return Aggregates.random(player.getCardsIn(ZoneType.Library)).getName();
|
||||
} else if (logic.equals("MostProminentSpellInComputerDeck")) {
|
||||
CardCollectionView cards = CardLists.getValidCards(player.getCardsIn(ZoneType.Library),
|
||||
"Card.Instant,Card.Sorcery", player, sa.getHostCard());
|
||||
CardCollectionView cards = CardLists.getValidCards(player.getCardsIn(ZoneType.Library), "Card.Instant,Card.Sorcery", player, sa.getHostCard());
|
||||
return ComputerUtilCard.getMostProminentCardName(cards);
|
||||
}
|
||||
} else {
|
||||
@@ -914,21 +857,19 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Card chooseSingleCardForZoneChange(ZoneType destination, List<ZoneType> origin, SpellAbility sa,
|
||||
CardCollection fetchList, DelayedReveal delayedReveal, String selectPrompt, boolean isOptional,
|
||||
Player decider) {
|
||||
public Card chooseSingleCardForZoneChange(ZoneType destination,
|
||||
List<ZoneType> origin, SpellAbility sa, CardCollection fetchList, DelayedReveal delayedReveal,
|
||||
String selectPrompt, boolean isOptional, Player decider) {
|
||||
|
||||
if (delayedReveal != null) {
|
||||
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(),
|
||||
delayedReveal.getMessagePrefix());
|
||||
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix());
|
||||
}
|
||||
return ChangeZoneAi.chooseCardToHiddenOriginChangeZone(destination, origin, sa, fetchList, player, decider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetAtEndOfTurn() {
|
||||
// TODO - if card memory is ever used to remember something for longer
|
||||
// than a turn, make sure it's not reset here.
|
||||
// TODO - if card memory is ever used to remember something for longer than a turn, make sure it's not reset here.
|
||||
getAi().getCardMemory().clearAllRemembered();
|
||||
}
|
||||
|
||||
@@ -941,7 +882,6 @@ public class PlayerControllerAi extends PlayerController {
|
||||
public void awaitNextInput() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelAwaitNextInput() {
|
||||
// Do nothing
|
||||
|
||||
Reference in New Issue
Block a user