From e09aa4af9534367c937b3d3c2d7ae51fc46026b0 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Mon, 28 Feb 2022 22:41:28 +0100 Subject: [PATCH] Fix card KW on player --- .../src/main/java/forge/ai/AiController.java | 4 +--- .../main/java/forge/ai/AiCostDecision.java | 6 ++---- .../src/main/java/forge/ai/AiProfileUtil.java | 3 +-- .../src/main/java/forge/ai/ComputerUtil.java | 4 ++-- .../java/forge/ai/ComputerUtilAbility.java | 6 ++---- .../main/java/forge/ai/ComputerUtilCard.java | 8 +++----- .../java/forge/ai/PlayerControllerAi.java | 19 +++++++++---------- .../src/main/java/forge/game/GameAction.java | 1 + .../forge/game/player/PlayerController.java | 15 +++++++-------- .../forge/game/spellability/SpellAbility.java | 3 +-- .../res/cardsfolder/b/bag_of_holding.txt | 2 +- forge-gui/res/cardsfolder/c/carbonize.txt | 4 ++-- forge-gui/res/cardsfolder/d/disintegrate.txt | 4 ++-- .../res/cardsfolder/s/scorching_lava.txt | 4 ++-- 14 files changed, 36 insertions(+), 47 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 7b00f98b9bb..572fc0e2f25 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -160,9 +160,7 @@ public class AiController { all.add(ccvPlayerLibrary.get(0)); } - for (final Player opp : player.getOpponents()) { - all.addAll(opp.getCardsIn(ZoneType.Exile)); - } + all.addAll(player.getOpponents().getCardsIn(ZoneType.Exile)); final List spellAbilities = Lists.newArrayList(); for (final Card c : all) { diff --git a/forge-ai/src/main/java/forge/ai/AiCostDecision.java b/forge-ai/src/main/java/forge/ai/AiCostDecision.java index 2b6f3500335..d18fe49da37 100644 --- a/forge-ai/src/main/java/forge/ai/AiCostDecision.java +++ b/forge-ai/src/main/java/forge/ai/AiCostDecision.java @@ -344,8 +344,7 @@ public class AiCostDecision extends CostDecisionMakerBase { } } chosen = chosen.subList(0, c); - } - else { + } else { chosen = ComputerUtil.choosePutToLibraryFrom(player, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c, ability); } return chosen.isEmpty() ? null : PaymentDecision.card(chosen); @@ -363,8 +362,7 @@ public class AiCostDecision extends CostDecisionMakerBase { Card card; if (cost.getType().equals("Creature.YouCtrl")) { card = ComputerUtilCard.getWorstCreatureAI(typeList); - } - else { + } else { card = ComputerUtilCard.getWorstPermanentAI(typeList, false, false, false, false); } return PaymentDecision.card(card); diff --git a/forge-ai/src/main/java/forge/ai/AiProfileUtil.java b/forge-ai/src/main/java/forge/ai/AiProfileUtil.java index e119d6b5ca0..a1848a9b558 100644 --- a/forge-ai/src/main/java/forge/ai/AiProfileUtil.java +++ b/forge-ai/src/main/java/forge/ai/AiProfileUtil.java @@ -119,8 +119,7 @@ public class AiProfileUtil { * @return ArrayList - an array of strings containing all * available profiles. */ - public static List getAvailableProfiles() - { + public static List getAvailableProfiles() { final List availableProfiles = new ArrayList<>(); final File dir = new File(AI_PROFILE_DIR); diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtil.java b/forge-ai/src/main/java/forge/ai/ComputerUtil.java index 9ff0c3f8b41..f130e08e967 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtil.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtil.java @@ -703,13 +703,13 @@ public class ComputerUtil { if (pow <= 0) { continue; } - totalPower += pow; if (pow >= amount) { // If the power of this creature matches the totalPower needed // Might as well only use this creature? tapList.clear(); } tapList.add(next); + totalPower = CardLists.getTotalPower(tapList, true, sa.hasParam("Crew")); if (totalPower >= amount) { break; } @@ -793,7 +793,7 @@ public class ComputerUtil { boolean exceptSelf = "ExceptSelf".equals(source.getParam("AILogic")); boolean removedSelf = false; - if (isOptional && source.hasParam("Devour") || source.hasParam("Exploit")) { + if (isOptional && (source.hasParam("Devour") || source.hasParam("Exploit"))) { if (source.hasParam("Exploit")) { for (Trigger t : host.getTriggers()) { if (t.getMode() == TriggerType.Exploited) { diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilAbility.java b/forge-ai/src/main/java/forge/ai/ComputerUtilAbility.java index 8766eff1f05..bfcad761181 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilAbility.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilAbility.java @@ -72,10 +72,8 @@ public class ComputerUtilAbility { if (!player.getCardsIn(ZoneType.Library).isEmpty()) { all.add(player.getCardsIn(ZoneType.Library).get(0)); } - for (Player p : game.getPlayers()) { - all.addAll(p.getCardsIn(ZoneType.Exile)); - all.addAll(p.getCardsIn(ZoneType.Battlefield)); - } + all.addAll(game.getPlayers().getCardsIn(ZoneType.Exile)); + all.addAll(game.getPlayers().getCardsIn(ZoneType.Battlefield)); return all; } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index eae57125e27..939f79f7a26 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -1361,7 +1361,7 @@ public class ComputerUtilCard { if (!Iterables.any(oppCreatures, CardPredicates.possibleBlockers(pumped))) { threat *= 2; } - if (c.getNetPower() == 0 && c == sa.getHostCard() && power > 0 ) { + if (c.getNetPower() == 0 && c == sa.getHostCard() && power > 0) { threat *= 4; //over-value self +attack for 0 power creatures which may be pumped further after attacking } chance += threat; @@ -1378,9 +1378,7 @@ public class ComputerUtilCard { && ComputerUtilMana.hasEnoughManaSourcesToCast(sa, ai)) { combatTrick = true; - final List kws = sa.hasParam("KW") ? Arrays.asList(sa.getParam("KW").split(" & ")) - : Lists.newArrayList(); - for (String kw : kws) { + for (String kw : keywords) { if (!kw.equals("Trample") && !kw.equals("First Strike") && !kw.equals("Double Strike")) { combatTrick = false; break; @@ -1565,7 +1563,7 @@ public class ComputerUtilCard { } //5. if the life of the computer is in danger, try to pump blockers blocking Tramplers - if (combat.isBlocking(c) && toughness > 0 ) { + if (combat.isBlocking(c) && toughness > 0) { List blockedBy = combat.getAttackersBlockedBy(c); boolean attackerHasTrample = false; for (Card b : blockedBy) { diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index 1406126a762..616e66069e4 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -242,11 +242,11 @@ public class PlayerControllerAi extends PlayerController { SpellAbility selected; do { selected = chooseSingleSpellForEffect(remaining, sa, title, params); - if ( selected != null ) { + if (selected != null) { remaining.remove(selected); selecteds.add(selected); } - } while ( (selected != null ) && (selecteds.size() < num) ); + } while (selected != null && selecteds.size() < num); return selecteds; } @@ -544,12 +544,6 @@ public class PlayerControllerAi extends PlayerController { return getAi().chooseCardsToDelve(genericAmount, grave); } - @Override - public TargetChoices chooseNewTargetsFor(SpellAbility ability, Predicate filter, boolean optional) { - // 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) { String [] splitUTypes = uType.split(","); @@ -1099,6 +1093,12 @@ public class PlayerControllerAi extends PlayerController { return brains.doTrigger(currentAbility, true); } + @Override + public TargetChoices chooseNewTargetsFor(SpellAbility ability, Predicate filter, boolean optional) { + // AI currently can't do this. But when it can it will need to be based on Ability API + return null; + } + @Override public boolean chooseCardsPile(SpellAbility sa, CardCollectionView pile1, CardCollectionView pile2, String faceUp) { if (faceUp.equals("True")) { @@ -1341,8 +1341,7 @@ public class PlayerControllerAi extends PlayerController { } @Override - public List chooseOptionalCosts(SpellAbility chosen, - List optionalCostValues) { + public List chooseOptionalCosts(SpellAbility chosen, List optionalCostValues) { List chosenOptCosts = Lists.newArrayList(); Cost costSoFar = chosen.getPayCosts().copy(); diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 4d93d16a262..08ac6758544 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -1308,6 +1308,7 @@ public class GameAction { desCreats = new CardCollection(); } desCreats.add(c); + c.setHasBeenDealtDeathtouchDamage(false); checkAgain = true; break; } diff --git a/forge-game/src/main/java/forge/game/player/PlayerController.java b/forge-game/src/main/java/forge/game/player/PlayerController.java index b596ce17c6c..137bcc5b8a3 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -101,7 +101,7 @@ public abstract class PlayerController { public final SpellAbility getAbilityToPlay(final Card hostCard, final List abilities) { return getAbilityToPlay(hostCard, abilities, null); } public abstract SpellAbility getAbilityToPlay(Card hostCard, List abilities, ITriggerEvent triggerEvent); - //public abstract void playFromSuspend(Card c); + @Deprecated public abstract void playSpellAbilityForFree(SpellAbility copySA, boolean mayChoseNewTargets); public abstract void playSpellAbilityNoStack(SpellAbility effectSA, boolean mayChoseNewTargets); @@ -130,13 +130,13 @@ public abstract class PlayerController { public abstract List chooseSpellAbilitiesForEffect(List spells, SpellAbility sa, String title, int num, Map params); - public abstract SpellAbility chooseSingleSpellForEffect(List spells, SpellAbility sa, String title, - Map params); + public abstract SpellAbility chooseSingleSpellForEffect(List spells, SpellAbility sa, String title, Map params); public abstract List chooseEntitiesForEffect(FCollectionView optionList, int min, int max, DelayedReveal delayedReveal, SpellAbility sa, String title, Player relatedPlayer, Map params); public abstract boolean confirmAction(SpellAbility sa, PlayerActionConfirmMode mode, String message); public abstract boolean confirmBidAction(SpellAbility sa, PlayerActionConfirmMode bidlife, String string, int bid, Player winner); + public abstract boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, GameEntity affected, String question); public abstract boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message); public abstract boolean confirmTrigger(WrappedAbility sa); public abstract Player chooseStartingPlayer(boolean isFirstGame); @@ -170,10 +170,11 @@ public abstract class PlayerController { /** p = target player, validCards - possible discards, min cards to discard */ public abstract CardCollectionView chooseCardsToDiscardFrom(Player playerDiscard, SpellAbility sa, CardCollection validCards, int min, int max); + public abstract CardCollectionView chooseCardsToDiscardUnlessType(int min, CardCollectionView hand, String param, SpellAbility sa); + public abstract CardCollection chooseCardsToDiscardToMaximumHandSize(int numDiscard); public abstract CardCollectionView chooseCardsToDelve(int genericAmount, CardCollection grave); public abstract CardCollectionView chooseCardsToRevealFromHand(int min, int max, CardCollectionView valid); - public abstract CardCollectionView chooseCardsToDiscardUnlessType(int min, CardCollectionView hand, String param, SpellAbility sa); public abstract List chooseSaToActivateFromOpeningHand(List usableFromOpeningHand); public abstract Mana chooseManaFromPool(List manaChoices); @@ -183,7 +184,6 @@ public abstract class PlayerController { } public abstract Object vote(SpellAbility sa, String prompt, List options, ListMultimap votes, Player forPlayer); - public abstract boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, GameEntity affected, String question); public abstract CardCollectionView getCardsToMulligan(Player firstPlayer); public abstract boolean mulliganKeepHand(Player player, int cardsToReturn); @@ -194,7 +194,6 @@ public abstract class PlayerController { public abstract List chooseSpellAbilityToPlay(); public abstract boolean playChosenSpellAbility(SpellAbility sa); - public abstract CardCollection chooseCardsToDiscardToMaximumHandSize(int numDiscard); public abstract boolean payManaOptional(Card card, Cost cost, SpellAbility sa, String prompt, ManaPaymentPurpose purpose); public abstract int chooseNumberForKeywordCost(SpellAbility sa, Cost cost, KeywordInterface keyword, String prompt, int max); @@ -213,6 +212,8 @@ public abstract class PlayerController { public boolean chooseBinary(SpellAbility sa, String question, BinaryChoiceType kindOfChoice, Map params) { return chooseBinary(sa, question, kindOfChoice); } public abstract boolean chooseFlipResult(SpellAbility sa, Player flipper, boolean[] results, boolean call); + + @Deprecated public abstract Card chooseProtectionShield(GameEntity entityBeingDamaged, List options, Map choiceMap); public abstract List chooseModeForAbility(SpellAbility sa, List possible, int min, int num, boolean allowRepeat); @@ -250,7 +251,6 @@ public abstract class PlayerController { public final boolean payManaCost(CostPartMana costPartMana, SpellAbility sa, String prompt, boolean effect) { return payManaCost(costPartMana, sa, prompt, null, effect); } - public final boolean payManaCost(CostPartMana costPartMana, SpellAbility sa, String prompt, ManaConversionMatrix matrix, boolean effect) { return payManaCost(costPartMana.getManaCostFor(sa), costPartMana, sa, prompt, matrix, effect); } @@ -261,7 +261,6 @@ public abstract class PlayerController { public abstract List chooseCardsForSplice(SpellAbility sa, List cards); public abstract String chooseCardName(SpellAbility sa, Predicate cpp, String valid, String message); - public abstract String chooseCardName(SpellAbility sa, List faces, String message); public abstract Card chooseDungeon(Player player, List dungeonCards, String message); diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index 8d494be7d60..4df71c13d17 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -913,8 +913,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit // if alternate state is viewed while card uses original if (node.isIntrinsic() && node.cardState != null && node.cardState.getCard() == node.getHostCard()) { currentName = node.cardState.getName(); - } - else { + } else { currentName = node.getHostCard().getName(); } desc = CardTranslation.translateMultipleDescriptionText(desc, currentName); diff --git a/forge-gui/res/cardsfolder/b/bag_of_holding.txt b/forge-gui/res/cardsfolder/b/bag_of_holding.txt index 1833b22d7f3..026655ffea8 100644 --- a/forge-gui/res/cardsfolder/b/bag_of_holding.txt +++ b/forge-gui/res/cardsfolder/b/bag_of_holding.txt @@ -5,7 +5,7 @@ T:Mode$ Discarded | ValidCard$ Card.YouCtrl | TriggerZones$ Battlefield | Execut SVar:TrigExile:DB$ ChangeZone | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Exile A:AB$ Draw | Cost$ 2 T | NumCards$ 1 | SpellDescription$ Draw a card, then discard a card. | SubAbility$ DBDiscard SVar:DBDiscard:DB$ Discard | Defined$ You | NumCards$ 1 | Mode$ TgtChoose -AI:RemoveDeck:All A:AB$ ChangeZoneAll | Cost$ 4 T Sac<1/CARDNAME> | ChangeType$ Card.ExiledWithSource | Origin$ Exile | Destination$ Hand | AILogic$ DiscardAllAndRetExiled.noDiscard.minAdv2 | SpellDescription$ Return all cards exiled with CARDNAME to their owner's hand. +AI:RemoveDeck:All AI:RemoveDeck:Random Oracle:Whenever you discard a card, exile that card from your graveyard.\n{2}, {T}: Draw a card, then discard a card.\n{4}, {T}, Sacrifice Bag of Holding: Return all cards exiled with Bag of Holding to their owner's hand. diff --git a/forge-gui/res/cardsfolder/c/carbonize.txt b/forge-gui/res/cardsfolder/c/carbonize.txt index 39cff6eba3b..17cd5453302 100644 --- a/forge-gui/res/cardsfolder/c/carbonize.txt +++ b/forge-gui/res/cardsfolder/c/carbonize.txt @@ -1,6 +1,6 @@ Name:Carbonize ManaCost:2 R Types:Instant -A:SP$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 3 | SubAbility$ DB | ReplaceDyingDefined$ Targeted.Creature | SpellDescription$ CARDNAME deals 3 damage to any target. If it's a creature, it can't be regenerated this turn, and if it would die this turn, exile it instead. -SVar:DB:DB$ Pump | KW$ HIDDEN CARDNAME can't be regenerated. | Defined$ Targeted.Creature | StackDescription$ None +A:SP$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 3 | SubAbility$ DB | ReplaceDyingDefined$ ThisTargetedCard.Creature | SpellDescription$ CARDNAME deals 3 damage to any target. If it's a creature, it can't be regenerated this turn, and if it would die this turn, exile it instead. +SVar:DB:DB$ Pump | KW$ HIDDEN CARDNAME can't be regenerated. | Defined$ ParentTarget | ConditionDefined$ ParentTarget | ConditionPresent$ Creature | StackDescription$ None Oracle:Carbonize deals 3 damage to any target. If it's a creature, it can't be regenerated this turn, and if it would die this turn, exile it instead. diff --git a/forge-gui/res/cardsfolder/d/disintegrate.txt b/forge-gui/res/cardsfolder/d/disintegrate.txt index 91fe3100764..550182c28a2 100644 --- a/forge-gui/res/cardsfolder/d/disintegrate.txt +++ b/forge-gui/res/cardsfolder/d/disintegrate.txt @@ -1,7 +1,7 @@ Name:Disintegrate ManaCost:X R Types:Sorcery -A:SP$ DealDamage | Cost$ X R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | SubAbility$ DB | ReplaceDyingDefined$ Targeted.Creature | SpellDescription$ CARDNAME deals X damage to any target. That creature can't be regenerated this turn. If the creature would die this turn, exile it instead. -SVar:DB:DB$ Pump | KW$ HIDDEN CARDNAME can't be regenerated. | Defined$ Targeted.Creature +A:SP$ DealDamage | Cost$ X R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | SubAbility$ DB | ReplaceDyingDefined$ ThisTargetedCard.Creature | SpellDescription$ CARDNAME deals X damage to any target. That creature can't be regenerated this turn. If the creature would die this turn, exile it instead. +SVar:DB:DB$ Pump | KW$ HIDDEN CARDNAME can't be regenerated. | Defined$ ParentTarget | ConditionDefined$ ParentTarget | ConditionPresent$ Creature SVar:X:Count$xPaid Oracle:Disintegrate deals X damage to any target. If it's a creature, it can't be regenerated this turn, and if it would die this turn, exile it instead. diff --git a/forge-gui/res/cardsfolder/s/scorching_lava.txt b/forge-gui/res/cardsfolder/s/scorching_lava.txt index 3085bdf1987..17a9793554b 100644 --- a/forge-gui/res/cardsfolder/s/scorching_lava.txt +++ b/forge-gui/res/cardsfolder/s/scorching_lava.txt @@ -2,6 +2,6 @@ Name:Scorching Lava ManaCost:1 R Types:Instant K:Kicker:R -A:SP$ DealDamage | Cost$ 1 R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 2 | ReplaceDyingDefined$ Targeted.Creature | ReplaceDyingCondition$ Kicked | SubAbility$ KickingLava | SpellDescription$ CARDNAME deals 2 damage to any target. If this spell was kicked, that creature can't be regenerated this turn and if it would die this turn, exile it instead. -SVar:KickingLava:DB$ Pump | KW$ HIDDEN CARDNAME can't be regenerated. | Defined$ Targeted.Creature | Condition$ Kicked +A:SP$ DealDamage | Cost$ 1 R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 2 | ReplaceDyingDefined$ ThisTargetedCard.Creature | ReplaceDyingCondition$ Kicked | SubAbility$ KickingLava | SpellDescription$ CARDNAME deals 2 damage to any target. If this spell was kicked, that creature can't be regenerated this turn and if it would die this turn, exile it instead. +SVar:KickingLava:DB$ Pump | KW$ HIDDEN CARDNAME can't be regenerated. | Defined$ ParentTarget | ConditionDefined$ ParentTarget | ConditionPresent$ Creature | Condition$ Kicked Oracle:Kicker {R} (You may pay an additional {R} as you cast this spell.)\nScorching Lava deals 2 damage to any target. If this spell was kicked, that creature can't be regenerated this turn and if it would die this turn, exile it instead.