Human Play: try to remove usage of game.getCard

This commit is contained in:
Hans Mackowiak
2020-05-24 11:02:51 +00:00
committed by Michael Kamensky
parent 27968cd561
commit ea26f6c689
53 changed files with 596 additions and 753 deletions

View File

@@ -1,161 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.match.input;
import forge.card.mana.ManaAtom;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostShard;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.mana.ManaCostBeingPaid;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.model.FModel;
import forge.player.PlayerControllerHuman;
import forge.properties.ForgePreferences;
import forge.util.ITriggerEvent;
import forge.util.Localizer;
//pays the cost of a card played from the player's hand
//the card is removed from the players hand if the cost is paid
//CANNOT be used for ABILITIES
public class InputPayManaSimple extends InputPayMana {
// anything that uses this should be converted to Ability_Cost
/** Constant <code>serialVersionUID=3467312982164195091L</code>. */
private static final long serialVersionUID = 3467312982164195091L;
private final Card originalCard;
private final ManaCost originalManaCost;
public InputPayManaSimple(final PlayerControllerHuman controller, final Game game, final SpellAbility sa, final ManaCostBeingPaid manaCostToPay) {
super(controller, sa, sa.getActivatingPlayer());
this.originalManaCost = manaCostToPay.toManaCost();
this.originalCard = sa.getHostCard();
if (sa.getHostCard().isCopiedSpell() && sa.isSpell()) {
this.manaCost = new ManaCostBeingPaid(ManaCost.ZERO);
game.getStack().add(this.saPaidFor);
}
else {
this.manaCost = manaCostToPay;
}
}
@Override
protected void onManaAbilityPaid() {
if (this.manaCost.isPaid()) {
this.originalCard.setSunburstValue(this.manaCost.getSunburst());
}
}
/** {@inheritDoc} */
@Override
protected final void onPlayerSelected(final Player selected, final ITriggerEvent triggerEvent) {
if (player == selected) {
if (player.canPayLife(this.phyLifeToLose + 2)) {
if (manaCost.payPhyrexian()) {
this.phyLifeToLose += 2;
} else {
if (player.hasKeyword("PayLifeInsteadOf:B") && manaCost.hasAnyKind(ManaAtom.BLACK)) {
manaCost.decreaseShard(ManaCostShard.BLACK, 1);
this.phyLifeToLose += 2;
}
}
}
this.showMessage();
}
}
/**
* <p>
* done.
* </p>
*/
@Override
protected void done() {
this.originalCard.setSunburstValue(this.manaCost.getSunburst());
if (this.phyLifeToLose > 0) {
player.payLife(this.phyLifeToLose, this.originalCard);
}
if (!this.saPaidFor.getHostCard().isCopiedSpell()) {
if (this.saPaidFor.isSpell()) {
this.saPaidFor.setHostCard(game.getAction().moveToStack(this.originalCard, null));
}
}
}
/** {@inheritDoc} */
@Override
protected final void onCancel() {
player.getManaPool().refundManaPaid(this.saPaidFor);
// Update UI
this.stop();
}
/** {@inheritDoc} */
@Override
public final void showMessage() {
if (isFinished()) { return; }
updateButtons();
if (this.manaCost.isPaid() && !new ManaCostBeingPaid(this.originalManaCost).isPaid()) {
this.done();
this.stop();
}
else {
updateMessage();
}
}
/* (non-Javadoc)
* @see forge.control.input.InputPayManaBase#updateMessage()
*/
@Override
protected String getMessage() {
final StringBuilder msg = new StringBuilder();
final Localizer localizer = Localizer.getInstance();
if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DETAILED_SPELLDESC_IN_PROMPT)) {
msg.append(saPaidFor.getStackDescription().replace("(Targeting ERROR)", "")).append("\n\n");
}
msg.append(localizer.getMessage("lblPayManaCost")).append(" ").append(this.manaCost.toString(false, player.getManaPool()));
if (this.phyLifeToLose > 0) {
msg.append(" ").append(String.format(localizer.getMessage("lblLifePaidForPhyrexianMana"), this.phyLifeToLose));
}
boolean isLifeInsteadBlack = player.hasKeyword("PayLifeInsteadOf:B") && manaCost.hasAnyKind(ManaAtom.BLACK);
if (manaCost.containsPhyrexianMana() || isLifeInsteadBlack) {
StringBuilder sb = new StringBuilder();
if (manaCost.containsPhyrexianMana() && !isLifeInsteadBlack) {
sb.append(localizer.getMessage("lblClickOnYourLifeTotalToPayLifeForPhyrexianMana"));
} else if (!manaCost.containsPhyrexianMana() && isLifeInsteadBlack) {
sb.append(localizer.getMessage("lblClickOnYourLifeTotalToPayLifeForBlackMana"));
} else if (manaCost.containsPhyrexianMana() && isLifeInsteadBlack) {
sb.append(localizer.getMessage("lblClickOnYourLifeTotalToPayLifeForPhyrexianOrBlackMana"));
}
msg.append("\n(").append(sb).append(")");
}
// has its own variant of checkIfPaid
return msg.toString();
}
}

View File

@@ -110,7 +110,7 @@ public class InputProxy implements Observer {
}
private Card getCard(final CardView cardView) {
return controller.getGame().getCard(cardView);
return controller.getCard(cardView);
}
public final String getActivateAction(final CardView cardView) {

View File

@@ -14,6 +14,8 @@ import com.google.common.collect.Lists;
import forge.card.CardType;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GameEntityView;
import forge.game.GameEntityViewMap;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollection;
@@ -35,6 +37,7 @@ import forge.match.input.InputSelectManyBase;
import forge.util.Aggregates;
import forge.util.TextUtil;
import forge.util.collect.FCollectionView;
import forge.util.gui.SGuiChoose;
import forge.util.ITriggerEvent;
import forge.util.Localizer;
import forge.util.CardTranslation;
@@ -310,11 +313,12 @@ public class HumanCostDecision extends CostDecisionMakerBase {
if (nNeeded == 0) {
return PaymentDecision.number(0);
}
final Game game = controller.getGame();
final Player p = game.getPlayer(controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblExileFromWhoseZone", cost.getFrom().getTranslatedName()), PlayerView.getCollection(payableZone)));
if (p == null) {
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(payableZone);
final PlayerView pv = controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblExileFromWhoseZone", cost.getFrom().getTranslatedName()), gameCachePlayer.getTrackableKeys());
if (pv == null || !gameCachePlayer.containsKey(pv)) {
return null;
}
final Player p = gameCachePlayer.get(pv);
final CardCollection typeList = CardLists.filter(list, CardPredicates.isOwner(p));
final int count = typeList.size();
@@ -322,8 +326,13 @@ public class HumanCostDecision extends CostDecisionMakerBase {
return null;
}
final CardCollection toExile = game.getCardList(controller.getGui().many(Localizer.getInstance().getMessage("lblExileFromZone", cost.getFrom().getTranslatedName()), Localizer.getInstance().getMessage("lblToBeExiled"), nNeeded, CardView.getCollection(typeList), null));
return PaymentDecision.card(toExile);
GameEntityViewMap<Card, CardView> gameCacheExile = GameEntityView.getMap(typeList);
List<CardView> views = controller.getGui().many(
Localizer.getInstance().getMessage("lblExileFromZone", cost.getFrom().getTranslatedName()),
Localizer.getInstance().getMessage("lblToBeExiled"), nNeeded, gameCacheExile.getTrackableKeys(), null);
List<Card> result = Lists.newArrayList();
gameCacheExile.addToList(views, result);
return PaymentDecision.card(result);
}
@Override
@@ -395,20 +404,17 @@ public class HumanCostDecision extends CostDecisionMakerBase {
return PaymentDecision.card(list);
}
private Card getCard(final CardView cardView) {
return controller.getGame().getCard(cardView);
}
private PaymentDecision exileFromMiscZone(final CostExile cost, final SpellAbility sa, final int nNeeded, final CardCollection typeList) {
if (typeList.size() < nNeeded) { return null; }
GameEntityViewMap<Card, CardView> gameCacheCard = GameEntityView.getMap(typeList);
final CardCollection exiled = new CardCollection();
for (int i = 0; i < nNeeded; i++) {
final Card c = getCard(controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblExileProgressFromZone", String.valueOf(i + 1), String.valueOf(nNeeded), cost.getFrom().getTranslatedName()), CardView.getCollection(typeList)));
if (c == null) { return null; }
final CardView cv = controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblExileProgressFromZone", String.valueOf(i + 1), String.valueOf(nNeeded), cost.getFrom().getTranslatedName()), gameCacheCard.getTrackableKeys());
if (cv == null || !gameCacheCard.containsKey(cv)) { return null; }
typeList.remove(c);
exiled.add(c);
exiled.add(gameCacheCard.remove(cv));
}
return PaymentDecision.card(exiled);
}
@@ -438,12 +444,17 @@ public class HumanCostDecision extends CostDecisionMakerBase {
if (ability.isOptionalTrigger()) {
min = 0;
}
final CardCollection choice = controller.getGame().getCardList(controller.getGui().many(Localizer.getInstance().getMessage("lblChooseAnExiledCardPutIntoGraveyard"), Localizer.getInstance().getMessage("lblToGraveyard"), min, c, CardView.getCollection(list), CardView.get(source)));
if (choice == null || choice.size() < c) {
GameEntityViewMap<Card, CardView> gameCacheExile = GameEntityView.getMap(list);
List<CardView> views = controller.getGui().many(
Localizer.getInstance().getMessage("lblChooseAnExiledCardPutIntoGraveyard"),
Localizer.getInstance().getMessage("lblToGraveyard"), min, c, CardView.getCollection(list), CardView.get(source));
if (views == null || views.size() < c) {
return null;
}
return PaymentDecision.card(choice);
List<Card> result = Lists.newArrayList();
gameCacheExile.addToList(views, result);
return PaymentDecision.card(result);
}
@Override
@@ -555,11 +566,12 @@ public class HumanCostDecision extends CostDecisionMakerBase {
return PaymentDecision.players(oppsThatCanGainLife);
}
final Player chosenToGain = controller.getGame().getPlayer(controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblCardChooseAnOpponentToGainNLife", CardTranslation.getTranslatedName(source.getName()), String.valueOf(c)), PlayerView.getCollection(oppsThatCanGainLife)));
if (chosenToGain == null) {
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(oppsThatCanGainLife);
final PlayerView pv = controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblCardChooseAnOpponentToGainNLife", CardTranslation.getTranslatedName(source.getName()), String.valueOf(c)), gameCachePlayer.getTrackableKeys());
if (pv == null || !gameCachePlayer.containsKey(pv)) {
return null;
}
return PaymentDecision.players(Lists.newArrayList(chosenToGain));
return PaymentDecision.players(Lists.newArrayList(gameCachePlayer.get(pv)));
}
@Override
@@ -694,13 +706,13 @@ public class HumanCostDecision extends CostDecisionMakerBase {
}
final CardCollection chosen = new CardCollection();
GameEntityViewMap<Card, CardView> gameCacheCard = GameEntityView.getMap(typeList);
for (int i = 0; i < nNeeded; i++) {
final Card c = getCard(controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblFromZonePutToLibrary", fromZone.getTranslatedName()), CardView.getCollection(typeList)));
if (c == null) {
final CardView cv = controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblFromZonePutToLibrary", fromZone.getTranslatedName()), gameCacheCard.getTrackableKeys());
if (cv == null || !gameCacheCard.containsKey(cv)) {
return null;
}
typeList.remove(c);
chosen.add(c);
chosen.add(gameCacheCard.remove(cv));
}
return PaymentDecision.card(chosen);
}
@@ -710,10 +722,12 @@ public class HumanCostDecision extends CostDecisionMakerBase {
return PaymentDecision.number(0);
}
final Player p = controller.getGame().getPlayer(controller.getGui().oneOrNone(TextUtil.concatNoSpace(Localizer.getInstance().getMessage("lblPutCardsFromWhoseZone"), fromZone.getTranslatedName()), PlayerView.getCollection(payableZone)));
if (p == null) {
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(payableZone);
PlayerView pv = SGuiChoose.oneOrNone(TextUtil.concatNoSpace(Localizer.getInstance().getMessage("lblPutCardsFromWhoseZone"), fromZone.getTranslatedName()), gameCachePlayer.getTrackableKeys());
if (pv == null || !gameCachePlayer.containsKey(pv)) {
return null;
}
Player p = gameCachePlayer.get(pv);
final CardCollection typeList = CardLists.filter(list, CardPredicates.isOwner(p));
if (typeList.size() < nNeeded) {
@@ -721,13 +735,13 @@ public class HumanCostDecision extends CostDecisionMakerBase {
}
final CardCollection chosen = new CardCollection();
GameEntityViewMap<Card, CardView> gameCacheCard = GameEntityView.getMap(typeList);
for (int i = 0; i < nNeeded; i++) {
final Card c = getCard(controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblPutZoneCardsToLibrary", fromZone.getTranslatedName()), CardView.getCollection(typeList)));
if (c == null) {
final CardView cv = controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblPutZoneCardsToLibrary", fromZone.getTranslatedName()), gameCacheCard.getTrackableKeys());
if (cv == null || !gameCacheCard.containsKey(cv)) {
return null;
}
typeList.remove(c);
chosen.add(c);
chosen.add(gameCacheCard.remove(cv));
}
return PaymentDecision.card(chosen);
}
@@ -1068,15 +1082,14 @@ public class HumanCostDecision extends CostDecisionMakerBase {
}
// Rift Elemental only - always removes 1 counter, so there will be no code for N counters.
final List<CardView> suspended = Lists.newArrayList();
for (final Card crd : validCards) {
if (crd.getCounters(cost.counter) > 0) {
suspended.add(CardView.get(crd));
}
GameEntityViewMap<Card, CardView> gameCacheSuspended = GameEntityView.getMap(CardLists.filter(validCards, CardPredicates.hasCounter(cost.counter)));
final CardView cv = controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblRemoveCountersFromAInZoneCard", cost.zone.getTranslatedName()), gameCacheSuspended.getTrackableKeys());
if (cv == null || !gameCacheSuspended.containsKey(cv)) {
return null;
}
final Card card = getCard(controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblRemoveCountersFromAInZoneCard", cost.zone.getTranslatedName()), suspended));
return null == card ? null : PaymentDecision.card(card, c);
return PaymentDecision.card(gameCacheSuspended.get(cv), c);
}
@Override

View File

@@ -6,6 +6,8 @@ import forge.FThreads;
import forge.card.mana.ManaCost;
import forge.game.Game;
import forge.game.GameActionUtil;
import forge.game.GameEntityView;
import forge.game.GameEntityViewMap;
import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.ability.effects.CharmEffect;
@@ -23,7 +25,6 @@ import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.match.input.InputPayMana;
import forge.match.input.InputPayManaOfCostPayment;
import forge.match.input.InputPayManaSimple;
import forge.match.input.InputSelectCardsFromList;
import forge.util.TextUtil;
import forge.util.collect.FCollectionView;
@@ -46,7 +47,7 @@ public class HumanPlay {
* <p>
* playSpellAbility.
* </p>
*
*
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
*/
@@ -94,34 +95,9 @@ public class HumanPlay {
source.animateBestow();
}
// Need to check PayCosts, and Ability + All SubAbilities for Target
boolean newAbility = sa.getPayCosts() != null;
SpellAbility ability = sa;
while ((ability != null) && !newAbility) {
final TargetRestrictions tgt = ability.getTargetRestrictions();
newAbility |= tgt != null;
ability = ability.getSubAbility();
}
// System.out.println("Playing:" + sa.getDescription() + " of " + sa.getHostCard() + " new = " + newAbility);
if (newAbility) {
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
if (!req.playAbility(true, false, false)) {
if (flippedToCast && !castFaceDown) {
source.turnFaceDown(true);
}
return false;
}
} else if (payManaCostIfNeeded(controller, p, sa)) {
if (sa.isSpell() && !source.isCopiedSpell()) {
sa.setHostCard(p.getGame().getAction().moveToStack(source, sa));
}
p.getGame().getStack().add(sa);
} else {
// Failed to pay costs, revert to original state
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
if (!req.playAbility(true, false, false)) {
if (flippedToCast && !castFaceDown) {
source.turnFaceDown(true);
}
@@ -133,7 +109,7 @@ public class HumanPlay {
/**
* choose optional additional costs. For HUMAN only
* @param p
*
*
* @param original
* the original sa
* @return an ArrayList<SpellAbility>.
@@ -159,31 +135,11 @@ public class HumanPlay {
//final List<SpellAbility> abilities = GameActionUtil.getOptionalCosts(original);
}
private static boolean payManaCostIfNeeded(final PlayerControllerHuman controller, final Player p, final SpellAbility sa) {
final ManaCostBeingPaid manaCost;
if (sa.getHostCard().isCopiedSpell() && sa.isSpell()) {
manaCost = new ManaCostBeingPaid(ManaCost.ZERO);
}
else {
manaCost = new ManaCostBeingPaid(sa.getPayCosts().getTotalMana());
CostAdjustment.adjust(manaCost, sa, null, false);
}
boolean isPaid = manaCost.isPaid();
if (!isPaid) {
InputPayManaSimple inputPay = new InputPayManaSimple(controller, p.getGame(), sa, manaCost);
inputPay.showAndWait();
isPaid = inputPay.isPaid();
}
return isPaid;
}
/**
* <p>
* playSpellAbilityForFree.
* </p>
*
*
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
*/
@@ -193,33 +149,22 @@ public class HumanPlay {
source.setSplitStateToPlayAbility(sa);
if (sa.getPayCosts() != null) {
if (!sa.isCopied()) {
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
CharmEffect.makeChoices(sa);
}
sa = AbilityUtils.addSpliceEffects(sa);
if (!sa.isCopied()) {
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
CharmEffect.makeChoices(sa);
}
sa = AbilityUtils.addSpliceEffects(sa);
}
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
req.playAbility(mayChooseNewTargets, true, false);
}
else {
if (sa.isSpell()) {
final Card c = sa.getHostCard();
if (!c.isCopiedSpell()) {
sa.setHostCard(game.getAction().moveToStack(c, sa));
}
}
game.getStack().add(sa);
}
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
req.playAbility(mayChooseNewTargets, true, false);
}
/**
* <p>
* playSpellAbility_NoStack.
* </p>
*
*
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
*/
@@ -230,14 +175,8 @@ public class HumanPlay {
public final static void playSpellAbilityNoStack(final PlayerControllerHuman controller, final Player player, final SpellAbility sa, boolean useOldTargets) {
sa.setActivatingPlayer(player);
if (sa.getPayCosts() != null) {
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
req.playAbility(!useOldTargets, false, true);
}
else if (payManaCostIfNeeded(controller, player, sa)) {
AbilityUtils.resolve(sa);
}
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
req.playAbility(!useOldTargets, false, true);
}
// ------------------------------------------------------------------------
@@ -506,14 +445,13 @@ public class HumanPlay {
} else {
// replace this with input
CardCollection newList = new CardCollection();
GameEntityViewMap<Card, CardView> gameCacheList = GameEntityView.getMap(list);
for (int i = 0; i < nNeeded; i++) {
final Card c = p.getGame().getCard(SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblExileFromZone", from.getTranslatedName()), CardView.getCollection(list)));
if (c == null) {
final CardView cv = SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblExileFromZone", from.getTranslatedName()), gameCacheList.getTrackableKeys());
if (cv == null || !gameCacheList.containsKey(cv)) {
return false;
}
list.remove(c);
newList.add(c);
newList.add(gameCacheList.remove(cv));
}
costExile.payAsDecided(p, PaymentDecision.card(newList), sourceAbility);
}
@@ -543,27 +481,28 @@ public class HumanPlay {
payableZone.add(player);
}
}
Player chosen = controller.getGame().getPlayer(SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblPutCardFromWhoseZone", from.getTranslatedName()), PlayerView.getCollection(payableZone)));
if (chosen == null) {
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(payableZone);
PlayerView pv = SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblPutCardFromWhoseZone", from.getTranslatedName()), gameCachePlayer.getTrackableKeys());
if (pv == null || !gameCachePlayer.containsKey(pv)) {
return false;
}
Player chosen = gameCachePlayer.get(pv);
List<Card> typeList = CardLists.filter(list, CardPredicates.isOwner(chosen));
GameEntityViewMap<Card, CardView> gameCacheTypeList = GameEntityView.getMap(typeList);
for (int i = 0; i < amount; i++) {
if (typeList.isEmpty()) {
if (gameCacheTypeList.isEmpty()) {
return false;
}
final Card c = p.getGame().getCard(SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblPutCardToLibrary"), CardView.getCollection(typeList)));
if (c != null) {
typeList.remove(c);
p.getGame().getAction().moveToLibrary(c, Integer.parseInt(((CostPutCardToLib) part).getLibPos()), null);
}
else {
final CardView cv = SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblPutCardToLibrary"), gameCacheTypeList.getTrackableKeys());
if (cv == null || !gameCacheTypeList.containsKey(cv)) {
return false;
}
final Card c = gameCacheTypeList.get(cv);
gameCacheTypeList.remove(c);
p.getGame().getAction().moveToLibrary(c, Integer.parseInt(((CostPutCardToLib) part).getLibPos()), null);
}
}
else { // Tainted Specter, Gurzigost, etc.

View File

@@ -114,7 +114,7 @@ public class HumanPlaySpellAbility {
ability = GameActionUtil.addExtraKeywordCost(ability);
Cost abCost = ability.getPayCosts() == null ? new Cost("0", ability.isAbility()) : ability.getPayCosts();
Cost abCost = ability.getPayCosts();
CostPayment payment = new CostPayment(abCost, ability);
// TODO Apply this to the SAStackInstance instead of the Player

View File

@@ -96,6 +96,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
private final Localizer localizer = Localizer.getInstance();
protected Map<SpellAbilityView, SpellAbility> spellViewCache = null;
protected GameEntityViewMap<Card, CardView> gameCache = new GameEntityViewMap<>();
public PlayerControllerHuman(final Game game0, final Player p, final LobbyPlayer lp) {
super(game0, p, lp);
@@ -151,7 +152,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
if (t instanceof Card) {
tempShowCard((Card) t);
} else if (t instanceof CardView) {
tempShowCard(game.getCard((CardView) t));
tempShowCard(getCard((CardView) t));
}
}
}
@@ -287,14 +288,16 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
if (defender != null && assignDamageAsIfNotBlocked(attacker)) {
map.put(null, damageDealt);
} else {
final List<CardView> vBlockers = CardView.getCollection(blockers);
if ((attacker.hasKeyword(Keyword.TRAMPLE) && defender != null) || (blockers.size() > 1)) {
GameEntityViewMap<Card, CardView> gameCacheBlockers = GameEntityView.getMap(blockers);
final CardView vAttacker = CardView.get(attacker);
final GameEntityView vDefender = GameEntityView.get(defender);
final Map<CardView, Integer> result = getGui().assignCombatDamage(vAttacker, vBlockers, damageDealt,
final Map<CardView, Integer> result = getGui().assignCombatDamage(vAttacker, gameCacheBlockers.getTrackableKeys(), damageDealt,
vDefender, overrideOrder);
for (final Entry<CardView, Integer> e : result.entrySet()) {
map.put(game.getCard(e.getKey()), e.getValue());
if (gameCacheBlockers.containsKey(e.getKey())) {
map.put(gameCacheBlockers.get(e.getKey()), e.getValue());
}
}
} else {
map.put(blockers.get(0), damageDealt);
@@ -377,9 +380,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
final boolean useUiPointAtCard =
(FModel.getPreferences().getPrefBoolean(FPref.UI_SELECT_FROM_CARD_DISPLAYS) && (!GuiBase.getInterface().isLibgdxPort())) ?
(cz.is(ZoneType.Battlefield) || cz.is(ZoneType.Hand) || cz.is(ZoneType.Library) ||
cz.is(ZoneType.Graveyard) || cz.is(ZoneType.Exile) || cz.is(ZoneType.Flashback) || cz.is(ZoneType.Command)) :
(cz.is(ZoneType.Hand) && cz.getPlayer() == player || cz.is(ZoneType.Battlefield));
(cz.is(ZoneType.Battlefield) || cz.is(ZoneType.Hand) || cz.is(ZoneType.Library) ||
cz.is(ZoneType.Graveyard) || cz.is(ZoneType.Exile) || cz.is(ZoneType.Flashback) || cz.is(ZoneType.Command)) :
(cz.is(ZoneType.Hand) && cz.getPlayer() == player || cz.is(ZoneType.Battlefield));
if (!useUiPointAtCard) {
return false;
}
@@ -412,23 +415,15 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
}
tempShowCards(sourceList);
final CardCollection choices = getGame().getCardList(getGui().many(title, localizer.getMessage("lblChosenCards"), min, max,
CardView.getCollection(sourceList), CardView.get(sa.getHostCard())));
GameEntityViewMap<Card, CardView> gameCachechoose = GameEntityView.getMap(sourceList);
List<CardView> views = getGui().many(title, localizer.getMessage("lblChosenCards"), min, max,
gameCachechoose.getTrackableKeys(), CardView.get(sa.getHostCard()));
endTempShowCards();
final CardCollection choices = new CardCollection();
gameCachechoose.addToList(views, choices);
return choices;
}
// pfps there should be a better way
private GameEntity convertToEntity(final GameEntityView view) {
if (view instanceof CardView) {
return game.getCard((CardView) view);
} else if (view instanceof PlayerView) {
return game.getPlayer((PlayerView) view);
} else return null;
}
@SuppressWarnings("unchecked")
@Override
public <T extends GameEntity> T chooseSingleEntityForEffect(final FCollectionView<T> optionList,
final DelayedReveal delayedReveal, final SpellAbility sa, final String title, final boolean isOptional,
@@ -454,6 +449,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
if (delayedReveal != null) {
tempShow(delayedReveal.getCards());
}
GameEntityViewMap<T, GameEntityView> gameCacheChoose = GameEntityView.getMap(optionList);
if (useSelectCardsInput(optionList)) {
final InputSelectEntitiesFromList<T> input = new InputSelectEntitiesFromList<>(this, isOptional ? 0 : 1, 1,
optionList, sa);
@@ -465,21 +463,25 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
}
final GameEntityView result = getGui().chooseSingleEntityForEffect(title,
GameEntityView.getEntityCollection(optionList), delayedReveal, isOptional);
gameCacheChoose.getTrackableKeys(), delayedReveal, isOptional);
endTempShowCards();
return (T) convertToEntity(result);
if (result != null || !gameCacheChoose.containsKey(result)) {
return null;
}
return gameCacheChoose.get(result);
}
@SuppressWarnings("unchecked")
@Override
public <T extends GameEntity> List<T> chooseEntitiesForEffect(final FCollectionView<T> optionList, final int min, final int max,
final DelayedReveal delayedReveal, final SpellAbility sa, final String title, final Player targetedPlayer) {
public <T extends GameEntity> List<T> chooseEntitiesForEffect(final FCollectionView<T> optionList, final int min,
final int max, final DelayedReveal delayedReveal, final SpellAbility sa, final String title,
final Player targetedPlayer) {
// useful details for debugging problems with the mass select logic
Sentry.getContext().addExtra("Card", sa.getCardView().toString());
Sentry.getContext().addExtra("SpellAbility", sa.toString());
// Human is supposed to read the message and understand from it what to // choose
// Human is supposed to read the message and understand from it what to //
// choose
if (optionList.isEmpty()) {
if (delayedReveal != null) {
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(),
@@ -494,29 +496,24 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
tempShow(optionList);
if (useSelectCardsInput(optionList)) {
final InputSelectEntitiesFromList<T> input = new InputSelectEntitiesFromList<>(this, min, max,
optionList, sa);
final InputSelectEntitiesFromList<T> input = new InputSelectEntitiesFromList<>(this, min, max, optionList,
sa);
input.setCancelAllowed(min == 0);
input.setMessage(MessageUtil.formatMessage(title, player, targetedPlayer));
input.showAndWait();
endTempShowCards();
return (List<T>) input.getSelected();
}
final List<GameEntityView> chosen = getGui().chooseEntitiesForEffect(title,
GameEntityView.getEntityCollection(optionList), min, max, delayedReveal);
endTempShowCards();
List<T> results = new ArrayList<>(); //pfps I'm not sure that the chosens should be modified this way
if (chosen instanceof List && chosen.size() > 0) {
for (GameEntityView entry: chosen) {
if (entry instanceof CardView) {
results.add((T)game.getCard((CardView) entry));
}
if (entry instanceof PlayerView) {
results.add((T)game.getPlayer((PlayerView) entry));
}
}
}
GameEntityViewMap<T, GameEntityView> gameCacheEntity = GameEntityView.getMap(optionList);
final List<GameEntityView> views = getGui().chooseEntitiesForEffect(title, gameCacheEntity.getTrackableKeys(), min, max, delayedReveal);
endTempShowCards();
List<T> results = Lists.newArrayList();
if (views != null) {
gameCacheEntity.addToList(views, results);
}
return results;
}
@@ -559,7 +556,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see
* forge.game.player.PlayerController#confirmAction(forge.card.spellability.
* SpellAbility, java.lang.String, java.lang.String)
@@ -686,43 +683,50 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override
public CardCollection orderBlockers(final Card attacker, final CardCollection blockers) {
GameEntityViewMap<Card, CardView> gameCacheBlockers = GameEntityView.getMap(blockers);
final CardView vAttacker = CardView.get(attacker);
getGui().setPanelSelection(vAttacker);
return game.getCardList(getGui().order(localizer.getMessage("lblChooseDamageOrderFor", CardTranslation.getTranslatedName(vAttacker.getName())), localizer.getMessage("lblDamagedFirst"),
CardView.getCollection(blockers), vAttacker));
List<CardView> chosen = getGui().order(localizer.getMessage("lblChooseDamageOrderFor", CardTranslation.getTranslatedName(vAttacker.getName())), localizer.getMessage("lblDamagedFirst"),
gameCacheBlockers.getTrackableKeys(), vAttacker);
CardCollection chosenCards = new CardCollection();
gameCacheBlockers.addToList(chosen, chosenCards);
return chosenCards;
}
@Override
public List<Card> exertAttackers(List<Card> attackers) {
HashMap<CardView, Card> mapCVtoC = new HashMap<>();
for (Card card : attackers) {
mapCVtoC.put(card.getView(), card);
}
List<CardView> chosen;
List<CardView> choices = new ArrayList<>(mapCVtoC.keySet());
chosen = getGui().order(localizer.getMessage("lblExertAttackersConfirm"), localizer.getMessage("lblExerted"), 0, choices.size(), choices, null, null, false);
List<Card> chosenCards = new ArrayList<>();
for (CardView cardView : chosen) {
chosenCards.add(mapCVtoC.get(cardView));
}
GameEntityViewMap<Card, CardView> gameCacheExert = GameEntityView.getMap(attackers);
List<CardView> chosen = getGui().order(localizer.getMessage("lblExertAttackersConfirm"), localizer.getMessage("lblExerted"),
0, gameCacheExert.size(), gameCacheExert.getTrackableKeys(), null, null, false);
List<Card> chosenCards = new CardCollection();
gameCacheExert.addToList(chosen, chosenCards);
return chosenCards;
}
@Override
public CardCollection orderBlocker(final Card attacker, final Card blocker, final CardCollection oldBlockers) {
GameEntityViewMap<Card, CardView> gameCacheBlockers = GameEntityView.getMap(oldBlockers);
final CardView vAttacker = CardView.get(attacker);
getGui().setPanelSelection(vAttacker);
return game.getCardList(getGui().insertInList(
List<CardView> chosen = getGui().insertInList(
localizer.getMessage("lblChooseBlockerAfterWhichToPlaceAttackert", CardTranslation.getTranslatedName(vAttacker.getName())),
CardView.get(blocker), CardView.getCollection(oldBlockers)));
CardView.get(blocker), CardView.getCollection(oldBlockers));
CardCollection chosenCards = new CardCollection();
gameCacheBlockers.addToList(chosen, chosenCards);
return chosenCards;
}
@Override
public CardCollection orderAttackers(final Card blocker, final CardCollection attackers) {
GameEntityViewMap<Card, CardView> gameCacheAttackers = GameEntityView.getMap(attackers);
final CardView vBlocker = CardView.get(blocker);
getGui().setPanelSelection(vBlocker);
return game.getCardList(getGui().order(localizer.getMessage("lblChooseDamageOrderFor", CardTranslation.getTranslatedName(vBlocker.getName())), localizer.getMessage("lblDamagedFirst"),
CardView.getCollection(attackers), vBlocker));
List<CardView> chosen = getGui().order(localizer.getMessage("lblChooseDamageOrderFor", CardTranslation.getTranslatedName(vBlocker.getName())), localizer.getMessage("lblDamagedFirst"),
CardView.getCollection(attackers), vBlocker);
CardCollection chosenCards = new CardCollection();
gameCacheAttackers.addToList(chosen, chosenCards);
return chosenCards;
}
@Override
@@ -739,7 +743,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
}
final String fm = MessageUtil.formatMessage(message, getLocalPlayerView(), owner);
if (!cards.isEmpty()) {
tempShowCards(game.getCardList(cards));
tempShowCards(getCardList(cards));
getGui().reveal(fm, cards);
endTempShowCards();
} else {
@@ -749,23 +753,27 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
}
public List<Card> manipulateCardList(final String title, final Iterable<Card> cards, final Iterable<Card> manipulable, final boolean toTop, final boolean toBottom, final boolean toAnywhere) {
Iterable<CardView> result = getGui().manipulateCardList(title, CardView.getCollection(cards), CardView.getCollection(manipulable), toTop, toBottom, toAnywhere);
return game.getCardList(result);
GameEntityViewMap<Card, CardView> gameCacheManipulate = GameEntityView.getMap(cards);
gameCacheManipulate.putAll(manipulable);
List<CardView> views = getGui().manipulateCardList(title, CardView.getCollection(cards), CardView.getCollection(manipulable), toTop, toBottom, toAnywhere);
List<Card> result = new CardCollection();
gameCacheManipulate.addToList(views, result);
return result;
}
public ImmutablePair<CardCollection, CardCollection> arrangeForMove(final String title, final FCollectionView<Card> cards, final List<Card> manipulable, final boolean topOK, final boolean bottomOK) {
List<Card> result = manipulateCardList(localizer.getMessage("lblMoveCardstoToporBbottomofLibrary"), cards, manipulable, topOK, bottomOK, false);
List<Card> result = manipulateCardList(localizer.getMessage("lblMoveCardstoToporBbottomofLibrary"), cards, manipulable, topOK, bottomOK, false);
CardCollection toBottom = new CardCollection();
CardCollection toTop = new CardCollection();
for (int i = 0; i<cards.size() && manipulable.contains(result.get(i)) ; i++ ) {
toTop.add(result.get(i));
}
if (toTop.size() < cards.size()) { // the top isn't everything
for (int i = result.size()-1; i>=0 && manipulable.contains(result.get(i)); i-- ) {
toBottom.add(result.get(i));
for (int i = 0; i<cards.size() && manipulable.contains(result.get(i)) ; i++ ) {
toTop.add(result.get(i));
}
}
return ImmutablePair.of(toTop,toBottom);
if (toTop.size() < cards.size()) { // the top isn't everything
for (int i = result.size()-1; i>=0 && manipulable.contains(result.get(i)); i-- ) {
toBottom.add(result.get(i));
}
}
return ImmutablePair.of(toTop,toBottom);
}
@Override
@@ -789,16 +797,24 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
toBottom = topN;
}
} else {
toBottom = game.getCardList(getGui().many(localizer.getMessage("lblSelectCardsToBeOutOnTheBottomOfYourLibrary"),
localizer.getMessage("lblCardsToPutOnTheBottom"), -1, CardView.getCollection(topN), null));
GameEntityViewMap<Card, CardView> cardCacheScry = GameEntityView.getMap(topN);
toBottom = new CardCollection();
List<CardView> views = getGui().many(localizer.getMessage("lblSelectCardsToBeOutOnTheBottomOfYourLibrary"),
localizer.getMessage("lblCardsToPutOnTheBottom"), -1, cardCacheScry.getTrackableKeys(), null);
cardCacheScry.addToList(views, toBottom);
topN.removeAll(toBottom);
if (topN.isEmpty()) {
toTop = null;
} else if (topN.size() == 1) {
toTop = topN;
} else {
toTop = game.getCardList(getGui().order(localizer.getMessage("lblArrangeCardsToBePutOnTopOfYourLibrary"),
localizer.getMessage("lblTopOfLibrary"), CardView.getCollection(topN), null));
GameEntityViewMap<Card, CardView> cardCacheOrder = GameEntityView.getMap(topN);
toTop = new CardCollection();
views = getGui().order(localizer.getMessage("lblArrangeCardsToBePutOnTopOfYourLibrary"),
localizer.getMessage("lblTopOfLibrary"), cardCacheOrder.getTrackableKeys(), null);
cardCacheOrder.addToList(views, toTop);
}
}
}
@@ -827,16 +843,22 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
toGrave = topN;
}
} else {
toGrave = game.getCardList(getGui().many(localizer.getMessage("lblSelectCardsToBePutIntoTheGraveyard"),
localizer.getMessage("lblCardsToPutInTheGraveyard"), -1, CardView.getCollection(topN), null));
GameEntityViewMap<Card, CardView> gameCacheSurveil = GameEntityView.getMap(topN);
toGrave = new CardCollection();
List<CardView> views = getGui().many(localizer.getMessage("lblSelectCardsToBePutIntoTheGraveyard"),
localizer.getMessage("lblCardsToPutInTheGraveyard"), -1, gameCacheSurveil.getTrackableKeys(), null);
gameCacheSurveil.addToList(views, toGrave);
topN.removeAll(toGrave);
if (topN.isEmpty()) {
toTop = null;
} else if (topN.size() == 1) {
toTop = topN;
} else {
toTop = game.getCardList(getGui().order(localizer.getMessage("lblArrangeCardsToBePutOnTopOfYourLibrary"),
localizer.getMessage("lblTopOfLibrary"), CardView.getCollection(topN), null));
GameEntityViewMap<Card, CardView> cardCacheOrder = GameEntityView.getMap(topN);
toTop = new CardCollection();
views = getGui().order(localizer.getMessage("lblArrangeCardsToBePutOnTopOfYourLibrary"),
localizer.getMessage("lblTopOfLibrary"), cardCacheOrder.getTrackableKeys(), null);
cardCacheOrder.addToList(views, toTop);
}
}
endTempShowCards();
@@ -882,32 +904,28 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
}
}
List<CardView> choices;
tempShowCards(cards);
GameEntityViewMap<Card, CardView> gameCacheMove = GameEntityView.getMap(cards);
List<CardView> choices = gameCacheMove.getTrackableKeys();
switch (destinationZone) {
case Library:
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoLibrary"), localizer.getMessage("lblClosestToTop"),
CardView.getCollection(cards), null);
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoLibrary"), localizer.getMessage("lblClosestToTop"), choices, null);
break;
case Battlefield:
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutOntoBattlefield"), localizer.getMessage("lblPutFirst"),
CardView.getCollection(cards), null);
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutOntoBattlefield"), localizer.getMessage("lblPutFirst"), choices, null);
break;
case Graveyard:
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoGraveyard"), localizer.getMessage("lblClosestToBottom"),
CardView.getCollection(cards), null);
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoGraveyard"), localizer.getMessage("lblClosestToBottom"), choices, null);
break;
case PlanarDeck:
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoPlanarDeck"), localizer.getMessage("lblClosestToTop"),
CardView.getCollection(cards), null);
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoPlanarDeck"), localizer.getMessage("lblClosestToTop"), choices, null);
break;
case SchemeDeck:
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoSchemeDeck"), localizer.getMessage("lblClosestToTop"),
CardView.getCollection(cards), null);
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoSchemeDeck"), localizer.getMessage("lblClosestToTop"), choices, null);
break;
case Stack:
choices = getGui().order(localizer.getMessage("lblChooseOrderCopiesCast"), localizer.getMessage("lblPutFirst"), CardView.getCollection(cards),
null);
choices = getGui().order(localizer.getMessage("lblChooseOrderCopiesCast"), localizer.getMessage("lblPutFirst"), choices, null);
break;
default:
System.out.println("ZoneType " + destinationZone + " - Not Ordered");
@@ -915,7 +933,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
return cards;
}
endTempShowCards();
return game.getCardList(choices);
CardCollection result = new CardCollection();
gameCacheMove.addToList(choices, result);
return result;
}
@Override
@@ -923,10 +943,12 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
final CardCollection valid, final int min, final int max) {
if (p != player) {
tempShowCards(valid);
final CardCollection choices = game
.getCardList(getGui().many(String.format(localizer.getMessage("lblChooseMinCardToDiscard"), min),
localizer.getMessage("lblDiscarded"), min, min, CardView.getCollection(valid), null));
GameEntityViewMap<Card, CardView> gameCacheDiscard = GameEntityView.getMap(valid);
List<CardView> views = getGui().many(String.format(localizer.getMessage("lblChooseMinCardToDiscard"), min),
localizer.getMessage("lblDiscarded"), min, min, gameCacheDiscard.getTrackableKeys(), null);
endTempShowCards();
final CardCollection choices = new CardCollection();
gameCacheDiscard.addToList(views, choices);
return choices;
}
@@ -949,25 +971,26 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
cntChoice.add(Integer.valueOf(i));
}
final int chosenAmount = getGui().one(localizer.getMessage("lblDelveHowManyCards"), cntChoice.build()).intValue();
for (int i = 0; i < chosenAmount; i++) {
final CardView nowChosen = getGui().oneOrNone(localizer.getMessage("lblExileWhichCard", String.valueOf(i + 1), String.valueOf(chosenAmount)), CardView.getCollection(grave));
if (nowChosen == null) {
GameEntityViewMap<Card, CardView> gameCacheGrave = GameEntityView.getMap(grave);
for (int i = 0; i < chosenAmount; i++) {
String title = localizer.getMessage("lblExileWhichCard", String.valueOf(i + 1), String.valueOf(chosenAmount));
final CardView nowChosen = getGui().oneOrNone(title, gameCacheGrave.getTrackableKeys());
if (nowChosen == null || !gameCacheGrave.containsKey(nowChosen)) {
// User canceled,abort delving.
toExile.clear();
break;
}
final Card card = game.getCard(nowChosen);
grave.remove(card);
toExile.add(card);
toExile.add(gameCacheGrave.remove(nowChosen));
}
return toExile;
}
/*
* (non-Javadoc)
*
*
* @see
* forge.game.player.PlayerController#chooseTargets(forge.card.spellability.
* SpellAbility, forge.card.spellability.SpellAbilityStackInstance)
@@ -991,7 +1014,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see
* forge.game.player.PlayerController#chooseCardsToDiscardUnlessType(int,
* java.lang.String, forge.card.spellability.SpellAbility)
@@ -1020,7 +1043,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see
* forge.game.player.PlayerController#chooseManaFromPool(java.util.List)
*/
@@ -1038,7 +1061,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.game.player.PlayerController#chooseSomeType(java.lang.String,
* java.lang.String, java.util.List, java.util.List, java.lang.String)
*/
@@ -1185,7 +1208,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see
* forge.game.player.PlayerController#confirmReplacementEffect(forge.card.
* replacement.ReplacementEffect, forge.card.spellability.SpellAbility,
@@ -1355,6 +1378,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override
public List<SpellAbility> chooseSaToActivateFromOpeningHand(final List<SpellAbility> usableFromOpeningHand) {
final CardCollection srcCards = new CardCollection();
for (final SpellAbility sa : usableFromOpeningHand) {
srcCards.add(sa.getHostCard());
@@ -1363,10 +1388,15 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
if (srcCards.isEmpty()) {
return result;
}
GameEntityViewMap<Card, CardView> gameCacheOpenHand = GameEntityView.getMap(srcCards);
final List<CardView> chosen = getGui().many(localizer.getMessage("lblChooseCardsActivateOpeningHandandOrder"),
localizer.getMessage("lblActivateFirst"), -1, CardView.getCollection(srcCards), null);
for (final CardView view : chosen) {
final Card c = game.getCard(view);
if (!gameCacheOpenHand.containsKey(view)) {
continue;
}
final Card c = gameCacheOpenHand.get(view);
for (final SpellAbility sa : usableFromOpeningHand) {
if (sa.getHostCard() == c) {
result.add(sa);
@@ -1474,7 +1504,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.game.player.PlayerController#chooseModeForAbility(forge.card.
* spellability.SpellAbility, java.util.List, int, int)
*/
@@ -1983,7 +2013,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#setCanPlayUnlimitedLands(boolean)
*/
@Override
@@ -1994,7 +2024,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#setViewAllCards(boolean)
*/
@Override
@@ -2007,7 +2037,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#generateMana()
*/
@Override
@@ -2042,7 +2072,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#dumpGameState()
*/
@Override
@@ -2069,7 +2099,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#setupGameState()
*/
@Override
@@ -2109,7 +2139,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#tutorForCard()
*/
@Override
@@ -2140,7 +2170,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#addCountersToPermanent()
*/
@Override
@@ -2160,12 +2190,14 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
public void modifyCountersOnPermanent(boolean subtract) {
final String titleMsg = subtract ? localizer.getMessage("lblRemoveCountersFromWhichCard") : localizer.getMessage("lblAddCountersToWhichCard");
final CardCollectionView cards = game.getCardsIn(ZoneType.Battlefield);
final Card card = game
.getCard(getGui().oneOrNone(titleMsg, CardView.getCollection(cards)));
if (card == null) {
GameEntityViewMap<Card, CardView> gameCacheCounters = GameEntityView.getMap(game.getCardsIn(ZoneType.Battlefield));
final CardView cv = getGui().oneOrNone(titleMsg, gameCacheCounters.getTrackableKeys());
if (cv == null || !gameCacheCounters.containsKey(cv)) {
return;
}
final Card card = gameCacheCounters.get(cv);
final ImmutableList<CounterType> counters = subtract ? ImmutableList.copyOf(card.getCounters().keySet())
: CounterType.values;
@@ -2190,7 +2222,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#tapPermanents()
*/
@Override
@@ -2216,7 +2248,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#untapPermanents()
*/
@Override
@@ -2242,16 +2274,19 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#setPlayerLife()
*/
@Override
public void setPlayerLife() {
final Player player = game.getPlayer(
getGui().oneOrNone(localizer.getMessage("lblSetLifeforWhichPlayer"), PlayerView.getCollection(game.getPlayers())));
if (player == null) {
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(game.getPlayers());
final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblSetLifeforWhichPlayer"), gameCachePlayer.getTrackableKeys());
if (pv == null || !gameCachePlayer.containsKey(pv)) {
return;
}
final Player player = gameCachePlayer.get(pv);
final Integer life = getGui().getInteger(localizer.getMessage("lblSetLifetoWhat"), 0);
if (life == null) {
@@ -2263,7 +2298,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#winGame()
*/
@Override
@@ -2289,7 +2324,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#addCardToHand()
*/
@Override
@@ -2375,12 +2410,21 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
}
}
final Player p = repeatLast ? lastAddedPlayer
: game.getPlayer(getGui().oneOrNone(message,
PlayerView.getCollection(game.getPlayers())));
if (p == null) {
return;
Player pOld = lastAddedPlayer;
if (repeatLast) {
if (pOld == null) {
return;
}
} else {
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(game.getPlayers());
PlayerView pv = getGui().oneOrNone(message, gameCachePlayer.getTrackableKeys());
if (pv == null || !gameCachePlayer.containsKey(pv)) {
return;
}
pOld = gameCachePlayer.get(pv);
}
final Player p = pOld;
final CardDb carddb = FModel.getMagicDb().getCommonCards();
final List<ICardFace> faces = Lists.newArrayList(carddb.getAllFaces());
@@ -2478,70 +2522,76 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#exileCardsFromHand()
*/
@Override
public void exileCardsFromHand() {
final Player p = game.getPlayer(getGui().oneOrNone(localizer.getMessage("lblExileCardsFromPlayerHandConfirm"),
PlayerView.getCollection(game.getPlayers())));
if (p == null) {
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(game.getPlayers());
final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblExileCardsFromPlayerHandConfirm"),
gameCachePlayer.getTrackableKeys());
if (pv == null || !gameCachePlayer.containsKey(pv)) {
return;
}
Player p = gameCachePlayer.get(pv);
final CardCollection selection;
GameEntityViewMap<Card, CardView> gameCacheExile = GameEntityView.getMap(p.getCardsIn(ZoneType.Hand));
CardCollectionView cardsInHand = p.getCardsIn(ZoneType.Hand);
selection = game.getCardList(getGui().many(localizer.getMessage("lblChooseCardsExile"), localizer.getMessage("lblDiscarded"), 0, -1,
CardView.getCollection(cardsInHand), null));
List<CardView> views = getGui().many(localizer.getMessage("lblChooseCardsExile"), localizer.getMessage("lblDiscarded"), 0, -1,
gameCacheExile.getTrackableKeys(), null);
if (selection != null && selection.size() > 0) {
for (Card c : selection) {
if (c == null) {
continue;
}
if (game.getAction().moveTo(ZoneType.Exile, c, null) != null) {
StringBuilder sb = new StringBuilder();
sb.append(p).append(" exiles ").append(c).append(" due to Dev Cheats.");
game.getGameLog().add(GameLogEntryType.DISCARD, sb.toString());
} else {
game.getGameLog().add(GameLogEntryType.INFORMATION, "DISCARD CHEAT ERROR");
}
final CardCollection selection = new CardCollection();
gameCacheExile.addToList(views, selection);
for (Card c : selection) {
if (c == null) {
continue;
}
if (game.getAction().moveTo(ZoneType.Exile, c, null) != null) {
StringBuilder sb = new StringBuilder();
sb.append(p).append(" exiles ").append(c).append(" due to Dev Cheats.");
game.getGameLog().add(GameLogEntryType.DISCARD, sb.toString());
} else {
game.getGameLog().add(GameLogEntryType.INFORMATION, "DISCARD CHEAT ERROR");
}
}
}
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#exileCardsFromBattlefield()
*/
@Override
public void exileCardsFromBattlefield() {
final Player p = game.getPlayer(getGui().oneOrNone(localizer.getMessage("lblExileCardsFromPlayerBattlefieldConfirm"),
PlayerView.getCollection(game.getPlayers())));
if (p == null) {
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(game.getPlayers());
final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblExileCardsFromPlayerBattlefieldConfirm"),
gameCachePlayer.getTrackableKeys());
if (pv == null || !gameCachePlayer.containsKey(pv)) {
return;
}
Player p = gameCachePlayer.get(pv);
final CardCollection selection;
GameEntityViewMap<Card, CardView> gameCacheExile = GameEntityView.getMap(p.getCardsIn(ZoneType.Battlefield));
CardCollectionView cardsInPlay = p.getCardsIn(ZoneType.Battlefield);
selection = game.getCardList(getGui().many(localizer.getMessage("lblChooseCardsExile"), localizer.getMessage("lblDiscarded"), 0, -1,
CardView.getCollection(cardsInPlay), null));
List<CardView> views = getGui().many(localizer.getMessage("lblChooseCardsExile"), localizer.getMessage("lblDiscarded"), 0, -1,
gameCacheExile.getTrackableKeys(), null);
if (selection != null && selection.size() > 0) {
for (Card c : selection) {
if (c == null) {
continue;
}
if (game.getAction().moveTo(ZoneType.Exile, c, null) != null) {
StringBuilder sb = new StringBuilder();
sb.append(p).append(" exiles ").append(c).append(" due to Dev Cheats.");
game.getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString());
} else {
game.getGameLog().add(GameLogEntryType.INFORMATION, "EXILE FROM PLAY CHEAT ERROR");
}
final CardCollection selection = new CardCollection();
gameCacheExile.addToList(views, selection);
for (Card c : selection) {
if (c == null) {
continue;
}
if (game.getAction().moveTo(ZoneType.Exile, c, null) != null) {
StringBuilder sb = new StringBuilder();
sb.append(p).append(" exiles ").append(c).append(" due to Dev Cheats.");
game.getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString());
} else {
game.getGameLog().add(GameLogEntryType.INFORMATION, "EXILE FROM PLAY CHEAT ERROR");
}
}
}
@@ -2553,48 +2603,53 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
*/
@Override
public void removeCardsFromGame() {
final Player p = game.getPlayer(getGui().oneOrNone(localizer.getMessage("lblRemoveCardBelongingWitchPlayer"),
PlayerView.getCollection(game.getPlayers())));
if (p == null) {
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(game.getPlayers());
final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblRemoveCardBelongingWitchPlayer"),
gameCachePlayer.getTrackableKeys());
if (pv == null || !gameCachePlayer.containsKey(pv)) {
return;
}
Player p = gameCachePlayer.get(pv);
final String zone = getGui().one(localizer.getMessage("lblRemoveCardFromWhichZone"),
Arrays.asList("Hand", "Battlefield", "Library", "Graveyard", "Exile"));
final CardCollection selection;
CardCollectionView cards = p.getCardsIn(ZoneType.smartValueOf(zone));
selection = game.getCardList(getGui().many(localizer.getMessage("lblChooseCardsRemoveFromGame"), localizer.getMessage("lblRemoved"), 0, -1,
CardView.getCollection(cards), null));
GameEntityViewMap<Card, CardView> gameCacheExile = GameEntityView.getMap(cards);
List<CardView> views = getGui().many(localizer.getMessage("lblChooseCardsRemoveFromGame"), localizer.getMessage("lblRemoved"), 0, -1,
gameCacheExile.getTrackableKeys(), null);
if (selection != null && selection.size() > 0) {
for (Card c : selection) {
if (c == null) {
continue;
}
c.getZone().remove(c);
c.ceaseToExist();
final CardCollection selection = new CardCollection();
gameCacheExile.addToList(views, selection);
StringBuilder sb = new StringBuilder();
sb.append(p).append(" removes ").append(c).append(" from game due to Dev Cheats.");
game.getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString());
for (Card c : selection) {
if (c == null) {
continue;
}
c.getZone().remove(c);
c.ceaseToExist();
StringBuilder sb = new StringBuilder();
sb.append(p).append(" removes ").append(c).append(" from game due to Dev Cheats.");
game.getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString());
}
}
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#riggedPlanarRoll()
*/
@Override
public void riggedPlanarRoll() {
final Player player = game.getPlayer(
getGui().oneOrNone(localizer.getMessage("lblWhichPlayerShouldRoll"), PlayerView.getCollection(game.getPlayers())));
if (player == null) {
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(game.getPlayers());
final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblWhichPlayerShouldRoll"), gameCachePlayer.getTrackableKeys());
if (pv == null || !gameCachePlayer.containsKey(pv)) {
return;
}
final Player player = gameCachePlayer.get(pv);
final PlanarDice res = getGui().oneOrNone(localizer.getMessage("lblChooseResult"), PlanarDice.values);
if (res == null) {
@@ -2613,7 +2668,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/*
* (non-Javadoc)
*
*
* @see forge.player.IDevModeCheats#planeswalkTo()
*/
@Override
@@ -2868,7 +2923,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override
public void reorderHand(final CardView card, final int index) {
final PlayerZone hand = player.getZone(ZoneType.Hand);
hand.reorder(game.getCard(card), index);
hand.reorder(getCard(card), index);
player.updateZoneForView(hand);
}
@@ -2880,30 +2935,25 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override
public List<Card> chooseCardsForSplice(SpellAbility sa, List<Card> cards) {
HashMap<CardView, Card> mapCVtoC = new HashMap<>();
for (Card card : cards) {
mapCVtoC.put(card.getView(), card);
}
List<CardView> choices = new ArrayList<>(mapCVtoC.keySet());
List<CardView> chosen;
chosen = getGui().many(
GameEntityViewMap<Card, CardView> gameCacheSplice = GameEntityView.getMap(cards);
List<CardView> chosen = getGui().many(
localizer.getMessage("lblChooseCardstoSpliceonto"),
localizer.getMessage("lblChosenCards"),
0,
choices.size(),
choices,
gameCacheSplice.size(),
gameCacheSplice.getTrackableKeys(),
sa.getHostCard().getView()
);
List<Card> chosenCards = new ArrayList<>();
for (CardView cardView : chosen) {
chosenCards.add(mapCVtoC.get(cardView));
}
List<Card> chosenCards = new CardCollection();
gameCacheSplice.addToList(chosen, chosenCards);
return chosenCards;
}
/*
* (non-Javadoc)
*
*
* @see forge.game.player.PlayerController#chooseOptionalCosts(forge.game.
* spellability.SpellAbility, java.util.List)
*/
@@ -2942,5 +2992,25 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
return result;
}
public Card getCard(final CardView cardView) {
if (gameCache.containsKey(cardView)) {
return gameCache.get(cardView);
}
final Card c = getGame().findById(cardView.getId());
gameCache.put(cardView, c);
return c;
}
public CardCollection getCardList(Iterable<CardView> cardViews) {
CardCollection result = new CardCollection();
for(CardView cardView : cardViews){
final Card c = this.getCard(cardView);
if (c != null) {
result.add(c);
}
}
return result;
}
}

View File

@@ -6,12 +6,12 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -21,6 +21,8 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GameEntityView;
import forge.game.GameEntityViewMap;
import forge.game.GameObject;
import forge.game.card.Card;
import forge.game.card.CardUtil;
@@ -44,7 +46,7 @@ import java.util.Map;
* <p>
* Target_Selection class.
* </p>
*
*
* @author Forge
* @version $Id: TargetSelection.java 25148 2014-03-12 08:28:52Z swordshine $
*/
@@ -69,8 +71,8 @@ public class TargetSelection {
if (!canTarget) {
throw new RuntimeException("TargetSelection.chooseTargets called for ability that does not target - " + ability);
}
// Number of targets is explicitly set only if spell is being redirected (ex. Swerve or Redirect)
// Number of targets is explicitly set only if spell is being redirected (ex. Swerve or Redirect)
final int minTargets = numTargets != null ? numTargets.intValue() : tgt.getMinTargets(ability.getHostCard(), ability);
final int maxTargets = numTargets != null ? numTargets.intValue() : tgt.getMaxTargets(ability.getHostCard(), ability);
//final int maxTotalCMC = tgt.getMaxTotalCMC(ability.getHostCard(), ability);
@@ -99,10 +101,10 @@ public class TargetSelection {
// Mandatory target selection, that has no candidates but enough targets (Min == 0, but no choices)
return true;
}
final List<ZoneType> zones = tgt.getZone();
final boolean mandatory = tgt.getMandatory() && hasCandidates;
final boolean choiceResult;
final boolean random = tgt.isRandomTarget();
if (random) {
@@ -167,7 +169,7 @@ public class TargetSelection {
choiceResult = this.chooseCardFromList(validTargets, true, mandatory);
}
}
// some inputs choose cards one-by-one and need to be called again
// some inputs choose cards one-by-one and need to be called again
return choiceResult && chooseTargets(numTargets);
}
@@ -175,6 +177,8 @@ public class TargetSelection {
// Send in a list of valid cards, and popup a choice box to target
final Game game = ability.getActivatingPlayer().getGame();
GameEntityViewMap<Card, CardView> gameCacheChooseCard = GameEntityView.getMap(choices);
final List<CardView> crdsBattle = Lists.newArrayList();
final List<CardView> crdsExile = Lists.newArrayList();
final List<CardView> crdsGrave = Lists.newArrayList();
@@ -228,7 +232,7 @@ public class TargetSelection {
// is there a more elegant way of doing this?
choicesFiltered.add(msgDone);
}
Object chosen = null;
if (!choices.isEmpty() && mandatory) {
chosen = controller.getGui().one(getTgt().getVTSelection(), choicesFiltered);
@@ -245,7 +249,10 @@ public class TargetSelection {
}
if (chosen instanceof CardView) {
ability.getTargets().add(game.getCard((CardView) chosen));
if (!gameCacheChooseCard.containsKey(chosen)) {
return false;
}
ability.getTargets().add(gameCacheChooseCard.get((CardView) chosen));
}
return true;
}
@@ -292,7 +299,7 @@ public class TargetSelection {
if (madeChoice instanceof StackItemView) {
ability.getTargets().add(stackItemViewCache.get(madeChoice).getSpellAbility(true));
}
else {// 'FINISH TARGETING' chosen
else {// 'FINISH TARGETING' chosen
bTargetingDone = true;
}
}