From 3f20b725db3e8f5a2dc91a6b9793c697384f68a8 Mon Sep 17 00:00:00 2001 From: magenoxx Date: Sun, 25 Dec 2011 11:42:32 +0400 Subject: [PATCH] [MAD2.0] New scoring and undo system. Migrated draw cards action. --- .../src/main/java/mage/client/MageFrame.java | 5 +- Mage.Common/src/mage/interfaces/Action.java | 3 +- Mage.Server/plugins/mage-deck-constructed.jar | Bin 7050 -> 7070 bytes Mage.Server/plugins/mage-deck-limited.jar | Bin 2398 -> 2416 bytes Mage.Server/plugins/mage-game-freeforall.jar | Bin 5290 -> 5308 bytes .../plugins/mage-game-twoplayerduel.jar | Bin 4909 -> 4909 bytes Mage.Server/plugins/mage-player-ai-ma.jar | Bin 46795 -> 46795 bytes Mage.Server/plugins/mage-player-ai.jar | Bin 54107 -> 54107 bytes Mage.Server/plugins/mage-player-aimcts.jar | Bin 24352 -> 24352 bytes Mage.Server/plugins/mage-player-aiminimax.jar | Bin 39808 -> 39808 bytes Mage.Server/plugins/mage-player-human.jar | Bin 13192 -> 13193 bytes .../plugins/mage-tournament-booster-draft.jar | Bin 5754 -> 5772 bytes .../plugins/mage-tournament-sealed.jar | Bin 5053 -> 5072 bytes Mage/src/mage/Constants.java | 38 +++++--- Mage/src/mage/actions/MageDrawAction.java | 90 ++++++++++++++++++ Mage/src/mage/actions/MageLoseGameAction.java | 43 +++++++++ Mage/src/mage/actions/impl/MageAction.java | 68 +++++++++++++ .../score/ArtificialScoringSystem.java | 38 ++++++++ .../mage/actions/score/ScoringConstants.java | 13 +++ .../src/mage/actions/score/ScoringSystem.java | 12 +++ Mage/src/mage/game/Game.java | 8 ++ Mage/src/mage/game/GameImpl.java | 45 +++++++++ Mage/src/mage/players/Library.java | 2 +- Mage/src/mage/players/Player.java | 1 + Mage/src/mage/players/PlayerImpl.java | 33 ++----- 25 files changed, 357 insertions(+), 42 deletions(-) create mode 100644 Mage/src/mage/actions/MageDrawAction.java create mode 100644 Mage/src/mage/actions/MageLoseGameAction.java create mode 100644 Mage/src/mage/actions/impl/MageAction.java create mode 100644 Mage/src/mage/actions/score/ArtificialScoringSystem.java create mode 100644 Mage/src/mage/actions/score/ScoringConstants.java create mode 100644 Mage/src/mage/actions/score/ScoringSystem.java diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index a0cfcf465fb..a15029bccb4 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -35,6 +35,7 @@ package mage.client; import mage.Constants; +import mage.interfaces.Action; import mage.cards.Card; import mage.cards.decks.Deck; import mage.client.cards.CardsStorage; @@ -181,10 +182,10 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { this.setExtendedState(JFrame.MAXIMIZED_BOTH); session = new Session(this); - session.setEmbeddedMageServerAction(new mage.interfaces.Action() { + session.setEmbeddedMageServerAction(new Action() { @Override public void execute() { - Main.main(new String[] {}); + Main.main(new String[]{}); } }); callbackClient = new CallbackClientImpl(this); diff --git a/Mage.Common/src/mage/interfaces/Action.java b/Mage.Common/src/mage/interfaces/Action.java index 3ead56d4c26..5ff3ae5831c 100644 --- a/Mage.Common/src/mage/interfaces/Action.java +++ b/Mage.Common/src/mage/interfaces/Action.java @@ -1,7 +1,8 @@ package mage.interfaces; /** - * Action interface + * Light weight action interface + * For executing actions without any context. * * @author ayratn */ diff --git a/Mage.Server/plugins/mage-deck-constructed.jar b/Mage.Server/plugins/mage-deck-constructed.jar index 8ea92082fad93588e62e0650015ecdfb49dc1a3e..0efd592ff1a000ca061ccd8be7b5371675a70313 100644 GIT binary patch delta 728 zcmeA&pJ&b+;LXg!#Q*{yqGwLzRpEUfJ=6Z*)wlQSfI<@|+GW^@tHsi zTv3;kUyHeur>zJVk8GU0Y0n&e-v1ZazrDZre2eJHeY~Q7fF5RK5@801A`2)OC!30! zpoZh*GI3L|%h!oZOI!zrY;IzDsy>oFu(pTd(u}_*{}q=6E0vUxW>R9Dtj#DjIY5F3 zEEF#x&G>q9wFD#-HUfEbC!dut1j{i>N;7&+mX%aj00oHqFTd%QtPBiBoD2-&pxA|i zC5<6GlVf=#C)Y|sjO>w=W;!G|`Lv+?zE|Wz~Ji|;;8HC z=cb>VSeBZH?gtdj5-6JcCmTqqgPj^BCCzkHcyghbfes=FI2eF2YJYTrXa)-t1H%?J q1_o2Ob_Rweje;UT4JMP>rTLL!TwYp~DMJh>VK=!%T7b<8>{S3|IqjJM delta 761 zcmbPd-et}k;LXg!#Q*}=GCL>os_sp%)6l$Dkm!VzRshYXe(sE{Hr@%## z*!5F#CWxk0v3+z~wkKv!3lwj}RctFEj4%!k z7O+SnPc|!J5JPc8T1b zYkWt8AKiB%UAVTmw~j}E zyxhd}RDERA(6vD90O-6hvE|lr+;OkdV>jy;5ADWH9*@Q0N~>$Y64;2>WC?X&$hV;6wp* XYAq1kpg1{H46L|HT8>Rk93%q(g7n{B diff --git a/Mage.Server/plugins/mage-deck-limited.jar b/Mage.Server/plugins/mage-deck-limited.jar index fd7b0a98b9df914ce5971277a196afba94f7bf32..4ba399190596e991ff7c20fd9523677e49405d50 100644 GIT binary patch delta 691 zcmca7^g)O>z?+$civa{aM9-YatHS#}dZzuqt8eeu0fi<`w9Bv)SBtq(lz6^XR{UGs zjlzu|lP(`^ve5a>6E22=Q-|~Xs9o)FV28!^M zGXJyQx?Vb-zJVUALO%HFc%OazG>A{{Y;b|6ZuQ%32G=!KF?-q268jdsc^swX9+O8b-WJb zIZnkO#>Td#V&363nrP8nw*WKf&-+&e&PoymUc!4hGHfL264Ed3=B&el_vMG ztHq*Q%nw%sviKfQm#=Gxqpqi)n|^L$S!y1V1>i_WakT`BW^U%mf*fk#__5-UW^x2^ zr6#Xo7Scg@gM$GWZT86r*T5&I+|j3>fQ^ NJvar}CbEGP0071nz6t;U delta 594 zcmew$bWeykz?+$civa|#Wp+;FRpGsw*=e6s*0nYpDAYL7EAegnEk?8obkII5OWo^60`@`Hqv4 zO=c6bqdvS}`#L(#JV^0duaeC^gP*-!B6p`6$7nFjbCjRE?VOav^52YWomrZryf+H! z@0`YX)l*Va==#^U#RQ>E|YvrRE_S1-8r{rWHg> zz&Qd8ZykRyO+LsWHQAPf2W*}Xhcu(!#pDuLJnMa>pgpfv`Q130DF>e)at03>|2ga7~l diff --git a/Mage.Server/plugins/mage-game-freeforall.jar b/Mage.Server/plugins/mage-game-freeforall.jar index a10ff5eeaf2ec4c56c09bb98836bc258f699a0cc..451a3fac5675728391b38b1f4c50fc2fcadd0a5a 100644 GIT binary patch delta 585 zcmZ3bxkr;Xz?+$civa{aM$eqctHS#sdZzuqt8eeu0fi<`w9Bv)SBtq(lz6^XR{UGs zjlzu|lP(`^ve5a>6E22=Q-|~Xs9o)FV28!|dSezT)WW6gDs2z&^m6kx7IZ5>jC2nF^YqhSlUUK~u2IIzefP>%h>+;Z zuFj(iXWJKSn=X(sx#(C^{rY_$O_kHdR_!_PnORtN&ep8FNe@mLKVZ#yzxMOG_QI+; z7b;y|T!>oBH!WPN(xKRFZdl-{>izo86En=Z)`)ugHa`1xx_-+g2_{6dmo1GI&tnfMtePY@ED9490s57O4KZ2ih;CI*IMEDQ|tF#SM!Nn_dMejz=G zy+Cbz++b~=g~Y%@Ji^k9@sl-#<-j~oVQHow-pL<%r6xBB^MHl=fkKBsLWYy?3Uh%1 peDW)x5HBB4NPn`Kh_C`Y=z+G?0I@ZS?coAog)>Ct*wh3;G63}ozmos} diff --git a/Mage.Server/plugins/mage-game-twoplayerduel.jar b/Mage.Server/plugins/mage-game-twoplayerduel.jar index a02d71567ec5235f3e8f619483e49cde128e03a7..6d7db63412b8ec9e28ee0adf11a8cf2016377ad2 100644 GIT binary patch delta 325 zcmZ3hwpNWdz?+$civa{aM$eqctHS&NNSUl<2JxOKfT+prjH)1dvp(ZqRxsl|n;#RH z;lMcw%$R(YTMMj|iN_c$VZk$#i36y|{^P3^E|YKah13`PFL)5a17#T_4Y#Uln?OVyjVg&0C8L#{@&ZY6#}rEZV(bYi@DI2KjmF#d*Ds>1$ZG zZmd}*V!e3%twyd%r>efkPFf(&#nYwYpD*=!;{O%Qx-rl5qtb6h);yHF!XMzx$RxrH z_m@4x39$@;WfDf3~5cCAoC4yF9dZVB-nEoz! K0O7IyLU{l}B8b%h delta 325 zcmZ3hwpNWdz?+$civa}QZJaTYSB3d4kTO}z4B|ae08x|K8C5~_W_`xJtYF4_Ha{jX z!+~=Wm@)Y(w-#6_6OS=i!h&Ze69-U_eJ<-euE{s~Lh2{fTNLQDJ=w5@vX&Xdd!hiMCbKiDgK0xXEifI&s0*Su z_c16|>>12pkt(iOGcepiEZU`f<^$3Jv+R-5eR(xPlDl3?wv0^@0YVxU75chpwWek?kT|I?~ z1L#nDzcX9ZCZAmER`1Q#Y#_jJp;n<>q99U8?Pa^t4s8$db#GXgS@AZ`I$^?fFOEC^ z>#AwO+@f+1_d2?3tFK*E=lS6Q;~&vEtIxMfZ@K%rWxAB0jn(q2r#^LCnr6JemMyBH z|G7A46N`0V!defnKNkY}{ShYDE(rCKbUW|5hC8V5yF44(H$(V zwJ8`(H*AUm(|0#P)ERDusB7LF02aTtIS5Q^Z-MaZwm{@BY=Nj(*$Qz_;#Oy{y5(E9 KAi^|xTLu8&9102m delta 583 zcmX^8mg)3cCf)#VW)?065cs%p#zbBf<_|#1WG$F_q5z^MvooqQ10^RLGHQY8I7VF% zy}6I^DHE7c#xf1U;AhWZ28&d2#hQT`w;Ws`B8o1z<-sEVli#v{8SgV5vV$3y3(C2` z4BzTk5GkvMVkVH)n>RG=hM1h!dIZ8S?dXsKD?YF&l@+W;W5s;1)Z|mEAnyCV${4Id zcl8t|4xmHr6*D)MOg_2Rt$ridAp-%13$_#LEnaAFo{V&4y4!MT;pBe@Zq8Fom|V21 z_21rK$F6^w6S?9O&v|CITb9{Z@2ou3tA0RCpm~3bv6H=>-#XrNj8^Zr-iowa`Q+Tq z)vjw7P05vgw$5VrB9b zdVHNdnC4t>0H$r$n}ZxZxoo`^nBKhJ7EFI$?**nEHUxs{DNy>w27fT$Y9mCvZzF{N zV52)&Tx(M>m~Pk<1*Y$Af~Ygx><_lDd2;|*{MzOqFs;1>!mrx`k-xA7qF!Yy#65{y Qox$psZ{30j)8uU#04zlzlK=n! diff --git a/Mage.Server/plugins/mage-player-ai.jar b/Mage.Server/plugins/mage-player-ai.jar index ecc3ba72d859aece05c6028db3f1b4a8bed7882e..7bea513e96f23a32334408056d6c5e99a9eb1319 100644 GIT binary patch delta 615 zcmcb;jQRF5X5IjAW)?065cm{5b0V(_^G6_MvX&Xdd!hiMCbKiDgK0xXEifI&XbPsM zF&cpA%_kWjF@YKDSb|x=3>MBeOng8o`;X<{-e}NAcI=Rmi zIPS4+YF_@9-RP`W;EYcOX9XX!2Y53w zi7>;%+@4|bsZ&NECr|!=${y@u$J5||om_I-9L!&L+6qj+KJ5yojn6oM>9RAPVEWJ* ze=sd_794Vu)1mY(D9w8gBA#$A60B~|IX^JXdp;OUC!Y@j(>u;bfoahT@nE|A0)&6% pLJXL1e9;f=&X$X2VE($((vxpoln1kaU33Q14wu#;0{7dcQ~*CA8KwXL delta 615 zcmcb;jQRF5X5IjAW)?065O}?D#zbBf=2t+AHKn@=)6VgfVPu>`Y#87!P{nD~HF_Avz=sq>f^7&KWY^K+_fR^nL?QF(=LGBa3Z zme6j9h=wQ=grO^L832~bOpkzw9LW@c7<)U{o)s)5TkOpNW@K0ULKwT7*Fp@;ZvVs& z^26qY>9h1fY9{|Z26495abvKagyZv=I6#i;@lmju%y!DP{*VC=!-eXF{{?OYhFvmn zO#QNM_f(=U`@}rdG7eyOIXIuWQsUTe z&fN_hE%%}~ch&`+wB6OMoV{q;`>N<)i!Sc9>@rvX&Xdd!hiMCbKiDgK0xXEfBpqj!~T- z%;*qkVFfez#e$f?j1-AzVKC#6_CknAnw~2kSY(||nIwoYSv?GF%;b`Im)Bic2RepDbYw@g_$R!pG0p5&EBFxZmU;;W)GRg!L5|aa>?7@zn z6lDOWk4Bk;>HkqyVA>`+2ux3m_5srmqP@VhZj1+*u80W*(-&eO;B)Vu V@?iFcSZ6T(Ep`VY9Ja+}0RYrzvk?FQ delta 418 zcmZ3mk8#01M&1B#W)?065J=uMVYe23%(-EKr_%SH zt(|y7Pb5-%(yTa7!BRVETWQ6_~b(4g%8?qkX{igJ>@>tsCP3rYmAX!Ssa~h`4NQFqr>8N_ui% VtUQ>#A=Vj8e~aCL2#0NPSpYY-uj~K- diff --git a/Mage.Server/plugins/mage-player-aiminimax.jar b/Mage.Server/plugins/mage-player-aiminimax.jar index 437c1572c723e3d3632abc7e2a80ffdb8fc0d8b0..be792e4a2dd0f192620d0863b709be35d3001710 100644 GIT binary patch delta 554 zcmZqJ&eX7-i8sKTnT3l11U^O2oXD%f{1Hf*tYrrAo+yB*$?S~kVA_yT3q)^@V|>KK z2V~egn7n#v$Hc%8!7}**o9bl!Y3!S;SUi}(ijJ~nGlLn%T(SndAl340Q4vhc3=DH8 zpJ!9q+-M~Vk)LTBAP-jfCT0%{n6Wz1iwDg3kqguSvN5<|7la{DTp|hF_Bk=`8|*_S<4LKJy8Hrli3;7!L%Wx7Kq*)$M}ee z56G~0FnRUTj){RGf@SgrHr2`c)7Upxv3M|n6&+>EW(G5ixnvD^L8|51q9T}>85rhH zKF_AIxzS1#B0tkMKpw2{P0St^Fk^M17Y~^6BNwOvWMgo_E(k-QxI`2z(%zBG3TC|R zoeh?n+&uy8y2(2x7=tC=P1wi80kZeq#ktXww@mh_KV%@laKUy$y~PU+-susJOn14C zE}Z=Dz|DDz36qMBCH;@9eVpxfPA8p~JANXD?AtE~Ry-cqE5_$`#cOfnX+Aj9ydSxb-I4b>&a!)rX_V*s{P9N${OI! z$RxrH315(_CO1tn0fq47om1?={NGayz_i{}b1;2&ru5|Iso(&aymYE3SnT7}Krrn( z4MNYH<`3q-hVt#FL--S?yMe`TO%DRo`ZI#Tbn6U={Bx0Yu&wA^6>3I4EdaMfh;H%?( z_VLpoKE1QS1)jcP21cOcyl(<>T?+fHI3u`kovnn$?JIAftbY;<_GksMCNZh(3izc1fa^#870tF9;?F#A}jkbE2FE%k3%wT5- z@MdHZVFr1R73{ysVg@E44^H+qum?N1-@pJ&A2Kip(|-(X!L*H`ADHen3wR`XDP)mvwE@2~g5clF5! zcr!AIFoS)^0`lHuaRU>O|0eqx*n{0W!N34aA2u)t(|-+Y!L+TRADHel3{J=6Z*)wlQSfI<@|+GW^@tHss ztg6ZGf z^m%p&M+fiaI^3+r5&mJHt^B(S{O>34-g3^d;9m6R$vNK7&Y5mki{|9F49oiw3ZToDGrl-i9tFz<-ycwB9n1P|j1_`#w@t`c0P_B6A!){6lb;L8gFVkFEX}0BIN6ZVnjfK% z1FWzBD7BOsC}lGF5wnOknza23I|oNUpq=I13=HOQs~H%UG%lVb;s!R{Q$(7{jR$Cg z@#L8zVhZRE=7;M7IoN`4vLl}`FVyQ$$G#VlW=x$NC@PI)J=hy4J~u@%Xf{y2i##w! z?PX=(>;7kCVBiM^qzzmR$cgWOYAhz}@w4lodkY--K(#GE?2MwvU2t-MpzGumF#$Fu HA&?9Jzk1p$ delta 696 zcmeCt{iVYj;LXg!#Q*{~GCL>os_sp%)6l$Dkm!VzRshYXe(sE{Hr@%## z*!5F#CWxk0v3+z~wkKv!3fuc_$NC%?7pwtYAhk&wEC&ZdX1nFkQrF45nA`1u*vjP5aFk#>5FS?V#h+ z`s&G1f>N?iK0oH4VRMC8EQ7)7O-g7_vk^2toL66FHB5v~%*FoknK+B*0q z8;Y4vo-N7)io?mPfO>C(gsk-{a&ypK4vtu$_7)&^h8qKNxyfV$u`o6PA&?*d_bJvg diff --git a/Mage.Server/plugins/mage-tournament-sealed.jar b/Mage.Server/plugins/mage-tournament-sealed.jar index cec9fec81ba7b77d1c8edb5608a874b1f4468d32..ecc7ad1b1719d4be84363e89ab02b7cd3078ad9a 100644 GIT binary patch delta 787 zcmdn1enFi#z?+$civa|_M$eqctHS#wdZzuqt8eeu0fi<`w9Bv)SBtq(lz6^XR{UGs zjlzu|lP(`^ve5a>6E22=Q-|~Xs9o)FV28!=zPsNq=XhLVpKx8-$>IIln~~d9PdB`K(`4#dTpRy*g6Ynw zLeb7q)6~yCo&G<=d!5#nO;gH}s|vR~;|}m@EPpZ1FDu delta 673 zcmcbhzE_<$z?+$civa{~WOh#ERpGs!*=e6s*0nYpDAYL7EM|GpCOE;Y#z*Dkq?}Y z7{O|o;;8G7w<6U^}7S;)Mq9 zbg2O5yGI^fI4f^4+nD8+%eu^i`@`@5nAK>^9m@CN&jAnX^tH2QtL*s1Qo&gLIU#@wEo z`E0>e@c?f|CJ|;(2(f~LX!3l16Vx!8{D9xo4CGKyAi@ApF%$?eymdSRWalQPr|Kh2 zgBa#5AkFxEa=L&#*z27F(oCX^lmBz-PQEN40v37&6zXRN3%zC*o$M*dqX4pM%QE+} zKTHe^r-Aku!fXQ4OB!3*z={_M3V{_CE=_ls#K^#K9;nz9Md1ZbphEM>+(JBHi=>34 z8MjV06OsdKLsH2g0q20c@`!t~Adk%C2|`?8ZF7aBnIw3CLQ<30@rX};4KxiHd6Rzu qg;Qa|a+CdqA drawnCards; + + private static final int NEGATIVE_VALUE = -1000000; + + public MageDrawAction(Player player, int amount) { + this.player = player; + this.amount = amount; + } + + /** + * Draw and set action score. + * + * @param game Game context. + */ + @Override + public int doAction(Game game) { + int numDrawn = 0; + int score = 0; + for (int i = 0; i < amount; i++) { + int value = drawCard(game); + if (value == -1) { + break; + } + score += value; + } + game.fireInformEvent(player.getName() + " draws " + Integer.toString(numDrawn) + " card" + (numDrawn > 1 ? "s" : "")); + if (player.isEmptyDraw()) { + game.doAction(new MageLoseGameAction(player, MageLoseGameAction.DRAW_REASON)); + } + + setScore(player, score); + game.setStateCheckRequired(); + + return numDrawn; + } + + /** + * Draw a card if possible (there is no replacement effect that prevent us from drawing). + * Fire event about card drawn. + * + * @param game + * @return + */ + protected int drawCard(Game game) { + if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DRAW_CARD, player.getId(), player.getId()))) { + Card card = player.getLibrary().removeFromTop(game); + if (card != null) { + card.moveToZone(Constants.Zone.HAND, null, game, false); + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DREW_CARD, card.getId(), player.getId())); + return ArtificialScoringSystem.inst.getCardScore(card); + } + } + return NEGATIVE_VALUE; + } + + /** + * Return a card back to top. + * + * @param game Game context + */ + @Override + public void undoAction(Game game) { + for (int index = drawnCards.size() - 1; index >= 0; index--) { + Card card = drawnCards.get(index); + player.getHand().remove(card); + player.getLibrary().putOnTop(card, game); + } + } +} diff --git a/Mage/src/mage/actions/MageLoseGameAction.java b/Mage/src/mage/actions/MageLoseGameAction.java new file mode 100644 index 00000000000..c31831b1078 --- /dev/null +++ b/Mage/src/mage/actions/MageLoseGameAction.java @@ -0,0 +1,43 @@ +package mage.actions; + +import mage.actions.impl.MageAction; +import mage.actions.score.ArtificialScoringSystem; +import mage.game.Game; +import mage.players.Player; + +/** + * Lose game action. + * + * @author ayratn + */ +public class MageLoseGameAction extends MageAction { + + public static final String LIFE_REASON = "{L} You lose the game."; + public static final String POISON_REASON = "{L} You are poisoned. You lose the game."; + public static final String DRAW_REASON = "{L} You attempt to draw from an empty library. You lose the game."; + + private final Player player; + private final String reason; + private Player oldLosingPlayer; + + public MageLoseGameAction(final Player player, final String reason) { + this.player = player; + this.reason = reason; + } + + @Override + public int doAction(final Game game) { + oldLosingPlayer = game.getLosingPlayer(); + if (oldLosingPlayer == null && player.canLose(game)) { + setScore(player, ArtificialScoringSystem.inst.getLoseGameScore(game)); + game.setLosingPlayer(player); + game.informPlayer(player, reason); + } + return 0; + } + + @Override + public void undoAction(final Game game) { + game.setLosingPlayer(oldLosingPlayer); + } +} \ No newline at end of file diff --git a/Mage/src/mage/actions/impl/MageAction.java b/Mage/src/mage/actions/impl/MageAction.java new file mode 100644 index 00000000000..538e773e3ae --- /dev/null +++ b/Mage/src/mage/actions/impl/MageAction.java @@ -0,0 +1,68 @@ +package mage.actions.impl; + +import mage.game.Game; +import mage.players.Player; + +/** + * Base class for mage actions. + * + * @author ayratn + */ +public abstract class MageAction { + + /** + * {@link Player} we count score for. + */ + private Player scorePlayer; + + /** + * Current game score for the player. + */ + private int score = 0; + + /** + * Set or change action score. + * + * @param scorePlayer Set player. + * @param score Set score value. + */ + protected void setScore(Player scorePlayer, int score) { + this.scorePlayer = scorePlayer; + this.score = score; + } + + /** + * Get game score for the {@link Player}. + * Value depends on the owner of this action. + * In case player and owner differ, negative value is returned. + * + * @param player + * @return + */ + public int getScore(final Player player) { + if (player.getId().equals(scorePlayer.getId())) { + return score; + } else { + return -score; + } + } + + /** + * Execute action. + * + * @param game Game context. + */ + public abstract int doAction(final Game game); + + /** + * Undo action. + * + * @param game Game context + */ + public abstract void undoAction(final Game game); + + @Override + public String toString() { + return ""; + } +} diff --git a/Mage/src/mage/actions/score/ArtificialScoringSystem.java b/Mage/src/mage/actions/score/ArtificialScoringSystem.java new file mode 100644 index 00000000000..8b08a2a3a07 --- /dev/null +++ b/Mage/src/mage/actions/score/ArtificialScoringSystem.java @@ -0,0 +1,38 @@ +package mage.actions.score; + +import mage.cards.Card; +import mage.game.Game; +import org.apache.log4j.Logger; + +/** + * @author ayratn + */ +public class ArtificialScoringSystem implements ScoringSystem { + + public static ArtificialScoringSystem inst; + + private static final transient Logger log = Logger.getLogger(ArtificialScoringSystem.class); + + static { + inst = new ArtificialScoringSystem(); + log.info("ArtificialScoringSystem has been instantiated."); + } + + /** + * Lose score is lowered in function of the turn and phase when it occurs. + * Encourages AI to win as fast as possible. + * + * @param game + * @return + */ + public int getLoseGameScore(final Game game) { + return ScoringConstants.LOSE_GAME_SCORE + game.getTurnNum() * 2500 + game.getStep().getType().getIndex() * 200; + } + + @Override + public int getCardScore(Card card) { + //TODO: implement + return ScoringConstants.UNKNOWN_CARD_SCORE; + } + +} \ No newline at end of file diff --git a/Mage/src/mage/actions/score/ScoringConstants.java b/Mage/src/mage/actions/score/ScoringConstants.java new file mode 100644 index 00000000000..7003e5effb0 --- /dev/null +++ b/Mage/src/mage/actions/score/ScoringConstants.java @@ -0,0 +1,13 @@ +package mage.actions.score; + +/** + * Constants for scoring system. + * + * @author ayratn + */ +public class ScoringConstants { + public static final int WIN_GAME_SCORE = 100000000; + public static final int LOSE_GAME_SCORE = -WIN_GAME_SCORE; + + public static final int UNKNOWN_CARD_SCORE = 300; +} diff --git a/Mage/src/mage/actions/score/ScoringSystem.java b/Mage/src/mage/actions/score/ScoringSystem.java new file mode 100644 index 00000000000..d80a387bac5 --- /dev/null +++ b/Mage/src/mage/actions/score/ScoringSystem.java @@ -0,0 +1,12 @@ +package mage.actions.score; + +import mage.cards.Card; +import mage.game.Game; + +/** + * @author ayratn + */ +public interface ScoringSystem { + public int getLoseGameScore(final Game game); + public int getCardScore(final Card card); +} diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index ae695a24894..14a90f9bcc5 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -28,6 +28,7 @@ package mage.game; +import mage.actions.impl.MageAction; import mage.game.match.MatchType; import mage.cards.Card; import mage.game.stack.SpellStack; @@ -113,6 +114,10 @@ public interface Game extends MageItem, Serializable { public Card getLastKnownInformation(UUID objectId, Zone zone); public void rememberLKI(UUID objectId, Zone zone, Card card); public void resetLKI(); + public void setLosingPlayer(Player player); + public Player getLosingPlayer(); + public void setStateCheckRequired(); + public boolean getStateCheckRequired(); //client event methods public void addTableEventListener(Listener listener); @@ -134,6 +139,7 @@ public interface Game extends MageItem, Serializable { public void fireInformEvent(String message); public void fireUpdatePlayersEvent(); public void informPlayers(String message); + public void informPlayer(Player player, String message); public void debugMessage(String message); public void fireErrorEvent(String message, Exception ex); @@ -160,6 +166,8 @@ public interface Game extends MageItem, Serializable { public void playPriority(UUID activePlayerId, boolean resuming); public boolean endTurn(UUID playerId); + public int doAction(MageAction action); + //game transaction methods public void saveState(); public int bookmarkState(); diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index dd5cfd60202..e77029ba36b 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -36,6 +36,7 @@ import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffects; import mage.abilities.keyword.LeylineAbility; import mage.abilities.mana.TriggeredManaAbility; +import mage.actions.impl.MageAction; import mage.cards.Card; import mage.cards.Cards; import mage.cards.CardsImpl; @@ -108,6 +109,12 @@ public abstract class GameImpl> implements Game, Serializa public static volatile int copyCount = 0; public static volatile long copyTime = 0; + private LinkedList actions; + private Player scorePlayer; + private int score = 0; + private Player losingPlayer; + private boolean stateCheckRequired = false; + @Override public abstract T copy(); @@ -116,6 +123,7 @@ public abstract class GameImpl> implements Game, Serializa this.range = range; this.attackOption = attackOption; this.state = new GameState(); + this.actions = new LinkedList(); } public GameImpl(final GameImpl game) { @@ -142,6 +150,9 @@ public abstract class GameImpl> implements Game, Serializa copyCount++; copyTime += (System.currentTimeMillis() - t1); } + this.actions = new LinkedList(); + this.stateCheckRequired = game.stateCheckRequired; + this.scorePlayer = game.scorePlayer; } @Override @@ -365,6 +376,7 @@ public abstract class GameImpl> implements Game, Serializa public void start(UUID choosingPlayerId, GameOptions options) { startTime = new Date(); this.gameOptions = options; + scorePlayer = state.getPlayers().values().iterator().next(); init(choosingPlayerId, options.testMode); play(startingPlayerId); saveState(); @@ -1329,6 +1341,14 @@ public abstract class GameImpl> implements Game, Serializa return true; } + @Override + public int doAction(MageAction action) { + actions.add(action); + int value = action.doAction(this); + score += action.getScore(scorePlayer); + return value; + } + @Override public Date getStartTime() { return startTime; @@ -1343,4 +1363,29 @@ public abstract class GameImpl> implements Game, Serializa public void setGameOptions(GameOptions options) { this.gameOptions = options; } + + @Override + public void setLosingPlayer(Player player) { + this.losingPlayer = player; + } + + @Override + public Player getLosingPlayer() { + return this.losingPlayer; + } + + @Override + public void informPlayer(Player player, String message) { + //TODO: implement personal messages + } + + @Override + public boolean getStateCheckRequired() { + return stateCheckRequired; + } + + @Override + public void setStateCheckRequired() { + stateCheckRequired = true; + } } diff --git a/Mage/src/mage/players/Library.java b/Mage/src/mage/players/Library.java index 52dc0a11994..0bdf079efbc 100644 --- a/Mage/src/mage/players/Library.java +++ b/Mage/src/mage/players/Library.java @@ -197,7 +197,7 @@ public class Library implements Serializable { } - public boolean isEmtpyDraw() { + public boolean isEmptyDraw() { return emptyDraw; } diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index c9556011068..3c2bcecb69e 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -114,6 +114,7 @@ public interface Player extends MageItem, Copyable { public void setTopCardRevealed(boolean topCardRevealed); public UserData getUserData(); public void setUserData(UserData userData); + public boolean canLose(Game game); /** * Returns a set of players which turns under you control. diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index aa863fa2d76..de0cc796dd4 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -53,6 +53,7 @@ import mage.abilities.effects.common.LoseControlOnOtherPlayersControllerEffect; import mage.abilities.keyword.*; import mage.abilities.mana.ManaAbility; import mage.abilities.mana.ManaOptions; +import mage.actions.MageDrawAction; import mage.cards.Card; import mage.cards.Cards; import mage.cards.CardsImpl; @@ -60,7 +61,6 @@ import mage.cards.decks.Deck; import mage.counters.Counter; import mage.counters.CounterType; import mage.counters.Counters; -import mage.filter.FilterAbility; import mage.filter.common.FilterCreatureForCombat; import mage.game.Game; import mage.game.combat.CombatGroup; @@ -337,29 +337,9 @@ public abstract class PlayerImpl> implements Player, Ser return false; } - protected boolean drawCard(Game game) { - if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DRAW_CARD, playerId, playerId))) { - Card card = getLibrary().removeFromTop(game); - if (card != null) { - card.moveToZone(Zone.HAND, null, game, false); - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DREW_CARD, card.getId(), playerId)); - return true; - } - } - return false; - } - @Override public int drawCards(int num, Game game) { - int numDrawn = 0; - for (int i = 0; i < num; i++) { - if (drawCard(game)) - numDrawn++; - else - break; - } - game.fireInformEvent(name + " draws " + Integer.toString(numDrawn) + " card" + (numDrawn > 1?"s":"")); - return numDrawn; + return game.doAction(new MageDrawAction(this, num)); } @Override @@ -992,7 +972,7 @@ public abstract class PlayerImpl> implements Player, Ser @Override public boolean isEmptyDraw() { - return library.isEmtpyDraw(); + return library.isEmptyDraw(); } @Override @@ -1029,7 +1009,7 @@ public abstract class PlayerImpl> implements Player, Ser @Override public void lost(Game game) { - if (!game.replaceEvent(new GameEvent(GameEvent.EventType.LOSES, null, null, playerId))) { + if (canLose(game)) { this.loses = true; //20100423 - 603.9 if (!this.wins) @@ -1038,6 +1018,11 @@ public abstract class PlayerImpl> implements Player, Ser } } + @Override + public boolean canLose(Game game) { + return !game.replaceEvent(new GameEvent(GameEvent.EventType.LOSES, null, null, playerId)); + } + @Override public void won(Game game) { if (!game.replaceEvent(new GameEvent(GameEvent.EventType.WINS, null, null, playerId))) {