mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
removing more player type checks from discard
This commit is contained in:
@@ -5,6 +5,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang.ArrayUtils;
|
import org.apache.commons.lang.ArrayUtils;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
@@ -18,7 +19,6 @@ import forge.game.player.AIPlayer;
|
|||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.GuiChoose;
|
import forge.gui.GuiChoose;
|
||||||
import forge.gui.GuiDialog;
|
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
|
|
||||||
public class DiscardEffect extends RevealEffectBase {
|
public class DiscardEffect extends RevealEffectBase {
|
||||||
@@ -86,34 +86,6 @@ public class DiscardEffect extends RevealEffectBase {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
} // discardStackDescription()
|
} // discardStackDescription()
|
||||||
|
|
||||||
private List<Card> discardComputerChooses(SpellAbility sa, Player victim, Player chooser, int numCards, String[] dValid, boolean isReveal) {
|
|
||||||
final Card source = sa.getSourceCard();
|
|
||||||
List<Card> dPChHand = new ArrayList<Card>(victim.getCardsIn(ZoneType.Hand));
|
|
||||||
dPChHand = CardLists.getValidCards(dPChHand, dValid, source.getController(), source);
|
|
||||||
final List<Card> toDiscard = new ArrayList<Card>();
|
|
||||||
|
|
||||||
int max = Math.min(dPChHand.size(), numCards);
|
|
||||||
List<Card> list = new ArrayList<Card>();
|
|
||||||
|
|
||||||
if (!victim.isOpponentOf(chooser) && victim instanceof AIPlayer) { // discard AI cards
|
|
||||||
list = ((AIPlayer) victim).getAi().getCardsToDiscard(max, dValid, sa);
|
|
||||||
} else {
|
|
||||||
// discard hostile or human opponent
|
|
||||||
for (int i = 0; i < max; i++) {
|
|
||||||
Card dC = chooseCardToDiscardFromOpponent(sa, dPChHand);
|
|
||||||
dPChHand.remove(dC);
|
|
||||||
list.add(dC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isReveal) {
|
|
||||||
GuiChoose.oneOrNone("Computer has chosen", list);
|
|
||||||
}
|
|
||||||
|
|
||||||
return toDiscard;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Write javadoc for this method.
|
* TODO: Write javadoc for this method.
|
||||||
* @param sa
|
* @param sa
|
||||||
@@ -207,19 +179,9 @@ public class DiscardEffect extends RevealEffectBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mode.equals("Random")) {
|
if (mode.equals("Random")) {
|
||||||
boolean runDiscard = true;
|
String message = "Would you like to discard " + numCards + " random card(s)?";
|
||||||
if (sa.hasParam("Optional")) {
|
boolean runDiscard = !sa.hasParam("Optional") || p.getController().confirmAction(sa, mode, message);
|
||||||
if (p.isHuman()) {
|
|
||||||
// TODO Ask if Human would like to discard a card at Random
|
|
||||||
StringBuilder sb = new StringBuilder("Would you like to discard ");
|
|
||||||
sb.append(numCards).append(" random card(s)?");
|
|
||||||
runDiscard = GuiDialog.confirm(source, sb.toString());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// TODO For now AI will always discard Random used currently with:
|
|
||||||
// Balduvian Horde and similar cards
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runDiscard) {
|
if (runDiscard) {
|
||||||
final String valid = sa.hasParam("DiscardValid") ? sa.getParam("DiscardValid") : "Card";
|
final String valid = sa.hasParam("DiscardValid") ? sa.getParam("DiscardValid") : "Card";
|
||||||
@@ -253,68 +215,88 @@ public class DiscardEffect extends RevealEffectBase {
|
|||||||
// Is Reveal you choose right? I think the wrong player is
|
// Is Reveal you choose right? I think the wrong player is
|
||||||
// being used?
|
// being used?
|
||||||
List<Card> dPHand = new ArrayList<Card>(p.getCardsIn(ZoneType.Hand));
|
List<Card> dPHand = new ArrayList<Card>(p.getCardsIn(ZoneType.Hand));
|
||||||
if (dPHand.size() != 0) {
|
if (dPHand.isEmpty())
|
||||||
if (sa.hasParam("RevealNumber")) {
|
continue; // for loop over players
|
||||||
String amountString = sa.getParam("RevealNumber");
|
|
||||||
int amount = amountString.matches("[0-9][0-9]?") ? Integer.parseInt(amountString)
|
|
||||||
: CardFactoryUtil.xCount(source, source.getSVar(amountString));
|
|
||||||
dPHand = getRevealedList(p, dPHand, amount, false);
|
|
||||||
}
|
|
||||||
List<Card> dPChHand = new ArrayList<Card>(dPHand);
|
|
||||||
final String valid = sa.hasParam("DiscardValid") ? sa.getParam("DiscardValid") : "Card";
|
|
||||||
String[] dValid = ArrayUtils.EMPTY_STRING_ARRAY;
|
|
||||||
dValid = valid.split(",");
|
|
||||||
dPChHand = CardLists.getValidCards(dPHand, dValid, source.getController(), source);
|
|
||||||
|
|
||||||
Player chooser = p;
|
if (sa.hasParam("RevealNumber")) {
|
||||||
if (mode.equals("RevealYouChoose")) {
|
String amountString = sa.getParam("RevealNumber");
|
||||||
chooser = source.getController();
|
int amount = StringUtils.isNumeric(amountString) ? Integer.parseInt(amountString) : CardFactoryUtil.xCount(source, source.getSVar(amountString));
|
||||||
} else if (mode.equals("RevealOppChoose")) {
|
dPHand = getRevealedList(p, dPHand, amount, false);
|
||||||
chooser = source.getController().getOpponent();
|
}
|
||||||
}
|
List<Card> dPChHand = new ArrayList<Card>(dPHand);
|
||||||
|
final String valid = sa.hasParam("DiscardValid") ? sa.getParam("DiscardValid") : "Card";
|
||||||
|
String[] dValid = ArrayUtils.EMPTY_STRING_ARRAY;
|
||||||
|
dValid = valid.split(",");
|
||||||
|
dPChHand = CardLists.getValidCards(dPHand, dValid, source.getController(), source);
|
||||||
|
|
||||||
List<Card> toBeDiscarded = new ArrayList<Card>();
|
Player chooser = p;
|
||||||
if (chooser.isComputer()) {
|
if (mode.equals("RevealYouChoose")) {
|
||||||
toBeDiscarded = discardComputerChooses(sa, p, chooser, numCards, dValid, mode.startsWith("Reveal"));
|
chooser = source.getController();
|
||||||
|
} else if (mode.equals("RevealOppChoose")) {
|
||||||
|
chooser = source.getController().getOpponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Card> toBeDiscarded = new ArrayList<Card>();
|
||||||
|
if (chooser.isComputer()) {
|
||||||
|
List<Card> dPChHand1 = new ArrayList<Card>(p.getCardsIn(ZoneType.Hand));
|
||||||
|
dPChHand1 = CardLists.getValidCards(dPChHand1, dValid, source.getController(), source);
|
||||||
|
|
||||||
|
int max = Math.min(dPChHand1.size(), numCards);
|
||||||
|
List<Card> list = new ArrayList<Card>();
|
||||||
|
|
||||||
|
if (!p.isOpponentOf(chooser) && p instanceof AIPlayer) { // discard AI cards
|
||||||
|
toBeDiscarded = ((AIPlayer) p).getAi().getCardsToDiscard(max, dValid, sa);
|
||||||
} else {
|
} else {
|
||||||
// human
|
// discard hostile or human opponent
|
||||||
if (mode.startsWith("Reveal")) {
|
for (int i = 0; i < max; i++) {
|
||||||
GuiChoose.oneOrNone("Revealed " + p + " hand", dPHand);
|
Card dC = chooseCardToDiscardFromOpponent(sa, dPChHand1);
|
||||||
}
|
dPChHand1.remove(dC);
|
||||||
|
toBeDiscarded.add(dC);
|
||||||
if (sa.hasParam("AnyNumber")) {
|
|
||||||
List<Card> chosen = getDiscardedList(p, dPChHand, dPChHand.size(), true);
|
|
||||||
|
|
||||||
for (Card c : chosen) {
|
|
||||||
dPChHand.remove(chosen);
|
|
||||||
toBeDiscarded.add(c);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
for (int i = 0; i < numCards; i++) {
|
|
||||||
if (dPChHand.isEmpty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Card dC = null;
|
|
||||||
if (sa.hasParam("Optional")) {
|
|
||||||
dC = GuiChoose.oneOrNone("Choose a card to be discarded", dPChHand);
|
|
||||||
} else {
|
|
||||||
dC = GuiChoose.one("Choose a card to be discarded", dPChHand);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dC != null) {
|
|
||||||
dPChHand.remove(dC);
|
|
||||||
toBeDiscarded.add(dC);
|
|
||||||
}
|
|
||||||
else break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toBeDiscarded != null) {
|
if (mode.startsWith("Reveal")) {
|
||||||
for (Card card : toBeDiscarded) {
|
GuiChoose.oneOrNone("Computer has chosen", list);
|
||||||
if ( null == card ) continue;
|
}
|
||||||
p.discard(card, sa);
|
|
||||||
discarded.add(card);
|
} else {
|
||||||
|
// human
|
||||||
|
if (mode.startsWith("Reveal")) {
|
||||||
|
GuiChoose.oneOrNone("Revealed " + p + " hand", dPHand);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sa.hasParam("AnyNumber")) {
|
||||||
|
List<Card> chosen = getDiscardedList(p, dPChHand);
|
||||||
|
|
||||||
|
for (Card c : chosen) {
|
||||||
|
dPChHand.remove(chosen);
|
||||||
|
toBeDiscarded.add(c);
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
for (int i = 0; i < numCards; i++) {
|
||||||
|
if (dPChHand.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Card dC = null;
|
||||||
|
if (sa.hasParam("Optional")) {
|
||||||
|
dC = GuiChoose.oneOrNone("Choose a card to be discarded", dPChHand);
|
||||||
|
} else {
|
||||||
|
dC = GuiChoose.one("Choose a card to be discarded", dPChHand);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dC != null) {
|
||||||
|
dPChHand.remove(dC);
|
||||||
|
toBeDiscarded.add(dC);
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toBeDiscarded != null) {
|
||||||
|
for (Card card : toBeDiscarded) {
|
||||||
|
if ( null == card ) continue;
|
||||||
|
p.discard(card, sa);
|
||||||
|
discarded.add(card);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -329,11 +311,11 @@ public class DiscardEffect extends RevealEffectBase {
|
|||||||
|
|
||||||
} // discardResolve()
|
} // discardResolve()
|
||||||
|
|
||||||
public static List<Card> getDiscardedList(final Player player, final List<Card> valid, final int max, boolean anyNumber) {
|
public static List<Card> getDiscardedList(final Player player, final List<Card> valid) {
|
||||||
final List<Card> chosen = new ArrayList<Card>();
|
final List<Card> chosen = new ArrayList<Card>();
|
||||||
final int validamount = Math.min(valid.size(), max);
|
final int validamount = Math.min(valid.size(), valid.size());
|
||||||
|
|
||||||
if (anyNumber && player.isHuman() && validamount > 0) {
|
if (player.isHuman() && validamount > 0) {
|
||||||
final List<Card> selection = GuiChoose.order("Choose Which Cards to Discard", "Discarded", -1, valid, null, null);
|
final List<Card> selection = GuiChoose.order("Choose Which Cards to Discard", "Discarded", -1, valid, null, null);
|
||||||
for (final Object o : selection) {
|
for (final Object o : selection) {
|
||||||
if (o != null && o instanceof Card) {
|
if (o != null && o instanceof Card) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.ai;
|
package forge.game.ai;
|
||||||
|
|
||||||
|
import java.security.InvalidParameterException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@@ -545,7 +546,7 @@ public class AiController {
|
|||||||
// look for good discards
|
// look for good discards
|
||||||
while (count < numDiscard) {
|
while (count < numDiscard) {
|
||||||
Card prefCard = null;
|
Card prefCard = null;
|
||||||
if (sa != null && sa.getActivatingPlayer() != null && sa.getActivatingPlayer().isHuman()) {
|
if (sa != null && sa.getActivatingPlayer() != null && sa.getActivatingPlayer().isOpponentOf(player)) {
|
||||||
for (Card c : hand) {
|
for (Card c : hand) {
|
||||||
if (c.hasKeyword("If a spell or ability an opponent controls causes you to discard CARDNAME,"
|
if (c.hasKeyword("If a spell or ability an opponent controls causes you to discard CARDNAME,"
|
||||||
+ " put it onto the battlefield instead of putting it into your graveyard.")) {
|
+ " put it onto the battlefield instead of putting it into your graveyard.")) {
|
||||||
@@ -604,5 +605,38 @@ public class AiController {
|
|||||||
|
|
||||||
return discardList;
|
return discardList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Card chooseSingleCardForEffect(List<Card> options, SpellAbility sa, String title, boolean isOptional) {
|
||||||
|
ApiType api = sa.getApi();
|
||||||
|
if ( null == api ) {
|
||||||
|
throw new InvalidParameterException("SA is not api-based, this is not supported yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(api) {
|
||||||
|
case Bond: return CardFactoryUtil.getBestCreatureAI(options);
|
||||||
|
default: throw new InvalidParameterException("AI chooseSingleCard does not know how to choose card for " + api);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean confirmAction(SpellAbility sa, String mode, String message) {
|
||||||
|
ApiType api = sa.getApi();
|
||||||
|
if ( null == api ) {
|
||||||
|
throw new InvalidParameterException("SA is not api-based, this is not supported yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(api) {
|
||||||
|
case Discard:
|
||||||
|
if ( mode.equals("Random") ) { //
|
||||||
|
// TODO For now AI will always discard Random used currently with: Balduvian Horde and similar cards
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
String exMsg = String.format("AI confirmAction does not know what to decide about %s with %s mode.", api, mode);
|
||||||
|
throw new InvalidParameterException(exMsg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,4 +94,5 @@ public abstract class PlayerController {
|
|||||||
|
|
||||||
public Card chooseSingleCardForEffect(List<Card> sourceList, SpellAbility sa, String title) { return chooseSingleCardForEffect(sourceList, sa, title); }
|
public Card chooseSingleCardForEffect(List<Card> sourceList, SpellAbility sa, String title) { return chooseSingleCardForEffect(sourceList, sa, title); }
|
||||||
public abstract Card chooseSingleCardForEffect(List<Card> sourceList, SpellAbility sa, String title, boolean isOptional);
|
public abstract Card chooseSingleCardForEffect(List<Card> sourceList, SpellAbility sa, String title, boolean isOptional);
|
||||||
|
public abstract boolean confirmAction(SpellAbility sa, String mode, String message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
package forge.game.player;
|
package forge.game.player;
|
||||||
|
|
||||||
import java.security.InvalidParameterException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.GameEntity;
|
import forge.GameEntity;
|
||||||
import forge.card.ability.ApiType;
|
|
||||||
import forge.card.cardfactory.CardFactoryUtil;
|
|
||||||
import forge.card.spellability.Spell;
|
import forge.card.spellability.Spell;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.control.input.Input;
|
import forge.control.input.Input;
|
||||||
@@ -193,15 +190,12 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Card chooseSingleCardForEffect(List<Card> options, SpellAbility sa, String title, boolean isOptional) {
|
public Card chooseSingleCardForEffect(List<Card> options, SpellAbility sa, String title, boolean isOptional) {
|
||||||
ApiType api = sa.getApi();
|
return brains.chooseSingleCardForEffect(options, sa, title, isOptional);
|
||||||
if ( null == api ) {
|
}
|
||||||
throw new InvalidParameterException("SA is not api-based, this is not supported yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(api) {
|
@Override
|
||||||
case Bond: return CardFactoryUtil.getBestCreatureAI(options);
|
public boolean confirmAction(SpellAbility sa, String mode, String message) {
|
||||||
default: throw new InvalidParameterException("AI chooseSingleCard does not know how to choose card for " + api);
|
return brains.confirmAction(sa, mode, message);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,5 +237,13 @@ public class PlayerControllerHuman extends PlayerController {
|
|||||||
return GuiChoose.one(title, options);
|
return GuiChoose.one(title, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.game.player.PlayerController#confirmAction(forge.card.spellability.SpellAbility, java.lang.String, java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean confirmAction(SpellAbility sa, String mode, String message) {
|
||||||
|
return GuiDialog.confirm(sa.getSourceCard(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user