Merge pull request #5350 from Zzooouhh/Zzooouhh-unh

Implemented Unhinged cards
This commit is contained in:
L_J 2018-09-30 14:13:32 +02:00 committed by GitHub
commit be1c7316a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 2637 additions and 0 deletions

View file

@ -0,0 +1,107 @@
package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.repository.CardRepository;
import mage.choices.ChoiceImpl;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public final class AchHansRun extends CardImpl {
public AchHansRun(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{R}{G}{G}");
// At the beginning of your upkeep, you may say "Ach! Hans, run! Its the …" and the name of a creature card. If you do, search your library for a card with that name, put it onto the battlefield, then shuffle your library. That creature gains haste. Exile it at the beginning of the next end step.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AchHansRunEffect(), TargetController.YOU, true));
}
public AchHansRun(final AchHansRun card) {
super(card);
}
@Override
public AchHansRun copy() {
return new AchHansRun(this);
}
}
class AchHansRunEffect extends OneShotEffect {
public AchHansRunEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "you may say \"Ach! Hans, run! Its the …\" and the name of a creature card. If you do, search your library for a card with that name, put it onto the battlefield, then shuffle your library. That creature gains haste. Exile it at the beginning of the next end step";
}
public AchHansRunEffect(final AchHansRunEffect effect) {
super(effect);
}
@Override
public AchHansRunEffect copy() {
return new AchHansRunEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
ChoiceImpl cardChoice = new ChoiceImpl(true);
cardChoice.setChoices(CardRepository.instance.getCreatureNames());
cardChoice.setMessage("Choose a creature card name");
if (controller.choose(Outcome.Detriment, cardChoice, game)) {
String cardName = cardChoice.getChoice();
if (!game.isSimulation()) {
game.informPlayers(controller.getLogName() + ": \"Ach! Hans, run! It's the " + cardName + "!\"");
}
FilterCard nameFilter = new FilterCard();
nameFilter.add(new NamePredicate(cardName));
TargetCardInLibrary target = new TargetCardInLibrary(1, 1, nameFilter);
if (controller.searchLibrary(target, game)) {
Card card = controller.getLibrary().remove(target.getFirstTarget(), game);
if (card != null) {
if (card != null && controller.moveCards(card, Zone.BATTLEFIELD, source, game)) {
Permanent creature = game.getPermanent(card.getId());
if (creature != null) {
// gains haste
ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(creature, game));
game.addEffect(effect, source);
// Exile at begin of next end step
ExileTargetEffect exileEffect = new ExileTargetEffect(null, null, Zone.BATTLEFIELD);
exileEffect.setTargetPointer(new FixedTarget(creature, game));
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
game.addDelayedTriggeredAbility(delayedAbility, source);
}
}
}
controller.shuffleLibrary(source, game);
}
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,186 @@
package mage.cards.b;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.SpellCastAllTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.FilterSpell;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.util.CardUtil;
/**
*
* @author L_J
*/
public final class BINGO extends CardImpl {
public BINGO(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}");
this.subtype.add(SubType.HOUND);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Trample
this.addAbility(TrampleAbility.getInstance());
// Whenever a player casts a spell, put a chip counter on its converted mana cost.
this.addAbility(new SpellCastAllTriggeredAbility(new BingoEffect(), new FilterSpell("a spell"), false, SetTargetPointer.SPELL));
// B-I-N-G-O gets +9/+9 for each set of three numbers in a row with chip counters on them.
BingoCount count = new BingoCount();
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostSourceEffect(count, count, Duration.WhileOnBattlefield)));
}
public BINGO(final BINGO card) {
super(card);
}
@Override
public BINGO copy() {
return new BINGO(this);
}
}
class BingoEffect extends OneShotEffect {
public BingoEffect() {
super(Outcome.Neutral);
staticText = "put a chip counter on its converted mana cost";
}
public BingoEffect(final BingoEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Spell spell = game.getStack().getSpell(this.getTargetPointer().getFirst(game, source));
if (spell != null) {
if (spell.getConvertedManaCost() > 9) {
return true;
}
MageObject mageObject = game.getObject(source.getSourceId());
if (mageObject != null) {
Map<Integer, Integer> chipCounters = new HashMap<>(); // Map<number, amount of counters>
if (game.getState().getValue(mageObject.getId() + "_chip") != null) {
chipCounters.putAll((Map<Integer, Integer>) game.getState().getValue(mageObject.getId() + "_chip"));
}
chipCounters.putIfAbsent(spell.getConvertedManaCost(), 0);
chipCounters.put(spell.getConvertedManaCost(), chipCounters.get(spell.getConvertedManaCost()) + 1);
game.getState().setValue(mageObject.getId() + "_chip", chipCounters);
if (mageObject instanceof Permanent) {
StringBuilder sb = new StringBuilder();
int i = 0;
for (Map.Entry<Integer, Integer> entry : chipCounters.entrySet()) {
i++;
sb.append(entry.getKey());
if (i < chipCounters.size()) {
sb.append(", ");
}
}
((Permanent) mageObject).addInfo("chip counters", CardUtil.addToolTipMarkTags("Chip counters at: " + sb), game);
new AddCountersSourceEffect(CounterType.CHIP.createInstance()).apply(game, source);
}
return true;
}
}
return false;
}
@Override
public BingoEffect copy() {
return new BingoEffect(this);
}
}
class BingoCount implements DynamicValue {
public BingoCount() {
}
public BingoCount(final BingoCount countersCount) {
}
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
MageObject mageObject = game.getObject(sourceAbility.getSourceId());
if (mageObject instanceof Permanent) {
Permanent permanent = game.getPermanentOrLKIBattlefield(sourceAbility.getSourceId());
if (permanent != null && game.getState().getValue(mageObject.getId() + "_chip") != null) {
int rows = 0;
Set<Integer> nums = ((Map<Integer, Integer>) game.getState().getValue(mageObject.getId() + "_chip")).keySet();
// if (nums.size() <= permanent.getCounters(game).getCount(CounterType.CHIP)) {
// 1 4 7
// 8 5 3
// 2 0 6
if (nums.contains(1) && nums.contains(4) && nums.contains(7)) {
rows++;
}
if (nums.contains(1) && nums.contains(8) && nums.contains(2)) {
rows++;
}
if (nums.contains(1) && nums.contains(5) && nums.contains(6)) {
rows++;
}
if (nums.contains(8) && nums.contains(5) && nums.contains(3)) {
rows++;
}
if (nums.contains(4) && nums.contains(5) && nums.contains(0)) {
rows++;
}
if (nums.contains(2) && nums.contains(0) && nums.contains(6)) {
rows++;
}
if (nums.contains(7) && nums.contains(3) && nums.contains(6)) {
rows++;
}
if (nums.contains(2) && nums.contains(5) && nums.contains(7)) {
rows++;
}
return rows * 9;
// }
}
}
return 0;
}
@Override
public BingoCount copy() {
return new BingoCount(this);
}
@Override
public String toString() {
return "9";
}
@Override
public String getMessage() {
return "set of three numbers in a row with chip counters on them";
}
}

View file

@ -0,0 +1,57 @@
package mage.cards.b;
import java.util.UUID;
import mage.abilities.condition.common.KickedCondition;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.keyword.BuybackAbility;
import mage.abilities.keyword.CyclingAbility;
import mage.abilities.keyword.FlashbackAbility;
import mage.abilities.keyword.KickerAbility;
import mage.abilities.keyword.MadnessAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TimingRule;
import mage.game.permanent.token.GoblinToken;
import mage.target.common.TargetAnyTarget;
/**
*
* @author L_J
*/
public final class BlastFromThePast extends CardImpl {
public BlastFromThePast (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}");
// Madness {R}
this.addAbility(new MadnessAbility(this, new ManaCostsImpl("{R}")));
// Cycling {1}{R}
this.addAbility(new CyclingAbility(new ManaCostsImpl("{1}{R}")));
// Kicker {2}{R}
this.addAbility(new KickerAbility("{2}{R}"));
// Flashback {3}{R}
this.addAbility(new FlashbackAbility(new ManaCostsImpl("{3}{R}"), TimingRule.INSTANT));
// Buyback {4}{R}
this.addAbility(new BuybackAbility("{4}{R}"));
// Blast from the Past deals 2 damage to any target. If this spell was kicked, create a 1/1 red Goblin creature token.
this.getSpellAbility().addEffect(new DamageTargetEffect(2));
this.getSpellAbility().addTarget(new TargetAnyTarget());
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new CreateTokenEffect(new GoblinToken()), KickedCondition.instance));
}
public BlastFromThePast (final BlastFromThePast card) {
super(card);
}
@Override
public BlastFromThePast copy() {
return new BlastFromThePast(this);
}
}

View file

@ -0,0 +1,110 @@
package mage.cards.b;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.StateTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageEverythingEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterNonlandPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
/**
*
* @author L_J
*/
public final class Bloodletter extends CardImpl {
public Bloodletter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}");
this.subtype.add(SubType.ZOMBIE);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// When the names of three or more nonland permanents begin with the same letter, sacrifice Bloodletter. If you do, it deals 2 damage to each creature and each player.
this.addAbility(new BloodletterStateTriggeredAbility());
}
public Bloodletter(final Bloodletter card) {
super(card);
}
@Override
public Bloodletter copy() {
return new Bloodletter(this);
}
}
class BloodletterStateTriggeredAbility extends StateTriggeredAbility {
public BloodletterStateTriggeredAbility() {
super(Zone.BATTLEFIELD, new BloodletterEffect());
}
public BloodletterStateTriggeredAbility(final BloodletterStateTriggeredAbility ability) {
super(ability);
}
@Override
public BloodletterStateTriggeredAbility copy() {
return new BloodletterStateTriggeredAbility(this);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Map<Character, Integer> initialCount = new HashMap<>();
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterNonlandPermanent(), getControllerId(), getSourceId(), game)) {
Character initial = permanent.getName().charAt(0);
initialCount.putIfAbsent(initial, 0);
initialCount.put(initial, initialCount.get(initial) + 1);
}
for (Map.Entry<Character, Integer> entry : initialCount.entrySet()) {
if (entry.getValue() >= 3) {
return true;
}
}
return false;
}
@Override
public String getRule() {
return "When the names of three or more nonland permanents begin with the same letter, " + super.getRule();
}
}
class BloodletterEffect extends OneShotEffect {
public BloodletterEffect() {
super(Outcome.Sacrifice);
staticText = "sacrifice {this}. If you do, it deals 2 damage to each creature and each player";
}
public BloodletterEffect(final BloodletterEffect effect) {
super(effect);
}
@Override
public BloodletterEffect copy() {
return new BloodletterEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null && permanent.sacrifice(source.getSourceId(), game)) {
return new DamageEverythingEffect(2).apply(game, source);
}
return false;
}
}

View file

@ -0,0 +1,106 @@
package mage.cards.b;
import java.util.HashSet;
import java.util.Set;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseExpansionSetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.cards.ExpansionSet;
import mage.cards.Sets;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
/**
*
* @author spjspj & L_J
*/
public final class BoosterTutor extends CardImpl {
public BoosterTutor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}");
// Open a sealed Magic booster pack, reveal the cards, and put one of those cards into your hand.
this.getSpellAbility().addEffect(new BoosterTutorEffect());
}
public BoosterTutor(final BoosterTutor card) {
super(card);
}
@Override
public BoosterTutor copy() {
return new BoosterTutor(this);
}
}
class BoosterTutorEffect extends OneShotEffect {
public BoosterTutorEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "Open a sealed Magic booster pack, reveal the cards, and put one of those cards into your hand";
}
public BoosterTutorEffect(final BoosterTutorEffect effect) {
super(effect);
}
@Override
public BoosterTutorEffect copy() {
return new BoosterTutorEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
ChooseExpansionSetEffect effect = new ChooseExpansionSetEffect(Outcome.UnboostCreature);
effect.apply(game, source);
Player controller = game.getPlayer(source.getControllerId());
String setChosen = null;
if (effect.getValue("setchosen") != null) {
setChosen = (String) effect.getValue("setchosen");
} else if (game.getState().getValue(this.getId() + "_set") != null) {
setChosen = (String) game.getState().getValue(this.getId() + "_set");
}
if (setChosen != null && controller != null) {
//ExpansionInfo set = ExpansionRepository.instance.getSetByName(setChosen);
ExpansionSet expansionSet = Sets.findSet(setChosen);
if (expansionSet != null) {
List<Card> boosterPack = expansionSet.create15CardBooster();
if (boosterPack != null) {
StringBuilder message = new StringBuilder(controller.getLogName()).append(" opened: ");
for (Card card : boosterPack) {
message.append(card.getName()).append(" ");
}
game.informPlayers(message.toString());
TargetCard targetCard = new TargetCard(Zone.ALL, new FilterCard());
Set<Card> cardsToLoad = new HashSet<Card>(boosterPack);
game.loadCards(cardsToLoad, controller.getId());
CardsImpl cards = new CardsImpl();
cards.addAll(boosterPack);
if (controller.choose(Outcome.Benefit, cards, targetCard, game)) {
Card card = game.getCard(targetCard.getFirstTarget());
if (card != null) {
controller.moveCards(card, Zone.HAND, source, game);
}
}
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,94 @@
package mage.cards.d;
import java.util.UUID;
import java.util.regex.Pattern;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SpellAbilityType;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.target.TargetPermanent;
/**
*
* @author L_J
*/
public final class DoubleHeader extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("permanent with a two-word name");
static {
filter.add(new DoubleHeaderPredicate());
}
public DoubleHeader(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{U}");
this.subtype.add(SubType.DRAKE);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Double Header enters the battlefield, you may return target permanent with a two-word name to its owners hand.
Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true);
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}
public DoubleHeader(final DoubleHeader card) {
super(card);
}
@Override
public DoubleHeader copy() {
return new DoubleHeader(this);
}
}
class DoubleHeaderPredicate implements Predicate<MageObject> {
public DoubleHeaderPredicate() {
}
@Override
public boolean apply(MageObject input, Game game) {
String name = input.getName();
if (input instanceof SplitCard) {
return hasTwoWords(((SplitCard)input).getLeftHalfCard().getName()) || hasTwoWords(((SplitCard)input).getRightHalfCard().getName());
} else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED){
SplitCard card = (SplitCard) ((Spell)input).getCard();
return hasTwoWords(card.getLeftHalfCard().getName()) || hasTwoWords(card.getRightHalfCard().getName());
} else {
if (name.contains(" // ")) {
String leftName = name.substring(0, name.indexOf(" // "));
String rightName = name.substring(name.indexOf(" // ") + 4, name.length());
return hasTwoWords(leftName) || hasTwoWords(rightName);
} else {
return hasTwoWords(name);
}
}
}
private boolean hasTwoWords(String str) {
return Pattern.compile("\\s+").split(str).length == 2;
}
@Override
public String toString() {
return "";
}
}

View file

@ -0,0 +1,74 @@
package mage.cards.f;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.UUID;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.common.FilterAttackingOrBlockingCreature;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
/**
*
* @author L_J
*/
public final class FirstComeFirstServed extends CardImpl {
private static final FilterAttackingOrBlockingCreature filter = new FilterAttackingOrBlockingCreature("Each attacking or blocking creature with the lowest collector number among attacking or blocking creatures");
static {
filter.add(new FirstComeFirstServedPredicate());
}
public FirstComeFirstServed(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
// Each attacking or blocking creature with the lowest collector number among attacking or blocking creatures has first strike.
GainAbilityAllEffect gainEffect = new GainAbilityAllEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield, filter, false);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, gainEffect));
}
public FirstComeFirstServed(final FirstComeFirstServed card) {
super(card);
}
@Override
public FirstComeFirstServed copy() {
return new FirstComeFirstServed(this);
}
}
class FirstComeFirstServedPredicate implements Predicate<Permanent> {
@Override
public boolean apply(Permanent input, Game game) {
if (input instanceof PermanentCard) {
int lowestNumber = Integer.MAX_VALUE;
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterAttackingOrBlockingCreature(), game)) {
int number = parseCardNumber(permanent);
if (lowestNumber > number) {
lowestNumber = number;
}
}
return parseCardNumber(input) == lowestNumber;
}
return false;
}
public int parseCardNumber(Permanent input) {
String str = input.getCardNumber();
Matcher matcher = Pattern.compile("\\d+").matcher(str);
matcher.find();
return Integer.valueOf(matcher.group());
}
}

View file

@ -0,0 +1,122 @@
package mage.cards.f;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.LoseGameTargetPlayerEffect;
import mage.abilities.effects.common.combat.CantAttackYouAllEffect;
import mage.abilities.effects.common.continuous.GainAbilityControllerEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.ShroudAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.token.SquirrelToken;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public final class FormOfTheSquirrel extends CardImpl {
public FormOfTheSquirrel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{G}");
// As Form of the Squirrel enters the battlefield, create a 1/1 green Squirrel creature token. You lose the game when that creature leaves the battlefield.
this.addAbility(new AsEntersBattlefieldAbility(new FormOfTheSquirrelCreateTokenEffect()));
// Creatures can't attack you.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackYouAllEffect(Duration.WhileOnBattlefield)));
// You have shroud.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControllerEffect(ShroudAbility.getInstance())));
// You can't cast spells.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new FormOfTheSquirrelCantCastEffect()));
}
public FormOfTheSquirrel(final FormOfTheSquirrel card) {
super(card);
}
@Override
public FormOfTheSquirrel copy() {
return new FormOfTheSquirrel(this);
}
}
class FormOfTheSquirrelCreateTokenEffect extends OneShotEffect {
public FormOfTheSquirrelCreateTokenEffect() {
super(Outcome.PutCreatureInPlay);
staticText = "create a 1/1 green Squirrel creature token. You lose the game when that creature leaves the battlefield";
}
public FormOfTheSquirrelCreateTokenEffect(final FormOfTheSquirrelCreateTokenEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player sourceController = game.getPlayer(source.getControllerId());
if (sourceController != null) {
CreateTokenEffect effect = new CreateTokenEffect(new SquirrelToken());
effect.apply(game, source);
game.getState().setValue(source.getSourceId() + "_token", effect.getLastAddedTokenIds());
for (UUID addedTokenId : effect.getLastAddedTokenIds()) {
Effect loseGameEffect = new LoseGameTargetPlayerEffect();
loseGameEffect.setTargetPointer(new FixedTarget(sourceController.getId(), game));
LeavesBattlefieldTriggeredAbility triggerAbility = new LeavesBattlefieldTriggeredAbility(loseGameEffect, false);
ContinuousEffect continuousEffect = new GainAbilityTargetEffect(triggerAbility, Duration.WhileOnBattlefield);
continuousEffect.setTargetPointer(new FixedTarget(addedTokenId, game));
game.addEffect(continuousEffect, source);
}
return true;
}
return false;
}
@Override
public FormOfTheSquirrelCreateTokenEffect copy() {
return new FormOfTheSquirrelCreateTokenEffect(this);
}
}
class FormOfTheSquirrelCantCastEffect extends ContinuousRuleModifyingEffectImpl {
public FormOfTheSquirrelCantCastEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
staticText = "You can't cast spells";
}
public FormOfTheSquirrelCantCastEffect(final FormOfTheSquirrelCantCastEffect effect) {
super(effect);
}
@Override
public FormOfTheSquirrelCantCastEffect copy() {
return new FormOfTheSquirrelCantCastEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return event.getType() == GameEvent.EventType.CAST_SPELL && event.getPlayerId().equals(source.getControllerId());
}
}

View file

@ -0,0 +1,83 @@
package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author L_J
*/
public final class GoblinSecretAgent extends CardImpl {
public GoblinSecretAgent(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}");
this.subtype.add(SubType.GOBLIN);
this.subtype.add(SubType.ROGUE);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// First strike
this.addAbility(FirstStrikeAbility.getInstance());
// At the beginning of your upkeep, reveal a card from your hand at random.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GoblinSecretAgentEffect(), TargetController.YOU, false));
}
public GoblinSecretAgent(final GoblinSecretAgent card) {
super(card);
}
@Override
public GoblinSecretAgent copy() {
return new GoblinSecretAgent(this);
}
}
class GoblinSecretAgentEffect extends OneShotEffect {
public GoblinSecretAgentEffect() {
super(Outcome.Detriment);
this.staticText = "reveal a card from your hand at random";
}
public GoblinSecretAgentEffect(final GoblinSecretAgentEffect effect) {
super(effect);
}
@Override
public GoblinSecretAgentEffect copy() {
return new GoblinSecretAgentEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (controller != null && sourceObject != null) {
if (!controller.getHand().isEmpty()) {
CardsImpl randomCard = new CardsImpl();
Card card = controller.getHand().getRandom(game);
randomCard.add(card);
controller.revealCards(sourceObject.getIdName(), randomCard, game);
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,96 @@
package mage.cards.m;
import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author L_J
*/
public final class ManaScrew extends CardImpl {
public ManaScrew(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
// {1}: Flip a coin. If you win the flip, add {C}{C}. Activate this ability only any time you could cast an instant.
this.addAbility(new ManaScrewAbility());
}
public ManaScrew(final ManaScrew card) {
super(card);
}
@Override
public ManaScrew copy() {
return new ManaScrew(this);
}
}
class ManaScrewAbility extends ActivatedManaAbilityImpl {
public ManaScrewAbility() {
super(Zone.BATTLEFIELD, new ManaScrewEffect(), new GenericManaCost(1));
this.netMana.add(new Mana(0, 0, 0, 0, 0, 2, 0, 0));
}
public ManaScrewAbility(final ManaScrewAbility ability) {
super(ability);
}
@Override
public ActivationStatus canActivate(UUID playerId, Game game) {
Player player = game.getPlayer(playerId);
if (player != null && !player.isInPayManaMode()) {
return super.canActivate(playerId, game);
}
return ActivationStatus.getFalse();
}
@Override
public ManaScrewAbility copy() {
return new ManaScrewAbility(this);
}
@Override
public String getRule() {
return super.getRule() + " Activate this ability only any time you could cast an instant.";
}
}
class ManaScrewEffect extends BasicManaEffect {
public ManaScrewEffect() {
super(Mana.ColorlessMana(2));
this.staticText = "Flip a coin. If you win the flip, add {C}{C}";
}
public ManaScrewEffect(final ManaScrewEffect effect) {
super(effect);
this.manaTemplate = effect.manaTemplate.copy();
}
@Override
public ManaScrewEffect copy() {
return new ManaScrewEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null && player.flipCoin(game)) {
player.getManaPool().addMana(getMana(game, source), game, source);
}
return true;
}
}

View file

@ -0,0 +1,75 @@
package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseACardNameEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author L_J
*/
public final class Mise extends CardImpl {
public Mise(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}");
// Choose a nonland card name, then reveal the top card of your library. If that card has the chosen name, you draw three cards.
this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME));
this.getSpellAbility().addEffect(new MiseEffect());
}
public Mise(final Mise card) {
super(card);
}
@Override
public Mise copy() {
return new Mise(this);
}
}
class MiseEffect extends OneShotEffect {
public MiseEffect() {
super(Outcome.Detriment);
staticText = "then reveal the top card of your library. If that card has the chosen name, you draw three cards";
}
public MiseEffect(final MiseEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Object object = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
if (player != null && object instanceof String) {
Card card = player.getLibrary().getFromTop(game);
String namedCard = (String) object;
CardsImpl cards = new CardsImpl(card);
if (card != null) {
player.revealCards("Mise", cards, game, true);
if (card.getName().equals(namedCard)) {
player.drawCards(3, game);
}
}
return true;
}
return false;
}
@Override
public MiseEffect copy() {
return new MiseEffect(this);
}
}

View file

@ -0,0 +1,150 @@
package mage.cards.m;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterNonlandPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
/**
*
* @author L_J
*/
public final class MonkeyMonkeyMonkey extends CardImpl {
public MonkeyMonkeyMonkey(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
this.subtype.add(SubType.MONKEY);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// As Monkey Monkey Monkey enters the battlefield, choose a letter.
this.addAbility(new AsEntersBattlefieldAbility(new ChooseLetterEffect()));
// Monkey Monkey Monkey gets +1/+1 for each nonland permanent whose name begins with the chosen letter.
MonkeyMonkeyMonkeyCount count = new MonkeyMonkeyMonkeyCount();
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostSourceEffect(count, count, Duration.WhileOnBattlefield)));
}
public MonkeyMonkeyMonkey(final MonkeyMonkeyMonkey card) {
super(card);
}
@Override
public MonkeyMonkeyMonkey copy() {
return new MonkeyMonkeyMonkey(this);
}
}
class ChooseLetterEffect extends OneShotEffect {
public ChooseLetterEffect() {
super(Outcome.Benefit);
staticText = "choose a letter";
}
public ChooseLetterEffect(final ChooseLetterEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject mageObject = game.getPermanentEntering(source.getSourceId());
if (mageObject == null) {
mageObject = game.getObject(source.getSourceId());
}
ChoiceImpl choice = new ChoiceImpl(true);
choice.setMessage("Choose letter");
Set<String> choices = new HashSet<>();
for (Character letter = 'A'; letter <= 'Z'; letter++) {
choices.add(letter.toString());
}
choice.setChoices(choices);
if (controller != null && mageObject != null && controller.choose(outcome, choice, game)) {
if (!game.isSimulation()) {
game.informPlayers(mageObject.getLogName() + ": " + controller.getLogName() + " has chosen " + choice.getChoice());
}
game.getState().setValue(mageObject.getId() + "_letter", choice.getChoice());
if (mageObject instanceof Permanent) {
((Permanent) mageObject).addInfo("chosen letter", CardUtil.addToolTipMarkTags("Chosen letter: " + choice.getChoice()), game);
}
return true;
}
return false;
}
@Override
public ChooseLetterEffect copy() {
return new ChooseLetterEffect(this);
}
}
class MonkeyMonkeyMonkeyCount implements DynamicValue {
public MonkeyMonkeyMonkeyCount() {
}
public MonkeyMonkeyMonkeyCount(final MonkeyMonkeyMonkeyCount countersCount) {
}
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
MageObject mageObject = game.getObject(sourceAbility.getSourceId());
if (mageObject instanceof Permanent) {
Permanent permanent = game.getPermanentOrLKIBattlefield(sourceAbility.getSourceId());
if (permanent != null && game.getState().getValue(mageObject.getId() + "_letter") != null) {
int letters = 0;
for (Permanent p : game.getBattlefield().getActivePermanents(new FilterNonlandPermanent(), sourceAbility.getControllerId(), sourceAbility.getSourceId(), game)) {
Character initial = Character.toUpperCase(p.getName().charAt(0));
if (initial.toString().equals(game.getState().getValue(mageObject.getId() + "_letter"))) {
letters++;
}
}
return letters;
}
}
return 0;
}
@Override
public MonkeyMonkeyMonkeyCount copy() {
return new MonkeyMonkeyMonkeyCount(this);
}
@Override
public String toString() {
return "1";
}
@Override
public String getMessage() {
return "nonland permanent whose name begins with the chosen letter";
}
}

View file

@ -0,0 +1,69 @@
package mage.cards.n;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.WinGameSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author L_J
*/
public final class NowIKnowMyABCs extends CardImpl {
public NowIKnowMyABCs(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{U}{U}");
// At the beginning of your upkeep, if you control permanents with names that include all twenty-six letters of the English alphabet, you win the game.
this.addAbility(new ConditionalTriggeredAbility(
new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect(), TargetController.YOU, false),
new NowIKnowMyABCsCondition(),
"At the beginning of your upkeep, if you control permanents with names that include all twenty-six letters of the English alphabet, you win the game."));
}
public NowIKnowMyABCs(final NowIKnowMyABCs card) {
super(card);
}
@Override
public NowIKnowMyABCs copy() {
return new NowIKnowMyABCs(this);
}
}
class NowIKnowMyABCsCondition implements Condition {
public NowIKnowMyABCsCondition() {
}
@Override
public boolean apply(Game game, Ability source) {
Set<Character> letters = new HashSet<>();
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
String permName = permanent.getName();
for (int i = 0; i < permName.length(); i++) {
Character letter = permName.charAt(i);
if (Character.isLetter(letter)) {
letters.add(Character.toUpperCase(letter));
}
}
}
return letters.size() >= 26;
}
@Override
public String toString() {
return "if you control permanents with names that include all twenty-six letters of the English alphabet";
}
}

View file

@ -0,0 +1,119 @@
package mage.cards.r;
import java.util.*;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author L_J
*/
public final class RareBGone extends CardImpl {
public RareBGone(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}{R}");
// Each player sacrifices all permanents that are rare or mythic rare, then each player reveals their hand and discards all cards that are rare or mythic rare.
this.getSpellAbility().addEffect(new RareBGoneEffect());
}
public RareBGone(final RareBGone card) {
super(card);
}
@Override
public RareBGone copy() {
return new RareBGone(this);
}
}
class RareBGoneEffect extends OneShotEffect {
private static final FilterPermanent filterPermanent = new FilterPermanent();
private static final FilterCard filterCard = new FilterCard();
static {
filterPermanent.add(Predicates.or(
new RarityPredicate(Rarity.RARE),
new RarityPredicate(Rarity.MYTHIC)
));
filterCard.add(Predicates.or(
new RarityPredicate(Rarity.RARE),
new RarityPredicate(Rarity.MYTHIC)
));
}
public RareBGoneEffect() {
super(Outcome.Benefit);
this.staticText = "Each player sacrifices all permanents that are rare or mythic rare, then each player reveals their hand and discards all cards that are rare or mythic rare";
}
public RareBGoneEffect(final RareBGoneEffect effect) {
super(effect);
}
@Override
public RareBGoneEffect copy() {
return new RareBGoneEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filterPermanent, playerId, game)) {
permanent.sacrifice(source.getSourceId(), game);
}
Cards hand = player.getHand();
player.revealCards("Rare-B-Gone", hand, game);
Set<Card> cards = hand.getCards(game);
for (Card card : cards) {
if (card != null && filterCard.match(card, game)) {
player.discard(card, source, game);
}
}
}
}
return true;
}
return false;
}
}
class RarityPredicate implements Predicate<Card> {
private final Rarity rarity;
public RarityPredicate(Rarity rarity) {
this.rarity = rarity;
}
@Override
public boolean apply(Card input, Game game) {
return input.getRarity().equals(rarity);
}
@Override
public String toString() {
return "Rarity(" + rarity + ')';
}
}

View file

@ -0,0 +1,95 @@
package mage.cards.s;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetOpponent;
/**
*
* @author L_J
*/
public final class SixyBeast extends CardImpl {
public SixyBeast(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.BEAST);
this.power = new MageInt(0);
this.toughness = new MageInt(0);
// As Six-y Beast enters the battlefield, you secretly put six or fewer +1/+1 counters on it, then an opponent guesses the number of counters. If that player guesses right, sacrifice Six-y Beast after it enters the battlefield.
this.addAbility(new AsEntersBattlefieldAbility(new SixyBeastEffect()));
}
public SixyBeast(final SixyBeast card) {
super(card);
}
@Override
public SixyBeast copy() {
return new SixyBeast(this);
}
}
class SixyBeastEffect extends OneShotEffect {
public SixyBeastEffect() {
super(Outcome.BoostCreature);
this.staticText = "you secretly put six or fewer +1/+1 counters on it, then an opponent guesses the number of counters. If that player guesses right, sacrifice {this} after it enters the battlefield";
}
public SixyBeastEffect(final SixyBeastEffect effect) {
super(effect);
}
@Override
public SixyBeastEffect copy() {
return new SixyBeastEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanentEntering(source.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
if (permanent != null && controller != null) {
int counterAmount = controller.getAmount(0, 6, "Secretly put up to six counters on " + permanent.getName(), game);
permanent.addCounters(CounterType.P1P1.createInstance(counterAmount), source, game);
Player opponent = null;
Set<UUID> opponents = game.getOpponents(source.getControllerId());
if (!opponents.isEmpty()) {
if (opponents.size() > 1) {
Target targetOpponent = new TargetOpponent(true);
if (controller.chooseTarget(Outcome.Neutral, targetOpponent, source, game)) {
opponent = game.getPlayer(targetOpponent.getFirstTarget());
}
} else {
opponent = game.getPlayer(opponents.iterator().next());
}
}
if (opponent != null) {
int guessedAmount = opponent.getAmount(0, 6, "Guess the number of counters on " + permanent.getName(), game);
game.informPlayers(opponent.getLogName() + " guessed " + guessedAmount + " as the number of counters on " + permanent.getLogName());
if (counterAmount == guessedAmount) {
permanent.sacrifice(source.getSourceId(), game);
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,65 @@
package mage.cards.s;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.ExpansionSymbolToken;
/**
*
* @author L_J
*/
public class SymbolStatus extends CardImpl {
public SymbolStatus(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}{G}");
// Create a 1/1 colorless Expansion-Symbol creature token for each different expansion symbol among permanents you control.
this.getSpellAbility().addEffect(new SymbolStatusEffect());
}
public SymbolStatus(final SymbolStatus card) {
super(card);
}
@Override
public SymbolStatus copy() {
return new SymbolStatus(this);
}
}
class SymbolStatusEffect extends OneShotEffect {
public SymbolStatusEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "Create a 1/1 colorless Expansion-Symbol creature token for each different expansion symbol among permanents you control";
}
public SymbolStatusEffect(final SymbolStatusEffect effect) {
super(effect);
}
@Override
public SymbolStatusEffect copy() {
return new SymbolStatusEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Set<String> symbols = new HashSet<>();
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
symbols.add(permanent.getExpansionSetCode());
}
return new CreateTokenEffect(new ExpansionSymbolToken(), symbols.size()).apply(game, source);
}
}

View file

@ -0,0 +1,186 @@
package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.DealtDamageToSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.RestrictionEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
/**
*
* @author L_J
*/
public final class TheFallenApart extends CardImpl {
public TheFallenApart(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}");
this.subtype.add(SubType.ZOMBIE);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// The Fallen Apart enters the battlefield with two arms and two legs.
this.addAbility(new EntersBattlefieldAbility(new TheFallenApartEntersEffect()));
// Whenever damage is dealt to The Fallen Apart, remove an arm or a leg from it.
this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new TheFallenApartToggleEffect(), false));
// The Fallen Apart cant attack if it has no legs and cant block if it has no arms.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new TheFallenApartRestrictionEffect()));
}
public TheFallenApart(final TheFallenApart card) {
super(card);
}
@Override
public TheFallenApart copy() {
return new TheFallenApart(this);
}
}
class TheFallenApartEntersEffect extends OneShotEffect {
public TheFallenApartEntersEffect() {
super(Outcome.Neutral);
staticText = "with two arms and two legs";
}
public TheFallenApartEntersEffect(final TheFallenApartEntersEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
MageObject mageObject = game.getPermanentEntering(source.getSourceId());
if (mageObject == null) {
mageObject = game.getObject(source.getSourceId());
}
if (mageObject != null) {
game.getState().setValue(mageObject.getId() + "_arms", 2);
game.getState().setValue(mageObject.getId() + "_legs", 2);
if (mageObject instanceof Permanent) {
((Permanent) mageObject).addInfo("armslegs", CardUtil.addToolTipMarkTags("Arms: 2, Legs: 2"), game);
}
return true;
}
return false;
}
@Override
public TheFallenApartEntersEffect copy() {
return new TheFallenApartEntersEffect(this);
}
}
class TheFallenApartToggleEffect extends OneShotEffect {
public TheFallenApartToggleEffect() {
super(Outcome.Neutral);
staticText = "remove an arm or a leg from it";
}
public TheFallenApartToggleEffect(final TheFallenApartToggleEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject mageObject = game.getObject(source.getSourceId());
if (controller != null && mageObject != null) {
if (game.getState().getValue(mageObject.getId() + "_arms") == null
|| game.getState().getValue(mageObject.getId() + "_legs") == null) {
return false;
}
int arms = (Integer) game.getState().getValue(mageObject.getId() + "_arms");
int legs = (Integer) game.getState().getValue(mageObject.getId() + "_legs");
if (arms > 0) {
if (legs > 0) {
if (controller.chooseUse(Outcome.Detriment, "Remove an arm or a leg:",
source.getSourceObject(game).getLogName(), "Arm", "Leg", source, game)) {
arms -= 1;
game.informPlayers(mageObject.getLogName() + " loses an arm");
} else {
legs -= 1;
game.informPlayers(mageObject.getLogName() + " loses a leg");
}
} else {
arms -= 1;
game.informPlayers(mageObject.getLogName() + " loses an arm");
}
} else {
if (legs > 0) {
legs -= 1;
game.informPlayers(mageObject.getLogName() + " loses a leg");
}
}
game.getState().setValue(mageObject.getId() + "_arms", arms);
game.getState().setValue(mageObject.getId() + "_legs", legs);
((Permanent) mageObject).addInfo("armslegs", CardUtil.addToolTipMarkTags("Arms: " + arms + ", Legs: " + legs), game);
return true;
}
return false;
}
@Override
public TheFallenApartToggleEffect copy() {
return new TheFallenApartToggleEffect(this);
}
}
class TheFallenApartRestrictionEffect extends RestrictionEffect {
public TheFallenApartRestrictionEffect() {
super(Duration.WhileOnBattlefield);
staticText = "{this} cant attack if it has no legs and cant block if it has no arms";
}
public TheFallenApartRestrictionEffect(final TheFallenApartRestrictionEffect effect) {
super(effect);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return permanent.getId().equals(source.getSourceId());
}
@Override
public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) {
MageObject mageObject = game.getObject(source.getSourceId());
if (mageObject != null) {
return (Integer) game.getState().getValue(mageObject.getId() + "_arms") > 0;
}
return false;
}
@Override
public boolean canAttack(Permanent attacker, UUID defenderId, Ability source, Game game) {
MageObject mageObject = game.getObject(source.getSourceId());
if (mageObject != null) {
return (Integer) game.getState().getValue(mageObject.getId() + "_legs") > 0;
}
return false;
}
@Override
public TheFallenApartRestrictionEffect copy() {
return new TheFallenApartRestrictionEffect(this);
}
}

View file

@ -0,0 +1,199 @@
package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.SpellCastAllTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalReplacementEffect;
import mage.abilities.decorator.ConditionalRestrictionEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.RestrictionEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.util.CardUtil;
/**
*
* @author L_J
*/
public final class Togglodyte extends CardImpl {
public Togglodyte(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}");
this.subtype.add(SubType.GOLEM);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Togglodyte enters the battlefield turned on.
this.addAbility(new EntersBattlefieldAbility(new TogglodyteEntersEffect()));
// Whenever a player casts a spell, toggle Togglodytes ON/OFF switch.
this.addAbility(new SpellCastAllTriggeredAbility(new TogglodyteToggleEffect(), false));
// As long as Togglodyte is turned off, it cant attack or block, and prevent all damage it would deal.
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalRestrictionEffect(new TogglodyteRestrictionEffect(), new TogglodyteCondition()));
ability.addEffect(new ConditionalReplacementEffect(new TogglodytePreventionEffect(), new TogglodyteCondition()));
this.addAbility(ability);
}
public Togglodyte(final Togglodyte card) {
super(card);
}
@Override
public Togglodyte copy() {
return new Togglodyte(this);
}
}
class TogglodyteEntersEffect extends OneShotEffect {
public TogglodyteEntersEffect() {
super(Outcome.Neutral);
staticText = "turned on";
}
public TogglodyteEntersEffect(final TogglodyteEntersEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
MageObject mageObject = game.getPermanentEntering(source.getSourceId());
if (mageObject == null) {
mageObject = game.getObject(source.getSourceId());
}
if (mageObject != null) {
boolean toggled = true;
game.getState().setValue(mageObject.getId() + "_toggle", toggled);
if (mageObject instanceof Permanent) {
((Permanent) mageObject).addInfo("toggle", CardUtil.addToolTipMarkTags("Switch: " + (toggled ? "ON" : "OFF")), game);
}
return true;
}
return false;
}
@Override
public TogglodyteEntersEffect copy() {
return new TogglodyteEntersEffect(this);
}
}
class TogglodyteToggleEffect extends OneShotEffect {
public TogglodyteToggleEffect() {
super(Outcome.Neutral);
staticText = "toggle {this}s ON/OFF switch";
}
public TogglodyteToggleEffect(final TogglodyteToggleEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
MageObject mageObject = game.getObject(source.getSourceId());
if (mageObject != null) {
if (game.getState().getValue(mageObject.getId() + "_toggle") == null) {
return false;
}
boolean toggled = (Boolean) game.getState().getValue(mageObject.getId() + "_toggle");
game.getState().setValue(mageObject.getId() + "_toggle", !toggled);
((Permanent) mageObject).addInfo("toggle", CardUtil.addToolTipMarkTags("Switch: " + (!toggled ? "ON" : "OFF")), game);
return true;
}
return false;
}
@Override
public TogglodyteToggleEffect copy() {
return new TogglodyteToggleEffect(this);
}
}
class TogglodyteRestrictionEffect extends RestrictionEffect {
public TogglodyteRestrictionEffect() {
super(Duration.WhileOnBattlefield);
staticText = "";
}
public TogglodyteRestrictionEffect(final TogglodyteRestrictionEffect effect) {
super(effect);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return permanent.getId().equals(source.getSourceId());
}
@Override
public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) {
return false;
}
@Override
public boolean canAttack(Game game) {
return false;
}
@Override
public TogglodyteRestrictionEffect copy() {
return new TogglodyteRestrictionEffect(this);
}
}
class TogglodytePreventionEffect extends PreventionEffectImpl {
public TogglodytePreventionEffect() {
super(Duration.WhileOnBattlefield, Integer.MAX_VALUE, false);
staticText = "As long as {this} is turned off, it cant attack or block, and prevent all damage it would deal";
}
public TogglodytePreventionEffect(final TogglodytePreventionEffect effect) {
super(effect);
}
@Override
public TogglodytePreventionEffect copy() {
return new TogglodytePreventionEffect(this);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (super.applies(event, source, game)) {
if (event.getSourceId().equals(source.getSourceId())) {
return true;
}
}
return false;
}
}
class TogglodyteCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
MageObject mageObject = game.getObject(source.getSourceId());
if (mageObject != null && game.getState().getValue(mageObject.getId() + "_toggle") != null) {
return !((Boolean) game.getState().getValue(mageObject.getId() + "_toggle"));
}
return false;
}
}

View file

@ -0,0 +1,62 @@
package mage.cards.u;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapTargetCost;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.permanent.token.UktabiKongApeToken;
import mage.filter.common.FilterArtifactPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.target.common.TargetControlledPermanent;
/**
*
* @author LoneFox
*/
public final class UktabiKong extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Apes you control");
static {
filter.add(Predicates.not(new TappedPredicate()));
filter.add(new SubtypePredicate(SubType.APE));
}
public UktabiKong(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{G}{G}{G}");
this.subtype.add(SubType.APE);
this.power = new MageInt(8);
this.toughness = new MageInt(8);
// Trample
this.addAbility(TrampleAbility.getInstance());
// When Uktabi Kong enters the battlefield, destroy all artifacts.
this.addAbility(new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(new FilterArtifactPermanent("artifacts")), false));
// Tap two untapped Apes you control: Create a 1/1 green Ape creature token.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new UktabiKongApeToken()), new TapTargetCost(new TargetControlledPermanent(2, 2, filter, true))));
}
public UktabiKong(final UktabiKong card) {
super(card);
}
@Override
public UktabiKong copy() {
return new UktabiKong(this);
}
}

View file

@ -0,0 +1,130 @@
package mage.cards.u;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.DiscardTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetCardInLibrary;
/**
*
* @author L_J
*/
public class UrzasHotTub extends CardImpl {
public UrzasHotTub(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
// {2}, Discard a card: Search your library for a card that shares a complete word in its name with the discarded card, reveal it, put it into your hand, then shuffle your library.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new UrzasHotTubEffect(), new ManaCostsImpl("{2}"));
ability.addCost(new DiscardTargetCost(new TargetCardInHand()));
this.addAbility(ability);
}
public UrzasHotTub(final UrzasHotTub card) {
super(card);
}
@Override
public UrzasHotTub copy() {
return new UrzasHotTub(this);
}
}
class UrzasHotTubEffect extends OneShotEffect {
public UrzasHotTubEffect() {
super(Outcome.ReturnToHand);
this.staticText = "Search your library for a card that shares a complete word in its name with the discarded card, reveal it, put it into your hand, then shuffle your library";
}
public UrzasHotTubEffect(final UrzasHotTubEffect effect) {
super(effect);
}
@Override
public UrzasHotTubEffect copy() {
return new UrzasHotTubEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
for (Cost cost : source.getCosts()) {
if (cost instanceof DiscardTargetCost) {
DiscardTargetCost discardCost = (DiscardTargetCost) cost;
Card discardedCard = discardCost.getCards().get(0);
if (discardedCard != null) {
FilterCard filter = new FilterCard();
filter.add(new UrzasHotTubPredicate(discardedCard.getName()));
return new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true, true).apply(game, source);
}
}
}
return false;
}
}
class UrzasHotTubPredicate implements Predicate<MageObject> {
private final String referenceName;
public UrzasHotTubPredicate(String referenceName) {
this.referenceName = referenceName;
}
@Override
public boolean apply(MageObject input, Game game) {
String name = input.getName();
if (input instanceof SplitCard) {
return sharesWordWithName(((SplitCard)input).getLeftHalfCard().getName()) || sharesWordWithName(((SplitCard)input).getRightHalfCard().getName());
} else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED){
SplitCard card = (SplitCard) ((Spell)input).getCard();
return sharesWordWithName(card.getLeftHalfCard().getName()) || sharesWordWithName(card.getRightHalfCard().getName());
} else {
if (name.contains(" // ")) {
String leftName = name.substring(0, name.indexOf(" // "));
String rightName = name.substring(name.indexOf(" // ") + 4, name.length());
return sharesWordWithName(leftName) || sharesWordWithName(rightName);
} else {
return sharesWordWithName(name);
}
}
}
private boolean sharesWordWithName(String str) {
if (referenceName == null || referenceName == "") {
return false;
}
String[] arr = referenceName.split("\\s+");
for (int i = 0; i < arr.length; i++) {
if (str.contains(arr[i].replaceAll(",", ""))) {
return true;
}
}
return false;
}
@Override
public String toString() {
return "";
}
}

View file

@ -0,0 +1,101 @@
package mage.cards.w;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public final class WhenFluffyBunniesAttack extends CardImpl {
public WhenFluffyBunniesAttack (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{B}");
// Target creature gets -X/-X until end of turn, where X is the number of times the letter of your choice appears in that creatures name.
this.getSpellAbility().addEffect(new WhenFluffyBunniesAttackEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
public WhenFluffyBunniesAttack (final WhenFluffyBunniesAttack card) {
super(card);
}
@Override
public WhenFluffyBunniesAttack copy() {
return new WhenFluffyBunniesAttack(this);
}
}
class WhenFluffyBunniesAttackEffect extends OneShotEffect {
public WhenFluffyBunniesAttackEffect() {
super(Outcome.Detriment);
staticText = "Target creature gets -X/-X until end of turn, where X is the number of times the letter of your choice appears in that creatures name";
}
public WhenFluffyBunniesAttackEffect(final WhenFluffyBunniesAttackEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getFirstTarget());
ChoiceImpl choice = new ChoiceImpl(true);
choice.setMessage("Choose letter");
Set<String> choices = new HashSet<>();
for (Character letter = 'A'; letter <= 'Z'; letter++) {
choices.add(letter.toString());
}
choice.setChoices(choices);
if (controller != null && permanent != null && controller.choose(outcome, choice, game)) {
if (!game.isSimulation()) {
MageObject mageObject = game.getObject(source.getSourceId());
if (mageObject != null) {
game.informPlayers(mageObject.getLogName() + ": " + controller.getLogName() + " has chosen " + choice.getChoice());
}
}
Character chosenLetter = choice.getChoice().charAt(0);
int unboostValue = 0;
String permName = permanent.getName();
for (int i = 0; i < permName.length(); i++) {
Character letter = permName.charAt(i);
if (Character.isLetter(letter) && Character.toUpperCase(letter) == chosenLetter) {
unboostValue--;
}
}
BoostTargetEffect effect = new BoostTargetEffect(unboostValue, unboostValue, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(permanent.getId()));
game.addEffect(effect, source);
return true;
}
return false;
}
@Override
public WhenFluffyBunniesAttackEffect copy() {
return new WhenFluffyBunniesAttackEffect(this);
}
}

View file

@ -0,0 +1,90 @@
package mage.cards.w;
import java.util.UUID;
import java.util.regex.Pattern;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author L_J
*/
public final class Wordmail extends CardImpl {
public Wordmail(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{W}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// Enchanted creature gets +1/+1 for each word in its name.
WordmailCount count = new WordmailCount();
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(count, count, Duration.WhileOnBattlefield)));
}
public Wordmail(final Wordmail card) {
super(card);
}
@Override
public Wordmail copy() {
return new Wordmail(this);
}
}
class WordmailCount implements DynamicValue {
public WordmailCount() {
}
public WordmailCount(final WordmailCount dynamicValue) {
}
@Override
public int calculate(Game game, Ability source, Effect effect) {
Permanent aura = game.getPermanent(source.getSourceId());
if (aura != null) {
Permanent permanent = game.getPermanent(aura.getAttachedTo());
if (permanent != null) {
return Pattern.compile("\\s+").split(permanent.getName()).length;
}
}
return 0;
}
@Override
public WordmailCount copy() {
return new WordmailCount(this);
}
@Override
public String toString() {
return "1";
}
@Override
public String getMessage() {
return "word in its name";
}
}

View file

@ -0,0 +1,94 @@
package mage.cards.w;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseExpansionSetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author L_J
*/
public final class WorldBottlingKit extends CardImpl {
public WorldBottlingKit(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}");
// {5}, Sacrifice World-Bottling Kit: Choose a Magic set. Exile all permanents with that sets expansion symbol except for basic lands.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new WorldBottlingKitEffect(), new ManaCostsImpl("{5}"));
ability.addCost(new SacrificeSourceCost());
this.addAbility(ability);
}
public WorldBottlingKit(final WorldBottlingKit card) {
super(card);
}
@Override
public WorldBottlingKit copy() {
return new WorldBottlingKit(this);
}
}
class WorldBottlingKitEffect extends OneShotEffect {
public WorldBottlingKitEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "Choose a Magic set. Exile all permanents with that sets expansion symbol except for basic lands";
}
public WorldBottlingKitEffect(final WorldBottlingKitEffect effect) {
super(effect);
}
@Override
public WorldBottlingKitEffect copy() {
return new WorldBottlingKitEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
ChooseExpansionSetEffect effect = new ChooseExpansionSetEffect(Outcome.Exile);
effect.apply(game, source);
String setChosen = null;
if (effect.getValue("setchosen") != null) {
setChosen = (String) effect.getValue("setchosen");
} else if (game.getState().getValue(this.getId() + "_set") != null) {
setChosen = (String) game.getState().getValue(this.getId() + "_set");
}
if (setChosen != null) {
game.informPlayers(controller.getLogName() + " has chosen set " + setChosen);
FilterPermanent filter = new FilterPermanent();
filter.add(Predicates.not(Predicates.and(new CardTypePredicate(CardType.LAND), new SupertypePredicate(SuperType.BASIC))));
List<Permanent> permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game);
for (Permanent permanent : permanents) {
if (permanent.getExpansionSetCode().equals(setChosen)) {
controller.moveCardToExileWithInfo(permanent, null, "", source.getSourceId(), game, Zone.BATTLEFIELD, true);
}
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,82 @@
package mage.cards.z;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author L_J
*/
public final class ZzzyxassAbyss extends CardImpl {
public ZzzyxassAbyss(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{B}{B}");
// At the beginning of your upkeep, destroy all nonland permanents with the first name alphabetically among nonland permanents.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ZzzyxassAbyssEffect(), TargetController.YOU, false));
}
public ZzzyxassAbyss(final ZzzyxassAbyss card) {
super(card);
}
@Override
public ZzzyxassAbyss copy() {
return new ZzzyxassAbyss(this);
}
}
class ZzzyxassAbyssEffect extends OneShotEffect {
public ZzzyxassAbyssEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "destroy all nonland permanents with the first name alphabetically among nonland permanents";
}
public ZzzyxassAbyssEffect(final ZzzyxassAbyssEffect effect) {
super(effect);
}
@Override
public ZzzyxassAbyssEffect copy() {
return new ZzzyxassAbyssEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
List<String> permanentNames = new ArrayList<>();
FilterPermanent filter = new FilterNonlandPermanent();
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, controller.getId(), game)) {
permanentNames.add(permanent.getName());
}
if (permanentNames.isEmpty()) {
return true;
}
Collections.sort(permanentNames);
filter.add(new NamePredicate(permanentNames.get(0)));
return new DestroyAllEffect(filter).apply(game, source);
}
return false;
}
}

View file

@ -21,12 +21,36 @@ public final class Unhinged extends ExpansionSet {
private Unhinged() {
super("Unhinged", "UNH", ExpansionSet.buildDate(2004, 11, 20), SetType.JOKESET);
cards.add(new SetCardInfo("\"Ach! Hans, Run!\"", 116, Rarity.RARE, mage.cards.a.AchHansRun.class));
cards.add(new SetCardInfo("B-I-N-G-O", 92, Rarity.RARE, mage.cards.b.BINGO.class));
cards.add(new SetCardInfo("Blast from the Past", 72, Rarity.RARE, mage.cards.b.BlastFromThePast.class));
cards.add(new SetCardInfo("Bloodletter", 50, Rarity.COMMON, mage.cards.b.Bloodletter.class));
cards.add(new SetCardInfo("Booster Tutor", 51, Rarity.UNCOMMON, mage.cards.b.BoosterTutor.class));
cards.add(new SetCardInfo("Double Header", 31, Rarity.COMMON, mage.cards.d.DoubleHeader.class));
cards.add(new SetCardInfo("First Come, First Served", 12, Rarity.UNCOMMON, mage.cards.f.FirstComeFirstServed.class));
cards.add(new SetCardInfo("Forest", 140, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false)));
cards.add(new SetCardInfo("Form of the Squirrel", 96, Rarity.RARE, mage.cards.f.FormOfTheSquirrel.class));
cards.add(new SetCardInfo("Goblin Secret Agent", 79, Rarity.COMMON, mage.cards.g.GoblinSecretAgent.class));
cards.add(new SetCardInfo("Island", 137, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false)));
cards.add(new SetCardInfo("Johnny, Combo Player", 35, Rarity.RARE, mage.cards.j.JohnnyComboPlayer.class));
cards.add(new SetCardInfo("Mana Screw", 123, Rarity.UNCOMMON, mage.cards.m.ManaScrew.class));
cards.add(new SetCardInfo("Mise", 38, Rarity.UNCOMMON, mage.cards.m.Mise.class));
cards.add(new SetCardInfo("Monkey Monkey Monkey", 104, Rarity.COMMON, mage.cards.m.MonkeyMonkeyMonkey.class));
cards.add(new SetCardInfo("Mountain", 139, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false)));
cards.add(new SetCardInfo("Mox Lotus", 124, Rarity.RARE, mage.cards.m.MoxLotus.class));
cards.add(new SetCardInfo("Now I Know My ABC's", 41, Rarity.RARE, mage.cards.n.NowIKnowMyABCs.class));
cards.add(new SetCardInfo("Plains", 136, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false)));
cards.add(new SetCardInfo("Rare-B-Gone", 119, Rarity.RARE, mage.cards.r.RareBGone.class));
cards.add(new SetCardInfo("Six-y Beast", 89, Rarity.UNCOMMON, mage.cards.s.SixyBeast.class));
cards.add(new SetCardInfo("Swamp", 138, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false)));
cards.add(new SetCardInfo("Symbol Status", 114, Rarity.UNCOMMON, mage.cards.s.SymbolStatus.class));
cards.add(new SetCardInfo("The Fallen Apart", 55, Rarity.COMMON, mage.cards.t.TheFallenApart.class));
cards.add(new SetCardInfo("Togglodyte", 129, Rarity.UNCOMMON, mage.cards.t.Togglodyte.class));
cards.add(new SetCardInfo("Uktabi Kong", 115, Rarity.RARE, mage.cards.u.UktabiKong.class));
cards.add(new SetCardInfo("Urza's Hot Tub", 131, Rarity.UNCOMMON, mage.cards.u.UrzasHotTub.class));
cards.add(new SetCardInfo("When Fluffy Bunnies Attack", 67, Rarity.COMMON, mage.cards.w.WhenFluffyBunniesAttack.class));
cards.add(new SetCardInfo("Wordmail", 22, Rarity.COMMON, mage.cards.w.Wordmail.class));
cards.add(new SetCardInfo("World-Bottling Kit", 133, Rarity.RARE, mage.cards.w.WorldBottlingKit.class));
cards.add(new SetCardInfo("Zzzyxas's Abyss", 70, Rarity.RARE, mage.cards.z.ZzzyxassAbyss.class));
}
}

View file

@ -132,6 +132,7 @@ public enum SubType {
ELK("Elk", SubTypeSet.CreatureType),
EYE("Eye", SubTypeSet.CreatureType),
EWOK("Ewok", SubTypeSet.CreatureType, true), // Star Wars
EXPANSION_SYMBOL("Expansion-Symbol", SubTypeSet.CreatureType, true), // Unhinged
// F
FAERIE("Faerie", SubTypeSet.CreatureType),
FERRET("Ferret", SubTypeSet.CreatureType),

View file

@ -19,6 +19,7 @@ public enum CounterType {
CAGE("cage"),
CARRION("carrion"),
CHARGE("charge"),
CHIP("chip"),
CORPSE("corpse"),
CREDIT("credit"),
CRYSTAL("crystal"),

View file

@ -0,0 +1,29 @@
package mage.game.permanent.token;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.MageInt;
/**
*
* @author L_J
*/
public final class ExpansionSymbolToken extends TokenImpl {
public ExpansionSymbolToken() {
super("Expansion-Symbol", "1/1 colorless Expansion-Symbol creature token");
cardType.add(CardType.CREATURE);
subtype.add(SubType.EXPANSION_SYMBOL);
power = new MageInt(1);
toughness = new MageInt(1);
}
public ExpansionSymbolToken(final ExpansionSymbolToken token) {
super(token);
}
public ExpansionSymbolToken copy() {
return new ExpansionSymbolToken(this);
}
}

View file

@ -0,0 +1,30 @@
package mage.game.permanent.token;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.MageInt;
/**
*
* @author L_J
*/
public final class UktabiKongApeToken extends TokenImpl {
public UktabiKongApeToken() {
super("Ape", "1/1 green Ape creature token");
cardType.add(CardType.CREATURE);
subtype.add(SubType.APE);
color.setGreen(true);
power = new MageInt(1);
toughness = new MageInt(1);
}
public UktabiKongApeToken(final UktabiKongApeToken token) {
super(token);
}
public UktabiKongApeToken copy() {
return new UktabiKongApeToken(this);
}
}