Fix Bargaining Table (#1727)

This commit is contained in:
tool4ever
2022-10-22 14:10:39 +02:00
committed by GitHub
parent b4c0c517e7
commit ae255a8e8f
9 changed files with 45 additions and 33 deletions

View File

@@ -1086,7 +1086,7 @@ public class AiController {
if (source.hasSVar("AIPriorityModifier")) { if (source.hasSVar("AIPriorityModifier")) {
p += Integer.parseInt(source.getSVar("AIPriorityModifier")); p += Integer.parseInt(source.getSVar("AIPriorityModifier"));
} }
if (ComputerUtilCard.isCardRemAIDeck(source)) { if (ComputerUtilCard.isCardRemAIDeck(sa.getOriginalHost() != null ? sa.getOriginalHost() : source)) {
p -= 10; p -= 10;
} }
// don't play equipments before having any creatures // don't play equipments before having any creatures
@@ -1955,6 +1955,22 @@ public class AiController {
return max; return max;
} }
public int chooseNumber(SpellAbility sa, String title, List<Integer> options, Player relatedPlayer) {
switch(sa.getApi())
{
case SetLife: // Reverse the Sands
if (relatedPlayer.equals(sa.getHostCard().getController())) {
return Collections.max(options);
} else if (relatedPlayer.isOpponentOf(sa.getHostCard().getController())) {
return Collections.min(options);
} else {
return options.get(0);
}
default:
return options.get(0);
}
}
public boolean confirmPayment(CostPart costPart) { public boolean confirmPayment(CostPart costPart) {
throw new UnsupportedOperationException("AI is not supposed to reach this code at the moment"); throw new UnsupportedOperationException("AI is not supposed to reach this code at the moment");
} }
@@ -2120,22 +2136,6 @@ public class AiController {
return library; return library;
} // smoothComputerManaCurve() } // smoothComputerManaCurve()
public int chooseNumber(SpellAbility sa, String title, List<Integer> options, Player relatedPlayer) {
switch(sa.getApi())
{
case SetLife: // Reverse the Sands
if (relatedPlayer.equals(sa.getHostCard().getController())) {
return Collections.max(options);
} else if (relatedPlayer.isOpponentOf(sa.getHostCard().getController())) {
return Collections.min(options);
} else {
return options.get(0);
}
default:
return 0;
}
}
public boolean chooseDirection(SpellAbility sa) { public boolean chooseDirection(SpellAbility sa) {
if (sa == null || sa.getApi() == null) { if (sa == null || sa.getApi() == null) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();

View File

@@ -591,11 +591,6 @@ public class PlayerControllerAi extends PlayerController {
return ComputerUtil.vote(player, options, sa, votes, forPlayer); return ComputerUtil.vote(player, options, sa, votes, forPlayer);
} }
@Override
public boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, GameEntity affected, String question) {
return brains.aiShouldRun(replacementEffect, effectSA, affected);
}
@Override @Override
public boolean mulliganKeepHand(Player firstPlayer, int cardsToReturn) { public boolean mulliganKeepHand(Player firstPlayer, int cardsToReturn) {
return !ComputerUtil.wantMulligan(player, cardsToReturn); return !ComputerUtil.wantMulligan(player, cardsToReturn);
@@ -1012,6 +1007,11 @@ public class PlayerControllerAi extends PlayerController {
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 boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, GameEntity affected, String question) {
return brains.aiShouldRun(replacementEffect, effectSA, affected);
}
@Override @Override
public ReplacementEffect chooseSingleReplacementEffect(String prompt, List<ReplacementEffect> possibleReplacers) { public ReplacementEffect chooseSingleReplacementEffect(String prompt, List<ReplacementEffect> possibleReplacers) {
return brains.chooseSingleReplacementEffect(possibleReplacers); return brains.chooseSingleReplacementEffect(possibleReplacers);

View File

@@ -61,7 +61,7 @@ public class ChooseNumberEffect extends SpellAbilityEffect {
String title = sa.hasParam("ListTitle") ? sa.getParam("ListTitle") : Localizer.getInstance().getMessage("lblChooseNumber"); String title = sa.hasParam("ListTitle") ? sa.getParam("ListTitle") : Localizer.getInstance().getMessage("lblChooseNumber");
if (anyNumber) { if (anyNumber) {
Integer value = p.getController().announceRequirements(sa, title); Integer value = p.getController().announceRequirements(sa, title);
chosen = (value == null ? 0 : value); chosen = value == null ? 0 : value;
} else { } else {
chosen = p.getController().chooseNumber(sa, title, min, max); chosen = p.getController().chooseNumber(sa, title, min, max);
} }

View File

@@ -245,7 +245,7 @@ public class Cost implements Serializable {
this.isMandatory = true; this.isMandatory = true;
} else { } else {
CostPart cp = parseCostPart(part, tapCost, untapCost); CostPart cp = parseCostPart(part, tapCost, untapCost);
if (null != cp ) if (null != cp)
if (cp instanceof CostPartMana) { if (cp instanceof CostPartMana) {
parsedMana = (CostPartMana) cp; parsedMana = (CostPartMana) cp;
} else { } else {

View File

@@ -1,7 +1,7 @@
Name:Bargaining Table Name:Bargaining Table
ManaCost:5 ManaCost:5
Types:Artifact Types:Artifact
# The ability is untargeted (see: http://magiccards.info/mm/en/288.html), so the opponent is automaticaly chosen. This has to be modified as soon as multiplayer formats get supported. A:AB$ Draw | Cost$ X T | NumCards$ 1 | AnnounceType$ Opponent | SpellDescription$ Draw a card. X is the number of cards in an opponent's hand.
A:AB$ Draw | Cost$ X T | NumCards$ 1 | SpellDescription$ Draw a card. X is the number of cards in an opponent's hand. SVar:X:Count$InChosenHand
SVar:X:Count$InOppHand AI:RemoveDeck:All
Oracle:{X}, {T}: Draw a card. X is the number of cards in an opponent's hand. Oracle:{X}, {T}: Draw a card. X is the number of cards in an opponent's hand.

View File

@@ -3,7 +3,6 @@ ManaCost:G G
Types:Enchantment Types:Enchantment
K:Cumulative upkeep:2 K:Cumulative upkeep:2
S:Mode$ Continuous | Affected$ Creature.withFlying | AddHiddenKeyword$ CARDNAME doesn't untap during your untap step. | Description$ Creatures with flying don't untap during their controllers' untap steps. S:Mode$ Continuous | Affected$ Creature.withFlying | AddHiddenKeyword$ CARDNAME doesn't untap during your untap step. | Description$ Creatures with flying don't untap during their controllers' untap steps.
S:Mode$ CantBeCast | ValidCard$ Card.Self | EffectZone$ All | CheckSVar$ X | SVarCompare$ EQ0 | Description$ Cast CARDNAME only if you control a snow land. S:Mode$ CantBeCast | ValidCard$ Card.Self | EffectZone$ All | IsPresent$ Snow.Land+YouCtrl | PresentCompare$ EQ0 | Description$ Cast CARDNAME only if you control a snow land.
SVar:X:Count$Valid Snow.Land+YouCtrl
AI:RemoveDeck:Random AI:RemoveDeck:Random
Oracle:Cast this spell only if you control a snow land.\nCumulative upkeep {2} (At the beginning of your upkeep, put an age counter on this permanent, then sacrifice it unless you pay its upkeep cost for each age counter on it.)\nCreatures with flying don't untap during their controllers' untap steps. Oracle:Cast this spell only if you control a snow land.\nCumulative upkeep {2} (At the beginning of your upkeep, put an age counter on this permanent, then sacrifice it unless you pay its upkeep cost for each age counter on it.)\nCreatures with flying don't untap during their controllers' untap steps.

View File

@@ -4,7 +4,7 @@ Types:Creature Vampire
PT:3/3 PT:3/3
K:Flying K:Flying
A:AB$ Token | Cost$ T | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ b_2_2_vampire_flying | SpellDescription$ Create a 2/2 black Vampire creature token with flying. A:AB$ Token | Cost$ T | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ b_2_2_vampire_flying | SpellDescription$ Create a 2/2 black Vampire creature token with flying.
A:AB$ SetState | Cost$ B | Defined$ Self | IsPresent$ Card.Vampire+YouCtrl | PresentCompare$ GE5 | Mode$ Transform | SpellDescription$ Transform CARDNAME.Activate only if you control five or more Vampires. A:AB$ SetState | Cost$ B | Defined$ Self | IsPresent$ Card.Vampire+YouCtrl | PresentCompare$ GE5 | Mode$ Transform | SpellDescription$ Transform CARDNAME. Activate only if you control five or more Vampires.
AlternateMode:DoubleFaced AlternateMode:DoubleFaced
Oracle:Flying\n{T}: Create a 2/2 black Vampire creature token with flying.\n{B}: Transform Bloodline Keeper. Activate only if you control five or more Vampires. Oracle:Flying\n{T}: Create a 2/2 black Vampire creature token with flying.\n{B}: Transform Bloodline Keeper. Activate only if you control five or more Vampires.

View File

@@ -689,8 +689,13 @@ public class HumanCostDecision extends CostDecisionMakerBase {
} }
// Cards to use this branch: Scarscale Ritual, Wandering Mage - each adds only one counter // Cards to use this branch: Scarscale Ritual, Wandering Mage - each adds only one counter
final CardCollectionView typeList = CardLists.getValidCards(source.getGame().getCardsIn(ZoneType.Battlefield), CardCollectionView typeList = CardLists.getValidCards(source.getGame().getCardsIn(ZoneType.Battlefield),
cost.getType().split(";"), player, ability.getHostCard(), ability); cost.getType().split(";"), player, ability.getHostCard(), ability);
typeList = CardLists.filter(typeList, CardPredicates.canReceiveCounters(cost.getCounter()));
if (typeList.isEmpty()) {
return null;
}
final InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 1, 1, typeList, ability); final InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 1, 1, typeList, ability);
inp.setMessage(Localizer.getInstance().getMessage("lblPutNTypeCounterOnTarget", String.valueOf(c), cost.getCounter().getName(), cost.getDescriptiveType())); inp.setMessage(Localizer.getInstance().getMessage("lblPutNTypeCounterOnTarget", String.valueOf(c), cost.getCounter().getName(), cost.getDescriptiveType()));
@@ -717,6 +722,10 @@ public class HumanCostDecision extends CostDecisionMakerBase {
final CardCollectionView validCards = CardLists.getValidCards(ability.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), final CardCollectionView validCards = CardLists.getValidCards(ability.getActivatingPlayer().getCardsIn(ZoneType.Battlefield),
cost.getType().split(";"), player, source, ability); cost.getType().split(";"), player, source, ability);
if (validCards.size() < c) {
return null;
}
final InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, validCards, ability); final InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, validCards, ability);
inp.setCancelAllowed(!mandatory); inp.setCancelAllowed(!mandatory);
inp.setMessage(Localizer.getInstance().getMessage("lblNTypeCardsToHand", "%d", cost.getDescriptiveType())); inp.setMessage(Localizer.getInstance().getMessage("lblNTypeCardsToHand", "%d", cost.getDescriptiveType()));
@@ -804,7 +813,6 @@ public class HumanCostDecision extends CostDecisionMakerBase {
int c = cost.getAbilityAmount(ability); int c = cost.getAbilityAmount(ability);
final String type = cost.getType(); final String type = cost.getType();
CardCollectionView list = CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), type.split(";"), player, source, ability); CardCollectionView list = CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), type.split(";"), player, source, ability);
list = CardLists.filter(list, CardPredicates.hasCounters()); list = CardLists.filter(list, CardPredicates.hasCounters());

View File

@@ -41,6 +41,7 @@ import forge.game.player.Player;
import forge.game.player.PlayerController; import forge.game.player.PlayerController;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.zone.Zone; import forge.game.zone.Zone;
import forge.util.Localizer;
/** /**
* <p> * <p>
@@ -281,9 +282,13 @@ public class HumanPlaySpellAbility {
final int min = Integer.parseInt(ability.getParam("Min")); final int min = Integer.parseInt(ability.getParam("Min"));
final int max = Integer.parseInt(ability.getParam("Max")); final int max = Integer.parseInt(ability.getParam("Max"));
final int i = ability.getActivatingPlayer().getController().chooseNumber(ability, final int i = ability.getActivatingPlayer().getController().chooseNumber(ability,
"Choose a number", min, max); Localizer.getInstance().getMessage("lblChooseNumber") , min, max);
ability.getHostCard().setChosenNumber(i); ability.getHostCard().setChosenNumber(i);
} }
if ("Opponent".equals(varName)) {
Player opp = ability.getActivatingPlayer().getController().chooseSingleEntityForEffect(ability.getActivatingPlayer().getOpponents(), ability, Localizer.getInstance().getMessage("lblChooseAnOpponent"), null);
ability.getHostCard().setChosenPlayer(opp);
}
} }
} }
return true; return true;