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) { WheneverYouCycleOrDiscard("Whenever you cycle or discard a(nother)? card, " + ARG.EFFECT, 0) {
@Override @Override
protected void addAbilityImpl(final MagicAbilityStore card, final Matcher arg) { 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.ai.ArtificialScoringSystem;
import magic.model.MagicCard; import magic.model.MagicCard;
import magic.model.MagicCardList;
import magic.model.MagicGame; import magic.model.MagicGame;
import magic.model.MagicLocationType;
import magic.model.MagicMessage; import magic.model.MagicMessage;
import magic.model.MagicPlayer; import magic.model.MagicPlayer;
import magic.model.MagicLocationType;
import java.util.List; import java.util.List;

View File

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

View File

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

View File

@ -1,10 +1,12 @@
package magic.model.action; package magic.model.action;
import magic.model.MagicCard; import magic.model.MagicCard;
import magic.model.MagicGame; import magic.model.MagicGame;
import magic.model.MagicPlayer; import magic.model.MagicPlayer;
/**
* This action corresponds to "scry 1" action.
*/
public class ScryAction extends MagicAction { public class ScryAction extends MagicAction {
private final MagicPlayer player; 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; package magic.model.choice;
import java.util.List; /**
import magic.exception.UndoClickedException; * Choice for "scry 1" action.
import magic.model.IUIGameController; */
import magic.model.MagicCardList; public class MagicScryChoice extends MagicTopCardChoice {
import magic.model.MagicGame;
import magic.model.MagicPlayer;
import magic.model.MagicSource;
import magic.model.event.MagicEvent;
public class MagicScryChoice extends MagicMayChoice {
// translatable UI text (prefix with _S). // translatable UI text (prefix with _S).
private static final String _S1 = "Move this card from the top of the library to the bottom?"; private static final String _S1 = "Move this card from the top of the library to the bottom?";
public MagicScryChoice() { public MagicScryChoice() {
super(_S1); 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)); 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( PseudoScry(
"Look at the top card of your library\\. You may put that card on the bottom of your library", "Look at the top card of your library\\. You may put that card on the bottom of your library",
MagicTiming.Draw, MagicTiming.Draw,

View File

@ -17,10 +17,18 @@ public class MagicScryEvent extends MagicEvent {
this(source, player, true); 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) { public static MagicScryEvent Pseudo(final MagicEvent event) {
return new MagicScryEvent(event.getSource(), event.getPlayer(), false); 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) { public static MagicScryEvent Pseudo(final MagicSource source, final MagicPlayer player) {
return new MagicScryEvent(source, player, false); return new MagicScryEvent(source, player, false);
} }

View File

@ -9,6 +9,10 @@ import magic.model.MagicSource;
import magic.model.action.ScryComplAction; import magic.model.action.ScryComplAction;
import magic.model.choice.MagicFromCardListChoice; 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 class MagicScryXEvent extends MagicEvent {
public MagicScryXEvent(final MagicSource source, final MagicPlayer player, final int X) { 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 WhenCycle, // card
WhenOtherCycle, // card WhenOtherCycle, // card
WhenScry, // player WhenScry, // player
WhenSurveil, // player
WhenSacrifice, // RemoveFromPlayAction WhenSacrifice, // RemoveFromPlayAction
IfDamageWouldBeDealt, // item on stack IfDamageWouldBeDealt, // item on stack
IfPlayerWouldLose, // player[] 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);
}
};
}
}