[SPM] Implement Black Cat, Cunning Thief

This commit is contained in:
jmlundeen 2025-09-03 15:18:46 -05:00
parent 6e29b8e7fa
commit 538debf2e0
3 changed files with 158 additions and 0 deletions

View file

@ -0,0 +1,91 @@
package mage.cards.b;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect;
import mage.cards.*;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetOpponent;
import mage.target.targetpointer.FixedTargets;
import java.util.UUID;
import java.util.stream.Collectors;
/**
*
* @author Jmlundeen
*/
public final class BlackCatCunningThief extends CardImpl {
public BlackCatCunningThief(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ROGUE);
this.subtype.add(SubType.VILLAIN);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// When Black Cat enters, look at the top nine cards of target opponent's library, exile two of them face down, then put the rest on the bottom of their library in a random order. You may play the exiled cards for as long as they remain exiled. Mana of any type can be spent to cast spells this way.
Ability ability = new EntersBattlefieldTriggeredAbility(new BlackCatCunningThiefEffect());
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
}
private BlackCatCunningThief(final BlackCatCunningThief card) {
super(card);
}
@Override
public BlackCatCunningThief copy() {
return new BlackCatCunningThief(this);
}
}
class BlackCatCunningThiefEffect extends OneShotEffect {
public BlackCatCunningThiefEffect() {
super(Outcome.Benefit);
this.staticText = "look at the top nine cards of target opponent's library, exile two of them face down, then put the rest on the bottom of their library in a random order. You may play the exiled cards for as long as they remain exiled. Mana of any type can be spent to cast spells this way";
}
private BlackCatCunningThiefEffect(final BlackCatCunningThiefEffect effect) {
super(effect);
}
@Override
public BlackCatCunningThiefEffect copy() {
return new BlackCatCunningThiefEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source));
MageObject sourceObject = source.getSourceObject(game);
if (controller == null || opponent == null || sourceObject == null) {
return false;
}
Cards topCards = new CardsImpl();
topCards.addAllCards(opponent.getLibrary().getTopCards(game, 9));
TargetCard target = new TargetCard(2, 2, Zone.LIBRARY, new FilterCard("card to exile"));
controller.choose(outcome, topCards, target, source, game);
Cards exiledCards = new CardsImpl(target.getTargets().stream()
.map(game::getCard)
.collect(Collectors.toList()));
new ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect(false, CastManaAdjustment.AS_THOUGH_ANY_MANA_TYPE)
.setTargetPointer(new FixedTargets(exiledCards, game))
.apply(game, source);
topCards.retainZone(Zone.LIBRARY, game);
// then put the rest on the bottom of that library in a random order
controller.putCardsOnBottomOfLibrary(topCards, game, source, false);
return true;
}
}

View file

@ -36,6 +36,8 @@ public final class MarvelsSpiderMan extends ExpansionSet {
cards.add(new SetCardInfo("Beetle, Legacy Criminal", 26, Rarity.COMMON, mage.cards.b.BeetleLegacyCriminal.class));
cards.add(new SetCardInfo("Behold the Sinister Six!", 221, Rarity.MYTHIC, mage.cards.b.BeholdTheSinisterSix.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Behold the Sinister Six!", 51, Rarity.MYTHIC, mage.cards.b.BeholdTheSinisterSix.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Black Cat, Cunning Thief", 222, Rarity.RARE, mage.cards.b.BlackCatCunningThief.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Black Cat, Cunning Thief", 52, Rarity.RARE, mage.cards.b.BlackCatCunningThief.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Carnage, Crimson Chaos", 125, Rarity.RARE, mage.cards.c.CarnageCrimsonChaos.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Carnage, Crimson Chaos", 227, Rarity.RARE, mage.cards.c.CarnageCrimsonChaos.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Chameleon, Master of Disguise", 27, Rarity.UNCOMMON, mage.cards.c.ChameleonMasterOfDisguise.class));

View file

@ -0,0 +1,65 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class BlackCatCunningThiefTest extends CardTestPlayerBase {
/*
Black Cat, Cunning Thief
{3}{B}{B}
Legendary Creature - Human Rogue Villain
When Black Cat enters, look at the top nine cards of target opponent's library, exile two of them face down, then put the rest on the bottom of their library in a random order. You may play the exiled cards for as long as they remain exiled. Mana of any type can be spent to cast spells this way.
2/3
*/
private static final String blackCatCunningThief = "Black Cat, Cunning Thief";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
private static final String bearCub = "Bear Cub";
/*
Fugitive Wizard
{U}
Creature - Human Wizard
1/1
*/
private static final String fugitiveWizard = "Fugitive Wizard";
@Test
public void testBlackCatCunningThief() {
setStrictChooseMode(true);
skipInitShuffling();
addCard(Zone.HAND, playerA, blackCatCunningThief);
addCard(Zone.LIBRARY, playerB, bearCub);
addCard(Zone.LIBRARY, playerB, fugitiveWizard);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 8);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, blackCatCunningThief);
addTarget(playerA, playerB);
setChoice(playerA, bearCub);
setChoice(playerA, fugitiveWizard);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bearCub, true);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, fugitiveWizard);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, bearCub, 1);
assertPermanentCount(playerA, fugitiveWizard, 1);
}
}