use of mage.abilities.common.SimpleStaticAbility in project mage by magefree.
the class SystemUtil method addCardsForTesting.
/**
* Replaces cards in player's hands by specified in config/init.txt.<br/>
* <br/>
* <b>Implementation note:</b><br/>
* 1. Read init.txt line by line<br/>
* 2. Parse line using for searching groups like: [group 1] 3. Parse line
* using the following format: line ::=
* <zone>:<nickname>:<card name>:<amount><br/>
* 4. If zone equals to 'hand', add card to player's library<br/>
* 5a. Then swap added card with any card in player's hand<br/>
* 5b. Parse next line (go to 2.), If EOF go to 4.<br/>
* 6. Log message to all players that cards were added (to prevent unfair
* play).<br/>
* 7. Exit<br/>
*
* @param game
*/
public static void addCardsForTesting(Game game, String fileSource, Player feedbackPlayer) {
// fake test ability for triggers and events
Ability fakeSourceAbilityTemplate = new SimpleStaticAbility(Zone.OUTSIDE, new InfoEffect("adding testing cards"));
fakeSourceAbilityTemplate.setControllerId(feedbackPlayer.getId());
try {
String fileName = fileSource;
if (fileName == null) {
fileName = INIT_FILE_PATH;
}
File f = new File(fileName);
if (!f.exists()) {
logger.warn("Couldn't find init file: " + fileName);
return;
}
logger.info("Parsing init file... ");
// steps:
// 1. parse groups and commands
// 2. ask user if many groups
// 3. process system commands
// 4. run commands from selected group
// 1. parse
List<CommandGroup> groups = new ArrayList<>();
try (Scanner scanner = new Scanner(f)) {
CommandGroup currentGroup = null;
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
// skip comments
if (line.isEmpty() || line.startsWith("#") || line.startsWith("//")) {
continue;
}
// group
Matcher matchGroup = patternGroup.matcher(line);
if (matchGroup.matches()) {
String groupName = matchGroup.group(1);
if (groupName.startsWith("@")) {
// special command group
if (supportedCommands.containsKey(groupName)) {
currentGroup = new CommandGroup(groupName, true);
groups.add(currentGroup);
} else {
logger.warn("Special group [" + groupName + "] is not supported.");
}
continue;
} else {
// basic group
currentGroup = new CommandGroup(groupName);
groups.add(currentGroup);
continue;
}
}
// command
if (currentGroup == null) {
currentGroup = new CommandGroup("default group");
groups.add(currentGroup);
}
currentGroup.commands.add(line);
}
}
// 2. ask user
CommandGroup runGroup = null;
if (groups.size() == 1) {
// not need to ask
runGroup = groups.get(0);
} else if (groups.size() > 1) {
// need to ask
logger.info("Found " + groups.size() + " groups. Need to select.");
// choice dialog
Map<String, String> list = new LinkedHashMap<>();
Map<String, Integer> sort = new LinkedHashMap<>();
for (int i = 0; i < groups.size(); i++) {
list.put(Integer.toString(i + 1), groups.get(i).getPrintNameWithStats());
sort.put(Integer.toString(i + 1), i);
}
Choice groupChoice = new ChoiceImpl(false);
groupChoice.setMessage("Choose commands group to run");
groupChoice.setKeyChoices(list);
groupChoice.setSortData(sort);
if (feedbackPlayer.choose(Outcome.Benefit, groupChoice, game)) {
String need = groupChoice.getChoiceKey();
if ((need != null) && list.containsKey(need)) {
runGroup = groups.get(Integer.parseInt(need) - 1);
}
}
}
if (runGroup == null) {
// was canceled
logger.info("Command file was empty or canceled");
return;
}
logger.info("Selected group [" + runGroup.name + "] with " + runGroup.commands.size() + " commands");
// 3. system commands
if (runGroup.isSpecialCommand) {
Player opponent = game.getPlayer(game.getOpponents(feedbackPlayer.getId()).stream().findFirst().orElse(null));
String info;
switch(runGroup.name) {
case COMMAND_SHOW_OPPONENT_HAND:
if (opponent != null) {
info = getCardsListForSpecialInform(game, opponent.getHand(), runGroup.commands);
game.informPlayer(feedbackPlayer, info);
}
break;
case COMMAND_SHOW_OPPONENT_LIBRARY:
if (opponent != null) {
info = getCardsListForSpecialInform(game, opponent.getLibrary().getCardList(), runGroup.commands);
game.informPlayer(feedbackPlayer, info);
}
break;
case COMMAND_SHOW_MY_HAND:
info = getCardsListForSpecialInform(game, feedbackPlayer.getHand(), runGroup.commands);
game.informPlayer(feedbackPlayer, info);
break;
case COMMAND_SHOW_MY_LIBRARY:
info = getCardsListForSpecialInform(game, feedbackPlayer.getLibrary().getCardList(), runGroup.commands);
game.informPlayer(feedbackPlayer, info);
break;
case COMMAND_ACTIVATE_OPPONENT_ABILITY:
// WARNING, maybe very bugged if called in wrong priority
// uses choose triggered ability dialog to select it
UUID savedPriorityPlayer = null;
if (game.getActivePlayerId() != opponent.getId()) {
savedPriorityPlayer = game.getActivePlayerId();
}
// change active player to find and play selected abilities (it's danger and buggy code)
if (savedPriorityPlayer != null) {
game.getState().setPriorityPlayerId(opponent.getId());
game.firePriorityEvent(opponent.getId());
}
List<ActivatedAbility> abilities = opponent.getPlayable(game, true);
Map<String, String> choices = new HashMap<>();
abilities.forEach(ability -> {
MageObject object = ability.getSourceObject(game);
choices.put(ability.getId().toString(), object.getName() + ": " + ability.toString());
});
// TODO: set priority for us?
Choice choice = new ChoiceImpl();
choice.setMessage("Choose playable ability to activate by opponent " + opponent.getName());
choice.setKeyChoices(choices);
if (feedbackPlayer.choose(Outcome.Detriment, choice, game) && choice.getChoiceKey() != null) {
String needId = choice.getChoiceKey();
Optional<ActivatedAbility> ability = abilities.stream().filter(a -> a.getId().toString().equals(needId)).findFirst();
if (ability.isPresent()) {
// TODO: set priority for player?
ActivatedAbility activatedAbility = ability.get();
game.informPlayers(feedbackPlayer.getLogName() + " as another player " + opponent.getLogName() + " trying to force an activate ability: " + activatedAbility.getGameLogMessage(game));
if (opponent.activateAbility(activatedAbility, game)) {
game.informPlayers("Force to activate ability: DONE");
} else {
game.informPlayers("Force to activate ability: FAIL");
}
}
}
// restore original priority player
if (savedPriorityPlayer != null) {
game.getState().setPriorityPlayerId(savedPriorityPlayer);
game.firePriorityEvent(savedPriorityPlayer);
}
break;
}
return;
}
// insert group refs as extra commands (only user defined groups allowed, no special)
Map<String, CommandGroup> otherGroupRefs = new HashMap<>();
for (CommandGroup group : groups) {
if (group != runGroup) {
otherGroupRefs.putIfAbsent(COMMAND_REF_PREFIX + group.name, group);
}
}
for (int i = runGroup.commands.size() - 1; i >= 0; i--) {
String line = runGroup.commands.get(i);
// replace ref by real commands from another group
if (line.startsWith(COMMAND_REF_PREFIX)) {
CommandGroup other = otherGroupRefs.getOrDefault(line, null);
if (other != null && !other.isSpecialCommand) {
logger.info("Replace ref group " + line + " by " + other.commands.size() + " commands");
runGroup.commands.remove(i);
runGroup.commands.addAll(i, other.commands);
} else {
logger.error("Can't find ref group: " + line);
}
}
}
// 4. run commands
for (String line : runGroup.commands) {
CardCommandData command = parseCardCommand(line);
if (!command.OK) {
logger.warn(command.Error + ": " + line);
continue;
}
Optional<Player> playerOptional = findPlayer(game, command.player);
if (!playerOptional.isPresent()) {
logger.warn("Unknown player: " + line);
continue;
}
Player player = playerOptional.get();
// SPECIAL token/emblem call (without SET name)
if ("token".equalsIgnoreCase(command.zone)) {
// eg: token:Human:HippoToken:1
Class<?> c = Class.forName("mage.game.permanent.token." + command.cardName);
Constructor<?> cons = c.getConstructor();
Object obj = cons.newInstance();
if (obj instanceof Token) {
Token token = (Token) obj;
Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy();
fakeSourceAbility.setSourceId(token.getId());
token.putOntoBattlefield(command.Amount, game, fakeSourceAbility, player.getId(), false, false);
continue;
}
} else if ("emblem".equalsIgnoreCase(command.zone)) {
// eg: emblem:Human:ElspethSunsChampionEmblem:1
Class<?> c = Class.forName("mage.game.command.emblems." + command.cardName);
Constructor<?> cons = c.getConstructor();
Object emblem = cons.newInstance();
if (emblem instanceof mage.game.command.Emblem) {
((mage.game.command.Emblem) emblem).setControllerId(player.getId());
game.addEmblem((mage.game.command.Emblem) emblem, null, player.getId());
continue;
}
} else if ("plane".equalsIgnoreCase(command.zone)) {
if (putPlaneToGame(game, player, command.cardName)) {
continue;
}
} else if ("loyalty".equalsIgnoreCase(command.zone)) {
for (Permanent perm : game.getBattlefield().getAllActivePermanents(player.getId())) {
if (perm.getName().equals(command.cardName) && perm.getCardType(game).contains(CardType.PLANESWALKER)) {
Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy();
fakeSourceAbility.setSourceId(perm.getId());
perm.addCounters(CounterType.LOYALTY.createInstance(command.Amount), fakeSourceAbility.getControllerId(), fakeSourceAbility, game);
}
}
continue;
} else if ("stack".equalsIgnoreCase(command.zone)) {
// simple cast (without targets or modes)
// find card info
CardInfo cardInfo = CardRepository.instance.findCard(command.cardName);
if (cardInfo == null) {
logger.warn("Unknown card for stack command [" + command.cardName + "]: " + line);
continue;
}
// put card to game
Set<Card> cardsToLoad = new HashSet<>();
for (int i = 0; i < command.Amount; i++) {
cardsToLoad.add(cardInfo.getCard());
}
game.loadCards(cardsToLoad, player.getId());
// move card from exile to stack
for (Card card : cardsToLoad) {
Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy();
fakeSourceAbility.setSourceId(card.getId());
putCardToZone(fakeSourceAbility, game, player, card, Zone.STACK);
}
continue;
}
Zone gameZone;
if ("hand".equalsIgnoreCase(command.zone)) {
gameZone = Zone.HAND;
} else if ("battlefield".equalsIgnoreCase(command.zone)) {
gameZone = Zone.BATTLEFIELD;
} else if ("graveyard".equalsIgnoreCase(command.zone)) {
gameZone = Zone.GRAVEYARD;
} else if ("library".equalsIgnoreCase(command.zone)) {
gameZone = Zone.LIBRARY;
} else if ("token".equalsIgnoreCase(command.zone)) {
gameZone = Zone.BATTLEFIELD;
} else if ("exiled".equalsIgnoreCase(command.zone)) {
gameZone = Zone.EXILED;
} else if ("outside".equalsIgnoreCase(command.zone)) {
gameZone = Zone.OUTSIDE;
} else if ("emblem".equalsIgnoreCase(command.zone)) {
gameZone = Zone.COMMAND;
} else if ("plane".equalsIgnoreCase(command.zone)) {
gameZone = Zone.COMMAND;
} else if ("commander".equalsIgnoreCase(command.zone)) {
gameZone = Zone.COMMAND;
} else if ("sideboard".equalsIgnoreCase(command.zone)) {
gameZone = Zone.OUTSIDE;
} else {
logger.warn("Unknown zone [" + command.zone + "]: " + line);
continue;
}
List<CardInfo> cards = null;
if (command.cardSet.isEmpty()) {
// by name
cards = CardRepository.instance.findCards(command.cardName);
} else {
// by name and set
cards = CardRepository.instance.findCards(new CardCriteria().setCodes(command.cardSet).name(command.cardName));
}
if (cards.isEmpty()) {
logger.warn("Unknown card [" + command.cardName + "]: " + line);
continue;
}
Set<Card> cardsToLoad = new HashSet<>();
for (int i = 0; i < command.Amount; i++) {
CardInfo cardInfo = cards.get(RandomUtil.nextInt(cards.size()));
Card card = cardInfo != null ? cardInfo.getCard() : null;
if (card != null) {
cardsToLoad.add(card);
}
}
game.loadCards(cardsToLoad, player.getId());
if ("commander".equalsIgnoreCase(command.zone) && cardsToLoad.size() > 0) {
// as commander (only commander games, look at init code in GameCommanderImpl)
if (game instanceof GameCommanderImpl) {
GameCommanderImpl gameCommander = (GameCommanderImpl) game;
cardsToLoad.forEach(card -> gameCommander.addCommander(card, player));
cardsToLoad.forEach(card -> gameCommander.initCommander(card, player));
} else {
logger.fatal("Commander card can be used in commander game only: " + command.cardName);
}
} else if ("sideboard".equalsIgnoreCase(command.zone) && cardsToLoad.size() > 0) {
// put to sideboard
for (Card card : cardsToLoad) {
player.getSideboard().add(card);
}
} else {
// as other card
for (Card card : cardsToLoad) {
Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy();
fakeSourceAbility.setSourceId(card.getId());
putCardToZone(fakeSourceAbility, game, player, card, gameZone);
}
}
}
} catch (Exception e) {
logger.fatal("", e);
}
}
use of mage.abilities.common.SimpleStaticAbility in project mage by magefree.
the class DollhouseOfHorrorsEffect method apply.
@Override
public boolean apply(Game game, Ability source) {
Card card = game.getCard(getTargetPointer().getFirst(game, source));
if (card == null) {
return false;
}
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), CardType.ARTIFACT, false, 1, false, false, null, 0, 0, false);
effect.setSavedPermanent(new PermanentCard(card, source.getControllerId(), game));
effect.setAdditionalSubType(SubType.CONSTRUCT);
effect.addAdditionalAbilities(new SimpleStaticAbility(new BoostSourceEffect(ArtifactYouControlCount.instance, ArtifactYouControlCount.instance, Duration.WhileOnBattlefield).setText("This creature gets +1/+1 for each artifact you control")));
effect.apply(game, source);
game.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn).setTargetPointer(new FixedTargets(effect.getAddedPermanents(), game)), source);
return true;
}
use of mage.abilities.common.SimpleStaticAbility in project mage by magefree.
the class VesuvanDoppelgangerCopyEffect method apply.
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent == null) {
permanent = game.getPermanentEntering(source.getSourceId());
}
final Permanent sourcePermanent = permanent;
if (controller != null && sourcePermanent != null) {
Target target = new TargetPermanent(new FilterCreaturePermanent("target creature (you copy from)"));
target.setRequired(true);
if (source instanceof SimpleStaticAbility) {
target = new TargetPermanent(new FilterCreaturePermanent("creature (you copy from)"));
target.setRequired(false);
target.setNotTarget(true);
}
if (target.canChoose(source.getSourceId(), source.getControllerId(), game)) {
controller.choose(Outcome.Copy, target, source.getSourceId(), game);
Permanent copyFromPermanent = game.getPermanent(target.getFirstTarget());
if (copyFromPermanent != null) {
game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new CopyApplier() {
@Override
public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) {
blueprint.getColor().setColor(sourcePermanent.getColor(game));
blueprint.getAbilities().add(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new VesuvanDoppelgangerCopyEffect(), TargetController.YOU, true, false, rule2));
return true;
}
});
return true;
}
}
}
return false;
}
use of mage.abilities.common.SimpleStaticAbility in project mage by magefree.
the class EndOfTurnMultiOpponentsTest method test_UntilEndOfYourNextTurnMulti.
@Test
public void test_UntilEndOfYourNextTurnMulti() {
// Player order: A -> D -> C -> B
addCustomCardWithAbility("boost1", playerA, new SimpleStaticAbility(Zone.ALL, new BoostAllEffect(1, 1, Duration.UntilEndOfYourNextTurn)));
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilEndOfYourNextTurn effect", 1, playerA, true, PhaseStep.END_TURN);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilEndOfYourNextTurn effect", 2, playerD, true, PhaseStep.END_TURN);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilEndOfYourNextTurn effect", 3, playerC, true, PhaseStep.END_TURN);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilEndOfYourNextTurn effect", 4, playerB, true, PhaseStep.END_TURN);
//
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilEndOfYourNextTurn effect", 5, playerA, true, PhaseStep.END_TURN);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilEndOfYourNextTurn effect", 6, playerD, true, null);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilEndOfYourNextTurn effect", 7, playerC, true, null);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilEndOfYourNextTurn effect", 8, playerB, true, null);
//
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilEndOfYourNextTurn effect", 9, playerA, true, null);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilEndOfYourNextTurn effect", 10, playerD, true, null);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilEndOfYourNextTurn effect", 11, playerC, true, null);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilEndOfYourNextTurn effect", 12, playerB, true, null);
addCard(Zone.BATTLEFIELD, playerA, cardBear2, 1);
addCard(Zone.BATTLEFIELD, playerB, cardBear2, 1);
addCard(Zone.BATTLEFIELD, playerC, cardBear2, 1);
addCard(Zone.BATTLEFIELD, playerD, cardBear2, 1);
attack(1, playerA, cardBear2);
attack(2, playerD, cardBear2);
attack(3, playerC, cardBear2);
attack(4, playerB, cardBear2);
//
attack(5, playerA, cardBear2);
attack(6, playerD, cardBear2);
attack(7, playerC, cardBear2);
attack(8, playerB, cardBear2);
//
attack(9, playerA, cardBear2);
attack(10, playerD, cardBear2);
attack(11, playerC, cardBear2);
attack(12, playerB, cardBear2);
setStopAt(12, PhaseStep.CLEANUP);
setStrictChooseMode(true);
execute();
assertAllCommandsUsed();
}
use of mage.abilities.common.SimpleStaticAbility in project mage by magefree.
the class EndOfTurnMultiOpponentsTest method test_UntilYourNextTurnMulti_Leaved.
// leaved players
// 800.4i When a player leaves the game, any continuous effects with durations that last until that player's next turn
// or until a specific point in that turn will last until that turn would have begun.
// They neither expire immediately nor last indefinitely.
@Test
public void test_UntilYourNextTurnMulti_Leaved() {
// Player order: A -> D -> C -> B
addCustomCardWithAbility("boost1", playerA, new SimpleStaticAbility(Zone.ALL, new BoostAllEffect(1, 1, Duration.UntilYourNextTurn)));
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilYourNextTurn effect", 1, playerA, true, PhaseStep.END_TURN);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilYourNextTurn effect", 2, playerD, true, PhaseStep.END_TURN);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilYourNextTurn effect", 3, playerC, true, PhaseStep.END_TURN);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilYourNextTurn effect", 4, playerB, true, PhaseStep.END_TURN);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilYourNextTurn effect", 5, playerD, true, null);
addCard(Zone.BATTLEFIELD, playerA, cardBear2, 1);
addCard(Zone.BATTLEFIELD, playerB, cardBear2, 1);
addCard(Zone.BATTLEFIELD, playerC, cardBear2, 1);
addCard(Zone.BATTLEFIELD, playerD, cardBear2, 1);
//
// When Eye of Doom enters the battlefield, each player chooses a nonland permanent and puts a doom counter on it.
addCard(Zone.HAND, playerC, "Eye of Doom", 1);
addCard(Zone.BATTLEFIELD, playerC, "Forest", 4);
checkPlayerInGame("A must plays in 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerA, true);
attack(1, playerA, cardBear2);
checkPlayerInGame("A must plays in 2", 2, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, true);
attack(2, playerD, cardBear2);
checkPlayerInGame("A must plays in 3 before", 3, PhaseStep.PRECOMBAT_MAIN, playerC, playerA, true);
attack(3, playerC, cardBear2);
concede(3, PhaseStep.PRECOMBAT_MAIN, playerA);
checkPlayerInGame("A must leaved in 3 after", 3, PhaseStep.POSTCOMBAT_MAIN, playerC, playerA, false);
// test PlayerList.getNext processing
// play Eye of Doom, ask all players to put doom counter
castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerC, "Eye of Doom");
addTarget(playerC, cardBear2);
addTarget(playerB, cardBear2);
// addTarget(playerA, cardBear2); // leaved
addTarget(playerD, cardBear2);
checkPlayerInGame("A must leaved in 4", 4, PhaseStep.POSTCOMBAT_MAIN, playerB, playerA, false);
attack(4, playerB, cardBear2);
checkPlayerInGame("A must leaved in 5", 5, PhaseStep.POSTCOMBAT_MAIN, playerD, playerA, false);
attack(5, playerD, cardBear2);
setStopAt(5, PhaseStep.CLEANUP);
setStrictChooseMode(true);
execute();
assertAllCommandsUsed();
}
Aggregations