Refactor PutCards to address issue #9643 (#9644)

This commit is contained in:
Alex W. Jackson 2022-10-14 01:07:14 -04:00 committed by GitHub
parent 332db3aecb
commit 5e891f50c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 69 additions and 48 deletions

View file

@ -144,8 +144,8 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
}
protected boolean actionWithPickedCards(Game game, Ability source, Player player, Cards pickedCards, Cards otherCards) {
boolean result = moveCards(game, source, player, pickedCards, putPickedCards);
result |= moveCards(game, source, player, otherCards, putLookedCards);
boolean result = putPickedCards.moveCards(player, pickedCards, source, game);
result |= putLookedCards.moveCards(player, otherCards, source, game);
return result;
}

View file

@ -82,22 +82,7 @@ public class LookLibraryControllerEffect extends OneShotEffect {
}
protected boolean actionWithLookedCards(Game game, Ability source, Player player, Cards cards) {
return moveCards(game, source, player, cards, putLookedCards);
}
protected static boolean moveCards(Game game, Ability source, Player player, Cards cards, PutCards putCards) {
switch (putCards) {
case TOP_ANY:
return player.putCardsOnTopOfLibrary(cards, game, source, true);
case BOTTOM_ANY:
return player.putCardsOnBottomOfLibrary(cards, game, source, true);
case BOTTOM_RANDOM:
return player.putCardsOnBottomOfLibrary(cards, game, source, false);
case BATTLEFIELD_TAPPED:
return player.moveCards(cards.getCards(game), Zone.BATTLEFIELD, source, game, true, false, false, null);
default:
return player.moveCards(cards, putCards.getZone(), source, game);
}
return putLookedCards.moveCards(player, cards, source, game);
}
@Override

View file

@ -1,5 +1,12 @@
package mage.constants;
import mage.abilities.Ability;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author awjackson
@ -46,4 +53,55 @@ public enum PutCards {
String message = owner ? messageOwner : messageYour;
return withOrder ? message + order : message;
}
public boolean moveCard(Player player, Card card, Ability source, Game game, String description) {
switch (this) {
case TOP_OR_BOTTOM:
if (player.chooseUse(Outcome.Neutral,
"Put the " + description + " on the top or bottom of its owner's library?",
null, "Top", "Bottom", source, game
)) {
return player.putCardsOnTopOfLibrary(new CardsImpl(card), game, source, true);
} else {
return player.putCardsOnBottomOfLibrary(new CardsImpl(card), game, source, true);
}
case TOP_ANY:
return player.putCardsOnTopOfLibrary(new CardsImpl(card), game, source, true);
case BOTTOM_ANY:
return player.putCardsOnBottomOfLibrary(new CardsImpl(card), game, source, true);
case BOTTOM_RANDOM:
return player.putCardsOnBottomOfLibrary(new CardsImpl(card), game, source, false);
case BATTLEFIELD_TAPPED:
return player.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null);
case BATTLEFIELD:
case EXILED:
case HAND:
case GRAVEYARD:
return player.moveCards(card, this.zone, source, game);
default:
throw new UnsupportedOperationException("Missing case for " + this.name() + "in PutCards.moveCard");
}
}
public boolean moveCards(Player player, Cards cards, Ability source, Game game) {
switch (this) {
case TOP_OR_BOTTOM:
throw new UnsupportedOperationException("PutCards.TOP_OR_BOTTOM does not support moving multiple cards");
case TOP_ANY:
return player.putCardsOnTopOfLibrary(cards, game, source, true);
case BOTTOM_ANY:
return player.putCardsOnBottomOfLibrary(cards, game, source, true);
case BOTTOM_RANDOM:
return player.putCardsOnBottomOfLibrary(cards, game, source, false);
case BATTLEFIELD_TAPPED:
return player.moveCards(cards.getCards(game), Zone.BATTLEFIELD, source, game, true, false, false, null);
case BATTLEFIELD:
case EXILED:
case HAND:
case GRAVEYARD:
return player.moveCards(cards, this.zone, source, game);
default:
throw new UnsupportedOperationException("Missing case for " + this.name() + "in PutCards.moveCards");
}
}
}

View file

@ -65,7 +65,8 @@ public class GameEvent implements Serializable {
//player events
/* ZONE_CHANGE
targetId id of the zone changing object
sourceId sourceId of the ability with the object moving effect (WARNING, can be null if it move of fizzled spells)
sourceId sourceId of the ability with the object moving effect
WARNING: can be null if moved by game rules (e.g. draw in draw step, discard in cleanup step, fizzled spell)
playerId controller of the moved object
amount not used for this event
flag not used for this event

View file

@ -417,7 +417,7 @@ public class Spell extends StackObjectImpl implements Card {
}
@Override
public void counter(Ability source, Game game, PutCards zone) {
public void counter(Ability source, Game game, PutCards putCard) {
// source can be null for fizzled spells, don't use that code in your ZONE_CHANGE watchers/triggers:
// event.getSourceId().equals
// TODO: fizzled spells are no longer considered "countered" as of current rules; may need refactor
@ -429,30 +429,7 @@ public class Spell extends StackObjectImpl implements Card {
}
Player player = game.getPlayer(source == null ? getControllerId() : source.getControllerId());
if (player != null) {
switch (zone) {
case TOP_OR_BOTTOM:
if (player.chooseUse(Outcome.Detriment,
"Put the countered spell on the top or bottom of its owner's library?",
null, "Top", "Bottom", source, game
)) {
player.putCardsOnTopOfLibrary(new CardsImpl(card), game, source, false);
} else {
player.putCardsOnBottomOfLibrary(new CardsImpl(card), game, source, false);
}
break;
case TOP_ANY:
player.putCardsOnTopOfLibrary(new CardsImpl(card), game, source, false);
break;
case BOTTOM_ANY:
case BOTTOM_RANDOM:
player.putCardsOnBottomOfLibrary(new CardsImpl(card), game, source, false);
break;
case BATTLEFIELD_TAPPED:
player.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null);
break;
default:
player.moveCards(card, zone.getZone(), source, game);
}
putCard.moveCard(player, card, source, game, "countered spell");
}
}

View file

@ -62,7 +62,7 @@ public class SpellStack extends ArrayDeque<StackObject> {
return counter(objectId, source, game, PutCards.GRAVEYARD);
}
public boolean counter(UUID objectId, Ability source, Game game, PutCards zone) {
public boolean counter(UUID objectId, Ability source, Game game, PutCards putCard) {
StackObject stackObject = getStackObject(objectId);
MageObject sourceObject = game.getObject(source);
if (stackObject != null && sourceObject != null) {
@ -82,7 +82,7 @@ public class SpellStack extends ArrayDeque<StackObject> {
if (!(stackObject instanceof Spell)) { // spells are removed from stack by the card movement
this.remove(stackObject, game);
}
stackObject.counter(source, game, zone);
stackObject.counter(source, game, putCard);
if (!game.isSimulation()) {
game.informPlayers(counteredObjectName + " is countered by " + sourceObject.getLogName());
}

View file

@ -109,7 +109,7 @@ public class StackAbility extends StackObjectImpl implements Ability {
}
@Override
public void counter(Ability source, Game game, PutCards zone) {
public void counter(Ability source, Game game, PutCards putCard) {
//20100716 - 603.8
if (ability instanceof StateTriggeredAbility) {
((StateTriggeredAbility) ability).counter(game);

View file

@ -24,7 +24,7 @@ public interface StackObject extends MageObject, Controllable {
*/
void counter(Ability source, Game game);
void counter(Ability source, Game game, PutCards zone);
void counter(Ability source, Game game, PutCards putCard);
Ability getStackAbility();