Add support for "surveil 1" action and "Whenever you surveil" triggers

master
Bilbo 2018-10-23 22:55:04 +02:00 committed by Melvin Zhang
parent af0f668976
commit 7a29fc561a
15 changed files with 221 additions and 56 deletions

View File

@ -1483,6 +1483,14 @@ public enum MagicAbility {
));
}
},
WhenYouSurveil("Whenever you surveil, " + ARG.EFFECT, 0) {
@Override
protected void addAbilityImpl(final MagicAbilityStore card, final Matcher arg) {
card.add(YouSurveilTrigger.create(
MagicRuleEventAction.create(ARG.effect(arg))
));
}
},
WheneverYouCycleOrDiscard("Whenever you cycle or discard a(nother)? card, " + ARG.EFFECT, 0) {
@Override
protected void addAbilityImpl(final MagicAbilityStore card, final Matcher arg) {

View File

@ -2,11 +2,10 @@ package magic.model.action;
import magic.ai.ArtificialScoringSystem;
import magic.model.MagicCard;
import magic.model.MagicCardList;
import magic.model.MagicGame;
import magic.model.MagicLocationType;
import magic.model.MagicMessage;
import magic.model.MagicPlayer;
import magic.model.MagicLocationType;
import java.util.List;

View File

@ -1,9 +1,6 @@
package magic.model.action;
import magic.model.MagicCard;
import magic.model.MagicCardList;
import magic.model.MagicGame;
import magic.model.MagicLocationType;
import magic.model.MagicPlayer;
import java.util.List;

View File

@ -2,8 +2,6 @@ package magic.model.action;
import magic.model.MagicCard;
import magic.model.MagicCardList;
import magic.model.MagicGame;
import magic.model.MagicLocationType;
import magic.model.MagicPlayer;
import magic.model.MagicType;

View File

@ -1,10 +1,12 @@
package magic.model.action;
import magic.model.MagicCard;
import magic.model.MagicGame;
import magic.model.MagicPlayer;
/**
* This action corresponds to "scry 1" action.
*/
public class ScryAction extends MagicAction {
private final MagicPlayer player;

View File

@ -0,0 +1,30 @@
package magic.model.action;
import magic.model.MagicCard;
import magic.model.MagicGame;
import magic.model.MagicPlayer;
/**
* This action corresponds to "surveil 1" action.
*/
public class SurveilAction extends MagicAction {
private final MagicPlayer player;
private MagicCard card;
public SurveilAction(final MagicPlayer aPlayer) {
player = aPlayer;
}
@Override
public void doAction(final MagicGame game) {
card = player.getLibrary().removeCardAtTop();
player.getGraveyard().addToTop(card);
}
@Override
public void undoAction(final MagicGame game) {
player.getGraveyard().removeCardAtTop();
player.getLibrary().addToTop(card);
}
}

View File

@ -1,57 +1,13 @@
package magic.model.choice;
import java.util.List;
import magic.exception.UndoClickedException;
import magic.model.IUIGameController;
import magic.model.MagicCardList;
import magic.model.MagicGame;
import magic.model.MagicPlayer;
import magic.model.MagicSource;
import magic.model.event.MagicEvent;
public class MagicScryChoice extends MagicMayChoice {
/**
* Choice for "scry 1" action.
*/
public class MagicScryChoice extends MagicTopCardChoice {
// translatable UI text (prefix with _S).
private static final String _S1 = "Move this card from the top of the library to the bottom?";
public MagicScryChoice() {
super(_S1);
}
@Override
public List<Object[]> getArtificialChoiceResults(final MagicGame game, final MagicEvent event) {
final MagicPlayer player = event.getPlayer();
if (player.getLibrary().isEmpty()) {
return NO_CHOICE_LIST;
} else {
return NO_OTHER_CHOICE_RESULTS;
}
}
@Override
public Object[] getPlayerChoiceResults(final IUIGameController controller, final MagicGame game, final MagicEvent event) throws UndoClickedException {
final MagicPlayer player = event.getPlayer();
final MagicSource source = event.getSource();
final Object[] choiceResults=new Object[1];
choiceResults[0]=NO_CHOICE;
if (player.getLibrary().isEmpty()) {
return choiceResults;
}
final MagicCardList cards = new MagicCardList();
cards.add(player.getLibrary().getCardAtTop());
controller.showCardsToChoose(cards);
controller.disableActionButton(false);
if (controller.getMayChoice(source, getDescription())) {
choiceResults[0]=YES_CHOICE;
}
controller.clearCardsToChoose();
return choiceResults;
}
}

View File

@ -0,0 +1,13 @@
package magic.model.choice;
/**
* Choice for "surveil 1" action.
*/
public class MagicSurveilChoice extends MagicTopCardChoice {
// translatable UI text (prefix with _S).
private static final String _S1 = "Move this card from the top of the library to your graveyard?";
public MagicSurveilChoice() {
super(_S1);
}
}

View File

@ -0,0 +1,58 @@
package magic.model.choice;
import java.util.List;
import magic.exception.UndoClickedException;
import magic.model.IUIGameController;
import magic.model.MagicCardList;
import magic.model.MagicGame;
import magic.model.MagicPlayer;
import magic.model.MagicSource;
import magic.model.event.MagicEvent;
/**
* Choice about top card of player's library. Used for 'scry 1' and 'surveil 1'.
*/
public class MagicTopCardChoice extends MagicMayChoice {
public MagicTopCardChoice(final String description) {
super(description);
}
@Override
public List<Object[]> getArtificialChoiceResults(final MagicGame game, final MagicEvent event) {
final MagicPlayer player = event.getPlayer();
if (player.getLibrary().isEmpty()) {
return NO_CHOICE_LIST;
} else {
return NO_OTHER_CHOICE_RESULTS;
}
}
@Override
public Object[] getPlayerChoiceResults(final IUIGameController controller, final MagicGame game,
final MagicEvent event) throws UndoClickedException {
final MagicPlayer player = event.getPlayer();
final MagicSource source = event.getSource();
final Object[] choiceResults = new Object[1];
choiceResults[0] = NO_CHOICE;
if (player.getLibrary().isEmpty()) {
return choiceResults;
}
final MagicCardList cards = new MagicCardList();
cards.add(player.getLibrary().getCardAtTop());
controller.showCardsToChoose(cards);
controller.disableActionButton(false);
if (controller.getMayChoice(source, getDescription())) {
choiceResults[0] = YES_CHOICE;
}
controller.clearCardsToChoose();
return choiceResults;
}
}

View File

@ -2223,6 +2223,16 @@ public enum MagicRuleEventAction {
return (game, event) -> game.addEvent(new MagicScryEvent(event));
}
},
Surveil1(
"(pn )?surveil 1",
MagicTiming.Draw,
"Surveil"
) {
@Override
public MagicEventAction getAction(final Matcher matcher) {
return (game, event) -> game.addEvent(new MagicSurveilEvent(event));
}
},
PseudoScry(
"Look at the top card of your library\\. You may put that card on the bottom of your library",
MagicTiming.Draw,

View File

@ -17,10 +17,18 @@ public class MagicScryEvent extends MagicEvent {
this(source, player, true);
}
/**
* Pseudo-scry event is used for example as part of Clash action.
* As it is not a true "scry" event, it will not trigger "when scry" actions.
*/
public static MagicScryEvent Pseudo(final MagicEvent event) {
return new MagicScryEvent(event.getSource(), event.getPlayer(), false);
}
/**
* Pseudo-scry event is used for example as part of Clash action.
* As it is not a true "scry" event, it will not trigger "when scry" actions.
*/
public static MagicScryEvent Pseudo(final MagicSource source, final MagicPlayer player) {
return new MagicScryEvent(source, player, false);
}

View File

@ -9,6 +9,10 @@ import magic.model.MagicSource;
import magic.model.action.ScryComplAction;
import magic.model.choice.MagicFromCardListChoice;
/**
* General "Scry X" effect.
* Not used (commented out in MagicRuleEventAction), as there are too many choices for AI potentially to make
*/
public class MagicScryXEvent extends MagicEvent {
public MagicScryXEvent(final MagicSource source, final MagicPlayer player, final int X) {

View File

@ -0,0 +1,47 @@
package magic.model.event;
import magic.model.MagicGame;
import magic.model.MagicPlayer;
import magic.model.MagicSource;
import magic.model.action.SurveilAction;
import magic.model.choice.MagicSurveilChoice;
import magic.model.trigger.MagicTriggerType;
public class MagicSurveilEvent extends MagicEvent {
public MagicSurveilEvent(final MagicEvent event) {
this(event.getSource(), event.getPlayer(), true);
}
public MagicSurveilEvent(final MagicSource source, final MagicPlayer player) {
this(source, player, true);
}
private MagicSurveilEvent(final MagicSource source, final MagicPlayer player, final boolean trigger) {
super(
source,
player,
new MagicSurveilChoice(),
trigger ? 1 : 0,
EventAction,
""
);
}
private static final MagicEventAction EventAction = (final MagicGame game, final MagicEvent event) -> {
final boolean trigger = event.getRefInt() == 1;
final MagicPlayer p = event.getPlayer();
if (event.isYes()) {
game.logAppendMessage(p,
p + " looks at the top card of his or her library and puts it to his or her graveyard.");
game.doAction(new SurveilAction(p));
} else {
game.logAppendMessage(p, p + " looks at the top card of his or her library and puts it back on top.");
}
// Surveil triggers even if the card is not moved or library is empty.
// Only once regardless of amount of cards surveiled
if (trigger) {
game.executeTrigger(MagicTriggerType.WhenSurveil, p);
}
};
}

View File

@ -37,6 +37,7 @@ public enum MagicTriggerType {
WhenCycle, // card
WhenOtherCycle, // card
WhenScry, // player
WhenSurveil, // player
WhenSacrifice, // RemoveFromPlayAction
IfDamageWouldBeDealt, // item on stack
IfPlayerWouldLose, // player[]

View File

@ -0,0 +1,34 @@
package magic.model.trigger;
import magic.model.MagicGame;
import magic.model.MagicPermanent;
import magic.model.MagicPlayer;
import magic.model.event.MagicEvent;
import magic.model.event.MagicSourceEvent;
public abstract class YouSurveilTrigger extends MagicTrigger<MagicPlayer> {
public YouSurveilTrigger(final int priority) {
super(priority);
}
public YouSurveilTrigger() {}
@Override
public MagicTriggerType getType() {
return MagicTriggerType.WhenSurveil;
}
@Override
public boolean accept(final MagicPermanent permanent, final MagicPlayer player) {
return permanent.isFriend(player);
}
public static YouSurveilTrigger create(final MagicSourceEvent sourceEvent) {
return new YouSurveilTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent, final MagicPlayer player) {
return sourceEvent.getTriggerEvent(permanent);
}
};
}
}