Merge branch 'cardfix' into 'master'

Fix card KW on player

See merge request core-developers/forge!6323
This commit is contained in:
Michael Kamensky
2022-03-01 03:53:36 +00:00
14 changed files with 36 additions and 47 deletions

View File

@@ -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<SpellAbility> spellAbilities = Lists.newArrayList();
for (final Card c : all) {

View File

@@ -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);

View File

@@ -119,8 +119,7 @@ public class AiProfileUtil {
* @return ArrayList<String> - an array of strings containing all
* available profiles.
*/
public static List<String> getAvailableProfiles()
{
public static List<String> getAvailableProfiles() {
final List<String> availableProfiles = new ArrayList<>();
final File dir = new File(AI_PROFILE_DIR);

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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<String> 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<Card> blockedBy = combat.getAttackersBlockedBy(c);
boolean attackerHasTrample = false;
for (Card b : blockedBy) {

View File

@@ -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<GameObject> 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<GameObject> 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<OptionalCostValue> chooseOptionalCosts(SpellAbility chosen,
List<OptionalCostValue> optionalCostValues) {
public List<OptionalCostValue> chooseOptionalCosts(SpellAbility chosen, List<OptionalCostValue> optionalCostValues) {
List<OptionalCostValue> chosenOptCosts = Lists.newArrayList();
Cost costSoFar = chosen.getPayCosts().copy();

View File

@@ -1308,6 +1308,7 @@ public class GameAction {
desCreats = new CardCollection();
}
desCreats.add(c);
c.setHasBeenDealtDeathtouchDamage(false);
checkAgain = true;
break;
}

View File

@@ -101,7 +101,7 @@ public abstract class PlayerController {
public final SpellAbility getAbilityToPlay(final Card hostCard, final List<SpellAbility> abilities) { return getAbilityToPlay(hostCard, abilities, null); }
public abstract SpellAbility getAbilityToPlay(Card hostCard, List<SpellAbility> 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<SpellAbility> chooseSpellAbilitiesForEffect(List<SpellAbility> spells, SpellAbility sa, String title, int num, Map<String, Object> params);
public abstract SpellAbility chooseSingleSpellForEffect(List<SpellAbility> spells, SpellAbility sa, String title,
Map<String, Object> params);
public abstract SpellAbility chooseSingleSpellForEffect(List<SpellAbility> spells, SpellAbility sa, String title, Map<String, Object> params);
public abstract <T extends GameEntity> List<T> chooseEntitiesForEffect(FCollectionView<T> optionList, int min, int max, DelayedReveal delayedReveal, SpellAbility sa, String title, Player relatedPlayer, Map<String, Object> 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<SpellAbility> chooseSaToActivateFromOpeningHand(List<SpellAbility> usableFromOpeningHand);
public abstract Mana chooseManaFromPool(List<Mana> manaChoices);
@@ -183,7 +184,6 @@ public abstract class PlayerController {
}
public abstract Object vote(SpellAbility sa, String prompt, List<Object> options, ListMultimap<Object, Player> 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<SpellAbility> 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<String, Object> 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<String> options, Map<String, Card> choiceMap);
public abstract List<AbilitySub> chooseModeForAbility(SpellAbility sa, List<AbilitySub> 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<Card> chooseCardsForSplice(SpellAbility sa, List<Card> cards);
public abstract String chooseCardName(SpellAbility sa, Predicate<ICardFace> cpp, String valid, String message);
public abstract String chooseCardName(SpellAbility sa, List<ICardFace> faces, String message);
public abstract Card chooseDungeon(Player player, List<PaperCard> dungeonCards, String message);

View File

@@ -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);

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.