Search in sources :

Example 16 with Ability

use of mage.abilities.Ability in project mage by magefree.

the class LevelerCardBuilder method construct.

/**
 * Add abilities to card to enable switching between levels.
 *
 * @param card
 * @param levelAbilities
 * @return list of levelAbilities to add to card
 */
public static List<Ability> construct(LevelAbility... levelAbilities) {
    LevelerCardBuilder builder = new LevelerCardBuilder();
    List<Ability> abilities = new ArrayList<>();
    for (LevelAbility levelAbility : levelAbilities) {
        // set main params
        builder = builder.reset().setLevel1(levelAbility.getLevel1()).setLevel2(levelAbility.getLevel2() == -1 ? Integer.MAX_VALUE : levelAbility.getLevel2()).setPower(levelAbility.getPower()).setToughness(levelAbility.getToughness()).setRule(levelAbility.getRule());
        // set abilities that give the next level
        for (Ability addedAbility : levelAbility.getAbilities()) {
            builder.addAbility(addedAbility);
        }
        // build static abilities and add them to list
        abilities.addAll(builder.build());
    }
    return abilities;
}
Also used : SimpleStaticAbility(mage.abilities.common.SimpleStaticAbility) Ability(mage.abilities.Ability) ArrayList(java.util.ArrayList)

Example 17 with Ability

use of mage.abilities.Ability 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);
    }
}
Also used : SimpleStaticAbility(mage.abilities.common.SimpleStaticAbility) java.util(java.util) Zone(mage.constants.Zone) CardCriteria(mage.cards.repository.CardCriteria) SimpleDateFormat(java.text.SimpleDateFormat) Constructor(java.lang.reflect.Constructor) ContinuousEffect(mage.abilities.effects.ContinuousEffect) Player(mage.players.Player) Matcher(java.util.regex.Matcher) GameCommanderImpl(mage.game.GameCommanderImpl) CardType(mage.constants.CardType) MageObject(mage.MageObject) ActivatedAbility(mage.abilities.ActivatedAbility) Planes(mage.constants.Planes) Card(mage.cards.Card) RandomUtil(mage.util.RandomUtil) DateFormat(java.text.DateFormat) Choice(mage.choices.Choice) Outcome(mage.constants.Outcome) Plane(mage.game.command.Plane) CardUtil(mage.util.CardUtil) CardRepository(mage.cards.repository.CardRepository) Collectors(java.util.stream.Collectors) CommandObject(mage.game.command.CommandObject) File(java.io.File) TimeUnit(java.util.concurrent.TimeUnit) Game(mage.game.Game) ChoiceImpl(mage.choices.ChoiceImpl) Token(mage.game.permanent.token.Token) Effect(mage.abilities.effects.Effect) InfoEffect(mage.abilities.effects.common.InfoEffect) CardInfo(mage.cards.repository.CardInfo) Permanent(mage.game.permanent.Permanent) Pattern(java.util.regex.Pattern) CounterType(mage.counters.CounterType) Ability(mage.abilities.Ability) Choice(mage.choices.Choice) Permanent(mage.game.permanent.Permanent) Matcher(java.util.regex.Matcher) Token(mage.game.permanent.token.Token) InfoEffect(mage.abilities.effects.common.InfoEffect) SimpleStaticAbility(mage.abilities.common.SimpleStaticAbility) ActivatedAbility(mage.abilities.ActivatedAbility) Ability(mage.abilities.Ability) GameCommanderImpl(mage.game.GameCommanderImpl) Player(mage.players.Player) CardCriteria(mage.cards.repository.CardCriteria) Constructor(java.lang.reflect.Constructor) Zone(mage.constants.Zone) SimpleStaticAbility(mage.abilities.common.SimpleStaticAbility) ActivatedAbility(mage.abilities.ActivatedAbility) MageObject(mage.MageObject) CardInfo(mage.cards.repository.CardInfo) Card(mage.cards.Card) ChoiceImpl(mage.choices.ChoiceImpl) MageObject(mage.MageObject) CommandObject(mage.game.command.CommandObject) File(java.io.File)

Example 18 with Ability

use of mage.abilities.Ability in project mage by magefree.

the class AberrantResearcherEffect method apply.

@Override
public boolean apply(Game game, Ability source) {
    Player controller = game.getPlayer(source.getControllerId());
    if (controller == null || controller.millCards(1, source, game).getCards(game).stream().noneMatch(card -> card.isInstantOrSorcery(game))) {
        return false;
    }
    new TransformSourceEffect().apply(game, source);
    return true;
}
Also used : OneShotEffect(mage.abilities.effects.OneShotEffect) UUID(java.util.UUID) MageInt(mage.MageInt) TransformSourceEffect(mage.abilities.effects.common.TransformSourceEffect) Player(mage.players.Player) CardSetInfo(mage.cards.CardSetInfo) BeginningOfUpkeepTriggeredAbility(mage.abilities.common.BeginningOfUpkeepTriggeredAbility) Game(mage.game.Game) TransformAbility(mage.abilities.keyword.TransformAbility) CardImpl(mage.cards.CardImpl) FlyingAbility(mage.abilities.keyword.FlyingAbility) mage.constants(mage.constants) Ability(mage.abilities.Ability) Player(mage.players.Player) TransformSourceEffect(mage.abilities.effects.common.TransformSourceEffect)

Example 19 with Ability

use of mage.abilities.Ability in project mage by magefree.

the class AbandonedSarcophagusWatcher method applies.

@Override
public boolean applies(GameEvent event, Ability source, Game game) {
    boolean cardWasCycledThisTurn = false;
    boolean cardHasCycling = false;
    if (!(((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD)) {
        return false;
    }
    Player controller = game.getPlayer(source.getControllerId());
    AbandonedSarcophagusWatcher watcher = game.getState().getWatcher(AbandonedSarcophagusWatcher.class);
    Card card = game.getCard(event.getTargetId());
    if (card == null || controller == null || watcher == null || !card.isOwnedBy(controller.getId())) {
        return false;
    }
    for (Ability ability : card.getAbilities(game)) {
        if (ability instanceof CyclingAbility) {
            cardHasCycling = true;
        }
    }
    Cards cards = watcher.getCardsCycledThisTurn(controller.getId());
    for (Card c : cards.getCards(game)) {
        if (c == card) {
            cardWasCycledThisTurn = true;
            // remove reference to the card as it is no longer needed
            watcher.getCardsCycledThisTurn(controller.getId()).remove(card);
        }
    }
    return !cardWasCycledThisTurn && cardHasCycling;
}
Also used : SimpleStaticAbility(mage.abilities.common.SimpleStaticAbility) CyclingAbility(mage.abilities.keyword.CyclingAbility) Ability(mage.abilities.Ability) Player(mage.players.Player) CyclingAbility(mage.abilities.keyword.CyclingAbility) FilterCard(mage.filter.FilterCard)

Example 20 with Ability

use of mage.abilities.Ability in project mage by magefree.

the class BackdraftHellkiteEffect method apply.

@Override
public boolean apply(Game game, Ability source) {
    Player player = game.getPlayer(source.getControllerId());
    if (player == null) {
        return false;
    }
    player.getGraveyard().stream().filter(cardId -> affectedObjectList.contains(new MageObjectReference(cardId, game))).forEachOrdered(cardId -> {
        Card card = game.getCard(cardId);
        if (card == null) {
            return;
        }
        FlashbackAbility ability = new FlashbackAbility(card, card.getManaCost());
        ability.setSourceId(cardId);
        ability.setControllerId(card.getOwnerId());
        game.getState().addOtherAbility(card, ability);
    });
    return true;
}
Also used : AttacksTriggeredAbility(mage.abilities.common.AttacksTriggeredAbility) MageObjectReference(mage.MageObjectReference) UUID(java.util.UUID) MageInt(mage.MageInt) Player(mage.players.Player) CardSetInfo(mage.cards.CardSetInfo) ContinuousEffectImpl(mage.abilities.effects.ContinuousEffectImpl) Game(mage.game.Game) CardImpl(mage.cards.CardImpl) FlashbackAbility(mage.abilities.keyword.FlashbackAbility) FlyingAbility(mage.abilities.keyword.FlyingAbility) Card(mage.cards.Card) mage.constants(mage.constants) Ability(mage.abilities.Ability) FlashbackAbility(mage.abilities.keyword.FlashbackAbility) Player(mage.players.Player) MageObjectReference(mage.MageObjectReference) Card(mage.cards.Card)

Aggregations

Ability (mage.abilities.Ability)359 Player (mage.players.Player)173 Permanent (mage.game.permanent.Permanent)134 UUID (java.util.UUID)126 Game (mage.game.Game)123 OneShotEffect (mage.abilities.effects.OneShotEffect)98 SimpleStaticAbility (mage.abilities.common.SimpleStaticAbility)87 CardSetInfo (mage.cards.CardSetInfo)87 CardImpl (mage.cards.CardImpl)85 CardType (mage.constants.CardType)78 Outcome (mage.constants.Outcome)76 Card (mage.cards.Card)72 SimpleActivatedAbility (mage.abilities.common.SimpleActivatedAbility)64 MageObject (mage.MageObject)57 MageInt (mage.MageInt)47 SpellAbility (mage.abilities.SpellAbility)43 Objects (java.util.Objects)38 Zone (mage.constants.Zone)38 mage.constants (mage.constants)37 FilterCard (mage.filter.FilterCard)35