diff --git a/res/cardsfolder/vedalken_entrancer.txt b/res/cardsfolder/vedalken_entrancer.txt index 6c52d7ab8ae..af4b002fa78 100644 --- a/res/cardsfolder/vedalken_entrancer.txt +++ b/res/cardsfolder/vedalken_entrancer.txt @@ -2,6 +2,7 @@ Name:Vedalken Entrancer ManaCost:3 U Types:Creature Vedalken Wizard Text:no text +A:AB$Mill|Cost$U T|NumCards$2|ValidTgts$Player|TgtPrompt$Choose a player to mill|SpellDescription$Target player puts the top two cards of his or her library into his or her graveyard. PT:1/4 SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/vedalken_entrancer.jpg diff --git a/src/forge/AbilityFactory.java b/src/forge/AbilityFactory.java index cc72a7e540b..f4b36250f88 100644 --- a/src/forge/AbilityFactory.java +++ b/src/forge/AbilityFactory.java @@ -280,6 +280,14 @@ public class AbilityFactory { } } + if (API.equals("Mill")){ + if (isAb) + SA = AbilityFactory_ZoneAffecting.createAbilityMill(this); + if (isSp){ + SA = AbilityFactory_ZoneAffecting.createSpellMill(this); + } + } + // ********************************************* // set universal properties of the SpellAbility if (hasSpDesc) diff --git a/src/forge/AbilityFactory_ZoneAffecting.java b/src/forge/AbilityFactory_ZoneAffecting.java index d780f8899be..7a4a6cfde07 100644 --- a/src/forge/AbilityFactory_ZoneAffecting.java +++ b/src/forge/AbilityFactory_ZoneAffecting.java @@ -106,9 +106,9 @@ public class AbilityFactory_ZoneAffecting { if (params.containsKey("NumCards")) numCards = Integer.parseInt(params.get("NumCards")); - if (numCards >= AllZoneUtil.getCardsInZone(Constant.Zone.Library, AllZone.HumanPlayer).size()){ + if (!AllZone.HumanPlayer.cantLose() && numCards >= AllZoneUtil.getCardsInZone(Constant.Zone.Library, AllZone.HumanPlayer).size()){ // Deck the Human? DO IT! - tgt.addTarget(AllZone.ComputerPlayer); + tgt.addTarget(AllZone.HumanPlayer); return true; } @@ -153,4 +153,160 @@ public class AbilityFactory_ZoneAffecting { CardFactoryUtil.doDrawBack(DrawBack, 0, source.getController(), source.getController().getOpponent(), source.getController(), source, null, sa); } + + + // ******************** MILL **************************** + + public static SpellAbility createAbilityMill(final AbilityFactory AF){ + final SpellAbility abMill = new Ability_Activated(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()){ + private static final long serialVersionUID = 5445572699000471299L; + + final AbilityFactory af = AF; + + @Override + public String getStackDescription(){ + // when getStackDesc is called, just build exactly what is happening + Player player = af.getAbTgt() == null ? getActivatingPlayer() : getTargetPlayer(); + StringBuilder sb = new StringBuilder(); + + sb.append(getSourceCard().getName()); + sb.append(" - Mills "); + sb.append(af.getMapParams().get("NumCards")); + sb.append(" Cards from "); + sb.append(player.toString()); + sb.append("'s library."); + + return sb.toString(); + } + + public boolean canPlay(){ + // super takes care of AdditionalCosts + return super.canPlay(); + } + + public boolean canPlayAI() + { + return millCanPlayAI(af,this); + } + + @Override + public void resolve() { + millResolve(af, this); + } + + }; + return abMill; + } + + public static SpellAbility createSpellMill(final AbilityFactory AF){ + final SpellAbility spMill = new Spell(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()){ + private static final long serialVersionUID = -4990932993654533449L; + + final AbilityFactory af = AF; + + public boolean canPlay(){ + // super takes care of AdditionalCosts + return super.canPlay(); + } + + public boolean canPlayAI() + { + return millCanPlayAI(af, this); + } + + @Override + public void resolve() { + millResolve(af, this); + } + + }; + return spMill; + } + + public static boolean millCanPlayAI(final AbilityFactory af, SpellAbility sa){ + // AI cannot use this properly until he can use SAs during Humans turn + if (!ComputerUtil.canPayCost(sa)) + return false; + + Target tgt = af.getAbTgt(); + Card source = sa.getSourceCard(); + Ability_Cost abCost = af.getAbCost(); + HashMap params = af.getMapParams(); + + if (abCost != null){ + // AI currently disabled for these costs + if (abCost.getSacCost()){ + return false; + } + if (abCost.getLifeCost()){ + if (AllZone.ComputerPlayer.getLife() - abCost.getLifeAmount() < 4) + return false; + } + if (abCost.getDiscardCost()) return false; + + if (abCost.getSubCounter()) { + if (abCost.getCounterType().equals(Counters.P1P1)) return false; // Other counters should be used + } + + } + + if (tgt != null){ + tgt.resetTargets(); + + // todo: handle deciding what X would be around here for Psychic Drain type cards + int numCards = 1; + if (params.containsKey("NumCards")) + numCards = Integer.parseInt(params.get("NumCards")); + + CardList pLibrary = AllZoneUtil.getCardsInZone(Constant.Zone.Library, AllZone.HumanPlayer); + + if (pLibrary.size() == 0) // deck already empty, no need to mill + return false; + + if (numCards >= pLibrary.size()){ + // Can Mill out Human's deck? Do it! + tgt.addTarget(AllZone.HumanPlayer); + return true; + } + + // Obscure case when you know what your top card is so you might? want to mill yourself here + // if (AI wants to mill self) + // tgt.addTarget(AllZone.ComputerPlayer); + // else + tgt.addTarget(AllZone.HumanPlayer); + } + + Random r = new Random(); + boolean randomReturn = r.nextFloat() <= Math.pow(.6667, source.getAbilityUsed()); + + // some other variables here, like deck size, and phase and other fun stuff + + return randomReturn; + } + + public static void millResolve(final AbilityFactory af, final SpellAbility sa){ + HashMap params = af.getMapParams(); + + Card source = sa.getSourceCard(); + int numCards = Integer.parseInt(params.get("NumCards")); + + ArrayList tgtPlayers; + + Target tgt = af.getAbTgt(); + if (tgt != null) + tgtPlayers = tgt.getTargetPlayers(); + else{ + tgtPlayers = new ArrayList(); + tgtPlayers.add(sa.getActivatingPlayer()); + } + + for(Player p : tgtPlayers) + if (tgt == null || p.canTarget(af.getHostCard())) + p.mill(numCards); + + String DrawBack = params.get("SubAbility"); + if (af.hasSubAbility()) + CardFactoryUtil.doDrawBack(DrawBack, 0, source.getController(), source.getController().getOpponent(), tgtPlayers.get(0), source, null, sa); + + } } diff --git a/src/forge/CardFactory_Creatures.java b/src/forge/CardFactory_Creatures.java index a91b51f9bb6..4b81c56f8b0 100644 --- a/src/forge/CardFactory_Creatures.java +++ b/src/forge/CardFactory_Creatures.java @@ -17086,35 +17086,7 @@ public class CardFactory_Creatures { a1.setBeforePayMana(new Input_PayManaCost(a1)); a1.setBeforePayMana(CardFactoryUtil.input_targetPlayer(a1)); }//*************** END ************ END ************************** - - - //*************** START *********** START ************************** - else if(cardName.equals("Vedalken Entrancer")) { - final SpellAbility a1 = new Ability_Tap(card, "U") { - private static final long serialVersionUID = 2359247592519063187L; - - @Override - public void resolve() { - getTargetPlayer().mill(2); - - } - - - @Override - public boolean canPlayAI() { - Player player = getTargetPlayer(); - PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player); - CardList libList = new CardList(lib.getCards()); - return libList.size() > 0; - } - };//SpellAbility - card.addSpellAbility(a1); - a1.setDescription("U, tap: Target player puts the top two cards of his or her library into his or her graveyard."); - a1.setStackDescription("Player puts the top two cards of his or her library into his or her graveyard"); - a1.setBeforePayMana(new Input_PayManaCost(a1)); - a1.setBeforePayMana(CardFactoryUtil.input_targetPlayer(a1)); - }//*************** END ************ END ************************** - + //*************** START *********** START ************************** else if(cardName.equals("Cathartic Adept")) {