package magic.model.event;
import magic.model.MagicGame;
import magic.model.MagicPlayer;
import magic.model.MagicSource;
import magic.model.phase.MagicPhaseType;
public enum MagicTiming {
// Creature spells
Main("main",5), // Main
FirstMain("fmain",5), // First main : haste, can't block, shroud,
// comes into play, static effect, non tap ability, combat trigger
SecondMain("smain",5), // Second main : defender, non combat or defensive ability, red mana unlikely
Flash("flash",5), // Declare attackers or end of turn from opponent
CounterFlash("counterflash",9), // Like flash, but also when there is a spell of opponent on stack
PumpFlash("pumpFlash",6), // Like flash, but also declare blockers, as response
// Other permanent spells
Land("land",1), // Main
TapLand("tapland",1), // Second main
Enchantment("enchantment",4), // Main
Artifact("artifact",4), // Main
Aura("aura",7), // Main
Equipment("equipment",7), // Main
// Remaining spells & abilities.
Draw("draw",1), // Main
Tapping("tapping",2), // Main, declare attackers or as response
Removal("removal",3), // Main, declare blockers or as response
Pump("pump",8), // First main your turn, declare attackers, declare blockers or as response
Counter("counter",9), // When there is a spell of opponent on stack
Attack("attack",8), // Declare attackers
Block("block",8), // Declare blockers
Animate("animate",6), // First main of your turn, declare attackers opponent's turn
Token("token",6), // First main of your turn, declare attackers or end of turn opponent, as response
NextTurn("nextturn",9), // Second main opponent's turn
MustAttack("mustattack",8), // First main opponent's turn
LoseEvasion("loseEvasion",7), // First main opponent's turn, declare attackers opponent's turn
Spell("spell",9), // When there is a spell on stack
Storm("storm",1), // When a spell was played this turn, second main
// No timing
None("none",0), // No restrictions.
;
private final String code;
private final int priority;
private MagicTiming(final String code,final int priority) {
this.code=code;
this.priority=priority;
}
private String getCode() {
return code;
}
public int getPriority() {
return priority;
}
public boolean canPlay(final MagicGame game,final MagicSource source) {
final MagicPlayer controller=source.getController();
switch (this) {
case Main:
case Land:
case Enchantment:
case Artifact:
case Aura:
case Equipment:
case Draw:
return game.isMainPhase();
case FirstMain:
return game.isPhase(MagicPhaseType.FirstMain);
case SecondMain:
case TapLand:
return game.isPhase(MagicPhaseType.SecondMain);
case NextTurn:
return
game.getTurnPlayer() != controller &&
game.isPhase(MagicPhaseType.SecondMain);
case Flash:
return
game.getTurnPlayer() != controller &&
(game.isPhase(MagicPhaseType.DeclareAttackers) ||
game.isPhase(MagicPhaseType.EndOfTurn)
);
case CounterFlash:
return (game.getTurnPlayer() != controller &&
(game.isPhase(MagicPhaseType.DeclareAttackers) ||
game.isPhase(MagicPhaseType.EndOfTurn)
)
) || game.getStack().containsOpponentSpells(controller);
case PumpFlash:
return (game.getTurnPlayer() != controller &&
(game.isPhase(MagicPhaseType.DeclareAttackers) ||
game.isPhase(MagicPhaseType.EndOfTurn)
)
) ||
game.isPhase(MagicPhaseType.DeclareBlockers) ||
game.getStack().isResponse(controller);
case Tapping:
return game.isMainPhase() ||
game.isPhase(MagicPhaseType.DeclareAttackers) ||
game.getStack().isResponse(controller);
case Removal:
return game.isMainPhase() ||
game.isPhase(MagicPhaseType.DeclareBlockers) ||
game.getStack().isResponse(controller);
case Pump:
return (game.getTurnPlayer()==controller &&
game.isPhase(MagicPhaseType.FirstMain)
) ||
game.isPhase(MagicPhaseType.DeclareBlockers) ||
game.isPhase(MagicPhaseType.DeclareAttackers) ||
game.getStack().isResponse(controller);
case Spell:
return game.getStack().containsSpells();
case Counter:
return game.getStack().containsOpponentSpells(controller);
case Attack:
return game.isPhase(MagicPhaseType.DeclareAttackers);
case Block:
return game.isPhase(MagicPhaseType.DeclareBlockers);
case Animate:
return (game.getTurnPlayer()==controller &&
game.isPhase(MagicPhaseType.FirstMain)
) ||
(game.getTurnPlayer()!=controller &&
game.isPhase(MagicPhaseType.DeclareAttackers)
);
case Token:
return (game.getTurnPlayer()==controller &&
game.isPhase(MagicPhaseType.FirstMain)
) ||
(game.getTurnPlayer()!=controller &&
(game.isPhase(MagicPhaseType.DeclareAttackers) ||
game.isPhase(MagicPhaseType.EndOfTurn)
)
) ||
game.getStack().isResponse(controller);
case MustAttack:
return game.getTurnPlayer()!=controller &&
game.isPhase(MagicPhaseType.FirstMain);
case LoseEvasion:
return game.getTurnPlayer()!=controller &&
(game.isPhase(MagicPhaseType.FirstMain) ||
game.isPhase(MagicPhaseType.DeclareAttackers));
case Storm:
return game.getSpellsCast() > 0 ||
game.isPhase(MagicPhaseType.SecondMain);
default:
return true;
}
}
public static MagicTiming getTimingFor(final String code) {
for (final MagicTiming timing : values()) {
if (timing.getCode().equalsIgnoreCase(code)) {
return timing;
}
}
throw new RuntimeException("unknown timing: \"" + code + "\"");
}
}