From 0cd0b7045a93aa4fd7101c9857057a7f58861a2a Mon Sep 17 00:00:00 2001 From: BetaSteward Date: Tue, 23 Nov 2010 05:08:45 +0000 Subject: [PATCH] lots of fixes - mainly to continuous effects and zone changes --- .../src/mage/game/FreeForAll.java | 2 +- .../src/mage/player/ai/ComputerPlayer.java | 16 ++ .../src/mage/player/ai/ComputerPlayer2.java | 17 ++ .../src/mage/player/human/HumanPlayer.java | 54 ++++- Mage.Server/plugins/mage-deck-constructed.jar | Bin 3190 -> 3189 bytes Mage.Server/plugins/mage-game-freeforall.jar | Bin 4384 -> 4392 bytes .../plugins/mage-game-twoplayerduel.jar | Bin 3957 -> 3957 bytes Mage.Server/plugins/mage-player-ai.jar | Bin 28466 -> 28582 bytes Mage.Server/plugins/mage-player-aiminimax.jar | Bin 36352 -> 36470 bytes Mage.Server/plugins/mage-player-human.jar | Bin 10514 -> 10999 bytes .../src/mage/server/game/GameController.java | 2 +- .../sets/alarareborn/VengefulRebirth.java | 2 +- .../src/mage/sets/conflux/PathToExile.java | 2 +- .../sets/conflux/SigilOfTheEmptyThrone.java | 14 +- Mage.Sets/src/mage/sets/magic2010/Duress.java | 2 +- .../sets/magic2010/MasterOfTheWildHunt.java | 6 +- .../src/mage/sets/magic2011/CallToMind.java | 6 +- .../mage/sets/magic2011/ConundrumSphinx.java | 4 +- .../src/mage/sets/magic2011/Cultivate.java | 4 +- .../src/mage/sets/magic2011/DarkTutelage.java | 3 +- .../sets/magic2011/ElixirOfImmortality.java | 4 +- .../mage/sets/magic2011/LeylineOfTheVoid.java | 18 +- .../mage/sets/magic2011/MassPolymorph.java | 4 +- .../mage/sets/magic2011/MystifyingMaze.java | 2 +- .../mage/sets/magic2011/ObstinateBaloth.java | 12 +- .../src/mage/sets/magic2011/TimeReversal.java | 4 +- .../sets/riseoftheeldrazi/SeaGateOracle.java | 21 +- .../mage/sets/riseoftheeldrazi/SeeBeyond.java | 5 +- .../mage/sets/riseoftheeldrazi/Vengevine.java | 2 +- .../src/mage/sets/tenth/AngelsFeather.java | 4 +- Mage.Sets/src/mage/sets/tenth/DemonsHorn.java | 4 +- .../src/mage/sets/tenth/DragonsClaw.java | 4 +- Mage.Sets/src/mage/sets/tenth/KrakensEye.java | 4 +- Mage.Sets/src/mage/sets/tenth/WurmsTooth.java | 4 +- .../sets/worldwake/JaceTheMindSculptor.java | 9 +- .../src/mage/sets/zendikar/GoblinGuide.java | 3 +- Mage/src/mage/Constants.java | 21 ++ Mage/src/mage/MageObject.java | 4 +- Mage/src/mage/MageObjectImpl.java | 22 +- Mage/src/mage/abilities/Ability.java | 2 + Mage/src/mage/abilities/AbilityImpl.java | 14 +- .../mage/abilities/ActivatedAbilityImpl.java | 2 +- .../costs/common/ExileSourceCost.java | 3 +- .../costs/common/ReturnToHandTargetCost.java | 2 +- .../abilities/effects/AsThoughEffectImpl.java | 2 + .../effects/ContinuousEffectImpl.java | 2 + .../abilities/effects/ContinuousEffects.java | 223 ++++++++++++------ Mage/src/mage/abilities/effects/Effect.java | 2 + .../mage/abilities/effects/EffectImpl.java | 8 + .../mage/abilities/effects/OneShotEffect.java | 2 + .../effects/PreventionEffectImpl.java | 2 + .../abilities/effects/RedirectionEffect.java | 2 + .../effects/ReplacementEffectImpl.java | 2 + .../common/CantCounterControlledEffect.java | 6 +- .../common/CantTargetControlledEffect.java | 8 +- .../common/CantTargetControllerEffect.java | 2 - .../common/CantTargetSourceEffect.java | 2 - .../effects/common/ExileSourceEffect.java | 2 +- .../effects/common/ExileTargetEffect.java | 2 +- .../common/PutOnLibraryTargetEffect.java | 9 +- .../effects/common/ReturnFromExileEffect.java | 2 +- ...ReturnSourceFromGraveyardToHandEffect.java | 2 +- .../common/ReturnToHandTargetEffect.java | 2 +- .../abilities/effects/common/ScryEffect.java | 17 +- .../common/SearchLibraryPutInHandEffect.java | 2 +- .../SearchLibraryPutOnLibraryEffect.java | 2 +- .../SearchLibraryRevealPutInHandEffect.java | 2 +- .../abilities/keyword/CascadeAbility.java | 15 +- Mage/src/mage/cards/Card.java | 4 +- Mage/src/mage/cards/CardImpl.java | 34 +-- Mage/src/mage/cards/CardsImpl.java | 4 +- Mage/src/mage/choices/Choice.java | 1 + Mage/src/mage/choices/ChoiceImpl.java | 5 + Mage/src/mage/filter/Filter.java | 1 - Mage/src/mage/filter/FilterObject.java | 17 -- Mage/src/mage/game/Game.java | 5 +- Mage/src/mage/game/GameImpl.java | 58 +++-- Mage/src/mage/game/GameState.java | 22 +- Mage/src/mage/game/events/GameEvent.java | 4 +- .../mage/game/permanent/PermanentCard.java | 36 ++- .../mage/game/permanent/PermanentImpl.java | 24 +- .../mage/game/permanent/PermanentToken.java | 8 +- Mage/src/mage/game/stack/Spell.java | 22 +- Mage/src/mage/game/stack/SpellStack.java | 2 +- Mage/src/mage/game/stack/StackAbility.java | 15 +- Mage/src/mage/game/stack/StackObject.java | 2 +- Mage/src/mage/players/Library.java | 8 +- Mage/src/mage/players/Player.java | 1 + Mage/src/mage/players/PlayerImpl.java | 37 ++- Mage/src/mage/target/TargetObject.java | 2 +- .../target/common/TargetCardInGraveyard.java | 2 +- .../target/common/TargetCardInLibrary.java | 4 +- .../common/TargetCardInYourGraveyard.java | 2 +- 93 files changed, 600 insertions(+), 348 deletions(-) diff --git a/Mage.Game.FreeForAll/src/mage/game/FreeForAll.java b/Mage.Game.FreeForAll/src/mage/game/FreeForAll.java index 39d20ac0bd2..478dcb5b933 100644 --- a/Mage.Game.FreeForAll/src/mage/game/FreeForAll.java +++ b/Mage.Game.FreeForAll/src/mage/game/FreeForAll.java @@ -96,7 +96,7 @@ public class FreeForAll extends GameImpl { numCards += 1; mulliganed.add(playerId); } - player.getLibrary().addAll(player.getHand().getCards(this)); + player.getLibrary().addAll(player.getHand().getCards(this), this); player.getHand().clear(); player.shuffleLibrary(this); player.drawCards(numCards - 1, this); diff --git a/Mage.Player.AI/src/mage/player/ai/ComputerPlayer.java b/Mage.Player.AI/src/mage/player/ai/ComputerPlayer.java index c2ecd4873b8..8bb239904ef 100644 --- a/Mage.Player.AI/src/mage/player/ai/ComputerPlayer.java +++ b/Mage.Player.AI/src/mage/player/ai/ComputerPlayer.java @@ -641,6 +641,22 @@ public class ComputerPlayer> extends PlayerImpl i return true; } + @Override + public boolean choose(Cards cards, TargetCard target, Game game) { + logger.fine("choose"); + //TODO: improve this + //return first match + if (!target.doneChosing()) { + for (Card card: cards.getCards(target.getFilter(), game)) { + target.add(card.getId(), game); + if (target.doneChosing()) + return true; + } + return false; + } + return true; + } + @Override public void selectAttackers(Game game) { logger.fine("selectAttackers"); diff --git a/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java b/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java index 0f1161b0d79..6b145ff62c3 100644 --- a/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java +++ b/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java @@ -474,6 +474,23 @@ public class ComputerPlayer2 extends ComputerPlayer implements return true; } + @Override + public boolean choose(Cards cards, TargetCard target, Game game) { + if (targets.size() == 0) + return super.choose(cards, target, game); + if (!target.doneChosing()) { + for (UUID targetId: targets) { + target.add(targetId, game); + if (target.doneChosing()) { + targets.clear(); + return true; + } + } + return false; + } + return true; + } + public void playNext(Game game, UUID activePlayerId, SimulationNode node) { boolean skip = false; while (true) { diff --git a/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index d62c29862d9..c3a0ad9d447 100644 --- a/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -50,6 +50,7 @@ import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.VariableManaCost; import mage.cards.decks.Deck; +import mage.choices.ChoiceImpl; import mage.filter.common.FilterCreatureForCombat; import mage.game.Game; import mage.game.permanent.Permanent; @@ -72,8 +73,11 @@ public class HumanPlayer extends PlayerImpl { private boolean abort; protected static FilterCreatureForCombat filter = new FilterCreatureForCombat(); + protected static Choice replacementEffectChoice = new ChoiceImpl(true); + static { filter.setTargetController(TargetController.YOU); + replacementEffectChoice.setMessage("Choose replacement effect"); } protected transient TargetCreaturePermanent targetCombat = new TargetCreaturePermanent(filter); @@ -140,7 +144,23 @@ public class HumanPlayer extends PlayerImpl { @Override public int chooseEffect(List rEffects, Game game) { - //TODO: implement this + replacementEffectChoice.getChoices().clear(); + for (ReplacementEffect effect: rEffects) { + replacementEffectChoice.getChoices().add(effect.getText(null)); + } + if (replacementEffectChoice.getChoices().size() == 1) + return 0; + while (!abort) { + game.fireChooseEvent(playerId, replacementEffectChoice); + waitForResponse(); + if (response.getString() != null) { + replacementEffectChoice.setChoice(response.getString()); + for (int i = 0; i < rEffects.size(); i++) { + if (replacementEffectChoice.getChoice().equals(rEffects.get(i).getText(null))) + return i; + } + } + } return 0; } @@ -194,9 +214,26 @@ public class HumanPlayer extends PlayerImpl { } @Override - public boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game) { - game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired()); + public boolean choose(Cards cards, TargetCard target, Game game) { while (!abort) { + game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired()); + waitForResponse(); + if (response.getUUID() != null) { + if (target.canTarget(response.getUUID(), cards, game)) { + target.add(response.getUUID(), game); + return true; + } + } else if (!target.isRequired()) { + return false; + } + } + return false; + } + + @Override + public boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game) { + while (!abort) { + game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired()); waitForResponse(); if (response.getUUID() != null) { if (target.canTarget(response.getUUID(), cards, game)) { @@ -210,11 +247,10 @@ public class HumanPlayer extends PlayerImpl { return false; } - @Override public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) { - game.fireSelectTargetEvent(playerId, target.getMessage() + "\n Amount remaining:" + target.getAmountRemaining(), target.isRequired()); while (!abort) { + game.fireSelectTargetEvent(playerId, target.getMessage() + "\n Amount remaining:" + target.getAmountRemaining(), target.isRequired()); waitForResponse(); if (response.getUUID() != null) { if (target.canTarget(response.getUUID(), source, game)) { @@ -251,7 +287,7 @@ public class HumanPlayer extends PlayerImpl { MageObject object = game.getObject(response.getUUID()); if (object != null) { Map useableAbilities = null; - switch (object.getZone()) { + switch (game.getZone(object.getId())) { case HAND: useableAbilities = getUseableAbilities(object.getAbilities().getActivatedAbilities(Zone.HAND), game); break; @@ -314,7 +350,7 @@ public class HumanPlayer extends PlayerImpl { protected void playManaAbilities(Game game) { MageObject object = game.getObject(response.getUUID()); Map useableAbilities; - switch (object.getZone()) { + switch (game.getZone(object.getId())) { case HAND: useableAbilities = getUseableAbilities(object.getAbilities().getManaAbilities(Zone.HAND), game); if (useableAbilities.size() > 0) { @@ -399,17 +435,19 @@ public class HumanPlayer extends PlayerImpl { int remainingDamage = damage; while (remainingDamage > 0) { Target target = new TargetCreatureOrPlayer(); - chooseTarget(Outcome.Damage, target, null, game); + choose(Outcome.Damage, target, game); if (targets.size() == 0 || targets.contains(target.getFirstTarget())) { int damageAmount = getAmount(0, remainingDamage, "Select amount", game); Permanent permanent = game.getPermanent(target.getFirstTarget()); if (permanent != null) { permanent.damage(damageAmount, sourceId, game, true); + remainingDamage -= damageAmount; } else { Player player = game.getPlayer(target.getFirstTarget()); if (player != null) { player.damage(damageAmount, sourceId, game, false, true); + remainingDamage -= damageAmount; } } } diff --git a/Mage.Server/plugins/mage-deck-constructed.jar b/Mage.Server/plugins/mage-deck-constructed.jar index d27c8faaee510ee363ae6330b6708bd686cb0c5f..8a11731b1e0fb81c132b1ac80e244cc5e288d8b2 100644 GIT binary patch delta 298 zcmew+@l}F1z?+$civa|F?WFK-!m@OYM{{E?H`M1} z+rB4FNsV`=SjE2s?M^wqk6RzAu?jH$J~+2c`Ow#Y3?=O8zKVCl9$qZnYwDT$|J-Sf zS-bo_QhYD$+2?ddw6^t|)5p8>TDPyMUNh0OKERuiNrV~h0b8(77$(o<)CGBD@>x!M suv7WD48XJ#mnoR8;&KDihqk delta 299 zcmew=@lAp^z?+$civa{Aw&YIaRbdtfQYKTFLA=unVCtPJh}ta1IFALyn7o};3rs&@ zH3myav8`g_1WMS(P1vhnJozj~K>c5Z{{p3U4c*IYpL{r%fU zX`Of5m82Ceesy)!_7lBj++JRNDl_<|b1%;y#sF_dCJ|=14{X6+nLL|Q59E=_XE^P_ rPUYh=0Mm|KreL~~%MDB);<5tM|GAvOv@7=>B%g5cq_VYhf=mPeZWC>T diff --git a/Mage.Server/plugins/mage-game-freeforall.jar b/Mage.Server/plugins/mage-game-freeforall.jar index 51ed106cf9b4af6828c6071c46b774a40e669974..24f9d2e89f40b314ff9631b2e85936a72fac1ec1 100644 GIT binary patch delta 2349 zcmZuzXHXMb7N!OagrYPFp$TDwM0ziR;u8evC<0OwdM7|YGzLU@R3Rut5kZh99qC0% z6e$5CDAGc2k5ENA;R)+=cXsy9-22Tp_ndFeIe)&BDVi?|GBKcM0MZA+9$@1Ie)&2EdGXAgwLk?$YaXh$v703uWuO?b{MkV@ta=^P$)!SB> zsF5hqYa8qL0mf!s{NWIQ7l<1&RuF3@T=`1vwNDmJIxP; zm=}DIKQ46GRyJ1L|Cn56?Jv;aP=5nsml?9v7~0xn5kAt{GmOMs5-xY+we2rOKW(8x zw@CHh7yF0sf9gvT5{FBcjXid`aqlYZw;}`1b{`eXM_Z^n)M#d`c zao&BYFcwi&mL8P)B4&1O!Bzb zRkuBxE9w!Uc|GEfQm8{ty{O)_40xZ2>|E)$B9ency+esLemVmQkq$FYXx9K$iezm= z3bh|eWS`-y^BADJ+_^!oJpM^h<}$yw6d^LSp4gR4a4L zpjHY8R+(=cc0(RxJc@Pkt(Y0N+YFX!-jvL5;gGafou+N>SL>4a4P21<{86sU$YJ?f zn}0otDS01vD-sbnlO6Qnioqol>4zI~{kr}(b$M4%W#zay1He;)|w&ic3WqFvaP0)nr^0nY9 zv9pJ8*3sB+B$HOXX?w+2RJV2u*hffk!hd z6yK-sjV0y3bP{VC|=FN~L1$ zr$d$cT3FD%EwO0*c1$N?ed5D*NFp<(p=()(x46CUly?h8UfwfOPmxGiUO}j*=o^Jh zKfljh?I|dxGGeDb9CIt9MsV}V?w#nsn-DcjNKfv$Rq$o(4Wp|C+hF_UDjIh#+>ncU~>ZRTGs66HM%VM8N^&RWQQk>TYY z?%U&U#{woWzF+M&3`_52ym5>YP(4aviH}nlY$V33eClP5bbTK!*PM^LE(wPYwI!rG zRk#DozD^^Y=(;Y zCk2cwI_%3UN_@EygX)J)!cd)L@1;`Lp)DykU6Ku^>5y*x>~+6FwWnww0chM>EbM(^ zGxHHTz5pVv#EclAMlMWc+!T2!BtGk-yUVnh_u(^`qX4ek>n$9{SU#9?(6K|garzNw zUc8n-D_jG_WS!Pxs=ch0pg)|_VB;V6>~pup0y6fqY>9k9IS4hNsvqB!u)|HLBPeB^ z>UoV(Cc)OkwgPY*Xz*TmOwamt)D^$2-EAs-I;OC;#8J0}xZq&h)Z@l}cTBfeAv;+% zci}s9?hY7cN^$je@l!wNEKpVJ>X)vLRj(b7`gn&c)51AqTY^a*Y)zjkRe<#kz(NL6=F2%GjSEZ6)T&a& zM^+L`@+ITq7%5e$F-0 z?#m;dK1?uSC}ovYK#Pc6_op8J_h0SlDEwtI3K7a2!KVq1UrZw52-BwxGnRs z+gAEAXVV@#ERGu}$$4zCCqDe^;lq)DV4NoqcpOoQ2A0t=ABPm4V@<%xfJ`u&en);2 zMLDNl3#*_^{Pj||m`Z-|GZ3H1gEm)}!1js(POp39wJ?17est!H`e^^?ZNI?mF1#tOUs&dmt(qwd4PW+M%o{6+nAF)esVn9pB zMgMz8_*EqC2n0Xg6>!pQ7f*WdXOlU>95%)OSr_Km)P;^qzrQ0w@Svrk;iRLX5&W-K zbFdybZFcxcwjVo~mID{ZE_lL<*}-(0K%6O1K=S|9@NW(HZz&F%qocs%aDE&G$c?+m tAxYQ#4;7I5Pah}KKbd5}&s@~ctNvSqh9(CK1^v=Eo6N}%SO*<{{td&sRoMUl delta 2329 zcmZuzdpHy7A2%y@XsEf>+?g5Xk|xX|_v;8LiOyV-)~q4yn3l^b$#p7~Yvme4bLZre zyGpvaB#oVfVm3~-c#~lc>CidK!khQ#N&pqAXK*C+*xri_HM};NjZA?Ytf_ug zlOBkUOOP&!hmM5oi@micC|IQMdSSI`si~XoeKj3)LLsjB92mW`-z}fk&A@8}e(#); z;il&eg*lMlqch5r=?W<^r#Ug-rpc@!v-RaAErAsFB1tXXplY8j2)pYF>4-*ZAA&_g zHBfyt@-z)=>6z1+X_rermGhQM&_n4?d_buFLcSD?0XF1@8{HR6#|s{E4K7$=6} ztS((y){xoKt(uP8o8g$kd|>rwq6k zXbs-J(R##+abNqxh4#m_W|pzfLl?>|sEhBcKWE&~{DD1$n#o+Xr;TRN!;r1>VPm8Bzk6m%tD-{zIsdyRPfeb!L}dOd&R&<8;~D*Jo36v zeEBVS;MrJ`R&XTjRNcg`wP&!8!{ymIcMuIQR_NNxf(;z;kr!iZ_`|F*t=CDJ>i7^7 zmV(#K9JxtYyk46PFQhWks+VT82h*czvbAG*ND<-u-I$?YK(at!Yg|+YgWT}YE=o41LP;{T2)`VQJBq9DJkmYFkb^@izVGeNRCK-MP*VS11J?f_LWk! zAy$VHsU>-y_q7O?!*?r~51gl`NHT)1kgfI`@C;kx$(#V=1@drHIS_{-_zBv62%qSb z?FLguI=^vaR0cZ5xt0*Kj#Q~8Xi@+h9(DP*dQrqB94n;*@vx>Jo5e?5><+!nH_i=Q zc3Kr2%;Li?22PGp)pMV;B(gx$_57T~8D3m0>nVj#NyrWJ;H>1+Vnc zak~`^QH<-t)_(15V@Yx-VbNAoZO(PVJ~d)y@EXA2Q))R_<;wv`eKcgjRXv;2tqa&a z|JoE}G|rIsf1`;UJw_p{u~SAu}!?o$6h6XZQs?X#7YpWSgT6cI8T`_6LX_D770f*-sw#t8H?8IDO+r zi;w&G#HVz2b$O5vqw_$TUH#Pu@%xaoy7vB}@raDGC%Wz-QQ3AikGxTuVF$hBBcC}m zKhB}+M6S@xoy^liK34{H@y>~vw|h5l>}lQYOy!oENUs`-iQDi+5q*ke<#iHa4kEKx z(rsncGo1JIP0tM4o(#gR1J?SgdCnyt3@u~~cR!Bp6+N-;Ly5pA-oN_NMloed;r(SG z(ur-9@3Pn}N$8*R&CV~1y3L3hD+*6o9Q!b;Zt^Kxt;g5uZ=rh>>$=}Ho~9BD+^2%) zsWZw&Turv9{eF1e3#pFpK`efKr_?ZMqT}kN=Arh6KW+~lT4_qk-fIKXSD#zf`53K; zz{v#=PLs@3{pD&Kf=C%~nsC(n_!m$~QK(Vj#;Z2GlgAV$iU>=;Z=#Y3n$#Vaj+NeG~W-^^}XGu_6tKYrpVJ4On)EBV=8F}sg z+8!?&AM1haDY1z&x>zOMYXwU?zi1vNyL9o=P=JN2NLDz!`VK>wS`^jz(dN82Ylo%lezv#uN zU zUPN;n9YhSakaa~ z{`4^CPo=7&FV8B&KZe^Fb9DkMRbpO`*D0?8Tpa;|lE7b10JCig1n9zI$Sp@eKPYCl zJt*I#GwHECWF!!C8X%K5}JUz|FFIEA_;M& jf4?+zGe3NDqkq*A5O@%)0H&vk=+bxWRuGy4Z$nk diff --git a/Mage.Server/plugins/mage-game-twoplayerduel.jar b/Mage.Server/plugins/mage-game-twoplayerduel.jar index d8a23746b2f7cc6bb355f68175779eeac31e1355..cf7a4305be1a9bbac53fd04db57a59bb43036f4a 100644 GIT binary patch delta 307 zcmew=_f?KJz?+$civa}w>?oVatHS&nNSRDw2JucSfT?$?AZoK1V;?J+v7BuQBZx8C zk3$PgS92JHB{p*GVB!Eu*fKRI^iD41_N#Al5Ma3Q`@p}$4e6=T-3}kpJlcB|>Jv_7 z3YMrZD?Pmbe0h!Q`H547`hVQH5d17-!3Uv_YLauE!_B|lnbTKM$@AjPL8%jK?t3O> zufF9F5NUsXqbToHr$*ih%U=4f-?IGv;y0NOi+-G}UDmrby3*_edw@41lL#~1Ka=fv zOh6u*T*_k)cIkE=12FxH#}rH}@p^#iTwWhAy@%HdO#kF{2GjO@2M``&=g$KGO16t- delta 307 zcmew=_f?KJz?+$civa{Ax8zRbRbiF@QYKTFLA=unVCtPJh}ta1*vATHEN5H72x3h3 z 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

Via{;teooW~PcVyq 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 delta 14687 zcmZ9zV{m3$)GZv_wrv|7+qUg=*ufLqPuQ`|j%|0`LC3b9n0@=4bKkeV`>m?I$DE_a zTx(XXAG`LdHOjWZo3_A_RTUti5WxN!_{~nq$W)Mce}O9%@}F#q>|eN|{Re<};0*tw z6gc-k_#*&(58~gz97+S~-=H1t^gpHqu?qs_uSPfq;(61>YHCUej?RWCazgxQK)MlV+DS53P?PB*BwYqd*_SxtKS=&c=tsRReso)1HXlIBLIYP4BM;O z#Z-ZLU}L|d&!9O-T6O9&F1yv+Yvhmw6;#~BKD^h#o2FGf#C8TnMd{a7TJb&L?;*|i zOBCZ5sc~hQhtl)7Z!6*RDLNjFWtH(UehHYJK|79;56p3hx#Jjq0qj9&7-oV~4ok&> z1vs*gXluN)f$a~E2<@c=JtwzwL2j+gv2ug2Y5PGK8=q3vK3Xp`Bct=*bk^l0p-A#a2 zAHB`qzire1u;&@rJ>aQE@<}7QwYS{1I3l=*igamICpb>Fy?^+@PWDOlIqeY;bL*22 z4+4j*xQ|8s*rQDE+s@pxfKiP72rK`CC@R7|V!~;f{hUqz=^O*d+{-U}W&&$VqEcU> zgRDl1njPtD2i)~3-IC^kV!^m#S(R?Jz^-siepvb!Qw?ElTlWX-C6PuqZ$}RW`cEfP zSvz4UM!(|(Zr~-U6TIKdOBf!GnV_Fq5h#%>JuVYq%n zOD!P%qezw7At}5zm6*>~EAlY4Rdz8Xi&iZ?(Th|^`gEe==^jK6>%Q(6_>QWBLLo3Q z@Q#O(Byq_0t${|E@(#kieY!ldosJCAl3aLLD)42&tP&>K{Bz_mmcef52=ZO`ZwnlWv%s6t*=qSso7JRgc{ zq+6NR86ITBD*2kjJSHpX0=ybOC6)B@f+4B!0sRaesZKLWOEekK2ktbt2pV-rrg=iq zb}bBKD(U5!AkFlOdi+;Z2oP5X9hroC3q7Nfp4B891etEBr{``&7I&d77m<`~b##pp zq4SqOFQQzjcSm%HKk&07QXIb5v-4Z8{$+l*2eNg zoY~Geq9#HAnwLJ~r7N^om$%I&vSq25QT}=V>lgR0_+N@a?3HHWIV2;CjD*#^VFW{3 z-{!2L1)bDAjXd|UH0r3KGQ!T5BXDc!YXJrti&%BlCE={oi>eM4rS08~!BO~adsVK7 zueP^L-+uq%q$C(S*^xBGjAWHyvzD&HYNVwPH_-lJ1pQaLUX_=Qhf)J;gKtEg!w@T|vN>VA$D0-ocpe<05i>(X}G6B#I z5q5QJ>s;rpO1#0I0Aygm>gYQ1ZEyClJ7to>Rx`q8C8>foGu=Yho(Wy_U=-Ir?3AS< zFkaQv(CFdOET_>JTETFOIbN{XbH(tps4dd+GABe2fz!c`UkL}XO`Y~Xe_t~HuD69( zWvFsiC~H3H8I~?h4@4H{?5arIu=*3G+Oa!0B%!Afu34Ef`F1qtSm28+eMm4$gee$hFQ_u#+6=` zW*wulKJlixba+jzlKY2|V!7hMjUo!y;i=^j7d+#|OZp$&=DSQVgFB6RE@l9Moqa_d zv!E{)eI{AND7IEV$@+PD$Ib%wkok*K_UG}?$Xc_(9!Fm3o=x8a)3kW zkz1~xKJ#Eg_7_f4O2dJgTPF+Zw1R4;rVrIm z4W;akvd%jD#!Kc^CFwK5YD$3T1w3z9m4ohvmQ*t(67DHWm|42gPpKI)fKiEaFc0A= zLecWaLn=g4Jh^fuwgB=$X-bv{)*{0otL8923u`05it6_XJ~vQAV={Sw*hpdX*2mga zqNJ*lW8(`Wr>;V@7ZzJsRW+SBjZ#5rng$(uoj%by?~|=-EDdD_5gy>VC=DG&D1r$4 z3x%qNk*3+uw`qw=*TMNXr5Fr#wb0tP=~QynE}rTAXoYivA)80!BS$ zGHARkeJP%v*W#`T&DVD!q&rNO4cpt+7E%vu+wo&2nv_FVi!o9HMB^awKqb!oi^<;( zdDm708CzZh`K3N8rUAfUH@}VR7|~09?YHv|7{awO*Rie5|D8O?x2qfZ+r)AakQP+ksXxL8iY3S*DmAg{z!+z-*!9S6bMv;)C*KjVCEikER4#`VqB2 zlr4jIjnG&lpG7{zc%c`D53jpyUa`iy@Wo^x5~Q&3cWBrbc?r z{Z{pK`$>I`$HMmZ54;1f_yb>^(ij(jJM*x#_sZF zf)HU9KhRr(C(KGNoxBiLtJD>fIMHlB_o~%BFYtgr>ZH)N`J2;bjcTp>U88TQoTiHG zt-6$>oz|mIAIdm?DBfytxK2>!$=8%4h51WcHrXerry&4HULkR?H?1kZx=v%u8B;uo zoKK9@KuaZwi%kkD^T5o8q;YZHCy7Yh!mT7(q+0l!LT^D28CMH(KY^Dt3eh7%>r9i{ z96~$avVg!fTxKbSvCg1JaxTZH;`m9)W=JuaQACsO*D42swYfECm-tsp2Q|V<#^v~g z!z@g@xg$U*Oa|#)oXk)p)B098w-!1Njg#Z>Nx-zgS49yp`ch>BBO~0scIMa;er2|} zQ8pR7tU7Pqf+8M^mMWARhiKw{t7RFU2tw->x<#p8Fmz|WS1sZ!`|ax{PGS_gUGde_ zFnidc#1p{;_%x(0t>eVU&u9qac{G#^sVYAItUN%`w*_{^A@#OPfbPE9%`t#Nd_`3& z&0MM@18=Nlziht}IBEIDu%fk+RLoYaRNXTD-D_tsyV!n~yQi+wtBzPr6->+Ir<0Ko z=Cr0~*v3-Hqy=RUeL1JFg1Zr#=eX8VV#F_x-J>y1;^`vQ*+^I>F577|V-6}hIc&iq*)f${t@mUa$~uAm^Kw!H+oj?Pa3319*jd5l;wG$|d4-23~AJ8HH&G)~pmlMq1*)(7=nN<(& zZmE@MEBBymhSx?(&t@{}w_)wE@MAX>v5G*=-63*)MS*wy zbML(QW^r?CZ-l;IiF0YXv+s~FlZVx!Xl0Xht`$YicTKegc7j(SXL-N7^CPb#)YR(k zIIaxab#9U?IO*v@J-!Sqx>0(b3`Bs$!$!mGAjSb4*|I=SA$f`9+8{mOuffyzOfgiw z#Id`~()%PEUA|z^v3<8P#|BGH9{ncxe2zmH1?SXMPh?x(rDNi6TTzV%*1l!*D_I~W zg*@ij#)A%!P?4t~!et))S#3_rXS$GyvFQZjp%j)}My7i#b;Q2A#V{(e=#lp9Px;{yV;{NHeS*Hkgx+(#b2MpKQ@hz)q zJkSEsriN2HN@s!W6^tqCscD-SP78)pMAKH#{j{m8Fsu|VX9PLbS60y~E8%rITGOfc zMnZD56^vP38iv`DZ6=-4HvlXy%?GmwRtIbXTs!IAa#sxpKS9Tei3Us^8e1`{8zRQ7 zjk=bI1vBf+zS-TIDc<8sWsa=}x$c;dol~ja1|X7-sg$S5H$~q*YSNu_*h9~B|0o;( z%(Vss5%WnLg{wl;jhJIS_j<>cgJSo5deR>U`ykx14VMW>E=?@*Xn;zeqI9L+&F{Z^sot)XOhb|HoRyHg+Jt+=rb#F$)h%cb5ffOSrD(SMfc zUQKbCXrotd?NK%w2c%q&i)Mn16nbg@*iMS-fo4G;2ZuBy2YMjLmqKdM6jB3bl|DC9&zWCPUsMzVX++x&`VRV-Ur3E7 za6t;oc=pfoS8RtX>F?Skdj#Jf1btUioM3ce2nM-Itneac0UQelZ|P=}vvPKO2`~z; zl;cH36d+p}H=$6roADl|jp#Q0XWnf;55O>o2f)}&~H*Um%FnF`?kK~ zmP)ngB`J(9@1V&ISEKgAPLAaji=pH2qVw^HZ0Sxbs5m4<@7jVfrJlE5l%v#kzaj&5BUf4xU#dvth&(b1|;y zH^Km>V%E=1j#vB-=3QLL0dT6`XAFtU&3WrqDo+DTf|v_ zsQ26akDkRJJ(u_jk2Lo;qR-)0NWiD$T6WMLQRdN^tDzPC3kWq`?MuV}U2`0TMVJ*9 zA*GT979fr%p8cIfLF{z?x~tJT;p+j&HidE#&jo)BACqa{r+Aoyrs-}hIh}nX(~&@f z$)buK5MS!jX*Io5#xmhc$UECCnSNr4PXvq-E9$eFwrXZTgmrn4=~~p+&f3rr*ubQ`cxu+tK4IimNjm0jYHIMDHqAsf@%2 zX(^XKUbm22j&3r$!R2^}$fe5n3jGR}@NkK?9L48ZsCiBuY4lHZPGxcbiiiMdA+5X# zxMPatnkl>~n_L`etE)`E?tGYW;LX@6DYNnO7N`G8&N~iUNe>eDv~bJq+y~~ONr9~0 znqQ|I1n7@`aK2Rl&k|=9l6U=3^fhRoUW<$pv3w$U!=nF;<}5U=IfHUHLNS47bgc3w z&8N95&MKZkL{;^ucY`tNwOye|+uL}6d9CQ^Outi1uD z{+_dUJbo;f_@28;{*^@n0=yWN>NR}Pi8kV%2^gpXAYYjHq{6DI;Z}|>%_c?VI79^Vhi-0cwMr6bUf=2zjn!THv*%2q8Wwb~=>n}y%Hn4`1|i4Egd_@I{xfTyXMnPpu@S% zcK%+xZ5mhv?ii24kPTP3J)F9|JHc0xBW=!H}x#$#pyNas1edG}&4ijaVTKvxj=_T9y^=@F&)?rjbIF(k4DFQJe!GA2XV?dr`gxf*|eXle2z<37A>j}MAdZ6^li zD@9p>lw-2*b**~$BYDPd0H)|EL>d7#b$6h((#3l>CTGmyuvD7~2XqfHjews(W%h&y zT^A6j^W7aWw<9Y(o@fJByaV2%~#{5YR$z_ zmg;+Dc(SPzBw>8WP2(N^>b>K`S!vEAU<^lJ&es-Om}jN%_@x4(GtE`Mez zwv?+&EU$~zbCKL30R#l6K z-^<5p{N1RMu>WeltU@1jm<)~5_M9?d-s+PJteaG?j$y^E1?)EP&P?)U*hSNyy*6^d z4sU1OdgfZn=ci7Ni&)Nmo2YywNk1W z*hEzClaNIs1|(8EUmtDi#=PJc(_mD^Y@&U-u!c84dN|ucTRM+~Enc1;1EvmC9fz)5I~JXdO_138W#aZS9kd&se<#U7Y~JYC!*O4Jk@ z%E{gO(hYZ|W71`jo@v0Wa?dSx;nul780FIIi!9&P0H3CN8g`F?+oNYr#5R~2h6gcBwT;qr$j%cEYESeb! z*X(eg1TYp~I(QUqIy@C@ky^i1i(jX{FnYUPEu7AoYFDri`?^%j^cr|y;C@k&Z^zCC zsiVy*N}HASp8TSG*d!4Ispb+4dfHbXMrA8^$8fYDkCjp@aku{T0)}iHG}An4j9=&- z%n(py3y+Q|RqQGHF+IoCFGtLF)Sx*&?Sa2c0T^-@SZ+6LPEs3WWP8lR^a`GO?vZ99 zwxb@syVd{L3NZ#=vVkGGVUZ<7aIMZ9--3}nyXI}-f=)$Rl+-PxoQh z_<7e^Y$=mJTv>#V)qV<_&H=#2j&ZSYF2Sd_Va*Rok`jZ&q)4$BNx(U^@5f?JUzQke z0A$GNy7IHVrVC#&g$WA~B@0ox#7VdY@K%v9cNB9}YG1x_2!Z2P^l`chu?%y3(b5l# z6{}c?ZVxj}*H~*>SMEpnM(D3GApJf@rgc640_{h(uRE7umZNY0%?Ilr=Eh^T5z9s* zkCzzo6}xrw0g0ux_+>o$DAA1P_h_74Ctz^&0*3Gh#^|&FO$g3K#Iy_CN&k&F z9|;S{RBz8*FNCr3V5Dhy1Vm+MW$}VxMt|C~Lq2}CPzl|1=PhxpeIkCA-iqn(jtjUB ztqap{3(+1=ZfI!0?gT3JLVr6+5ggRR57^4 z8)qjgs~^$YnaDZ#!F_A~GV7%Ji`cC6}5e{8}h%_S>#YK>(^I8SL_0;Vq+!TVR7CQgnn3*Ia7UH0pWrB+bV_Z?i zkf2lK=2EkPztc~rr}mBC;M78OoXGeK2*tkRc>KSE*LXd%L;tKgHSp)J=m6SDM_c-R z^e5e@Mam|;ZeRoa%*5wbT<__bOdfyeL^;TL3 zvB1|0tIIRKcXT-MDv3A~8rDo~bK*x@pL{3f+N=6BDcnQ9&$ZkGtD}+Xf*BobX+R4^ zz;-3B2{|wPt|&%1unERHfCHd-J9OnVgl|(ncXFlNK>6tk`*Q*5dLY-f-zXEty8!yh zT%{d#Z1AHUjig_yfiOc1u`W~?FSutFuGR-xD5kanH9vUlW~G7DB-~`r;D+iGGBDif zrsf23Hd^ndTNi>g>hPvXy_Go$zRL`{j#^eEgpH*7)`RVqNH^@f5eBeO(Tm_Pq49iE zZ|ScYO}6$CwtcxGt*Xh$m|5JdSw;D-ns#=Jq^-};C=T33!{JHV}E^Pz9*S=gqLCegm{p_KRkCXf{CaWlC1!vg)vF_lBBOX!o zySk*iY+rtXNFjMNokFR)e1f2C>5h+O?d+5l>9u9A19&v7RSC%YzMi)nVFoM%u#M#W zoMRR}iLHOjJ5p|fs!yhVCe{ntmcZ{uQP@T1!`})c@QDp6XxnAtlU2SEZUO^Pt>1vJ zg`!TN_(P!%j@?lCLjc12OmUyFx(3EF5&!fT-l*h2=O=T%=XmTQE@ao=Fg+8nhPm9B zKjT~nNm#=74grpL*m}bt0Ff}gp(5`@AL8a;kcN@iQJC2YIY<02YM2JFlb}`lCnhmU z(8I{(hdz9;71aow7myC+hZe_+Y!#AdU<5wG4(~BBj?T1~=~pnAT$u+T{zCsxADS+| z!rX3fD<9o8sC);^`x-TGZH6^Y$xVEsY&NmAFn&u+z&BEg;ok7lNt)?G)D^JQq*qh{ zs5LiiOZb_=A1%UYG;0J+uyc<+>!GLXJ9z~IS2i%b8lQ3&Hk$}WvYQ>6!|HtNtEE;v zG7}fZnfsFtULsu!{FjsVdV)>AA-=W^z&@^w9c1U*lToyOF= zp#e6I8o;X=A*L%I;v?`F62D5wVK!gYRJsYef>&1|BZ>w}$HpX{B-rwod~)oFLJZY+B>-$|!_3?LH!feIjI$z5>9i7x6D5))O6d)S7f#aT zG+aDWbA%d|1Np@+)SYPiDpNLz*@C|-mjlkd#gpqe15r9&!i_E1LRL+Fbaz}*mkPIF z;SRS~bC`W!O+1!hQ8R_&zlN90m1<9e*isP6Y9Le`lFugSVB@C8Y?ZL+`UwESGrHH1 zoR|9oWCwy(S+3kd6j@MoZpF{<#pT{9&R%mqvDE zE2^Cv=V_#$;f(hZUW~v1%&DN*Qg(e;x;PB63s)?MfN9k0cVFH+Y9-8GpZWX~n^t&h zAIzB;q$NfK^yF2^-Q2c%@CTfTm-NQz2JlC}VXMaIV36nxNIhe=Bh^PZ&|m)!Uf%(8 zjtupov`#{Rxuqcr5@aKF8Ey0toEZ|7mC8=j-2lrih*lhY@qy=`C0(7g6sLzrWz;3$ zkMpdWfrXaLCEYD8i4xv1H#p_kX#C?gM&dCha-1N%lhCt*KSi-0MF~jLg;Pt@WfR`3 z_@>p~qfGf>?v?|o7g+#Xx$QkSH9VzR*gs7A!#-uG^baHSPXTdMzgdub(KU9$)oUl3 zSC-}n2R!l!rwzTRnE*6K@eeKX%}Vkfk;wa3LxcJ?&3v8FY@y?}erRS_vqBuELl0fu zxiM;khSYYW;hL?YM|40=eeJtyZ#i4$GKA>;xIU}S@{B2Rf#mTXPJ2nmWnwgOo1Y+# zo544>O=rPa1up}#6I7T~g!tVTz_58>$@t(`A78IskEIjcwV#QvivixZ`@l1hO5YR8ec=whG7kMyUF zkMzTC5M+aypb#!s&*!rm&CoBD=#Q(6jNwn8v-_B0<$ekCGoPPcQfVGAB@+!4ZtsTI zK2k4nrV*RzW7J(g5nw{ni~P&^qMYiv+k_W3mb+eVwuLH(xKz$unGfL={d3tpUMfGi z_C*(aUL>dE9FGA$Xx9-Q-H{x(MstYQ)L~blw?3j$3#h8{_h@0aW>I_2>MJbW68G#vxBWf85bjv1BC2IBwyT)#^%A-%Ij1!fKWx85f98eZpR%(Z)a3J#s z<*y|zN>O(hML0%>tJa)x3>)H=lfe$tA+T$Sz6)=Jub^3qiomf}`V0*d?o#^g+cO^0 z=0rZTiQfW}zsLWKA`I{JGK6I{)&7o*#0O<(tl$k-rbd2Fh$m)!#kh{+<*B&yVE?X;V83y@i3x^v;`UoM z5b;jd)tRiX$RZm$j0P6L&i~zY6Y@$;{Cm?*zE1)GX<;LXQi*l*t7Xy=3BDsO#@Ui> zGqIwffh$;D`Ik;pQA1XPU6`%UHSP4-{BS>0zvy`+Z81HOmnp)QHNLI$cDJnac3OJ{ zH?6k>znT>{T;ia7r_f%h-vModN{--yht(=ETLC#UB7SjT-u~NQE}y;NpYKs%*{IvQ za(m~10^HjZPK=LPa@apo^OLx2P<>(I@82<&UFefVp^o>wQfX^?!hpLeX1 zVXjkN1DM`#c$1^WlEXiwXqj-j~YZEkW577y$#SP0F-P@44^3-@B5n!geuB1HWYs0jkMSEZeq(}a=@Jc#xC)5_yazp)Kb%AHzTd?#1pZ(jd8O*|(!rU>Cp zIB2)86!U%2eY(fB3zI=p^>;Vyl}|r*H^w-{n=X=_Ih6-RwIP-CkSsgQGY?6-98mDXsitq2W zG&3s0(6(IxjA)8>WxWS31pjMq$q@fSi{Hjn$?Zm2&A3j1V=X+ z3_Wai!B9S=mzYeY$y4MO`qs#tS!2gvEKx||nu09n{P_VvcY4~T&$ao`Qgt9Ycj{AV z#rfCHnASonC7X~0t$?bcqgK@baiMG#pw9KntIgnj6Uj zJ*)z}8-XItTd|Zo-Wpr0A&f^jwQ>UVxzS`DEjmCm`t+Mhg4G&#BXUyS&R6sB-QOt4 z4a~@Ue=jO}BC$pGX(5>o8_~j5pjmT2)AeVQ9-qUg_;QlPx0u_G0WeeP{*~v0rt;3FWGFk? zK)By(L24I{bA~NJtKh`;3tixW?Mu$Cm|arr0vT?p7#0JmDjl-C_&>SydujZFH&pb9 zD}Hfvq?&zj&$^j0c#nbJ5#6HVMm^ruW<8xHqu}J$4?wESy7?2JYU41OueOWO7CU>Q zBo7{QSdUF62N`jMzdS&hv#PfOAha^ z0a;syPc?p7GG`nEd{B^bs|fszv=r}?a$`~|Z)k^{G$SH7h<@dFjn9|vGhL*ti|bR= z5l+kUnspygz_B8L&;_o43;+lF@hkUXpcZs^BW0?Ac|iIx<}Th6cmkRC5Nkl&fFg@f zmXEsnfwYE7+B3cLZ)6pX@mEF^z5F%gS@)5zP{%Jvtr-Qoq@qAHz>mW;MhQjv?yun|ZV|y)p6&hfsB8 zi9m}zMj9T#_h$pAS~-c{&_J4A`Mq22xOue&UM}`MhlEs9-R<#UW+rOZhD{oV&+lR8 ztli^K0hQC}*%=B*6B(wC@T>5LQp3wc`9GV>y@p&c)--pTPVx7;cOL_&Z82gmHNv)e z+IpHsB7ZvlWFJM=S^;+^AKjF{y7hvKvBqP%3S-{`u)sxk?GiDVP+e(F>lKBpl6@vL zDI!RkH7k9ZJ*qMM{iF6!-EZo7z6aVK$}KLUL| zz~iLoj5H~FGa7tTYc@nq=t=HO)6UJ)VgbXV^fm54f6KZteYyU;u+jY6fNU&Y47*HG z3A`-crCp~&3+RaE!EA_c$-?BpepBU7UwcFV2VlDoRM8_E2<43gNwJG)??IV~Rhrd! zKTA>No=O--YV5tceio8E{Tbiff6qkwg!*HyQ6K#JO0?CZ1otF=K&%IM+YL*}dM(nz zj<93mmiv>_t7GA?d}T)Po$GnFVihWOUBZXf3{~v?X!Q~80{b)6`kD5y^fy^e8}gtw zz<8I`HvDbJ2m}X<3yQl=!=`o=7_8h<8ha<(=6j-mur6=)ELfhms;H1 zpZ_%Ub^((YOwu{|$j7KKjq_~k%hsy!yS12&CZ?EQ46`2H4FJ2g_cUkJtvmoCWYg=0 zj~zC^y6Qo$9uaI1dk3Gvg`E)SKGu%}XpCUVYT(@73c0^EIQ$(b2fckR@vs42?;H(KvWZ-0dYOH*-fg3k8x6(MC8qKtlCA+AT zG*ehO0Pr5B@fQ}eBx>c{6}23p!hJ)(hI>1xgNRJgc*Uyd@4yz37KDz|3P{lfwBUX& zK;*X$n(&u%#apwLlwZ0q-*}h*%$R#j#Cf*aYu9}Sstls+1?-K&&Pn;hZ4S%K>G&fR z57V+KyhAHv<`1sz)w_m1XVdntU#WX{6$w|R%zV5KuElU}fw^>zc`$+hFd%fPpqEhC zePATIY-X3vBN)K7OKeS922lqBtQeQQ0=mFnIUhtd%>VF5ANKL}b%hLyVVnbgERAU@ z6OPqK!I%Ig10e&3+elijuj^X++@CAtztyfK#hdK&a#@guJfxhvHSayPQOmX6Mnq~a zx>S0=^?jX1{YZU)VDSG_{F6`0^lb-m@KvFOe;&El+=#*?;MVy0DCRa0VB!Bw`C9^j z*8e-O7q|DYHVTK&@@WmeCs!DBtzW>)dkfU zFVSWyJ(poYzh3*`9V;dB!3|3u>wUfEZVAKbG{v5#(0VwIppT_^5n8T|gP%B*l*W-+ zYTgOznX{fH;d&efos8W9Lbb^wPgvReafXTRc*YT|)o%t&_J1;;a{0BH>Q9H{AP7e} zJMGXqWK*MmlLhZs2!c2bb>l#$k&7WIA+53mv$ulDVPxPP*k%$O$mJl+OU~U@ zSi=s#h)ACva9ktylO=sj?zr+Y5XRa!OR+@E3#Mp+Oo2unB(kyqaF}6q$2(bq>`>aX z-3KbM^ta@ALWg7#p%0QwMN~ed`$aYH2iH66nAD=3(5q4sjN6wAatR*Wu6HfXaLJdX z=14MGN)S}PvMb@)o0NflQu=Fxy8IXkfOKX>$5jo-3%3aoM`77N$mgWTp;H;`ek`BB zh(s}5O>jy5Zn!1`gzgsz#RT?-&IllUz*qyIKPseSo7o0-MB%NfcLKr?s%KO&>?qjJ z$tKgF{pRS{K`%{Sh$-F!T)pAZ){5v|cXVsG3x{7$7+}R%`SD&S3Q4Sp&KUMprEE2+ zvx77j+RVDdbB`~sGm5~bhiqnHKWS5alw;v-XWI-a!U=Z1JV9Y$REs^ za>BZW``^@Ldr|ZB@VTB$)0c_LY}xv$e$pXXHw)E3kyk1J&=r#?O*@%rwD95259n6OWQHExkuFj#> zb|_vEZ&JJ=HeXma$lWEq1%Z3ST*B2-Kh8Re7$yO0*C6k{y?V$Migp5NRD+wh;A=J{ zNsW8W1pgp+DkaOb*=Gd*tK@dL6uyHP<5tjGJ-hF zfIUD6!Dip!(_B`c#eVj>@y&1;gF@=pXrenZjr2h{e$vq?Ow%euu)70s zT{_$W^N!WcD121mVK6IXnJ=Q$LLw*dn1%pxW;gg2Nqh+7XMZbEXuX5A$-q&#QZwDj zekM1$R!Mx=fHexj1GAF}uVgxI9_h+p$x5+p#8Smbb-~04b!^GXQprjy$;v~?%D-`% zWF;_4offlHIl6dh$D(WrEkj+RPevXY)3=q!$U-nmM2dli(ZjqcVAa!Vp5&qx7vSX! z$(2SuiN@^1tyd?XD0;GAv>o{;s&*ktgu(=i&S7D!l_m>o8Cd~t=5_VtoQIbWGd#>T z*)R6eks@c3UN{5o+oAUe5f7yQU1Y0x)h`~avH*`&Ne@2Y ziEDZWijPR%OV5Itc%%nk-e+1=bZg^UCBP2y4RJ5gn#4W9IwBSC^;P?Q;5aSX`}M-0 zKl}{GHP>h{kWp9BzelU-2G;jMb+4YVZe zC^RL3(8xu5&{E^X9zD+%fonFTK?Ca%G&oeDU+PB5 zOJ5ms0KxbeY$07w0`j~1T=`(N>2S)2^!bKFGV&mG7;&=MFs>ShCdr#2dSI7gLqsCi z>bs^zPB`8QrY=I|{)-~lhKQ|6BZNjS&i7x8&bQb=H-4R&X6w~c7x@f{MSKN2fM?{E zZfqo9LXVU-AYykY-5L_*VJ^um$E49d9lOSK%pFrP;C^!0aR>SDEs>~>pm%QtCn}pC zeTCkyB20!^eXy|@kCcZjvwGIw7WAw;y>Zp2XY-T`R2qa&JkACJ{9l;)D8QMPeEVNh z`d_(pp`8bw5S@3QU{KzRriHOciuCC!PGYdSu&+mwQ6+FVF@#Oe?J$%orOX?@-JGjm?lWETj3NgbyMSs2dZ1!k32!@?!S{bJ;gC1GD7m>a8KKc0B zyz>YAf9!E^|JdVx7)$B?XK?F~!TQhgHm4v8{jc{8Lrnqh-@sH4@S_H`j_VU zUrN!55Mo>RFGT^2b^5Qk@-KC7`j;XG?mJN!{nOq5XDu+)|4q=q{`@Ji1Oro&(iCHs zQW>r-HhrojTUwh;KQ;hfj6wg}%&8&!kfzAm3wioM62o4K0bN**XP=WK# q4B(3YH^T%nxS+!Q&+Y-mTyP-rZT{90{8bVIlU&eXOl<#|`Tqa|W#yOv diff --git a/Mage.Server/plugins/mage-player-aiminimax.jar b/Mage.Server/plugins/mage-player-aiminimax.jar index 4ffc7bee3d7844235db84005ed290501967219a8..8f800429c12cea0498ca2bcd3d1bfcfd48c78be1 100644 GIT binary patch delta 11237 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 diff --git a/Mage.Server/plugins/mage-player-human.jar b/Mage.Server/plugins/mage-player-human.jar index f18a79a36305c74fbad5eb2bc604697b21431bb5..8c98d5ef01ed01428039b358e0850662f40f8642 100644 GIT binary patch delta 8434 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

  • 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 B_ILmQ delta 7890 zcmZ9RWl)?;)U9zzAh^4`Gq^ipa19n*2G`&(4#5U8xVs0J;2PX55IndYG+2;(PU_z8 ztGZoXy?S-6{iCaPb^mzobiZg}YN#M0y@C60(A9b*VbUYg{ww^+i2u29>c8?2(|-aZ zhUY;0SH-;{f#xt(cv+zDhCRQzOmzW^l#bTmm$WJk@mbm4a_^#Lt#Cr+>+s+-#3GL8 z8UCewXk}gl)H1q0aXoP=)|j#W>~?iV+$+#BZ!oC!M%h>y$578xez=m>VQkmSc+s4< zI`gZb^C1T5(+v4lH#b{1d4zE!-E|5VvaDmzRARuEPmSk56b5i#1P+cXNb=2uS`&ts9-H_*${%R8UUn!e6B3h?$sqyFG-z z6mzY&G$d=;!T=EIXoFYb=!j5_1c4AwxQ{I`bresa-TO``+{9ii@*0=-cJvBOjoL@+ z|Ae^8M5cIHdnQf=H0^HMJMBn=<>i>jHIvgNE0G|Kt0s5F zG?F-}&93-@&|viz&+}90K3%d;0nEnIqTDeAm&dqJA(-%U^?Y85fmS{E%SInc43rQ+ z_}esi|Mm>pe_bP4kW$kUQ%fl!B+1L; zTA>>S!y&*U#Jn4YLmUNXXVkUrbnD=_!B;F+mKavafQXwRi-n6zh9`5Akh2=S)t|Q> z1^a*U{-l0rGy^1k&b$4m#qUlJ*7z>w(x8&^a(D|)674xeB%RBOF=@MVloA75CBT*G zevzXoXOW0+HFj?buOUPJZwb>$2Mme%sEkG{o3CP1sl&oo7jF+mxCD3I=unX$T~NUb zg$IoNOU4a$XsMXH-DG+L}sBEe0GlC)S?!Dtr;oaP>_}B5N1t@+v~+J0O4MR*(JZvzYgrDV4wgl8>BK`XdJ^rrl%1`qv;{ zkFOKPX)1pn9DD=BH@9|70*d0i4=g;jDbKgFkpCfk=+vcb-Mcj1VDf17_w8|fZHJz3 zx$Iu%1f+>|+h45vHl?3mY6jO{UUm6CaY#@HZ>E~u`91_u0Z~+m8Ruh%(tz+D&Ft`i zZ$RQnSAfz|HxnOp%L?JbnoxvU7ttB+r0^JM^_Yv$*S_(a1hHEij;vM}&p}^aU8G@$-=;rqi#Lt}2 zO_=uP&L-ItYJHJpOu@6V0+2fVaraU`Y?BCsYGg+?>~+7$$h`9j2VgJiA$!6KdmWVn z+o&?*N9zba6wOK{kCLIw8TA*~1>4{E+q_0f$*aHse`>Az`sNjYs?wlPGW92S3V7wk zYg;J}onK?>(M+2i+nlx4+c1v+b9;Z^wcH}%r7{8OseVbxOif6O!rAly3LiysttfzG zvDDhJn(67y)hczmu7ZH0frmEwPj;mlGqLFU7Qpk{^cc$tjotJkp5f*KDHIv_k4{3!qMv}> z=$)F0{Y8?5^3KRO-0V2g7&e~37%3uiM zMkurTcG0f-^ZJhgGvv~sx~xu!kED||<&^)H%%YDYDDiw``{sR^B>@_a2&9 zbH-mKcWp&L@!um|@e9y>XFt+VFK&ZF^s=i!3%{`XNn`v&;giP-s;afiyu2#$ayrD; z>B!bHD{Ottl-})p_9j~N7N=t*5ykEUcZ2xY>Ljos$q+Lc3%QSs(#%Em4BA44*MR#} zAG?-)(=ZEV9a!;w-e&20F%N?)_ss7ql$pA792)9&tqk0aERM0oP>^{_r3c;iQfhKQ zHVJ{4_@|r*IibVC{^mhwe;0N*dO~ zea}3f%`easLn(icE^Otgtg4DN#vguLy>F(J8??|qEN_H>DGk8Fr(KoU=`P8{)J2Dc zI@#TNT2@ShMEN`1KKUrW=NuU{GTa5nUVsi#id>(1unX~=-#9h=h@*!ic@laPAD(loi&VjVY3HwZeoml_e3k}3 zx5Wj+SxtlC58gWRS`amTL{SP8^_*}?O8&rGy6UjEWko!E;E-vQStr7M&8qik$q>|T zdRiJpf*B1*1j_OSie-s2NZ&MP+&h|1j$uvmI8^ zbRdoh`=`{uPCrTcZmt#l{YLdchjBe3X{^wDO-psJz`L}-L;p#eusM6AWjWC$&w*%-)_V^bcW4gA*XQhf}`ek`eY zEblHoE_)=a?A1Z^`BH&W*^L%mN=je;cJZ>5v|5dO5&IvmqJmNpO#%`~dNpQR29Abf z<>rJVrT|SFY2~sG-6At_TJ6Z2XnE)0T#L%tO1Y)s^h%wF-P@W*lO)}{OtBcnaeM1h zRwC*6lwl!V^Kuv%1ehM?Qun8iz>+Xd@6itU7wNqkMoVt$E7Ua0G9e8jm<(kVrRA)$ zs-VRq_hWw0x(?q0SXMU+lA7sMDGaHp*ssVat?c6mY$_k%cI(C7IXBTS*R?V4FL=p& zQ?T$Fn3YGAR_exT{K|mTCpOEy`Hk1X!ma8RdDY*RdfzGwWUHt)gLk{g+s(NGG0aE$ zeXBUrX`vO7m0@Dx7X-l?Y!R2bGG1MVPUWCFh@!WexOF8TvU{D#xQ@f(N~FlJPEhld z71aSrCA>L@uyIDErm}k3>anupr>+Wt88*f)*>l?DWyMtj#f9CVwH`JiWi}C4J{6je zar!%aiwZP=1Gx32MaaUpsv`6kah4e(q%l;Q9OPRL5ztkNz+9xII>=-#EMyetl9(~C zOdo01b>dmj({|Ec#cUqXIjFc+^-F)3d5qvyP{FB1ly!_N-L7qtS+l;-gxH~(Msn<~ zIYSWHKBuE!QHALh@7R-CL2LQoc-=g)iH%-^C4dA}motExDr)e4JY|+Y`{g=Tl6@P~ z>F`0BPvjiP8>|+9*mUN62)Keq9D`_utjJ{c)!oR1wQJJv%jzZRgW z76jeXSqzq?y2ORI8a@}oXPobF_a|4ek~3GhO9g>@M$CDi1*@rt%&K_`@*RuEo+g2;`xcnK2lfacNa?jxFlF{-@@_ft@X?7q-Ky3bvtjo zsB!;bX?+)YVqmgs)ny<4*2zG%lZ<`a{GoI?kWU~tZaU7oqZ^-pZ0h;Q4Vl_d z|Aet^eM3K%=-gL}wE{o%AxKr2eF59iZhtZ`7m646%*!r?U0$7C&qZuPD%46~%Wru4 zL&RwwL3sI%Wh%|eF!UH+u7)*5D#Bh~6qe?o*Yt%L5rnQMWi6?$i=e$gHr6jHi&4gYhhg1O| zGl>_nRn-^ms;}Eo(zVA}B#({rFx-ve;}LhL>jWX7-a*uVkJk#w=8zhl$Bq@RJ!fX# zh}a2tU+c<+n|XSB#I7NWhf?u?o#GEpx&Ol#FQGRpB9>A;g7f#y0+6mM`v`& z4LcnjxR>g1LfQ@VVs~(Yyo8Vrv>X6PwU2e6Uv-*)ff7osC%G^|EKUMHifqs>hqfn) zi$adZmnDg~yMJ8QI!R(}+MeT@22i|O2#j{KcYjJvL)A~%9gI!1X4U(>3}3wi?j)y+ zy?m~1rVP3RwoipYjYOee*VYE}I#l?nbbA&iRaH`}Un4%T@$7G!10y=#)!zJta-%hP^(HN$(#@Rz5q69$U= zAntnF8HX}W+Yc6Bi?;c%@28q?v8*0O`MgOR8$Jj2hpKsA5ex+Nb8UseEEK|Wzq$gP zRLi4Z_T(CW1ujS^$9>3I*!co5_Uc*Y7mPxaU4A@(@%%^h+{wu|OdJeQRmxD)UGgA; zdOYxB2S{|Y>9B`R%xw(}9&w0UipFXDIeW0zY!P|Jg3`puAVit0Fr495eX~eZlO5osmDB^#6)wTyxnS=!z&d z6*!Yws7IH&QOg^v{AirEz1did5F=Em#;m^fF*|i?zU5fWofjLkNZeBt$JZ{ciGW9I z4sXy%5c9GdY#8YSrA_5z$ldJw5wX0Tv@+LlRUh?PC68JcNN)fr8L%Q(en&AMaFam4 zv@TpT?@=!JQ1yDiS?~Cwknl%6&e5_KmhgW`o&CgP1Tim0J))r%|M$)NB}PI~cn%*H zM_HiAqB1{cGv7e+$I8jme#QLCOHFx&F8PjmuLQRdVOn^BY!IU)MaV3L(Iz-zj=_eX zVhAnc<73`!-yIyFpv1`;7%t{yHC7e0-MI9_4Ru7@=ynbMij&pf`E(vt+EapHhFa{} zo_mV+iK2A#LuTd<3+glodom-~;O%l_MdDNe&h94`*1FI!)#T&%5UnM@VQmDx-nq09{8(dO0i4z+@0`y&b)9#Kce(%Qbe9JJ2 z%_eWgY*veN=s}~&_W8VUkft%-h2W>K*S4CAyEF3Fwq-K-7dyfGyz@6e&(x*M_YJ4s zo-UOquw*fvz>7z{`biB2^Pf8oyE6C>;f*L`=zo|u^_0ml{isji@A${nxO&lv`qj7! zLp*sf%T#cI)28L-c?-V~(?NUn<8?9e0jgQ(*$&r0GVy72y?ekzeRdG?-fYT3Y)${& zV%@3(uCaHx|0CKXdRO5dcWBU?16@CQd~0ER%z>+_8$Nbn1R~AKa6}LOP?N`CT8Bk( zsab~`kFFYiL;2c{!n9^VZa;14X8$44jY`&al;ado#jdCBhNMxByp=wOb8O^{wR+?u zbcYB>GSO7KvsW#b6jx|0<`P-85z6e%Cg)DZyslztPo+zpt5*8Vk9^6`S;(3e#;Px; zd&BnFOsJ_F8r^V7c`!ftI>h(_5?x+08szebmJC6krop(TI9A>&n#N&mc{t>2$x)jq z?4kg;=)w5bAF?rVrYOO`s*?jm>PVs=WwGy~Xr@wUTcx)H`Ke|Bn*8J5AMXeEg+Be} z{5x+1p7lKR^Llea?ueSC?){@Snjij9Bu2-7ZN4|sJv_?o!%fSRQ5VI$4*q@sD~W$!)>1jwW%yp&v?Mo*rFX?&lE}uv$a8M~3kUZ`+c!JI6O4 zb+Qw~$r`4Rbq2zYp4OE>yh9}OoJm`JRyJRG#485Qn{G@ZU~lCUqv2$H3B;3Z+gaLepBfy&-P zdX>J+I|k*>ywt&Cp9^O|eU$SzT0%FTmH96g;k}3zWMNXs7s3(cKO*lK(X9}EA@zM7 z!y#bozf+62n+%3=Ap1My52*q(nrw0IYzCd!Kii4Hv1a=rFpww0bIJy)e%7JTW3a@+ zs9zadbxw`)DN;+1z4@7EL^IzC{a8=_18oiT(9*~_&tUsAYI32o@Q3k`l58PsuHRe^ zW!faEBEDRZbODjG{3(hvet8BTxpTS^Edwzrmu34Cv{Y`I-#=JT5A6ZLehL@pqh5>V zqUjhLheJ^X>ft;6U;bmK=At<@-&`#kH?Z6%gG`W_kwTAJocc{lJ2 z7c|Kag3C9GBV1H;C(l6G(5$5N027+-Ya!%OaB&VW+kB0>xMrygp0+~`OhCFvJ}WIk zTYZ%udHIqHk66n$Z%9y@mE(A{vYRDn=yf;N7UpJkg*mCV46C2K zmk?{>{ZzKMymG&}V5QiFL2QMf`I^RHrc0&F-lE<)yUadIT*zlg+6|;!Lg2FsU^qUxnDNpRmqnpBx^-Sb2*NREq zxYk9Z_A_Bkmg$gxbeB~T|xHhLvu8NOSMPHT-{YMRdg>$w4XqF+_((Wj+<#C}Z0 zM6jLa7LxFH8Kx_74fT-23Sv5Foo!D+6>)}slmI*}4n)44zd0UeJCZX+zWZ8M-$|;_ z7|D2@(Ud-27=Nn%jTXs-1qrVPP0J}k9Fy_aj#vjhu>MZ|T3Q*Av-4Ab@;HxkGA}qP z6At&zZyHg3Ci1c2YM{w2rtAhA`K@@|gQ~yzj`P%#s|d0`F0DGC6g#Twd zzAM#XU2WBXtrJDA(~+xJ`#V7ZL@}iM!!v(pLuc}Pew&`1^IQH_g3MKvNvEiNZz+!h zX^(?>!)_sI58IB3yqwCmH+D5tcdZY?R+|7`skroHv}S?49wE9cCI<_FCobJW#{xQP zwDQ5wQS*Wqi|+$3>0nwBWe>va@AssW`m;XWnQ8|Pcu$U*DhK@ZDR<4Zr7PPbv5*s| zVv_MHcV%Votq{a~sPu@?&nxP1a+Ah?CuH)guQ_Zpn|Lk@*i0M#e!x087 zzC1pr5bZZ}#Eu@64+?5Is`pR*8j(3$29!nNQqQSUeMrJBbdY##?S-m(Ckn|l`~b9_=syTsNyJ~{xDy+adLNio`F#d~ zBpOW4mt+OzRdEFwilRgw4v(J@)KD5dOiAwx^fS*~PKBvfhY5jpDXYR?;yB#^k@Ta{ zLK+tR8cXCiV~lOwtXLYQF)9dW;~MPYn&2?gHr^Ves_6T7o{w4RpOad;%O3m&~t~a zf2Jrks%vgXe!I6}cG*~E+-g4VMW!b`8g>Jc$*c=wshIq(h@JH@-}H$VbBl^byekJb3qvXaR4LUJ#I8aFJdr@es%~u)dK|Y=9L0m``*RQGI z`+W{qY)_snv!2JC^$KQuMMm!bh{Ld{e#n8PddNY9rm9Q<7+ExGVi_T+(w}(4{ve%I zaEXHjB~OPS>lS-ZT-O7`Z~oJ8p=|=8Z#u|wbg*E7yWM;XzJ3 z>G=NB#xc4agui5#O2xJv=E7)*@69%*b1}}P&E2HK&D+EaYUSnDg{?Dc{Vn5V;{Olw z!t9wO|N1H>?!UUhB=}c}nZ^H?^O`WLy!-zUUkkJB-`o>38NwPRY@M1JOG5=70Uz;y zFfvSog$%)q2Ij;<@i!U&uPvm3(a@8!|9?sGzvTJ { Player you = game.getPlayer(source.getControllerId()); if (you != null) { TargetCard target = new TargetCard(Zone.PICK, filter); - if (you.chooseTarget(player.getHand(), target, source, game)) { + if (you.choose(player.getHand(), target, game)) { Card card = player.getHand().get(target.getFirstTarget(), game); if (card != null) { return player.discard(card, source, game); diff --git a/Mage.Sets/src/mage/sets/magic2010/MasterOfTheWildHunt.java b/Mage.Sets/src/mage/sets/magic2010/MasterOfTheWildHunt.java index c43f600715e..2ed7826de80 100644 --- a/Mage.Sets/src/mage/sets/magic2010/MasterOfTheWildHunt.java +++ b/Mage.Sets/src/mage/sets/magic2010/MasterOfTheWildHunt.java @@ -116,15 +116,17 @@ class MasterOfTheWildHuntEffect extends OneShotEffect public boolean apply(Game game, Ability source) { List wolves = new ArrayList(); Permanent target = game.getPermanent(source.getFirstTarget()); - if (target != null) { + if (target != null && game.getBattlefield().countAll(filter, source.getControllerId()) > 0) { for (Permanent permanent: game.getBattlefield().getAllActivePermanents(filter, source.getControllerId())) { permanent.tap(game); target.damage(permanent.getToughness().getValue(), permanent.getId(), game, true); + wolves.add(permanent.getId()); } Player player = game.getPlayer(target.getControllerId()); player.assignDamage(target.getPower().getValue(), wolves, target.getId(), game); + return true; } - return true; + return false; } @Override diff --git a/Mage.Sets/src/mage/sets/magic2011/CallToMind.java b/Mage.Sets/src/mage/sets/magic2011/CallToMind.java index 1c345e622a0..a1ed3e9b0e2 100644 --- a/Mage.Sets/src/mage/sets/magic2011/CallToMind.java +++ b/Mage.Sets/src/mage/sets/magic2011/CallToMind.java @@ -37,6 +37,7 @@ import mage.cards.CardImpl; import mage.filter.Filter.ComparisonScope; import mage.filter.FilterCard; import mage.target.TargetCard; +import mage.target.common.TargetCardInYourGraveyard; /** * @@ -44,10 +45,9 @@ import mage.target.TargetCard; */ public class CallToMind extends CardImpl { - private static FilterCard filter = new FilterCard("instant or sorcery card from your graveyard"); + private static FilterCard filter = new FilterCard("instant or sorcery card"); static { - filter.setZone(Zone.GRAVEYARD); filter.getCardType().add(CardType.INSTANT); filter.getCardType().add(CardType.SORCERY); filter.setScopeCardType(ComparisonScope.Any); @@ -59,7 +59,7 @@ public class CallToMind extends CardImpl { this.color.setBlue(true); this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); - this.getSpellAbility().addTarget(new TargetCard(Zone.GRAVEYARD, filter)); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(filter)); } public CallToMind(final CallToMind card) { diff --git a/Mage.Sets/src/mage/sets/magic2011/ConundrumSphinx.java b/Mage.Sets/src/mage/sets/magic2011/ConundrumSphinx.java index bdb42da5799..203df70bc9c 100644 --- a/Mage.Sets/src/mage/sets/magic2011/ConundrumSphinx.java +++ b/Mage.Sets/src/mage/sets/magic2011/ConundrumSphinx.java @@ -106,10 +106,10 @@ class ConundrumSphinxEffect extends OneShotEffect { cards.add(card); player.revealCards(cards, game); if (card.getName().equals(cardChoice.getChoice())) { - card.moveToZone(Zone.HAND, game, true); + card.moveToZone(Zone.HAND, source.getId(), game, true); } else { - card.moveToZone(Zone.LIBRARY, game, false); + card.moveToZone(Zone.LIBRARY, source.getId(), game, false); } } diff --git a/Mage.Sets/src/mage/sets/magic2011/Cultivate.java b/Mage.Sets/src/mage/sets/magic2011/Cultivate.java index d32e61520c8..7b5984429f2 100644 --- a/Mage.Sets/src/mage/sets/magic2011/Cultivate.java +++ b/Mage.Sets/src/mage/sets/magic2011/Cultivate.java @@ -110,7 +110,7 @@ class CultivateEffect extends OneShotEffect { if (target.getTargets().size() == 2) { TargetCard target2 = new TargetCard(Zone.PICK, filter); target2.setRequired(true); - player.chooseTarget(revealed, target2, source, game); + player.choose(revealed, target2, game); Card card = revealed.get(target2.getFirstTarget(), game); card.putOntoBattlefield(game, Zone.LIBRARY, source.getControllerId()); revealed.remove(card); @@ -118,7 +118,7 @@ class CultivateEffect extends OneShotEffect { if (permanent != null) permanent.setTapped(true); card = revealed.getCards(game).iterator().next(); - card.moveToZone(Zone.HAND, game, false); + card.moveToZone(Zone.HAND, source.getId(), game, false); } else if (target.getTargets().size() == 1) { Card card = revealed.getCards(game).iterator().next(); diff --git a/Mage.Sets/src/mage/sets/magic2011/DarkTutelage.java b/Mage.Sets/src/mage/sets/magic2011/DarkTutelage.java index d9c1ab3c4c4..c43301ec716 100644 --- a/Mage.Sets/src/mage/sets/magic2011/DarkTutelage.java +++ b/Mage.Sets/src/mage/sets/magic2011/DarkTutelage.java @@ -88,8 +88,7 @@ class DarkTutelageEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); Card card = player.getLibrary().removeFromTop(game); if (card != null) { - card.moveToZone(Zone.HAND, game, false); -// player.putInHand(card, game); + card.moveToZone(Zone.HAND, source.getId(), game, false); player.loseLife(card.getManaCost().convertedManaCost(), game); Cards cards = new CardsImpl(); cards.add(card); diff --git a/Mage.Sets/src/mage/sets/magic2011/ElixirOfImmortality.java b/Mage.Sets/src/mage/sets/magic2011/ElixirOfImmortality.java index 1dad133f8e0..a08d9c14575 100644 --- a/Mage.Sets/src/mage/sets/magic2011/ElixirOfImmortality.java +++ b/Mage.Sets/src/mage/sets/magic2011/ElixirOfImmortality.java @@ -95,8 +95,8 @@ class ElixerOfImmortalityEffect extends OneShotEffect player.gainLife(5, game); player.removeFromBattlefield(game.getPermanent(source.getSourceId()), game); Card card = game.getCard(source.getSourceId()); - card.moveToZone(Zone.LIBRARY, game, true); - player.getLibrary().addAll(player.getGraveyard().getCards(game)); + card.moveToZone(Zone.LIBRARY, source.getId(), game, true); + player.getLibrary().addAll(player.getGraveyard().getCards(game), game); player.getGraveyard().clear(); player.getLibrary().shuffle(); return true; diff --git a/Mage.Sets/src/mage/sets/magic2011/LeylineOfTheVoid.java b/Mage.Sets/src/mage/sets/magic2011/LeylineOfTheVoid.java index 90a4f6a1800..d4319daed42 100644 --- a/Mage.Sets/src/mage/sets/magic2011/LeylineOfTheVoid.java +++ b/Mage.Sets/src/mage/sets/magic2011/LeylineOfTheVoid.java @@ -38,11 +38,13 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.LeylineAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; /** * @@ -96,14 +98,26 @@ class LeylineOfTheVoidEffect extends ReplacementEffectImpl { List creatures = game.getBattlefield().getAllActivePermanents(FilterCreaturePermanent.getDefault(), source.getControllerId()); count = creatures.size(); for (Permanent creature: creatures) { - creature.moveToExile(null, null, game); + creature.moveToExile(null, null, source.getId(), game); } Cards revealed = new CardsImpl(); Cards creatureCards = new CardsImpl(); @@ -107,7 +107,7 @@ class MassPolymorphEffect extends OneShotEffect { for (Card creatureCard: creatureCards.getCards(game)) { creatureCard.putOntoBattlefield(game, Zone.LIBRARY, source.getControllerId()); } - player.getLibrary().addAll(nonCreatureCards.getCards(game)); + player.getLibrary().addAll(nonCreatureCards.getCards(game), game); player.getLibrary().shuffle(); return true; } diff --git a/Mage.Sets/src/mage/sets/magic2011/MystifyingMaze.java b/Mage.Sets/src/mage/sets/magic2011/MystifyingMaze.java index 658592c225b..0c0ce58c715 100644 --- a/Mage.Sets/src/mage/sets/magic2011/MystifyingMaze.java +++ b/Mage.Sets/src/mage/sets/magic2011/MystifyingMaze.java @@ -101,7 +101,7 @@ class MystifyingMazeEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getFirstTarget()); if (permanent != null) { - if (permanent.moveToExile(source.getSourceId(), "Mystifying Maze Exile", game)) { + if (permanent.moveToExile(source.getSourceId(), "Mystifying Maze Exile", source.getId(), game)) { //create delayed triggered ability MystifyingMazeDelayedTriggeredAbility delayedAbility = new MystifyingMazeDelayedTriggeredAbility(source.getSourceId()); delayedAbility.setSourceId(source.getSourceId()); diff --git a/Mage.Sets/src/mage/sets/magic2011/ObstinateBaloth.java b/Mage.Sets/src/mage/sets/magic2011/ObstinateBaloth.java index 6a4518c8a52..19b46ee203d 100644 --- a/Mage.Sets/src/mage/sets/magic2011/ObstinateBaloth.java +++ b/Mage.Sets/src/mage/sets/magic2011/ObstinateBaloth.java @@ -100,10 +100,13 @@ class ObstinateBalothEffect extends ReplacementEffectImpl @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.DISCARD_CARD && event.getTargetId().equals(source.getSourceId())) { - StackObject spell = game.getStack().getStackObject(event.getSourceId()); - if (spell != null && game.getOpponents(source.getControllerId()).contains(spell.getControllerId())) { - return true; + if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(source.getSourceId())) { + ZoneChangeEvent zcEvent = (ZoneChangeEvent) event; + if (zcEvent.getFromZone() == Zone.HAND && zcEvent.getToZone() == Zone.GRAVEYARD) { + StackObject spell = game.getStack().getStackObject(event.getSourceId()); + if (spell != null && game.getOpponents(source.getControllerId()).contains(spell.getControllerId())) { + return true; + } } } return false; @@ -115,7 +118,6 @@ class ObstinateBalothEffect extends ReplacementEffectImpl if (card != null) { Player player = game.getPlayer(card.getOwnerId()); if (player != null) { - player.removeFromHand(card, game); if (card.putOntoBattlefield(game, Zone.HAND, player.getId())) { game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DISCARDED_CARD, card.getId(), source.getId(), player.getId())); return true; diff --git a/Mage.Sets/src/mage/sets/magic2011/TimeReversal.java b/Mage.Sets/src/mage/sets/magic2011/TimeReversal.java index 66ea729ac14..e2707e4df5e 100644 --- a/Mage.Sets/src/mage/sets/magic2011/TimeReversal.java +++ b/Mage.Sets/src/mage/sets/magic2011/TimeReversal.java @@ -84,8 +84,8 @@ class TimeReversalEffect extends OneShotEffect { for (UUID playerId: sourcePlayer.getInRange()) { Player player = game.getPlayer(playerId); if (player != null) { - player.getLibrary().addAll(player.getHand().getCards(game)); - player.getLibrary().addAll(player.getGraveyard().getCards(game)); + player.getLibrary().addAll(player.getHand().getCards(game), game); + player.getLibrary().addAll(player.getGraveyard().getCards(game), game); player.getLibrary().shuffle(); player.getHand().clear(); player.getGraveyard().clear(); diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeaGateOracle.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeaGateOracle.java index 702d3977cde..b880119c42a 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeaGateOracle.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeaGateOracle.java @@ -97,23 +97,24 @@ class SeaGateOracleEffect extends OneShotEffect { if (player.getLibrary().size() > 0) { if (player.getLibrary().size() == 1) { Card card = player.getLibrary().removeFromTop(game); - card.moveToZone(Zone.HAND, game, false); -// player.putInHand(player.getLibrary().removeFromTop(game), game); + card.moveToZone(Zone.HAND, source.getId(), game, false); } else { Cards cards = new CardsImpl(Zone.PICK); - cards.add(player.getLibrary().removeFromTop(game)); - cards.add(player.getLibrary().removeFromTop(game)); + Card card = player.getLibrary().removeFromTop(game); + cards.add(card); + game.setZone(card.getId(), Zone.PICK); + card = player.getLibrary().removeFromTop(game); + cards.add(card); + game.setZone(card.getId(), Zone.PICK); TargetCard target = new TargetCard(Zone.PICK, filter); target.setRequired(true); player.lookAtCards(cards, game); - player.chooseTarget(cards, target, source, game); - Card card = cards.get(target.getFirstTarget(), game); - card.moveToZone(Zone.HAND, game, false); -// player.putInHand(cards.get(target.getFirstTarget(), game), game); + player.choose(cards, target, game); + card = cards.get(target.getFirstTarget(), game); + card.moveToZone(Zone.HAND, source.getId(), game, false); for (Card card1: cards.getCards(game)) { - card1.moveToZone(Zone.LIBRARY, game, false); -// player.getLibrary().putOnBottom(cards.get(cardId, game), game); + card1.moveToZone(Zone.LIBRARY, source.getId(), game, false); } } return true; diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeeBeyond.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeeBeyond.java index c652a953274..0e15afba98c 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeeBeyond.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeeBeyond.java @@ -90,12 +90,11 @@ class SeeBeyondEffect extends OneShotEffect { if (player.getHand().size() > 0) { TargetCard target = new TargetCard(Zone.HAND, filter); target.setRequired(true); - player.chooseTarget(player.getHand(), target, source, game); + player.choose(player.getHand(), target, game); Card card = player.getHand().get(target.getFirstTarget(), game); if (card != null) { player.removeFromHand(card, game); - card.moveToZone(Zone.LIBRARY, game, true); -// player.getLibrary().putOnTop(card, game); + card.moveToZone(Zone.LIBRARY, source.getId(), game, true); player.getLibrary().shuffle(); return true; } diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/Vengevine.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/Vengevine.java index a19fa45f949..a751ebfdd6d 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/Vengevine.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/Vengevine.java @@ -134,7 +134,7 @@ class VengevineWatcher extends WatcherImpl { @Override public void watch(GameEvent event, Game game) { if (event.getType() == EventType.SPELL_CAST && event.getPlayerId().equals(controllerId)) { - Spell spell = (Spell)game.getStack().getStackObject(event.getTargetId()); + Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getCardType().contains(CardType.CREATURE)) { creatureSpellCount++; if (creatureSpellCount == 2) diff --git a/Mage.Sets/src/mage/sets/tenth/AngelsFeather.java b/Mage.Sets/src/mage/sets/tenth/AngelsFeather.java index f3ef9665efe..72fc30db1fa 100644 --- a/Mage.Sets/src/mage/sets/tenth/AngelsFeather.java +++ b/Mage.Sets/src/mage/sets/tenth/AngelsFeather.java @@ -32,13 +32,13 @@ import java.util.UUID; import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; -import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; /** * @@ -86,7 +86,7 @@ class AngelsFeatherAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.SPELL_CAST) { - MageObject spell = game.getObject(event.getTargetId()); + Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getColor().isWhite()) { trigger(game, event.getPlayerId()); return true; diff --git a/Mage.Sets/src/mage/sets/tenth/DemonsHorn.java b/Mage.Sets/src/mage/sets/tenth/DemonsHorn.java index 5f7529f2c9b..5e8135a22f2 100644 --- a/Mage.Sets/src/mage/sets/tenth/DemonsHorn.java +++ b/Mage.Sets/src/mage/sets/tenth/DemonsHorn.java @@ -32,13 +32,13 @@ import java.util.UUID; import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; -import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; /** * @@ -86,7 +86,7 @@ class DemonsHornAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.SPELL_CAST) { - MageObject spell = game.getObject(event.getTargetId()); + Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getColor().isBlack()) { trigger(game, event.getPlayerId()); return true; diff --git a/Mage.Sets/src/mage/sets/tenth/DragonsClaw.java b/Mage.Sets/src/mage/sets/tenth/DragonsClaw.java index bc69ae4a264..fca944816bb 100644 --- a/Mage.Sets/src/mage/sets/tenth/DragonsClaw.java +++ b/Mage.Sets/src/mage/sets/tenth/DragonsClaw.java @@ -32,13 +32,13 @@ import java.util.UUID; import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; -import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; /** * @@ -86,7 +86,7 @@ class DragonsClawAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.SPELL_CAST) { - MageObject spell = game.getObject(event.getTargetId()); + Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getColor().isRed()) { trigger(game, event.getPlayerId()); return true; diff --git a/Mage.Sets/src/mage/sets/tenth/KrakensEye.java b/Mage.Sets/src/mage/sets/tenth/KrakensEye.java index 613c5b3eaa7..c2cdf0520d0 100644 --- a/Mage.Sets/src/mage/sets/tenth/KrakensEye.java +++ b/Mage.Sets/src/mage/sets/tenth/KrakensEye.java @@ -32,13 +32,13 @@ import java.util.UUID; import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; -import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; /** * @@ -86,7 +86,7 @@ class KrakensEyeAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.SPELL_CAST) { - MageObject spell = game.getObject(event.getTargetId()); + Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getColor().isBlue()) { trigger(game, event.getPlayerId()); return true; diff --git a/Mage.Sets/src/mage/sets/tenth/WurmsTooth.java b/Mage.Sets/src/mage/sets/tenth/WurmsTooth.java index d21441472ae..e0c02bc783a 100644 --- a/Mage.Sets/src/mage/sets/tenth/WurmsTooth.java +++ b/Mage.Sets/src/mage/sets/tenth/WurmsTooth.java @@ -32,13 +32,13 @@ import java.util.UUID; import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; -import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; /** * @@ -86,7 +86,7 @@ class WurmsToothAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.SPELL_CAST) { - MageObject spell = game.getObject(event.getTargetId()); + Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getColor().isGreen()) { trigger(game, event.getPlayerId()); return true; diff --git a/Mage.Sets/src/mage/sets/worldwake/JaceTheMindSculptor.java b/Mage.Sets/src/mage/sets/worldwake/JaceTheMindSculptor.java index fb9f02f42cd..0f58fe86139 100644 --- a/Mage.Sets/src/mage/sets/worldwake/JaceTheMindSculptor.java +++ b/Mage.Sets/src/mage/sets/worldwake/JaceTheMindSculptor.java @@ -122,8 +122,7 @@ class JaceTheMindSculptorEffect1 extends OneShotEffect { defender.revealCards(cards, game); if (card.getCardType().contains(CardType.LAND)) { defender.getLibrary().removeFromTop(game); - card.moveToZone(Zone.HAND, game, true); -// defender.putInHand(card, game); + card.moveToZone(Zone.HAND, source.getId(), game, true); } } } diff --git a/Mage/src/mage/Constants.java b/Mage/src/mage/Constants.java index 2bb5436697c..572feb24ffd 100644 --- a/Mage/src/mage/Constants.java +++ b/Mage/src/mage/Constants.java @@ -139,6 +139,27 @@ public final class Constants { } } + public enum EffectType { + + ONESHOT("One Shot Effect"), + CONTINUOUS("Continuous Effect"), + REPLACEMENT("Replacement Effect"), + PREVENTION("Prevention Effect"), + REDIRECTION("Redirection Effect"), + ASTHOUGH("As Though Effect"); + + private String text; + + EffectType(String text) { + this.text = text; + } + + @Override + public String toString() { + return text; + } + } + public enum AsThoughEffectType { BLOCK, BE_BLOCKED, diff --git a/Mage/src/mage/MageObject.java b/Mage/src/mage/MageObject.java index c9f0323ea2b..0c41f4629f9 100644 --- a/Mage/src/mage/MageObject.java +++ b/Mage/src/mage/MageObject.java @@ -27,8 +27,8 @@ public interface MageObject extends MageItem, Serializable { public MageInt getToughness(); public MageInt getLoyalty(); - public Zone getZone(); - public void setZone(Zone zone); +// public Zone getZone(); +// public void setZone(Zone zone); public void adjustCosts(Ability ability, Game game); diff --git a/Mage/src/mage/MageObjectImpl.java b/Mage/src/mage/MageObjectImpl.java index 30133e742db..49ac4b7edc3 100644 --- a/Mage/src/mage/MageObjectImpl.java +++ b/Mage/src/mage/MageObjectImpl.java @@ -57,7 +57,7 @@ public abstract class MageObjectImpl> implements Mag protected MageInt power; protected MageInt toughness; protected MageInt loyalty; - protected Zone zone; +// protected Zone zone; @Override public abstract T copy(); @@ -81,7 +81,7 @@ public abstract class MageObjectImpl> implements Mag name = object.name; manaCost = object.manaCost.copy(); text = object.text; - zone = object.zone; +// zone = object.zone; color = object.color.copy(); power = object.power.copy(); toughness = object.toughness.copy(); @@ -158,15 +158,15 @@ public abstract class MageObjectImpl> implements Mag return manaCost; } - @Override - public Zone getZone() { - return zone; - } - - @Override - public void setZone(Zone zone) { - this.zone = zone; - } +// @Override +// public Zone getZone() { +// return zone; +// } +// +// @Override +// public void setZone(Zone zone) { +// this.zone = zone; +// } @Override public void adjustCosts(Ability ability, Game game) {} diff --git a/Mage/src/mage/abilities/Ability.java b/Mage/src/mage/abilities/Ability.java index f7485df3f13..89eb2a9db82 100644 --- a/Mage/src/mage/abilities/Ability.java +++ b/Mage/src/mage/abilities/Ability.java @@ -32,6 +32,7 @@ import java.io.Serializable; import java.util.List; import java.util.UUID; import mage.Constants.AbilityType; +import mage.Constants.EffectType; import mage.Constants.Zone; import mage.abilities.costs.AlternativeCost; import mage.abilities.costs.Cost; @@ -61,6 +62,7 @@ public interface Ability extends Serializable { public Costs getOptionalCosts(); public void addOptionalCost(Cost cost); public Effects getEffects(); + public Effects getEffects(EffectType effectType); public void addEffect(Effect effect); public Targets getTargets(); public UUID getFirstTarget(); diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index c851e32d3bf..f8bda1ad99b 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -33,6 +33,7 @@ import java.util.List; import java.util.UUID; import java.util.logging.Logger; import mage.Constants.AbilityType; +import mage.Constants.EffectType; import mage.Constants.Outcome; import mage.Constants.Zone; import mage.abilities.costs.AlternativeCost; @@ -46,8 +47,6 @@ import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.Effects; import mage.abilities.effects.OneShotEffect; -import mage.abilities.keyword.EnchantAbility; -import mage.cards.Card; import mage.choices.Choice; import mage.choices.Choices; import mage.game.Game; @@ -235,6 +234,17 @@ public abstract class AbilityImpl> implements Ability { return effects; } + @Override + public Effects getEffects(EffectType effectType) { + Effects typedEffects = new Effects(); + for (Effect effect: effects) { + if (effect.getEffectType() == effectType) { + typedEffects.add(effect); + } + } + return typedEffects; + } + @Override public Choices getChoices() { return choices; diff --git a/Mage/src/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/mage/abilities/ActivatedAbilityImpl.java index 9f139a59f5d..e220b8e32f5 100644 --- a/Mage/src/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/mage/abilities/ActivatedAbilityImpl.java @@ -154,7 +154,7 @@ public abstract class ActivatedAbilityImpl> ex return true; else { Card card = (Card)game.getObject(this.sourceId); - if (card != null && card.getZone() != Zone.BATTLEFIELD) + if (card != null && game.getZone(this.sourceId) != Zone.BATTLEFIELD) return card.getOwnerId().equals(playerId); } return false; diff --git a/Mage/src/mage/abilities/costs/common/ExileSourceCost.java b/Mage/src/mage/abilities/costs/common/ExileSourceCost.java index 26e19163b47..c1c50f08b02 100644 --- a/Mage/src/mage/abilities/costs/common/ExileSourceCost.java +++ b/Mage/src/mage/abilities/costs/common/ExileSourceCost.java @@ -29,7 +29,6 @@ package mage.abilities.costs.common; import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.game.Game; import mage.game.permanent.Permanent; @@ -52,7 +51,7 @@ public class ExileSourceCost extends CostImpl { public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { Permanent permanent = game.getPermanent(sourceId); if (permanent != null) { - paid = permanent.moveToExile(null, "", game); + paid = permanent.moveToExile(null, "", sourceId, game); } return paid; } diff --git a/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java b/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java index 0de197a4730..725e4382f4e 100644 --- a/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java +++ b/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java @@ -58,7 +58,7 @@ public class ReturnToHandTargetCost extends CostImpl { Permanent permanent = game.getPermanent(targetId); if (permanent == null) return false; - paid |= permanent.moveToZone(Zone.HAND, game, false); + paid |= permanent.moveToZone(Zone.HAND, sourceId, game, false); } } return paid; diff --git a/Mage/src/mage/abilities/effects/AsThoughEffectImpl.java b/Mage/src/mage/abilities/effects/AsThoughEffectImpl.java index 46ce0996b0d..251843d4ee7 100644 --- a/Mage/src/mage/abilities/effects/AsThoughEffectImpl.java +++ b/Mage/src/mage/abilities/effects/AsThoughEffectImpl.java @@ -30,6 +30,7 @@ package mage.abilities.effects; import mage.Constants.AsThoughEffectType; import mage.Constants.Duration; +import mage.Constants.EffectType; import mage.Constants.Outcome; /** @@ -43,6 +44,7 @@ public abstract class AsThoughEffectImpl> extend public AsThoughEffectImpl(AsThoughEffectType type, Duration duration, Outcome outcome) { super(duration, outcome); this.type = type; + this.effectType = EffectType.ASTHOUGH; } public AsThoughEffectImpl(final AsThoughEffectImpl effect) { diff --git a/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java b/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java index e661647ce40..9ed1ee404a4 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java @@ -30,6 +30,7 @@ package mage.abilities.effects; import java.util.Date; import mage.Constants.Duration; +import mage.Constants.EffectType; import mage.Constants.Layer; import mage.Constants.Outcome; import mage.Constants.SubLayer; @@ -52,6 +53,7 @@ public abstract class ContinuousEffectImpl> ex super(outcome); this.duration = duration; this.timestamp = new Date(); + this.effectType = EffectType.CONTINUOUS; } public ContinuousEffectImpl(Duration duration, Layer layer, SubLayer sublayer, Outcome outcome) { diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java index ebd007c8b9c..11555f95a3c 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java @@ -40,9 +40,12 @@ import java.util.Map.Entry; import java.util.UUID; import mage.Constants.AsThoughEffectType; import mage.Constants.Duration; +import mage.Constants.EffectType; import mage.Constants.Layer; import mage.Constants.SubLayer; +import mage.Constants.Zone; import mage.abilities.Ability; +import mage.cards.Card; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; @@ -54,10 +57,15 @@ import mage.players.Player; */ public class ContinuousEffects implements Serializable { - private final Map layeredEffects = new HashMap(); - private final Map replacementEffects = new HashMap(); - private final Map preventionEffects = new HashMap(); - private final Map asThoughEffects = new HashMap(); + //transient Continuous effects + private final List layeredEffects = new ArrayList(); + private final List replacementEffects = new ArrayList(); + private final List preventionEffects = new ArrayList(); + private final List asThoughEffects = new ArrayList(); + + //map Abilities to Continuous effects + private final Map abilityMap = new HashMap(); + private final ApplyCountersEffect applyCounters; private final PlaneswalkerRedirectionEffect planeswalkerRedirectionEffect; @@ -69,17 +77,20 @@ public class ContinuousEffects implements Serializable { public ContinuousEffects(final ContinuousEffects effect) { this.applyCounters = effect.applyCounters.copy(); this.planeswalkerRedirectionEffect = effect.planeswalkerRedirectionEffect.copy(); - for (Entry entry: effect.layeredEffects.entrySet()) { - layeredEffects.put((ContinuousEffect)entry.getKey().copy(), entry.getValue().copy()); + for (ContinuousEffect entry: effect.layeredEffects) { + layeredEffects.add((ContinuousEffect) entry.copy()); } - for (Entry entry: effect.replacementEffects.entrySet()) { - replacementEffects.put((ReplacementEffect)entry.getKey().copy(), entry.getValue().copy()); + for (ReplacementEffect entry: effect.replacementEffects) { + replacementEffects.add((ReplacementEffect)entry.copy()); } - for (Entry entry: effect.preventionEffects.entrySet()) { - preventionEffects.put((PreventionEffect)entry.getKey().copy(), entry.getValue().copy()); + for (PreventionEffect entry: effect.preventionEffects) { + preventionEffects.add((PreventionEffect)entry.copy()); } - for (Entry entry: effect.asThoughEffects.entrySet()) { - asThoughEffects.put((AsThoughEffect)entry.getKey().copy(), entry.getValue().copy()); + for (AsThoughEffect entry: effect.asThoughEffects) { + asThoughEffects.add((AsThoughEffect)entry.copy()); + } + for (Entry entry: effect.abilityMap.entrySet()) { + abilityMap.put((ContinuousEffect)entry.getKey().copy(), entry.getValue().copy()); } } @@ -88,22 +99,22 @@ public class ContinuousEffects implements Serializable { } public void removeEndOfTurnEffects() { - for (Iterator i = layeredEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = layeredEffects.iterator(); i.hasNext();) { ContinuousEffect entry = i.next(); if (entry.getDuration() == Duration.EndOfTurn) i.remove(); } - for (Iterator i = replacementEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = replacementEffects.iterator(); i.hasNext();) { ContinuousEffect entry = i.next(); if (entry.getDuration() == Duration.EndOfTurn) i.remove(); } - for (Iterator i = preventionEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = preventionEffects.iterator(); i.hasNext();) { ContinuousEffect entry = i.next(); if (entry.getDuration() == Duration.EndOfTurn) i.remove(); } - for (Iterator i = asThoughEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = asThoughEffects.iterator(); i.hasNext();) { ContinuousEffect entry = i.next(); if (entry.getDuration() == Duration.EndOfTurn) i.remove(); @@ -111,40 +122,40 @@ public class ContinuousEffects implements Serializable { } public void removeInactiveEffects(Game game) { - for (Iterator i = layeredEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = layeredEffects.iterator(); i.hasNext();) { ContinuousEffect entry = i.next(); if (entry.getDuration() == Duration.WhileOnBattlefield) { - Permanent permanent = game.getPermanent(layeredEffects.get(entry).getSourceId()); + Permanent permanent = game.getPermanent(abilityMap.get(entry).getSourceId()); if (permanent == null || !permanent.isPhasedIn()) i.remove(); } else if (entry.getDuration() == Duration.OneUse && entry.isUsed()) i.remove(); } - for (Iterator i = replacementEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = replacementEffects.iterator(); i.hasNext();) { ReplacementEffect entry = i.next(); if (entry.getDuration() == Duration.WhileOnBattlefield) { - Permanent permanent = game.getPermanent(replacementEffects.get(entry).getSourceId()); + Permanent permanent = game.getPermanent(abilityMap.get(entry).getSourceId()); if (permanent == null || !permanent.isPhasedIn()) i.remove(); } else if (entry.getDuration() == Duration.OneUse && entry.isUsed()) i.remove(); } - for (Iterator i = preventionEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = preventionEffects.iterator(); i.hasNext();) { PreventionEffect entry = i.next(); if (entry.getDuration() == Duration.WhileOnBattlefield) { - Permanent permanent = game.getPermanent(preventionEffects.get(entry).getSourceId()); + Permanent permanent = game.getPermanent(abilityMap.get(entry).getSourceId()); if (permanent == null || !permanent.isPhasedIn()) i.remove(); } else if (entry.getDuration() == Duration.OneUse && entry.isUsed()) i.remove(); } - for (Iterator i = asThoughEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = asThoughEffects.iterator(); i.hasNext();) { AsThoughEffect entry = i.next(); if (entry.getDuration() == Duration.WhileOnBattlefield) { - Permanent permanent = game.getPermanent(asThoughEffects.get(entry).getSourceId()); + Permanent permanent = game.getPermanent(abilityMap.get(entry).getSourceId()); if (permanent == null || !permanent.isPhasedIn()) i.remove(); } @@ -153,31 +164,93 @@ public class ContinuousEffects implements Serializable { } } - private List getLayeredEffects() { - List layerEffects = new ArrayList(layeredEffects.keySet()); + private List getLayeredEffects(Game game) { + List layerEffects = new ArrayList(layeredEffects); + for (Card card: game.getCards()) { + if (game.getZone(card.getId()) == Zone.HAND || game.getZone(card.getId()) == Zone.GRAVEYARD) { + for (Ability ability: card.getAbilities().getStaticAbilities(game.getZone(card.getId()))) { + for (Effect effect: ability.getEffects(EffectType.CONTINUOUS)) { + layerEffects.add((ContinuousEffect) effect); + abilityMap.put((ContinuousEffect) effect, ability); + } + } + } + } + for (Permanent permanent: game.getBattlefield().getAllPermanents()) { + for (Ability ability: permanent.getAbilities().getStaticAbilities(Zone.BATTLEFIELD)) { + for (Effect effect: ability.getEffects(EffectType.CONTINUOUS)) { + layerEffects.add((ContinuousEffect) effect); + abilityMap.put((ContinuousEffect) effect, ability); + } + } + } Collections.sort(layerEffects, new TimestampSorter()); return layerEffects; } + /** + * + * @param event + * @param game + * @return a list of all {@link ReplacementEffect} that apply to the current event + */ private List getApplicableReplacementEffects(GameEvent event, Game game) { List replaceEffects = new ArrayList(); if (planeswalkerRedirectionEffect.applies(event, null, game)) replaceEffects.add(planeswalkerRedirectionEffect); - for (ReplacementEffect effect: replacementEffects.keySet()) { - if (effect.applies(event, replacementEffects.get(effect), game)) { - if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) + //get all applicable Replacement effects in each players hand and graveyard + for (Card card: game.getCards()) { + if (game.getZone(card.getId()) == Zone.HAND || game.getZone(card.getId()) == Zone.GRAVEYARD) { + for (Ability ability: card.getAbilities().getStaticAbilities(game.getZone(card.getId()))) { + for (Effect effect: ability.getEffects(EffectType.REPLACEMENT)) { + ReplacementEffect rEffect = (ReplacementEffect) effect; + if (rEffect.applies(event, ability, game)) { + replaceEffects.add(rEffect); + abilityMap.put(rEffect, ability); + } + } + } + } + } + //get all applicable Replacement effects on the battlefield + for (Permanent permanent: game.getBattlefield().getAllPermanents()) { + for (Ability ability: permanent.getAbilities().getStaticAbilities(Zone.BATTLEFIELD)) { + for (Effect effect: ability.getEffects(EffectType.REPLACEMENT)) { + ReplacementEffect rEffect = (ReplacementEffect) effect; + if (rEffect.applies(event, ability, game)) { + replaceEffects.add(rEffect); + abilityMap.put(rEffect, ability); + } + } + } + } + //get all applicable transient Replacement effects + for (ReplacementEffect effect: replacementEffects) { + if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { + if (effect.applies(event, abilityMap.get(effect), game)) { replaceEffects.add(effect); + } } } return replaceEffects; } public boolean asThough(UUID objectId, AsThoughEffectType type, Game game) { - for (Entry entry: asThoughEffects.entrySet()) { - AsThoughEffect effect = entry.getKey(); + for (Permanent permanent: game.getBattlefield().getAllPermanents()) { + for (Ability ability: permanent.getAbilities().getStaticAbilities(Zone.BATTLEFIELD)) { + for (Effect effect: ability.getEffects(EffectType.ASTHOUGH)) { + AsThoughEffect rEffect = (AsThoughEffect) effect; + if (rEffect.applies(objectId, ability, game)) { + return true; + } + } + } + } + for (AsThoughEffect entry: asThoughEffects) { + AsThoughEffect effect = entry; if (effect.getAsThoughEffectType() == type) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { - if (effect.applies(objectId, entry.getValue(), game)) { + if (effect.applies(objectId, abilityMap.get(entry), game)) { return true; } } @@ -195,10 +268,12 @@ public class ContinuousEffects implements Serializable { index = 0; } else { + //20100716 - 616.1c Player player = game.getPlayer(event.getPlayerId()); index = player.chooseEffect(rEffects, game); } - caught = rEffects.get(index).replaceEvent(event, replacementEffects.get(rEffects.get(index)), game); + ReplacementEffect rEffect = rEffects.get(index); + caught = rEffect.replaceEvent(event, abilityMap.get(rEffect), game); } return caught; @@ -207,84 +282,90 @@ public class ContinuousEffects implements Serializable { //20091005 - 613 public void apply(Game game) { removeInactiveEffects(game); - List layerEffects = getLayeredEffects(); + List layerEffects = getLayeredEffects(game); for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.CopyEffects_1, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.CopyEffects_1, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.CopyEffects_1, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.CopyEffects_1, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.ControlChangingEffects_2, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.ControlChangingEffects_2, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.ControlChangingEffects_2, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.ControlChangingEffects_2, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.TextChangingEffects_3, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.TextChangingEffects_3, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.TextChangingEffects_3, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.TextChangingEffects_3, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.TypeChangingEffects_4, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.TypeChangingEffects_4, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.TypeChangingEffects_4, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.TypeChangingEffects_4, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.ColorChangingEffects_5, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.ColorChangingEffects_5, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.ColorChangingEffects_5, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.ColorChangingEffects_5, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.AbilityAddingRemovingEffects_6, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.AbilityAddingRemovingEffects_6, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.PTChangingEffects_7, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.PTChangingEffects_7, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.PTChangingEffects_7, SubLayer.SetPT_7b, layeredEffects.get(effect), game); + effect.apply(Layer.PTChangingEffects_7, SubLayer.SetPT_7b, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, layeredEffects.get(effect), game); + effect.apply(Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, abilityMap.get(effect), game); } applyCounters.apply(Layer.PTChangingEffects_7, SubLayer.Counters_7d, null, game); for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.PTChangingEffects_7, SubLayer.SwitchPT_e, layeredEffects.get(effect), game); + effect.apply(Layer.PTChangingEffects_7, SubLayer.SwitchPT_e, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.PlayerEffects, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.PlayerEffects, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.RulesEffects, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.RulesEffects, SubLayer.NA, abilityMap.get(effect), game); } } public void addEffect(ContinuousEffect effect, Ability source) { - if (effect instanceof ReplacementEffect) { - ReplacementEffect newEffect = (ReplacementEffect)effect.copy(); - newEffect.setTimestamp(); - replacementEffects.put(newEffect, source); - } - else if (effect instanceof PreventionEffect) { - PreventionEffect newEffect = (PreventionEffect)effect.copy(); - newEffect.setTimestamp(); - preventionEffects.put(newEffect, source); - } - else if (effect instanceof AsThoughEffect) { - AsThoughEffect newEffect = (AsThoughEffect)effect.copy(); - newEffect.setTimestamp(); - asThoughEffects.put(newEffect,source); - } - else { - ContinuousEffect newEffect = (ContinuousEffect)effect.copy(); - newEffect.setTimestamp(); - layeredEffects.put(newEffect, source); + switch (effect.getEffectType()) { + case REPLACEMENT: + ReplacementEffect newReplacementEffect = (ReplacementEffect)effect.copy(); + newReplacementEffect.setTimestamp(); + replacementEffects.add(newReplacementEffect); + abilityMap.put(newReplacementEffect, source); + break; + case PREVENTION: + PreventionEffect newPreventionEffect = (PreventionEffect)effect.copy(); + newPreventionEffect.setTimestamp(); + preventionEffects.add(newPreventionEffect); + abilityMap.put(newPreventionEffect, source); + break; + case ASTHOUGH: + AsThoughEffect newAsThoughEffect = (AsThoughEffect)effect.copy(); + newAsThoughEffect.setTimestamp(); + asThoughEffects.add(newAsThoughEffect); + abilityMap.put(newAsThoughEffect, source); + break; + default: + ContinuousEffect newEffect = (ContinuousEffect)effect.copy(); + newEffect.setTimestamp(); + layeredEffects.add(newEffect); + abilityMap.put(newEffect, source); + break; } } diff --git a/Mage/src/mage/abilities/effects/Effect.java b/Mage/src/mage/abilities/effects/Effect.java index 6765b2e3612..cf44c0105ce 100644 --- a/Mage/src/mage/abilities/effects/Effect.java +++ b/Mage/src/mage/abilities/effects/Effect.java @@ -29,6 +29,7 @@ package mage.abilities.effects; import java.io.Serializable; +import mage.Constants.EffectType; import mage.Constants.Outcome; import mage.abilities.Ability; import mage.game.Game; @@ -42,6 +43,7 @@ public interface Effect> extends Serializable { public String getText(Ability source); public boolean apply(Game game, Ability source); public Outcome getOutcome(); + public EffectType getEffectType(); public T copy(); diff --git a/Mage/src/mage/abilities/effects/EffectImpl.java b/Mage/src/mage/abilities/effects/EffectImpl.java index ed31d6294fc..856334f0150 100644 --- a/Mage/src/mage/abilities/effects/EffectImpl.java +++ b/Mage/src/mage/abilities/effects/EffectImpl.java @@ -28,6 +28,7 @@ package mage.abilities.effects; +import mage.Constants.EffectType; import mage.Constants.Outcome; import mage.abilities.Ability; @@ -38,6 +39,7 @@ import mage.abilities.Ability; public abstract class EffectImpl> implements Effect { protected final Outcome outcome; + protected EffectType effectType; public EffectImpl(Outcome outcome) { this.outcome = outcome; @@ -45,6 +47,7 @@ public abstract class EffectImpl> implements Effect { public EffectImpl(final EffectImpl effect) { this.outcome = effect.outcome; + this.effectType = effect.effectType; } @Override @@ -56,4 +59,9 @@ public abstract class EffectImpl> implements Effect { public Outcome getOutcome() { return outcome; } + + @Override + public EffectType getEffectType() { + return effectType; + } } diff --git a/Mage/src/mage/abilities/effects/OneShotEffect.java b/Mage/src/mage/abilities/effects/OneShotEffect.java index 6640e252ea0..608bd7c0b8f 100644 --- a/Mage/src/mage/abilities/effects/OneShotEffect.java +++ b/Mage/src/mage/abilities/effects/OneShotEffect.java @@ -28,6 +28,7 @@ package mage.abilities.effects; +import mage.Constants.EffectType; import mage.Constants.Outcome; /** @@ -38,6 +39,7 @@ public abstract class OneShotEffect> extends EffectIm public OneShotEffect(Outcome outcome) { super(outcome); + this.effectType = EffectType.ONESHOT; } public OneShotEffect(final OneShotEffect effect) { diff --git a/Mage/src/mage/abilities/effects/PreventionEffectImpl.java b/Mage/src/mage/abilities/effects/PreventionEffectImpl.java index d31159d8427..c3fc4f78c17 100644 --- a/Mage/src/mage/abilities/effects/PreventionEffectImpl.java +++ b/Mage/src/mage/abilities/effects/PreventionEffectImpl.java @@ -29,6 +29,7 @@ package mage.abilities.effects; import mage.Constants.Duration; +import mage.Constants.EffectType; import mage.Constants.Outcome; import mage.abilities.Ability; import mage.game.Game; @@ -43,6 +44,7 @@ public abstract class PreventionEffectImpl> ex public PreventionEffectImpl(Duration duration) { super(duration, Outcome.PreventDamage); + this.effectType = EffectType.PREVENTION; } public PreventionEffectImpl(final PreventionEffectImpl effect) { diff --git a/Mage/src/mage/abilities/effects/RedirectionEffect.java b/Mage/src/mage/abilities/effects/RedirectionEffect.java index 3e1e9734dea..99ead53d869 100644 --- a/Mage/src/mage/abilities/effects/RedirectionEffect.java +++ b/Mage/src/mage/abilities/effects/RedirectionEffect.java @@ -30,6 +30,7 @@ package mage.abilities.effects; import java.util.UUID; import mage.Constants.Duration; +import mage.Constants.EffectType; import mage.Constants.Outcome; import mage.abilities.Ability; import mage.game.Game; @@ -51,6 +52,7 @@ public abstract class RedirectionEffect> extends public RedirectionEffect(Duration duration) { super(duration, Outcome.RedirectDamage); + this.effectType = EffectType.REDIRECTION; } public RedirectionEffect(final RedirectionEffect effect) { diff --git a/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java b/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java index fcb5512f999..956e7cf30da 100644 --- a/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java +++ b/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java @@ -29,6 +29,7 @@ package mage.abilities.effects; import mage.Constants.Duration; +import mage.Constants.EffectType; import mage.Constants.Outcome; /** @@ -39,6 +40,7 @@ public abstract class ReplacementEffectImpl> public ReplacementEffectImpl(Duration duration, Outcome outcome) { super(duration, outcome); + this.effectType = EffectType.REPLACEMENT; } public ReplacementEffectImpl(final ReplacementEffectImpl effect) { diff --git a/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java b/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java index 1b4bdc01140..9c66181a0d5 100644 --- a/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java @@ -61,8 +61,10 @@ public class CantCounterControlledEffect extends ReplacementEffectImpl { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - return permanent.moveToExile(null, "", game); + return permanent.moveToExile(null, "", source.getId(), game); } return false; } diff --git a/Mage/src/mage/abilities/effects/common/ExileTargetEffect.java b/Mage/src/mage/abilities/effects/common/ExileTargetEffect.java index 06cd20a3a11..19fdc8ad145 100644 --- a/Mage/src/mage/abilities/effects/common/ExileTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/ExileTargetEffect.java @@ -69,7 +69,7 @@ public class ExileTargetEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getFirstTarget()); if (permanent != null) { - return permanent.moveToExile(exileId, exileZone, game); + return permanent.moveToExile(exileId, exileZone, source.getId(), game); } return false; } diff --git a/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java b/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java index 46f0de402b2..14e6fad02df 100644 --- a/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java @@ -66,19 +66,14 @@ public class PutOnLibraryTargetEffect extends OneShotEffect if (exile != null) { for (UUID cardId: exile) { Card card = game.getCard(cardId); - card.moveToZone(zone, game, tapped); + card.moveToZone(zone, source.getId(), game, tapped); } exile.clear(); return true; diff --git a/Mage/src/mage/abilities/effects/common/ReturnSourceFromGraveyardToHandEffect.java b/Mage/src/mage/abilities/effects/common/ReturnSourceFromGraveyardToHandEffect.java index 6a9791612db..3c5e5f68562 100644 --- a/Mage/src/mage/abilities/effects/common/ReturnSourceFromGraveyardToHandEffect.java +++ b/Mage/src/mage/abilities/effects/common/ReturnSourceFromGraveyardToHandEffect.java @@ -61,7 +61,7 @@ public class ReturnSourceFromGraveyardToHandEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); Cards cards = new CardsImpl(Zone.PICK); for (int i = 0; i < scryNumber; i++) { - cards.add(player.getLibrary().removeFromTop(game)); + Card card = player.getLibrary().removeFromTop(game); + cards.add(card); + game.setZone(card.getId(), Zone.PICK); } TargetCard target1 = new TargetCard(Zone.PICK, filter1); - while (cards.size() > 0 && player.chooseTarget(cards, target1, source, game)) { + while (cards.size() > 0 && player.choose(cards, target1, game)) { Card card = cards.get(target1.getFirstTarget(), game); cards.remove(card); - card.moveToZone(Zone.LIBRARY, game, false); -// player.getLibrary().putOnBottom(card, game); + card.moveToZone(Zone.LIBRARY, source.getId(), game, false); target1.clearChosen(); } if (cards.size() > 1) { TargetCard target2 = new TargetCard(Zone.PICK, filter2); target2.setRequired(true); while (cards.size() > 1) { - player.chooseTarget(cards, target2, source, game); + player.choose(cards, target2, game); Card card = cards.get(target2.getFirstTarget(), game); cards.remove(card); - card.moveToZone(Zone.LIBRARY, game, true); -// player.getLibrary().putOnTop(card, game); + card.moveToZone(Zone.LIBRARY, source.getId(), game, true); target2.clearChosen(); } } if (cards.size() == 1) { Card card = cards.get(cards.iterator().next(), game); - card.moveToZone(Zone.LIBRARY, game, true); -// player.getLibrary().putOnTop(cards.get(cards.iterator().next(), game), game); + card.moveToZone(Zone.LIBRARY, source.getId(), game, true); } return true; } diff --git a/Mage/src/mage/abilities/effects/common/SearchLibraryPutInHandEffect.java b/Mage/src/mage/abilities/effects/common/SearchLibraryPutInHandEffect.java index d89c7aec0b8..7dec267e349 100644 --- a/Mage/src/mage/abilities/effects/common/SearchLibraryPutInHandEffect.java +++ b/Mage/src/mage/abilities/effects/common/SearchLibraryPutInHandEffect.java @@ -66,7 +66,7 @@ public class SearchLibraryPutInHandEffect extends SearchEffect)target.getTargets()) { Card card = player.getLibrary().remove(cardId, game); if (card != null){ - card.moveToZone(Zone.HAND, game, false); + card.moveToZone(Zone.HAND, source.getId(), game, false); } } player.shuffleLibrary(game); diff --git a/Mage/src/mage/abilities/effects/common/SearchLibraryPutOnLibraryEffect.java b/Mage/src/mage/abilities/effects/common/SearchLibraryPutOnLibraryEffect.java index c09b8076206..15697fe22d4 100644 --- a/Mage/src/mage/abilities/effects/common/SearchLibraryPutOnLibraryEffect.java +++ b/Mage/src/mage/abilities/effects/common/SearchLibraryPutOnLibraryEffect.java @@ -72,7 +72,7 @@ public class SearchLibraryPutOnLibraryEffect extends SearchEffect)target.getTargets()) { Card card = player.getLibrary().remove(cardId, game); if (card != null) { - card.moveToZone(Zone.HAND, game, false); + card.moveToZone(Zone.HAND, source.getId(), game, false); revealed.add(card); } } diff --git a/Mage/src/mage/abilities/keyword/CascadeAbility.java b/Mage/src/mage/abilities/keyword/CascadeAbility.java index 720d202ce97..b04cac62948 100644 --- a/Mage/src/mage/abilities/keyword/CascadeAbility.java +++ b/Mage/src/mage/abilities/keyword/CascadeAbility.java @@ -31,6 +31,7 @@ package mage.abilities.keyword; import mage.Constants.CardType; import mage.Constants.Outcome; import mage.Constants.Zone; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.OneShotEffect; @@ -39,6 +40,7 @@ import mage.game.ExileZone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; import mage.players.Player; /** @@ -58,9 +60,12 @@ public class CascadeAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == EventType.SPELL_CAST && event.getTargetId().equals(this.getSourceId()) ) { - trigger(game, event.getPlayerId()); - return true; + if (event.getType() == EventType.SPELL_CAST) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null && spell.getSourceId().equals(this.getSourceId())) { + trigger(game, event.getPlayerId()); + return true; + } } return false; } @@ -96,7 +101,7 @@ class CascadeEffect extends OneShotEffect { card = player.getLibrary().removeFromTop(game); if (card == null) break; - card.moveToExile(exile.getId(), exile.getName(), game); + card.moveToExile(exile.getId(), exile.getName(), source.getId(), game); } while (card.getCardType().contains(CardType.LAND) || card.getManaCost().convertedManaCost() >= sourceCost); if (card != null) { @@ -109,7 +114,7 @@ class CascadeEffect extends OneShotEffect { while (exile.size() > 0) { card = exile.getRandom(game); exile.remove(card.getId()); - card.moveToZone(Zone.LIBRARY, game, false); + card.moveToZone(Zone.LIBRARY, source.getId(), game, false); } return true; diff --git a/Mage/src/mage/cards/Card.java b/Mage/src/mage/cards/Card.java index 00622c4b60c..6839fcda5f2 100644 --- a/Mage/src/mage/cards/Card.java +++ b/Mage/src/mage/cards/Card.java @@ -55,8 +55,8 @@ public interface Card extends MageObject { public String getExpansionSetCode(); public void setExpansionSetCode(String expansionSetCode); - public boolean moveToZone(Zone zone, Game game, boolean flag); - public boolean moveToExile(UUID exileId, String name, Game game); + public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag); + public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game); public boolean putOntoBattlefield(Game game, Zone fromZone, UUID controllerId); public void checkTriggers(Zone zone, GameEvent event, Game game); diff --git a/Mage/src/mage/cards/CardImpl.java b/Mage/src/mage/cards/CardImpl.java index 1941d8d88fd..e5355efa44e 100644 --- a/Mage/src/mage/cards/CardImpl.java +++ b/Mage/src/mage/cards/CardImpl.java @@ -45,6 +45,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.PermanentCard; +import mage.game.stack.Spell; import mage.util.Logging; import mage.watchers.Watchers; @@ -96,7 +97,7 @@ public abstract class CardImpl> extends MageObjectImpl Class theClass = Class.forName(name); Constructor con = theClass.getConstructor(new Class[]{UUID.class}); Card card = (Card) con.newInstance(new Object[] {null}); - card.setZone(Zone.OUTSIDE); +// card.setZone(Zone.OUTSIDE); return card; } catch (Exception e) { @@ -182,9 +183,10 @@ public abstract class CardImpl> extends MageObjectImpl this.expansionSetCode = expansionSetCode; } - public boolean moveToZone(Zone toZone, UUID controllerId, Game game, boolean flag) { - Zone fromZone = zone; - ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, controllerId, fromZone, toZone); + @Override + public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag) { + Zone fromZone = game.getZone(objectId); + ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, toZone); if (!game.replaceEvent(event)) { switch (event.getToZone()) { case GRAVEYARD: @@ -193,6 +195,9 @@ public abstract class CardImpl> extends MageObjectImpl case HAND: game.getPlayer(ownerId).getHand().add(this); break; + case STACK: + game.getStack().push(new Spell(this, this.getSpellAbility().copy(), ownerId)); + break; case EXILED: game.getExile().getPermanentExile().add(this); break; @@ -211,22 +216,17 @@ public abstract class CardImpl> extends MageObjectImpl permanent.setTapped(true); break; } - zone = event.getToZone(); + game.setZone(objectId, event.getToZone()); game.fireEvent(event); - return zone == toZone; + return game.getZone(objectId) == toZone; } return false; } @Override - public boolean moveToZone(Zone toZone, Game game, boolean flag) { - return moveToZone(toZone, ownerId, game, flag); - } - - @Override - public boolean moveToExile(UUID exileId, String name, Game game) { - Zone fromZone = zone; - ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, ownerId, fromZone, Zone.EXILED); + public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) { + Zone fromZone = game.getZone(objectId); + ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, Zone.EXILED); if (!game.replaceEvent(event)) { if (exileId == null) { game.getExile().getPermanentExile().add(this); @@ -234,8 +234,8 @@ public abstract class CardImpl> extends MageObjectImpl else { game.getExile().createZone(exileId, name).add(this); } - zone = event.getToZone(); - game.fireEvent(new ZoneChangeEvent(this.objectId, ownerId, fromZone, Zone.EXILED)); + game.setZone(objectId, event.getToZone()); + game.fireEvent(event); return true; } return false; @@ -245,7 +245,7 @@ public abstract class CardImpl> extends MageObjectImpl public boolean putOntoBattlefield(Game game, Zone fromZone, UUID controllerId) { PermanentCard permanent = new PermanentCard(this, controllerId); game.getBattlefield().addPermanent(permanent); - zone = Zone.BATTLEFIELD; + game.setZone(objectId, Zone.BATTLEFIELD); permanent.entersBattlefield(game); game.applyEffects(); game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD)); diff --git a/Mage/src/mage/cards/CardsImpl.java b/Mage/src/mage/cards/CardsImpl.java index 6e7e566d543..27c17f1f81c 100644 --- a/Mage/src/mage/cards/CardsImpl.java +++ b/Mage/src/mage/cards/CardsImpl.java @@ -81,8 +81,8 @@ public class CardsImpl extends LinkedHashSet implements Cards, Serializabl @Override public void add(Card card) { this.add(card.getId()); - if (zone != null) - card.setZone(zone); +// if (zone != null) +// card.setZone(zone); } @Override diff --git a/Mage/src/mage/choices/Choice.java b/Mage/src/mage/choices/Choice.java index 3d8c5381a8d..9be4d1d9735 100644 --- a/Mage/src/mage/choices/Choice.java +++ b/Mage/src/mage/choices/Choice.java @@ -40,6 +40,7 @@ public interface Choice { public boolean isRequired(); public void clearChoice(); public String getMessage(); + public void setMessage(String message); public void setChoice(String choice); public Set getChoices(); public void setChoices(Set choices); diff --git a/Mage/src/mage/choices/ChoiceImpl.java b/Mage/src/mage/choices/ChoiceImpl.java index a391881eeb6..eb32181e1a0 100644 --- a/Mage/src/mage/choices/ChoiceImpl.java +++ b/Mage/src/mage/choices/ChoiceImpl.java @@ -78,6 +78,11 @@ public class ChoiceImpl> implements Choice, Serializable return message; } + @Override + public void setMessage(String message) { + this.message = message; + } + @Override public Set getChoices() { return choices; diff --git a/Mage/src/mage/filter/Filter.java b/Mage/src/mage/filter/Filter.java index ec7430e7550..c3e866fe207 100644 --- a/Mage/src/mage/filter/Filter.java +++ b/Mage/src/mage/filter/Filter.java @@ -29,7 +29,6 @@ package mage.filter; import java.io.Serializable; -import java.util.UUID; /** * diff --git a/Mage/src/mage/filter/FilterObject.java b/Mage/src/mage/filter/FilterObject.java index 30658051bc4..ef80f89bfde 100644 --- a/Mage/src/mage/filter/FilterObject.java +++ b/Mage/src/mage/filter/FilterObject.java @@ -63,8 +63,6 @@ public class FilterObject> ex protected List supertype = new ArrayList(); protected ComparisonScope scopeSupertype = ComparisonScope.All; protected boolean notSupertype; - protected Zone zone; - protected boolean notZone; protected int convertedManaCost; protected ComparisonType convertedManaCostComparison; protected int power; @@ -114,8 +112,6 @@ public class FilterObject> ex } this.scopeSupertype = filter.scopeSupertype; this.notSupertype = filter.notSupertype; - this.zone = filter.zone; - this.notZone = filter.notZone; this.convertedManaCost = filter.convertedManaCost; this.convertedManaCostComparison = filter.convertedManaCostComparison; this.power = filter.power; @@ -139,11 +135,6 @@ public class FilterObject> ex return notFilter; } - if (zone != null) { - if (object.getZone().match(zone) == notZone) - return notFilter; - } - if (useColor) { if (scopeColor == ComparisonScope.All) { if (object.getColor().equals(color) == notColor) { @@ -314,12 +305,4 @@ public class FilterObject> ex this.notId = notId; } - public void setZone(Zone zone) { - this.zone = zone; - } - - public void setNotZone(boolean notZone) { - this.notZone = notZone; - } - } diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index 8bd87a0b790..7ecb3b88a28 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -37,6 +37,7 @@ import java.util.Set; import java.util.UUID; import mage.Constants.MultiplayerAttackOption; import mage.Constants.RangeOfInfluence; +import mage.Constants.Zone; import mage.MageItem; import mage.abilities.Ability; import mage.abilities.ActivatedAbility; @@ -46,7 +47,6 @@ import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffects; import mage.cards.Cards; import mage.choices.Choice; -import mage.choices.ChoiceImpl; import mage.game.combat.Combat; import mage.game.events.GameEvent; import mage.game.events.TableEvent; @@ -71,11 +71,14 @@ public interface Game extends MageItem, Serializable { //game data methods public void loadCards(Set cards, UUID ownerId); + public Collection getCards(); public Object getCustomData(); public void setCustomData(Object data); public MageObject getObject(UUID objectId); public Permanent getPermanent(UUID permanentId); public Card getCard(UUID cardId); + public Zone getZone(UUID objectId); + public void setZone(UUID objectId, Zone zone); public void addPlayer(Player player) throws GameException; public Player getPlayer(UUID playerId); public Players getPlayers(); diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 2757c932f71..68e52aedcbb 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -164,6 +164,11 @@ public abstract class GameImpl> implements Game, Serializa } } + @Override + public Collection getCards() { + return gameCards.values(); + } + @Override public void addPlayer(Player player) throws GameException { state.addPlayer(player); @@ -189,7 +194,7 @@ public abstract class GameImpl> implements Game, Serializa MageObject object; if (state.getBattlefield().containsPermanent(objectId)) { object = state.getBattlefield().getPermanent(objectId); - object.setZone(Zone.BATTLEFIELD); + state.setZone(objectId, Zone.BATTLEFIELD); return object; } object = getCard(objectId); @@ -197,7 +202,7 @@ public abstract class GameImpl> implements Game, Serializa return object; for (StackObject item: state.getStack()) { if (item.getId().equals(objectId)) { - item.setZone(Zone.STACK); + state.setZone(objectId, Zone.STACK); return item; } } @@ -215,6 +220,16 @@ public abstract class GameImpl> implements Game, Serializa return gameCards.get(cardId); } + @Override + public Zone getZone(UUID objectId) { + return state.getZone(objectId); + } + + @Override + public void setZone(UUID objectId, Zone zone) { + state.setZone(objectId, zone); + } + @Override public GameStates getGameStates() { return gameStates; @@ -404,7 +419,7 @@ public abstract class GameImpl> implements Game, Serializa public void mulligan(UUID playerId) { Player player = getPlayer(playerId); int numCards = player.getHand().size(); - player.getLibrary().addAll(player.getHand().getCards(this)); + player.getLibrary().addAll(player.getHand().getCards(this), this); player.getHand().clear(); player.shuffleLibrary(this); player.drawCards(numCards - 1, this); @@ -546,20 +561,20 @@ public abstract class GameImpl> implements Game, Serializa for (Permanent perm: getBattlefield().getAllActivePermanents(CardType.CREATURE)) { //20091005 - 704.5f if (perm.getToughness().getValue() == 0) { - perm.moveToZone(Zone.GRAVEYARD, this, false); - somethingHappened = true; + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + somethingHappened = true; } //20091005 - 704.5g/704.5h else if (perm.getToughness().getValue() <= perm.getDamage() || perm.isDeathtouched()) { - perm.destroy(null, this, false); - somethingHappened = true; + if (perm.destroy(null, this, false)) + somethingHappened = true; } } //20091005 - 704.5i for (Permanent perm: getBattlefield().getAllActivePermanents(CardType.PLANESWALKER)) { if (perm.getLoyalty().getValue() == 0) { - perm.moveToZone(Zone.GRAVEYARD, this, false); - return true; + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + return true; } } //20091005 - 704.5j, 801.14 @@ -571,7 +586,7 @@ public abstract class GameImpl> implements Game, Serializa filterPlaneswalker.setScopeSubtype(ComparisonScope.Any); if (getBattlefield().count(filterPlaneswalker, planeswalker.getControllerId(), this) > 1) { for (Permanent perm: getBattlefield().getActivePermanents(filterPlaneswalker, planeswalker.getControllerId(), this)) { - perm.moveToZone(Zone.GRAVEYARD, this, false); + perm.moveToZone(Zone.GRAVEYARD, null, this, false); } return true; } @@ -581,18 +596,21 @@ public abstract class GameImpl> implements Game, Serializa //20091005 - 704.5n for (Permanent perm: getBattlefield().getAllActivePermanents(filterAura)) { if (perm.getAttachedTo() == null) { - perm.moveToZone(Zone.GRAVEYARD, this, false); + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + somethingHappened = true; } else { //TODO: handle player auras Permanent attachedTo = getPermanent(perm.getAttachedTo()); if (attachedTo == null) { - perm.moveToZone(Zone.GRAVEYARD, this, false); + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + somethingHappened = true; } else { Filter auraFilter = perm.getSpellAbility().getTargets().get(0).getFilter(); if (!auraFilter.match(attachedTo)) { - perm.moveToZone(Zone.GRAVEYARD, this, false); + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + somethingHappened = true; } } } @@ -604,7 +622,7 @@ public abstract class GameImpl> implements Game, Serializa filterLegendName.getName().add(legend.getName()); if (getBattlefield().count(filterLegendName, legend.getControllerId(), this) > 1) { for (Permanent dupLegend: getBattlefield().getActivePermanents(filterLegendName, legend.getControllerId(), this)) { - dupLegend.moveToZone(Zone.GRAVEYARD, this, false); + dupLegend.moveToZone(Zone.GRAVEYARD, null, this, false); } return true; } @@ -618,8 +636,8 @@ public abstract class GameImpl> implements Game, Serializa perm.attachTo(null); } else if (!creature.getCardType().contains(CardType.CREATURE)) { - creature.removeAttachment(perm.getId(), this); - somethingHappened = true; + if (creature.removeAttachment(perm.getId(), this)) + somethingHappened = true; } } } @@ -630,8 +648,8 @@ public abstract class GameImpl> implements Game, Serializa perm.attachTo(null); } else if (!land.getCardType().contains(CardType.LAND)) { - land.removeAttachment(perm.getId(), this); - somethingHappened = true; + if (land.removeAttachment(perm.getId(), this)) + somethingHappened = true; } } } @@ -643,8 +661,8 @@ public abstract class GameImpl> implements Game, Serializa if (!(attachment.getSubtype().contains("Aura") || attachment.getSubtype().contains("Equipment") || attachment.getSubtype().contains("Fortification"))) { - perm.removeAttachment(id, this); - return true; + if (perm.removeAttachment(id, this)) + return true; } } } diff --git a/Mage/src/mage/game/GameState.java b/Mage/src/mage/game/GameState.java index 69310671d47..7e4f45536d9 100644 --- a/Mage/src/mage/game/GameState.java +++ b/Mage/src/mage/game/GameState.java @@ -88,6 +88,7 @@ public class GameState implements Serializable, Copyable { private TurnMods turnMods; private Watchers watchers; private Map values = new HashMap(); + private Map zones = new HashMap(); public GameState() { players = new Players(); @@ -127,6 +128,9 @@ public class GameState implements Serializable, Copyable { values.put(key, state.values.get(key)); //TODO: might have to change value to Copyable } + for (UUID key: state.zones.keySet()) { + zones.put(key, state.zones.get(key)); + } } @Override @@ -140,11 +144,6 @@ public class GameState implements Serializable, Copyable { } public int getValue() { -// final int prime = 31; -// int result = 1; -// result *= prime + turnNum; -// result *= prime + turn.getPhaseType().toString().hashCode(); - StringBuilder sb = new StringBuilder(1024); sb.append(turnNum).append(turn.getPhaseType()).append(turn.getStepType()).append(activePlayerId).append(priorityPlayerId); @@ -275,12 +274,22 @@ public class GameState implements Serializable, Copyable { Permanent permanent; if (battlefield.containsPermanent(permanentId)) { permanent = battlefield.getPermanent(permanentId); - permanent.setZone(Zone.BATTLEFIELD); + setZone(permanent.getId(), Zone.BATTLEFIELD); return permanent; } return null; } + public Zone getZone(UUID id) { + if (zones.containsKey(id)) + return zones.get(id); + return null; + } + + public void setZone(UUID id, Zone zone) { + zones.put(id, zone); + } + public void restore(GameState state) { this.stack = state.stack; this.effects = state.effects; @@ -288,6 +297,7 @@ public class GameState implements Serializable, Copyable { this.combat = state.combat; this.exile = state.exile; this.battlefield = state.battlefield; + this.zones = state.zones; for (Player copyPlayer: state.players.values()) { Player origPlayer = players.get(copyPlayer.getId()); origPlayer.restore(copyPlayer); diff --git a/Mage/src/mage/game/events/GameEvent.java b/Mage/src/mage/game/events/GameEvent.java index 36f35575f05..d5ed35b85b1 100644 --- a/Mage/src/mage/game/events/GameEvent.java +++ b/Mage/src/mage/game/events/GameEvent.java @@ -75,8 +75,8 @@ public class GameEvent { //player events ZONE_CHANGE, - DRAW_CARD, DREW_CARD, - DISCARD_CARD, DISCARDED_CARD, + DREW_CARD, + DISCARDED_CARD, CYCLE_CARD, CYCLED_CARD, DAMAGE_PLAYER, DAMAGED_PLAYER, COMBAT_DAMAGE_PLAYER, COMBAT_DAMAGED_PLAYER, diff --git a/Mage/src/mage/game/permanent/PermanentCard.java b/Mage/src/mage/game/permanent/PermanentCard.java index afce2ba4fc6..53128a23e7c 100644 --- a/Mage/src/mage/game/permanent/PermanentCard.java +++ b/Mage/src/mage/game/permanent/PermanentCard.java @@ -125,12 +125,12 @@ public class PermanentCard extends PermanentImpl { // } @Override - public boolean moveToZone(Zone toZone, Game game, boolean flag) { - Zone fromZone = zone; - ZoneChangeEvent event = new ZoneChangeEvent(this, controllerId, fromZone, toZone); - if (!game.replaceEvent(event)) { - Player controller = game.getPlayer(controllerId); - if (controller != null && controller.removeFromBattlefield(this, game)) { + public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag) { + Zone fromZone = game.getZone(objectId); + Player controller = game.getPlayer(controllerId); + if (controller != null && controller.removeFromBattlefield(this, game)) { + ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, controllerId, fromZone, toZone); + if (!game.replaceEvent(event)) { Card card = game.getCard(objectId); Player owner = game.getPlayer(ownerId); if (owner != null) { @@ -154,9 +154,9 @@ public class PermanentCard extends PermanentImpl { //should never happen break; } - zone = event.getToZone(); + game.setZone(objectId, event.getToZone()); game.fireEvent(event); - return zone == toZone; + return game.getZone(objectId) == toZone; } } } @@ -165,9 +165,23 @@ public class PermanentCard extends PermanentImpl { @Override - public boolean moveToExile(UUID exileId, String name, Game game) { - if (game.getPlayer(controllerId).removeFromBattlefield(this, game)) { - return game.getCard(objectId).moveToExile(exileId, name, game); + public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) { + Zone fromZone = game.getZone(objectId); + Player controller = game.getPlayer(controllerId); + if (controller != null && controller.removeFromBattlefield(this, game)) { + ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, ownerId, fromZone, Zone.EXILED); + if (!game.replaceEvent(event)) { + Card card = game.getCard(this.objectId); + if (exileId == null) { + game.getExile().getPermanentExile().add(card); + } + else { + game.getExile().createZone(exileId, name).add(card); + } + game.setZone(objectId, event.getToZone()); + game.fireEvent(event); + return true; + } } return false; } diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java index ebe889b20c4..6af049fe47d 100644 --- a/Mage/src/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/mage/game/permanent/PermanentImpl.java @@ -499,12 +499,22 @@ public abstract class PermanentImpl> extends CardImpl } protected void addEffects(Game game) { - for (StaticAbility ability: abilities.getStaticAbilities(Zone.BATTLEFIELD)) { - if (ability.activate(game, false)) { +// for (StaticAbility ability: abilities.getStaticAbilities(Zone.BATTLEFIELD)) { +// if (ability.activate(game, false)) { +// for (Effect effect: ability.getEffects()) { +// if (effect instanceof ContinuousEffect) +// game.addEffect((ContinuousEffect)effect, ability); +// else if (ability instanceof EntersBattlefieldStaticAbility && effect instanceof OneShotEffect) { +// //20100423 - 603.6e +// effect.apply(game, ability); +// } +// } +// } +// } + for (Ability ability: abilities.getStaticAbilities(Zone.BATTLEFIELD)) { + if (ability instanceof EntersBattlefieldStaticAbility) { for (Effect effect: ability.getEffects()) { - if (effect instanceof ContinuousEffect) - game.addEffect((ContinuousEffect)effect, ability); - else if (ability instanceof EntersBattlefieldStaticAbility && effect instanceof OneShotEffect) { + if (effect instanceof OneShotEffect) { //20100423 - 603.6e effect.apply(game, ability); } @@ -519,7 +529,7 @@ public abstract class PermanentImpl> extends CardImpl //TODO: handle noRegen if (!game.replaceEvent(GameEvent.getEvent(EventType.DESTROY_PERMANENT, objectId, sourceId, controllerId, noRegen?1:0))) { if (!this.getAbilities().containsKey(IndestructibleAbility.getInstance().getId())) { - if (moveToZone(Zone.GRAVEYARD, game, false)) { + if (moveToZone(Zone.GRAVEYARD, sourceId, game, false)) { game.fireEvent(GameEvent.getEvent(EventType.DESTROYED_PERMANENT, objectId, sourceId, controllerId)); return true; } @@ -532,7 +542,7 @@ public abstract class PermanentImpl> extends CardImpl public boolean sacrifice(UUID sourceId, Game game) { //20091005 - 701.13 if (!game.replaceEvent(GameEvent.getEvent(EventType.SACRIFICE_PERMANENT, objectId, sourceId, controllerId))) { - if (moveToZone(Zone.GRAVEYARD, game, true)) { + if (moveToZone(Zone.GRAVEYARD, sourceId, game, true)) { game.fireEvent(GameEvent.getEvent(EventType.SACRIFICED_PERMANENT, objectId, sourceId, controllerId)); return true; } diff --git a/Mage/src/mage/game/permanent/PermanentToken.java b/Mage/src/mage/game/permanent/PermanentToken.java index 323e1af5e42..c73099b531a 100644 --- a/Mage/src/mage/game/permanent/PermanentToken.java +++ b/Mage/src/mage/game/permanent/PermanentToken.java @@ -75,7 +75,7 @@ public class PermanentToken extends PermanentImpl { } @Override - public boolean moveToZone(Zone zone, Game game, boolean flag) { + public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag) { if (!game.replaceEvent(new ZoneChangeEvent(this, this.getControllerId(), Zone.BATTLEFIELD, zone))) { if (game.getPlayer(controllerId).removeFromBattlefield(this, game)) { game.fireEvent(new ZoneChangeEvent(this, this.getControllerId(), Zone.BATTLEFIELD, zone)); @@ -86,10 +86,10 @@ public class PermanentToken extends PermanentImpl { } @Override - public boolean moveToExile(UUID exileId, String name, Game game) { - if (!game.replaceEvent(new ZoneChangeEvent(this, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED))) { + public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) { + if (!game.replaceEvent(new ZoneChangeEvent(this, sourceId, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED))) { if (game.getPlayer(controllerId).removeFromBattlefield(this, game)) { - game.fireEvent(new ZoneChangeEvent(this, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED)); + game.fireEvent(new ZoneChangeEvent(this, sourceId, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED)); return true; } } diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index 61ff7b757f7..d768bf3102a 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -86,11 +86,11 @@ public class Spell> implements StackObject, Card { if (ability.getEffects().contains(ExileSpellEffect.getInstance())) game.getExile().getPermanentExile().add(card); else - card.moveToZone(Zone.GRAVEYARD, game, false); + card.moveToZone(Zone.GRAVEYARD, ability.getId(), game, false); return result; } //20091005 - 608.2b - counter(game); + counter(null, game); return false; } else if (card.getCardType().contains(CardType.ENCHANTMENT) && card.getSubtype().contains("Aura")) { @@ -101,7 +101,7 @@ public class Spell> implements StackObject, Card { return false; } //20091005 - 608.2b - counter(game); + counter(null, game); return false; } else { @@ -145,8 +145,8 @@ public class Spell> implements StackObject, Card { } @Override - public void counter(Game game) { - card.moveToZone(Zone.GRAVEYARD, game, false); + public void counter(UUID sourceId, Game game) { + card.moveToZone(Zone.GRAVEYARD, sourceId, game, false); } @Override @@ -220,14 +220,6 @@ public class Spell> implements StackObject, Card { return card.getLoyalty(); } - @Override - public Zone getZone() { - return Zone.STACK; - } - - @Override - public void setZone(Zone zone) {} - @Override public UUID getId() { return ability.getId(); @@ -296,12 +288,12 @@ public class Spell> implements StackObject, Card { public void adjustCosts(Ability ability, Game game) {} @Override - public boolean moveToZone(Zone zone, Game game, boolean flag) { + public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public boolean moveToExile(UUID exileId, String name, Game game) { + public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) { throw new UnsupportedOperationException("Not supported yet."); } diff --git a/Mage/src/mage/game/stack/SpellStack.java b/Mage/src/mage/game/stack/SpellStack.java index 990cf59eb3c..6e23e68798f 100644 --- a/Mage/src/mage/game/stack/SpellStack.java +++ b/Mage/src/mage/game/stack/SpellStack.java @@ -74,7 +74,7 @@ public class SpellStack extends Stack { if (stackObject != null) { if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, sourceId, stackObject.getControllerId()))) { this.remove(stackObject); - stackObject.counter(game); + stackObject.counter(sourceId, game); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, objectId, sourceId, stackObject.getControllerId())); return true; } diff --git a/Mage/src/mage/game/stack/StackAbility.java b/Mage/src/mage/game/stack/StackAbility.java index 4730bedce98..6d46ecd8e01 100644 --- a/Mage/src/mage/game/stack/StackAbility.java +++ b/Mage/src/mage/game/stack/StackAbility.java @@ -42,6 +42,7 @@ import mage.game.*; import java.util.List; import java.util.UUID; import mage.Constants.CardType; +import mage.Constants.EffectType; import mage.Constants.Zone; import mage.MageInt; import mage.ObjectColor; @@ -86,7 +87,7 @@ public class StackAbility implements StackObject, Ability { if (ability.getTargets().stillLegal(ability, game)) { return ability.resolve(game); } - counter(game); + counter(null, game); return false; } @@ -94,7 +95,7 @@ public class StackAbility implements StackObject, Ability { public void reset(Game game) { } @Override - public void counter(Game game) { + public void counter(UUID sourceId, Game game) { //20100716 - 603.8 if (ability instanceof StateTriggeredAbility) { ((StateTriggeredAbility)ability).counter(); @@ -153,12 +154,9 @@ public class StackAbility implements StackObject, Ability { @Override public Zone getZone() { - return Zone.STACK; + return this.ability.getZone(); } - @Override - public void setZone(Zone zone) {} - @Override public UUID getId() { return this.ability.getId(); @@ -184,6 +182,11 @@ public class StackAbility implements StackObject, Ability { return ability.getEffects(); } + @Override + public Effects getEffects(EffectType effectType) { + return ability.getEffects(effectType); + } + @Override public String getRule() { return ability.getRule(); diff --git a/Mage/src/mage/game/stack/StackObject.java b/Mage/src/mage/game/stack/StackObject.java index 365fb64d703..b81d86a7b49 100644 --- a/Mage/src/mage/game/stack/StackObject.java +++ b/Mage/src/mage/game/stack/StackObject.java @@ -40,7 +40,7 @@ public interface StackObject extends MageObject { public UUID getSourceId(); public UUID getControllerId(); public void checkTriggers(GameEvent event, Game game); - public void counter(Game game); + public void counter(UUID sourceId, Game game); @Override public StackObject copy(); } diff --git a/Mage/src/mage/players/Library.java b/Mage/src/mage/players/Library.java index 36121b60118..d0c92ca2b8e 100644 --- a/Mage/src/mage/players/Library.java +++ b/Mage/src/mage/players/Library.java @@ -114,7 +114,7 @@ public class Library implements Serializable { public void putOnTop(Card card, Game game) { if (card.getOwnerId().equals(playerId)) { - card.setZone(Zone.LIBRARY); + game.setZone(card.getId(), Zone.LIBRARY); library.addFirst(card.getId()); } else { @@ -124,7 +124,7 @@ public class Library implements Serializable { public void putOnBottom(Card card, Game game) { if (card.getOwnerId().equals(playerId)) { - card.setZone(Zone.LIBRARY); + game.setZone(card.getId(), Zone.LIBRARY); library.add(card.getId()); } else { @@ -195,9 +195,9 @@ public class Library implements Serializable { } } - public void addAll(Set cards) { + public void addAll(Set cards, Game game) { for (Card card: cards) { - card.setZone(Zone.LIBRARY); + game.setZone(card.getId(), Zone.LIBRARY); library.add(card.getId()); } } diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index 0f85ba8c93c..2955ee1204d 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -128,6 +128,7 @@ public interface Player extends MageItem, Copyable { public abstract void priority(Game game); public abstract boolean choose(Outcome outcome, Target target, Game game); + public abstract boolean choose(Cards cards, TargetCard target, Game game); public abstract boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game); public abstract boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game); public abstract boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 5892044058a..b1477f36ea4 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -70,12 +70,10 @@ import mage.game.Game; import mage.game.combat.CombatGroup; import mage.game.permanent.Permanent; import mage.game.events.GameEvent; -import mage.game.stack.Spell; import mage.game.stack.StackAbility; import mage.game.stack.StackObject; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetDiscard; -import mage.watchers.Watcher; public abstract class PlayerImpl> implements Player, Serializable { @@ -99,6 +97,7 @@ public abstract class PlayerImpl> implements Player, Ser protected boolean left; protected RangeOfInfluence range; protected Set inRange = new HashSet(); + protected Deck deck; @Override public abstract T copy(); @@ -107,13 +106,13 @@ public abstract class PlayerImpl> implements Player, Ser this(UUID.randomUUID()); this.name = name; this.range = range; + this.deck = deck; hand = new CardsImpl(Zone.HAND); graveyard = new CardsImpl(Zone.GRAVEYARD); abilities = new AbilitiesImpl(); counters = new Counters(); manaPool = new ManaPool(); library = new Library(playerId); - library.addAll(deck.getCards()); } protected PlayerImpl(UUID id) { @@ -147,6 +146,7 @@ public abstract class PlayerImpl> implements Player, Ser @Override public void init(Game game) { + library.addAll(deck.getCards(), game); this.hand.clear(); this.graveyard.clear(); this.abilities.clear(); @@ -246,14 +246,14 @@ public abstract class PlayerImpl> implements Player, Ser } protected boolean drawCard(Game game) { - if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DRAW_CARD, null, playerId))) { +// if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DRAW_CARD, null, playerId))) { Card card = getLibrary().removeFromTop(game); if (card != null) { - card.moveToZone(Zone.HAND, game, false); + card.moveToZone(Zone.HAND, null, game, false); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DREW_CARD, card.getId(), playerId)); return true; } - } +// } return false; } @@ -315,15 +315,11 @@ public abstract class PlayerImpl> implements Player, Ser @Override public boolean discard(Card card, Ability source, Game game) { - //20091005 - 701.1 - if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DISCARD_CARD, card.getId(), source==null?null:source.getId(), playerId))) { - removeFromHand(card, game); - if (card.moveToZone(Zone.GRAVEYARD, game, false)) { - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DISCARDED_CARD, card.getId(), source==null?null:source.getId(), playerId)); - return true; - } - } - return false; + //20100716 - 701.7 + removeFromHand(card, game); + card.moveToZone(Zone.GRAVEYARD, source==null?null:source.getId(), game, false); + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DISCARDED_CARD, card.getId(), source==null?null:source.getId(), playerId)); + return true; } @Override @@ -362,12 +358,13 @@ public abstract class PlayerImpl> implements Player, Ser if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, ability.getId(), playerId))) { game.bookmarkState(); removeFromHand(card, game); - game.getStack().push(new Spell(card, ability, playerId)); - if (ability.activate(game, noMana)) { + card.moveToZone(Zone.STACK, ability.getId(), game, false); + Ability spellAbility = game.getStack().getSpell(ability.getId()).getSpellAbility(); + if (spellAbility.activate(game, noMana)) { for (KickerAbility kicker: card.getAbilities().getKickerAbilities()) { kicker.activate(game, false); } - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.SPELL_CAST, ability.getId(), playerId)); + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.SPELL_CAST, spellAbility.getId(), playerId)); game.fireInformEvent(name + " casts " + card.getName()); game.removeLastBookmark(); return true; @@ -460,7 +457,7 @@ public abstract class PlayerImpl> implements Player, Ser result = playManaAbility((ManaAbility)ability.copy(), game); } else if (ability instanceof SpellAbility) { - result = cast((SpellAbility)ability.copy(), game, false); + result = cast((SpellAbility)ability, game, false); } else { result = playAbility((ActivatedAbility)ability.copy(), game); @@ -733,7 +730,7 @@ public abstract class PlayerImpl> implements Player, Ser for (Iterator it = game.getBattlefield().getAllPermanents().iterator(); it.hasNext();) { Permanent perm = it.next(); if (perm.getControllerId().equals(playerId)) { - perm.moveToExile(null, "", game); + perm.moveToExile(null, "", null, game); } } } diff --git a/Mage/src/mage/target/TargetObject.java b/Mage/src/mage/target/TargetObject.java index fb01cb9bb84..b7be81f5fc3 100644 --- a/Mage/src/mage/target/TargetObject.java +++ b/Mage/src/mage/target/TargetObject.java @@ -74,7 +74,7 @@ public abstract class TargetObject> extends TargetImpl @Override public boolean canTarget(UUID id, Game game) { MageObject object = game.getObject(id); - if (object != null && object.getZone().match(zone)) + if (object != null && game.getZone(id).match(zone)) return getFilter().match(object); return false; } diff --git a/Mage/src/mage/target/common/TargetCardInGraveyard.java b/Mage/src/mage/target/common/TargetCardInGraveyard.java index d35db3b3543..ffbddf046f4 100644 --- a/Mage/src/mage/target/common/TargetCardInGraveyard.java +++ b/Mage/src/mage/target/common/TargetCardInGraveyard.java @@ -66,7 +66,7 @@ public class TargetCardInGraveyard extends TargetCard { @Override public boolean canTarget(UUID id, Ability source, Game game) { Card card = game.getCard(id); - if (card != null && card.getZone() == Zone.GRAVEYARD) + if (card != null && game.getZone(card.getId()) == Zone.GRAVEYARD) return filter.match(card); return false; } diff --git a/Mage/src/mage/target/common/TargetCardInLibrary.java b/Mage/src/mage/target/common/TargetCardInLibrary.java index 017cbfb2fd0..02676100f11 100644 --- a/Mage/src/mage/target/common/TargetCardInLibrary.java +++ b/Mage/src/mage/target/common/TargetCardInLibrary.java @@ -70,13 +70,13 @@ public class TargetCardInLibrary extends TargetCard { Player player = game.getPlayer(playerId); while (!isChosen() && !doneChosing()) { chosen = targets.size() >= minNumberOfTargets; - if (!player.chooseTarget(new CardsImpl(Zone.LIBRARY, player.getLibrary().getCards(game)), this, null, game)) { + if (!player.choose(new CardsImpl(Zone.LIBRARY, player.getLibrary().getCards(game)), this, game)) { return chosen; } chosen = targets.size() >= minNumberOfTargets; } while (!doneChosing()) { - if (!player.chooseTarget(new CardsImpl(Zone.LIBRARY, player.getLibrary().getCards(game)), this, null, game)) { + if (!player.choose(new CardsImpl(Zone.LIBRARY, player.getLibrary().getCards(game)), this, game)) { break; } } diff --git a/Mage/src/mage/target/common/TargetCardInYourGraveyard.java b/Mage/src/mage/target/common/TargetCardInYourGraveyard.java index e4697ed3e1a..4c49904e457 100644 --- a/Mage/src/mage/target/common/TargetCardInYourGraveyard.java +++ b/Mage/src/mage/target/common/TargetCardInYourGraveyard.java @@ -66,7 +66,7 @@ public class TargetCardInYourGraveyard extends TargetCard