From e0224bd465377e369767d600a99395cab3e92029 Mon Sep 17 00:00:00 2001 From: jendave Date: Sat, 6 Aug 2011 02:37:41 +0000 Subject: [PATCH] --- .classpath | 6 + .gitattributes | 202 + .project | 17 + .settings/org.eclipse.jdt.core.prefs | 12 + src/.classpath | 6 + src/.project | 17 + src/2009-10-12-00.txt | 41 + src/Ability.java | 21 + src/Ability_Activated.java | 24 + src/Ability_Hand.java | 23 + src/Ability_Mana.java | 158 + src/Ability_Tap.java | 33 + src/All.java | 21 + src/AllZone.java | 99 + src/BackgroundPanel.java | 275 + src/BoosterDraft.java | 122 + src/BoosterDraftAI.java | 302 + src/BoosterPack.java | 27 + src/ButtonUtil.java | 34 + src/Card.java | 855 + src/CardDetailUtil.java | 48 + src/CardFactory.java | 41235 ++++++++++++++++ src/CardFactoryUtil.java | 2381 + src/CardList.java | 216 + src/CardListFilter.java | 4 + src/CardListUtil.java | 183 + src/CardPanel.java | 20 + src/CardUtil.java | 184 + src/Combat.java | 409 + src/CombatPlaneswalker.java | 183 + src/CombatUtil.java | 1288 + src/Command.java | 10 + src/CommandArgs.java | 4 + src/CommandList.java | 26 + src/CommandReturn.java | 4 + src/Computer.java | 15 + src/ComputerAI_Burn.java | 132 + src/ComputerAI_Burn2.java | 176 + src/ComputerAI_General.java | 304 + src/ComputerAI_Input.java | 83 + src/ComputerAI_Rats2.java | 140 + src/ComputerAI_StackNotEmpty.java | 10 + src/ComputerAI_Testing.java | 59 + src/ComputerAI_counterSpells.java | 117 + src/ComputerUtil.java | 382 + src/ComputerUtil_Attack2.java | 358 + src/ComputerUtil_Block2.java | 323 + src/Computer_Cleanup.java | 23 + src/Computer_Draw.java | 13 + src/Computer_Race.java | 162 + src/Constant.java | 179 + src/Deck.java | 76 + src/DeckIO.java | 203 + src/DefaultPlayerZone.java | 114 + src/Display.java | 18 + src/EndOfTurn.java | 65 + src/ErrorViewer.java | 120 + src/ExternalPanel.java | 90 + src/FileUtil.java | 70 + src/GameAction.java | 1259 + src/GameActionUtil.java | 10853 ++++ src/GenerateConstructedDeck.java | 297 + src/GenerateConstructedMultiColorDeck.java | 557 + src/GenerateDraftDeck.java | 212 + src/GenerateSealedDeck.java | 151 + src/GuiDisplay.java | 313 + src/GuiDisplay2.java | 961 + src/GuiDisplay3.java | 1273 + src/GuiDisplayUtil.java | 894 + src/GuiInput.java | 38 + src/Gui_BoosterDraft.java | 594 + src/Gui_DeckEditor.java | 722 + src/Gui_DeckEditor_Menu.java | 1059 + src/Gui_DownloadPictures.java | 314 + src/Gui_MultipleBlockers.java | 131 + src/Gui_NewGame.java | 670 + src/Gui_Quest.java | 241 + src/Gui_QuestOptions.java | 207 + src/Gui_Quest_DeckEditor.java | 744 + src/Gui_Quest_DeckEditor_Menu.java | 761 + src/Gui_SealedDeck.java | 61 + src/Gui_SetEditor.java | 135 + src/Gui_Welcome.java | 59 + src/Gui_WinLose.java | 206 + src/IO.java | 93 + src/ImageCache.java | 127 + src/ImageJPanel.java | 31 + src/ImageUtil.java | 98 + src/Input.java | 39 + src/InputControl.java | 247 + src/InputUtil.java | 30 + src/Input_Attack.java | 83 + src/Input_Attack_Instant.java | 24 + src/Input_Attack_Planeswalker.java | 46 + src/Input_Before_Attack_Instant.java | 25 + src/Input_Block.java | 65 + src/Input_Block_Instant.java | 29 + src/Input_Block_Planeswalker.java | 60 + src/Input_Cleanup.java | 41 + src/Input_CombatDamage.java | 241 + src/Input_Draw.java | 99 + src/Input_EOT.java | 32 + src/Input_FirstStrikeDamage.java | 189 + src/Input_Main.java | 48 + src/Input_Mulligan.java | 40 + src/Input_NoCost_TapAbility.java | 21 + src/Input_PayManaCost.java | 85 + src/Input_PayManaCostUtil.java | 83 + src/Input_PayManaCost_Ability.java | 73 + src/Input_StackNotEmpty.java | 72 + src/Input_Untap.java | 56 + src/KeyListenerTest.java | 29 + src/MagicStack.java | 61 + src/ManaCost.java | 76 + src/ManaPool.java | 320 + src/Mana_Part.java | 17 + src/Mana_PartColor.java | 44 + src/Mana_PartColorless.java | 43 + src/Mana_PartSplit.java | 75 + src/Mana_PartTest.java | 479 + src/Mana_PayCost.java | 123 + src/MenuItem_HowToPlay.java | 160 + src/Move.java | 39 + src/MoveAttack.java | 190 + src/MyButton.java | 12 + src/MyObservable.java | 22 + src/MyRandom.java | 26 + src/NameChanger.java | 155 + src/NewIO.java | 114 + src/NonScrollingJEditorPane.java | 20 + src/Phase.java | 181 + src/PhaseObserver.java | 75 + src/PicturePanel.java | 22 + src/PlayerLife.java | 32 + src/PlayerZone.java | 33 + src/PlayerZoneUtil.java | 65 + src/PlayerZone_ComesIntoPlay.java | 150 + src/PrintCardNames.java | 30 + src/PrintCardPictures.java | 38 + src/QuestData.java | 525 + src/QuestData_BoosterPack.java | 281 + src/ReadBoosterPack.java | 364 + src/ReadCard.java | 130 + src/Run.java | 206 + src/RunTest.java | 312 + src/SimpleCombat.java | 99 + src/Spell.java | 49 + src/SpellAbility.java | 156 + src/SpellAbilityList.java | 53 + src/SpellAbilityUtil.java | 62 + src/Spell_Evoke.java | 35 + src/Spell_Permanent.java | 44 + src/StackObserver.java | 17 + src/StateBasedEffects.java | 196 + src/TableModel.java | 303 + src/TableSorter.java | 157 + src/TempRun.java | 13 + src/Test.java | 9 + src/TestMove.java | 87 + src/TestPanel.java | 42 + src/Time.java | 23 + src/UndoCommand.java | 5 + src/Wait.java | 10 + src/WinLose.java | 16 + src/forge.properties | 46 + src/forge/error/ErrorViewer.java | 215 + src/forge/error/ExceptionHandler.java | 42 + src/forge/gui/ForgeAction.java | 50 + src/forge/gui/ListChooser.java | 292 + src/forge/properties/ForgeProps.java | 121 + src/forge/properties/NewConstants.java | 235 + src/org/jdesktop/swingx/MultiSplitLayout.java | 1358 + src/org/jdesktop/swingx/MultiSplitPane.java | 403 + src/res/AllTokens.txt | 836 + src/res/all-decks2 | Bin 0 -> 27877 bytes src/res/booster-decks | Bin 0 -> 136 bytes src/res/card-pictures.txt | 2215 + src/res/cards.txt | 14662 ++++++ src/res/common.txt | 378 + src/res/gui/display_layout.xml | 519 + src/res/gui/gui.properties | 1 + src/res/lang/de.properties | 105 + src/res/lang/en.properties | 105 + src/res/lang/howTo/de.properties | 79 + src/res/lang/howTo/en.properties | 68 + src/res/lang/lang.properties | 6 + src/res/main.properties | 24 + src/res/name-mutator.txt | 442 + src/res/quest/common.txt | 800 + src/res/quest/easy.txt | 11 + src/res/quest/hard.txt | 41 + src/res/quest/medium.txt | 14 + src/res/quest/quest.properties | 9 + src/res/quest/questData | Bin 0 -> 41369 bytes src/res/quest/rare.txt | 378 + src/res/quest/uncommon.txt | 446 + src/res/rare.txt | 208 + src/res/tokens.txt | 255 + src/res/uncommon.txt | 220 + src/treeProperties/PropertyElement.java | 38 + src/treeProperties/PropertyType.java | 34 + src/treeProperties/TreeProperties.java | 396 + src/treeProperties/types/FileType.java | 61 + 203 files changed, 107449 insertions(+) create mode 100644 .classpath create mode 100644 .project create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 src/.classpath create mode 100644 src/.project create mode 100644 src/2009-10-12-00.txt create mode 100644 src/Ability.java create mode 100644 src/Ability_Activated.java create mode 100644 src/Ability_Hand.java create mode 100644 src/Ability_Mana.java create mode 100644 src/Ability_Tap.java create mode 100644 src/All.java create mode 100644 src/AllZone.java create mode 100644 src/BackgroundPanel.java create mode 100644 src/BoosterDraft.java create mode 100644 src/BoosterDraftAI.java create mode 100644 src/BoosterPack.java create mode 100644 src/ButtonUtil.java create mode 100644 src/Card.java create mode 100644 src/CardDetailUtil.java create mode 100644 src/CardFactory.java create mode 100644 src/CardFactoryUtil.java create mode 100644 src/CardList.java create mode 100644 src/CardListFilter.java create mode 100644 src/CardListUtil.java create mode 100644 src/CardPanel.java create mode 100644 src/CardUtil.java create mode 100644 src/Combat.java create mode 100644 src/CombatPlaneswalker.java create mode 100644 src/CombatUtil.java create mode 100644 src/Command.java create mode 100644 src/CommandArgs.java create mode 100644 src/CommandList.java create mode 100644 src/CommandReturn.java create mode 100644 src/Computer.java create mode 100644 src/ComputerAI_Burn.java create mode 100644 src/ComputerAI_Burn2.java create mode 100644 src/ComputerAI_General.java create mode 100644 src/ComputerAI_Input.java create mode 100644 src/ComputerAI_Rats2.java create mode 100644 src/ComputerAI_StackNotEmpty.java create mode 100644 src/ComputerAI_Testing.java create mode 100644 src/ComputerAI_counterSpells.java create mode 100644 src/ComputerUtil.java create mode 100644 src/ComputerUtil_Attack2.java create mode 100644 src/ComputerUtil_Block2.java create mode 100644 src/Computer_Cleanup.java create mode 100644 src/Computer_Draw.java create mode 100644 src/Computer_Race.java create mode 100644 src/Constant.java create mode 100644 src/Deck.java create mode 100644 src/DeckIO.java create mode 100644 src/DefaultPlayerZone.java create mode 100644 src/Display.java create mode 100644 src/EndOfTurn.java create mode 100644 src/ErrorViewer.java create mode 100644 src/ExternalPanel.java create mode 100644 src/FileUtil.java create mode 100644 src/GameAction.java create mode 100644 src/GameActionUtil.java create mode 100644 src/GenerateConstructedDeck.java create mode 100644 src/GenerateConstructedMultiColorDeck.java create mode 100644 src/GenerateDraftDeck.java create mode 100644 src/GenerateSealedDeck.java create mode 100644 src/GuiDisplay.java create mode 100644 src/GuiDisplay2.java create mode 100644 src/GuiDisplay3.java create mode 100644 src/GuiDisplayUtil.java create mode 100644 src/GuiInput.java create mode 100644 src/Gui_BoosterDraft.java create mode 100644 src/Gui_DeckEditor.java create mode 100644 src/Gui_DeckEditor_Menu.java create mode 100644 src/Gui_DownloadPictures.java create mode 100644 src/Gui_MultipleBlockers.java create mode 100644 src/Gui_NewGame.java create mode 100644 src/Gui_Quest.java create mode 100644 src/Gui_QuestOptions.java create mode 100644 src/Gui_Quest_DeckEditor.java create mode 100644 src/Gui_Quest_DeckEditor_Menu.java create mode 100644 src/Gui_SealedDeck.java create mode 100644 src/Gui_SetEditor.java create mode 100644 src/Gui_Welcome.java create mode 100644 src/Gui_WinLose.java create mode 100644 src/IO.java create mode 100644 src/ImageCache.java create mode 100644 src/ImageJPanel.java create mode 100644 src/ImageUtil.java create mode 100644 src/Input.java create mode 100644 src/InputControl.java create mode 100644 src/InputUtil.java create mode 100644 src/Input_Attack.java create mode 100644 src/Input_Attack_Instant.java create mode 100644 src/Input_Attack_Planeswalker.java create mode 100644 src/Input_Before_Attack_Instant.java create mode 100644 src/Input_Block.java create mode 100644 src/Input_Block_Instant.java create mode 100644 src/Input_Block_Planeswalker.java create mode 100644 src/Input_Cleanup.java create mode 100644 src/Input_CombatDamage.java create mode 100644 src/Input_Draw.java create mode 100644 src/Input_EOT.java create mode 100644 src/Input_FirstStrikeDamage.java create mode 100644 src/Input_Main.java create mode 100644 src/Input_Mulligan.java create mode 100644 src/Input_NoCost_TapAbility.java create mode 100644 src/Input_PayManaCost.java create mode 100644 src/Input_PayManaCostUtil.java create mode 100644 src/Input_PayManaCost_Ability.java create mode 100644 src/Input_StackNotEmpty.java create mode 100644 src/Input_Untap.java create mode 100644 src/KeyListenerTest.java create mode 100644 src/MagicStack.java create mode 100644 src/ManaCost.java create mode 100644 src/ManaPool.java create mode 100644 src/Mana_Part.java create mode 100644 src/Mana_PartColor.java create mode 100644 src/Mana_PartColorless.java create mode 100644 src/Mana_PartSplit.java create mode 100644 src/Mana_PartTest.java create mode 100644 src/Mana_PayCost.java create mode 100644 src/MenuItem_HowToPlay.java create mode 100644 src/Move.java create mode 100644 src/MoveAttack.java create mode 100644 src/MyButton.java create mode 100644 src/MyObservable.java create mode 100644 src/MyRandom.java create mode 100644 src/NameChanger.java create mode 100644 src/NewIO.java create mode 100644 src/NonScrollingJEditorPane.java create mode 100644 src/Phase.java create mode 100644 src/PhaseObserver.java create mode 100644 src/PicturePanel.java create mode 100644 src/PlayerLife.java create mode 100644 src/PlayerZone.java create mode 100644 src/PlayerZoneUtil.java create mode 100644 src/PlayerZone_ComesIntoPlay.java create mode 100644 src/PrintCardNames.java create mode 100644 src/PrintCardPictures.java create mode 100644 src/QuestData.java create mode 100644 src/QuestData_BoosterPack.java create mode 100644 src/ReadBoosterPack.java create mode 100644 src/ReadCard.java create mode 100644 src/Run.java create mode 100644 src/RunTest.java create mode 100644 src/SimpleCombat.java create mode 100644 src/Spell.java create mode 100644 src/SpellAbility.java create mode 100644 src/SpellAbilityList.java create mode 100644 src/SpellAbilityUtil.java create mode 100644 src/Spell_Evoke.java create mode 100644 src/Spell_Permanent.java create mode 100644 src/StackObserver.java create mode 100644 src/StateBasedEffects.java create mode 100644 src/TableModel.java create mode 100644 src/TableSorter.java create mode 100644 src/TempRun.java create mode 100644 src/Test.java create mode 100644 src/TestMove.java create mode 100644 src/TestPanel.java create mode 100644 src/Time.java create mode 100644 src/UndoCommand.java create mode 100644 src/Wait.java create mode 100644 src/WinLose.java create mode 100644 src/forge.properties create mode 100644 src/forge/error/ErrorViewer.java create mode 100644 src/forge/error/ExceptionHandler.java create mode 100644 src/forge/gui/ForgeAction.java create mode 100644 src/forge/gui/ListChooser.java create mode 100644 src/forge/properties/ForgeProps.java create mode 100644 src/forge/properties/NewConstants.java create mode 100644 src/org/jdesktop/swingx/MultiSplitLayout.java create mode 100644 src/org/jdesktop/swingx/MultiSplitPane.java create mode 100644 src/res/AllTokens.txt create mode 100644 src/res/all-decks2 create mode 100644 src/res/booster-decks create mode 100644 src/res/card-pictures.txt create mode 100644 src/res/cards.txt create mode 100644 src/res/common.txt create mode 100644 src/res/gui/display_layout.xml create mode 100644 src/res/gui/gui.properties create mode 100644 src/res/lang/de.properties create mode 100644 src/res/lang/en.properties create mode 100644 src/res/lang/howTo/de.properties create mode 100644 src/res/lang/howTo/en.properties create mode 100644 src/res/lang/lang.properties create mode 100644 src/res/main.properties create mode 100644 src/res/name-mutator.txt create mode 100644 src/res/quest/common.txt create mode 100644 src/res/quest/easy.txt create mode 100644 src/res/quest/hard.txt create mode 100644 src/res/quest/medium.txt create mode 100644 src/res/quest/quest.properties create mode 100644 src/res/quest/questData create mode 100644 src/res/quest/rare.txt create mode 100644 src/res/quest/uncommon.txt create mode 100644 src/res/rare.txt create mode 100644 src/res/tokens.txt create mode 100644 src/res/uncommon.txt create mode 100644 src/treeProperties/PropertyElement.java create mode 100644 src/treeProperties/PropertyType.java create mode 100644 src/treeProperties/TreeProperties.java create mode 100644 src/treeProperties/types/FileType.java diff --git a/.classpath b/.classpath new file mode 100644 index 00000000000..d925f2fd147 --- /dev/null +++ b/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/.gitattributes b/.gitattributes index 1d80cb6bca8..abdeb92380e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,204 @@ * text=auto !eol +/.classpath -text +/.project -text +.settings/org.eclipse.jdt.core.prefs -text /delete-me.txt svneol=native#text/plain +src/.classpath -text +src/.project -text +src/2009-10-12-00.txt -text svneol=native#text/plain +src/Ability.java svneol=native#text/plain +src/Ability_Activated.java svneol=native#text/plain +src/Ability_Hand.java svneol=native#text/plain +src/Ability_Mana.java -text svneol=native#text/plain +src/Ability_Tap.java svneol=native#text/plain +src/All.java svneol=native#text/plain +src/AllZone.java svneol=native#text/plain +src/BackgroundPanel.java -text svneol=native#text/plain +src/BoosterDraft.java svneol=native#text/plain +src/BoosterDraftAI.java svneol=native#text/plain +src/BoosterPack.java svneol=native#text/plain +src/ButtonUtil.java svneol=native#text/plain +src/Card.java svneol=native#text/plain +src/CardDetailUtil.java svneol=native#text/plain +src/CardFactory.java svneol=native#text/plain +src/CardFactoryUtil.java svneol=native#text/plain +src/CardList.java svneol=native#text/plain +src/CardListFilter.java svneol=native#text/plain +src/CardListUtil.java svneol=native#text/plain +src/CardPanel.java svneol=native#text/plain +src/CardUtil.java svneol=native#text/plain +src/Combat.java svneol=native#text/plain +src/CombatPlaneswalker.java svneol=native#text/plain +src/CombatUtil.java svneol=native#text/plain +src/Command.java svneol=native#text/plain +src/CommandArgs.java svneol=native#text/plain +src/CommandList.java svneol=native#text/plain +src/CommandReturn.java svneol=native#text/plain +src/Computer.java svneol=native#text/plain +src/ComputerAI_Burn.java svneol=native#text/plain +src/ComputerAI_Burn2.java svneol=native#text/plain +src/ComputerAI_General.java svneol=native#text/plain +src/ComputerAI_Input.java svneol=native#text/plain +src/ComputerAI_Rats2.java svneol=native#text/plain +src/ComputerAI_StackNotEmpty.java svneol=native#text/plain +src/ComputerAI_Testing.java svneol=native#text/plain +src/ComputerAI_counterSpells.java -text svneol=native#text/plain +src/ComputerUtil.java -text svneol=native#text/plain +src/ComputerUtil_Attack2.java svneol=native#text/plain +src/ComputerUtil_Block2.java svneol=native#text/plain +src/Computer_Cleanup.java svneol=native#text/plain +src/Computer_Draw.java svneol=native#text/plain +src/Computer_Race.java svneol=native#text/plain +src/Constant.java svneol=native#text/plain +src/Deck.java svneol=native#text/plain +src/DeckIO.java svneol=native#text/plain +src/DefaultPlayerZone.java svneol=native#text/plain +src/Display.java svneol=native#text/plain +src/EndOfTurn.java svneol=native#text/plain +src/ErrorViewer.java svneol=native#text/plain +src/ExternalPanel.java svneol=native#text/plain +src/FileUtil.java -text svneol=native#text/plain +src/GameAction.java svneol=native#text/plain +src/GameActionUtil.java svneol=native#text/plain +src/GenerateConstructedDeck.java svneol=native#text/plain +src/GenerateConstructedMultiColorDeck.java -text svneol=native#text/plain +src/GenerateDraftDeck.java svneol=native#text/plain +src/GenerateSealedDeck.java svneol=native#text/plain +src/GuiDisplay.java svneol=native#text/plain +src/GuiDisplay2.java svneol=native#text/plain +src/GuiDisplay3.java -text svneol=native#text/plain +src/GuiDisplayUtil.java svneol=native#text/plain +src/GuiInput.java svneol=native#text/plain +src/Gui_BoosterDraft.java svneol=native#text/plain +src/Gui_DeckEditor.java -text svneol=native#text/plain +src/Gui_DeckEditor_Menu.java svneol=native#text/plain +src/Gui_DownloadPictures.java svneol=native#text/plain +src/Gui_MultipleBlockers.java svneol=native#text/plain +src/Gui_NewGame.java svneol=native#text/plain +src/Gui_Quest.java svneol=native#text/plain +src/Gui_QuestOptions.java svneol=native#text/plain +src/Gui_Quest_DeckEditor.java -text svneol=native#text/plain +src/Gui_Quest_DeckEditor_Menu.java -text svneol=native#text/plain +src/Gui_SealedDeck.java svneol=native#text/plain +src/Gui_SetEditor.java svneol=native#text/plain +src/Gui_Welcome.java svneol=native#text/plain +src/Gui_WinLose.java svneol=native#text/plain +src/IO.java svneol=native#text/plain +src/ImageCache.java svneol=native#text/plain +src/ImageJPanel.java -text svneol=native#text/plain +src/ImageUtil.java svneol=native#text/plain +src/Input.java svneol=native#text/plain +src/InputControl.java svneol=native#text/plain +src/InputUtil.java svneol=native#text/plain +src/Input_Attack.java svneol=native#text/plain +src/Input_Attack_Instant.java -text svneol=native#text/plain +src/Input_Attack_Planeswalker.java svneol=native#text/plain +src/Input_Before_Attack_Instant.java -text svneol=native#text/plain +src/Input_Block.java svneol=native#text/plain +src/Input_Block_Instant.java svneol=native#text/plain +src/Input_Block_Planeswalker.java svneol=native#text/plain +src/Input_Cleanup.java svneol=native#text/plain +src/Input_CombatDamage.java svneol=native#text/plain +src/Input_Draw.java svneol=native#text/plain +src/Input_EOT.java svneol=native#text/plain +src/Input_FirstStrikeDamage.java -text svneol=native#text/plain +src/Input_Main.java svneol=native#text/plain +src/Input_Mulligan.java svneol=native#text/plain +src/Input_NoCost_TapAbility.java svneol=native#text/plain +src/Input_PayManaCost.java svneol=native#text/plain +src/Input_PayManaCostUtil.java svneol=native#text/plain +src/Input_PayManaCost_Ability.java svneol=native#text/plain +src/Input_StackNotEmpty.java svneol=native#text/plain +src/Input_Untap.java svneol=native#text/plain +src/KeyListenerTest.java -text svneol=native#text/plain +src/MagicStack.java svneol=native#text/plain +src/ManaCost.java svneol=native#text/plain +src/ManaPool.java svneol=native#text/plain +src/Mana_Part.java svneol=native#text/plain +src/Mana_PartColor.java svneol=native#text/plain +src/Mana_PartColorless.java svneol=native#text/plain +src/Mana_PartSplit.java svneol=native#text/plain +src/Mana_PartTest.java svneol=native#text/plain +src/Mana_PayCost.java svneol=native#text/plain +src/MenuItem_HowToPlay.java svneol=native#text/plain +src/Move.java svneol=native#text/plain +src/MoveAttack.java svneol=native#text/plain +src/MyButton.java svneol=native#text/plain +src/MyObservable.java svneol=native#text/plain +src/MyRandom.java svneol=native#text/plain +src/NameChanger.java svneol=native#text/plain +src/NewIO.java svneol=native#text/plain +src/NonScrollingJEditorPane.java -text svneol=native#text/plain +src/Phase.java svneol=native#text/plain +src/PhaseObserver.java svneol=native#text/plain +src/PicturePanel.java svneol=native#text/plain +src/PlayerLife.java svneol=native#text/plain +src/PlayerZone.java svneol=native#text/plain +src/PlayerZoneUtil.java svneol=native#text/plain +src/PlayerZone_ComesIntoPlay.java svneol=native#text/plain +src/PrintCardNames.java svneol=native#text/plain +src/PrintCardPictures.java svneol=native#text/plain +src/QuestData.java svneol=native#text/plain +src/QuestData_BoosterPack.java svneol=native#text/plain +src/ReadBoosterPack.java svneol=native#text/plain +src/ReadCard.java svneol=native#text/plain +src/Run.java svneol=native#text/plain +src/RunTest.java svneol=native#text/plain +src/SimpleCombat.java svneol=native#text/plain +src/Spell.java svneol=native#text/plain +src/SpellAbility.java -text svneol=native#text/plain +src/SpellAbilityList.java svneol=native#text/plain +src/SpellAbilityUtil.java svneol=native#text/plain +src/Spell_Evoke.java svneol=native#text/plain +src/Spell_Permanent.java svneol=native#text/plain +src/StackObserver.java svneol=native#text/plain +src/StateBasedEffects.java -text svneol=native#text/plain +src/TableModel.java -text svneol=native#text/plain +src/TableSorter.java svneol=native#text/plain +src/TempRun.java svneol=native#text/plain +src/Test.java svneol=native#text/plain +src/TestMove.java svneol=native#text/plain +src/TestPanel.java svneol=native#text/plain +src/Time.java svneol=native#text/plain +src/UndoCommand.java svneol=native#text/plain +src/Wait.java svneol=native#text/plain +src/WinLose.java svneol=native#text/plain +src/forge.properties svneol=native#text/plain +src/forge/error/ErrorViewer.java svneol=native#text/plain +src/forge/error/ExceptionHandler.java -text svneol=native#text/plain +src/forge/gui/ForgeAction.java svneol=native#text/plain +src/forge/gui/ListChooser.java svneol=native#text/plain +src/forge/properties/ForgeProps.java svneol=native#text/plain +src/forge/properties/NewConstants.java svneol=native#text/plain +src/org/jdesktop/swingx/MultiSplitLayout.java -text svneol=native#text/plain +src/org/jdesktop/swingx/MultiSplitPane.java -text svneol=native#text/plain +src/res/AllTokens.txt -text svneol=native#text/plain +src/res/all-decks2 -text svneol=unset#unset +src/res/booster-decks -text svneol=unset#unset +src/res/card-pictures.txt -text svneol=native#text/plain +src/res/cards.txt -text svneol=native#text/plain +src/res/common.txt -text svneol=native#text/plain +src/res/gui/display_layout.xml svneol=native#text/xml +src/res/gui/gui.properties svneol=native#text/plain +src/res/lang/de.properties svneol=native#text/plain +src/res/lang/en.properties svneol=native#text/plain +src/res/lang/howTo/de.properties svneol=native#text/plain +src/res/lang/howTo/en.properties svneol=native#text/plain +src/res/lang/lang.properties svneol=native#text/plain +src/res/main.properties svneol=native#text/plain +src/res/name-mutator.txt -text svneol=native#text/plain +src/res/quest/common.txt -text svneol=native#text/plain +src/res/quest/easy.txt -text svneol=native#text/plain +src/res/quest/hard.txt -text svneol=native#text/plain +src/res/quest/medium.txt -text svneol=native#text/plain +src/res/quest/quest.properties svneol=native#text/plain +src/res/quest/questData -text svneol=unset#unset +src/res/quest/rare.txt -text svneol=native#text/plain +src/res/quest/uncommon.txt -text svneol=native#text/plain +src/res/rare.txt -text svneol=native#text/plain +src/res/tokens.txt -text svneol=native#text/plain +src/res/uncommon.txt -text svneol=native#text/plain +src/treeProperties/PropertyElement.java svneol=native#text/plain +src/treeProperties/PropertyType.java -text svneol=native#text/plain +src/treeProperties/TreeProperties.java -text svneol=native#text/plain +src/treeProperties/types/FileType.java -text svneol=native#text/plain diff --git a/.project b/.project new file mode 100644 index 00000000000..22afe0576f5 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + ForgeSVN + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..e3a5f24edd2 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Mon Oct 12 15:27:12 CDT 2009 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/src/.classpath b/src/.classpath new file mode 100644 index 00000000000..6d488d7cbbf --- /dev/null +++ b/src/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/.project b/src/.project new file mode 100644 index 00000000000..4fd226bab1d --- /dev/null +++ b/src/.project @@ -0,0 +1,17 @@ + + + Forge2 + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/src/2009-10-12-00.txt b/src/2009-10-12-00.txt new file mode 100644 index 00000000000..9eb2dc5e72d --- /dev/null +++ b/src/2009-10-12-00.txt @@ -0,0 +1,41 @@ +An error has occured. You can copy/paste this message or save it to a file. +Please report this, plus what you tried to do, to: + http://www.slightlymagic.net/forum/viewforum.php?f=26 +If you don't want to register an account, you can mail it directly to + mtgrares@yahoo.com + +Index: 7, Size: 4 + +Detailed error trace: +java.lang.IndexOutOfBoundsException: Index: 7, Size: 4 + at java.util.ArrayList.add(Unknown Source) + at CardList.add(CardList.java:69) + at GameAction.smoothComputerManaCurve(GameAction.java:831) + at GameAction.newGame(GameAction.java:783) + at Gui_NewGame.startButton_actionPerformed(Gui_NewGame.java:433) + at Gui_NewGame$5.actionPerformed(Gui_NewGame.java:272) + at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) + at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source) + at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) + at javax.swing.DefaultButtonModel.setPressed(Unknown Source) + at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source) + at java.awt.Component.processMouseEvent(Unknown Source) + at javax.swing.JComponent.processMouseEvent(Unknown Source) + at java.awt.Component.processEvent(Unknown Source) + at java.awt.Container.processEvent(Unknown Source) + at java.awt.Component.dispatchEventImpl(Unknown Source) + at java.awt.Container.dispatchEventImpl(Unknown Source) + at java.awt.Component.dispatchEvent(Unknown Source) + at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) + at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) + at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) + at java.awt.Container.dispatchEventImpl(Unknown Source) + at java.awt.Window.dispatchEventImpl(Unknown Source) + at java.awt.Component.dispatchEvent(Unknown Source) + at java.awt.EventQueue.dispatchEvent(Unknown Source) + at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) + at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) + at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) + at java.awt.EventDispatchThread.pumpEvents(Unknown Source) + at java.awt.EventDispatchThread.pumpEvents(Unknown Source) + at java.awt.EventDispatchThread.run(Unknown Source) diff --git a/src/Ability.java b/src/Ability.java new file mode 100644 index 00000000000..8899c56f58b --- /dev/null +++ b/src/Ability.java @@ -0,0 +1,21 @@ +abstract public class Ability extends SpellAbility +{ + public Ability(Card sourceCard, String manaCost) + { + super(SpellAbility.Ability, sourceCard); + setManaCost(manaCost); + } + public Ability(Card sourceCard, String manaCost, String stackDescription) + { + this(sourceCard, manaCost); + setStackDescription(stackDescription); + System.out.println("an ability is being played from" + sourceCard.getName()); + } + public boolean canPlay() + { +// if(getSourceCard().isCreature() && (!getSourceCard().hasSickness())) + return AllZone.GameAction.isCardInPlay(getSourceCard()) && !getSourceCard().isFaceDown(); + +// return false; + } +} diff --git a/src/Ability_Activated.java b/src/Ability_Activated.java new file mode 100644 index 00000000000..2746ecca904 --- /dev/null +++ b/src/Ability_Activated.java @@ -0,0 +1,24 @@ +abstract public class Ability_Activated extends SpellAbility implements java.io.Serializable +{ + /** + * + */ + private static final long serialVersionUID = 1L; + + public Ability_Activated(Card sourceCard) + { + this(sourceCard, ""); + } + public Ability_Activated(Card sourceCard, String manaCost) + { + super(SpellAbility.Ability, sourceCard); + setManaCost(manaCost); + } + public boolean canPlay() + { + Card c = getSourceCard(); + + return AllZone.GameAction.isCardInPlay(c) && !c.isFaceDown(); + //TODO: make sure you can't play the Computer's activated abilities + } +} diff --git a/src/Ability_Hand.java b/src/Ability_Hand.java new file mode 100644 index 00000000000..35a3dbebf77 --- /dev/null +++ b/src/Ability_Hand.java @@ -0,0 +1,23 @@ +//TODO: make this class a type of Ability +abstract public class Ability_Hand extends SpellAbility implements java.io.Serializable +{ + /** + * + */ + private static final long serialVersionUID = 1L; + + public Ability_Hand(Card sourceCard) + { + this(sourceCard, ""); + } + public Ability_Hand(Card sourceCard, String manaCost) + { + super(SpellAbility.Ability, sourceCard); + setManaCost(manaCost); + } + public boolean canPlay() + { + PlayerZone zone = AllZone.getZone(getSourceCard()); + return zone.is(Constant.Zone.Hand, getSourceCard().getController()); + } +} \ No newline at end of file diff --git a/src/Ability_Mana.java b/src/Ability_Mana.java new file mode 100644 index 00000000000..2c45cc8d6b5 --- /dev/null +++ b/src/Ability_Mana.java @@ -0,0 +1,158 @@ +import java.util.*; + +abstract public class Ability_Mana extends SpellAbility implements java.io.Serializable +{ + private ArrayList runcommands = new ArrayList(); + public String orig; + private String Mana; + + public boolean isBasic() + { + return(orig.length() ==10 && orig.startsWith("tap: add ") && "1WBURG".contains(""+orig.charAt(9))); + } + private static final long serialVersionUID = 8292723782268822439L; + /*public Ability_Mana(Card sourceCard, String mana) + { + this(sourceCard, "0"); + }*/ + public boolean isTapAbility(){return isTapAbility(orig);} + private static boolean isTapAbility(String orig){ + String cost = orig.split(":")[0]; + cost = cost.replaceAll("tap", "T"); + return (cost.contains("T")); + } + public Ability_Mana(Card sourceCard, String orig) + { + super(isTapAbility(orig) ? SpellAbility.Ability_Tap : SpellAbility.Ability, sourceCard); + this.orig=orig; + setDescription(orig); + if(isBasic())//lowers memory usage drastically + { + Mana = "" + orig.charAt(9); + setManaCost("0"); + return; + } + String[] parts = orig.split(":"); + Mana=parts[1]; + Mana = Mana.replaceAll(" add ", ""); + setStackDescription("Add "+ Mana +" to your mana pool."); + Mana = Mana.replaceAll(" ", ""); + + String cost=parts[0]; + cost = cost.replaceAll("tap", "T"); + //cost = cost.replaceAll("T, ", ""); + setManaCost(cost.replaceAll("T", "").split(",")[0]); + if (getManaCost().equals("")) setManaCost("0"); + //pain lands + ArrayList pain = new ArrayList(); + pain.add("Battlefield Forge"); + pain.add("Caves of Koilos"); + pain.add("Llanowar Wastes"); + pain.add("Shivan Reef"); + pain.add("Yavimaya Coast"); + pain.add("Adarkar Wastes"); + pain.add("Brushland"); + pain.add("Karplusan Forest"); + pain.add("Underground River"); + pain.add("Sulfurous Springs"); + if(pain.contains(sourceCard.getName()) && !Mana.equals("1")) + runcommands.add(new Command() + { + private static final long serialVersionUID = 1L; + public void execute(){ + + AllZone.GameAction.getPlayerLife(getController()).subtractLife(1); + }}); + //parseCosts(); + /*for(String subcost : cost.split(",")) + { + subcost.trim(); + if (subcost.equals("") || subcost.equals("T") || + subcost.equals(getManaCost())) continue; + if (subcost.startsWith("Sacrifice a")){ + String sactype= subcost.substring(12).trim();//will remove both "Sac a " and "Sac an" :P + Input bpM_old = getBeforePayMana(); + } + }*/ + } + public boolean equals(Object o)//Mana abilities with equal descriptions are considered equal, please take this into account + {return (o instanceof Ability_Mana ? ((Ability_Mana)o).orig.equals(orig) : (o instanceof String ? o.toString().equals(orig) : false )) ;} + public boolean equalsIgnoreMana(Ability_Mana ma) + { + String noManaDesc=orig.substring(0,orig.indexOf(Mana)); + noManaDesc+=orig.substring(orig.indexOf(Mana)+Mana.length()); + String noManaDesc_2=ma.orig.substring(0,ma.orig.indexOf(Mana)); + noManaDesc_2+=ma.orig.substring(ma.orig.indexOf(Mana)+Mana.length()); + return noManaDesc.equals(noManaDesc_2); + } + + + public String toString(){return orig;} + boolean undoable=false; + public void undo(){getSourceCard().untap();}//override undo() and set undoable for custom undo costs + public boolean undoable(){return isBasic() || undoable;} + public void parseCosts(){parseCosts(orig);} + private void parseCosts(String orig) + { + setBeforePayMana(null);// reset everything + setAfterPayMana(null); + setAfterResolve(null); + + String[] split={",",":","."};//i.e. "cost,cost,cost<...>:Effect.Effect.Effect. + String copy=orig+""; + for(String s : split) + { + copy=copy.replaceAll(" " + s, s); //trim splitter whitespace + copy=copy.replaceAll(s + " ", s); + } + copy=copy.replaceAll("T"+split[0], "");//i.e. "T,"-> ""(reason for this is that tapCost is already determined) + copy=copy.trim(); + if (!("123456789GWURBXY(".contains(copy.charAt(0)+""))) + { + setManaCost("0"); + copy=split[0] + copy; + }//Hacky, but should work + else setManaCost(copy.substring(0, copy.indexOf(","))); + String divider = ","; + while(!copy.trim().equals("")) + { + if(copy.startsWith(":")) + if (!divider.equals(".")) divider="."; + while (copy.startsWith(":") || copy.startsWith(divider) ) copy=copy.substring(1); + String current=copy.substring(0, copy.indexOf(",")); + if (current.startsWith("Sacrifice a")){ + + } + copy=copy.substring(current.length()); + } + } + public void resolve(){ + AllZone.ManaPool.addMana(this); + if(!runcommands.isEmpty()) + for(Command c : runcommands) c.execute(); + } + public int getX(){return getSourceCard().getX();}//override these when not defined by card, + public void setX(int X){getSourceCard().setX(X);}//i.e. "T, remove X charge counters from {name}: add X+1 mana to your mana pool" + public String Mana(){return Mana;}//override for all non-X variable mana, + public String getController(){return getSourceCard().getController();} + + public boolean canPlayAI(){return false;} + public boolean canPlay() + { + Card card = getSourceCard(); + if(AllZone.GameAction.isCardInPlay(card) &&(!isTapAbility() || card.isUntapped())) + { + if(card.isFaceDown()) + return false; + + if(card.isArtifact() && card.isCreature()) + return !(card.hasSickness() && isTapAbility()); + + if(card.isCreature() && (!card.hasSickness() || !isTapAbility())) + return true; + else if(card.isArtifact() || card.isGlobalEnchantment() || card.isLand()) + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/Ability_Tap.java b/src/Ability_Tap.java new file mode 100644 index 00000000000..e1924fdf871 --- /dev/null +++ b/src/Ability_Tap.java @@ -0,0 +1,33 @@ +abstract public class Ability_Tap extends SpellAbility implements java.io.Serializable +{ + + private static final long serialVersionUID = 8292723782268822539L; + public Ability_Tap(Card sourceCard) + { + this(sourceCard, "0"); + } + public Ability_Tap(Card sourceCard, String manaCost) + { + super(SpellAbility.Ability_Tap, sourceCard); + setManaCost(manaCost); + } + public boolean canPlay() + { + Card card = getSourceCard(); + + if(AllZone.GameAction.isCardInPlay(card) && card.isUntapped()) + { + if(card.isFaceDown()) + return false; + + if(card.isArtifact() && card.isCreature()) + return !card.hasSickness(); + + if(card.isCreature() && (!card.hasSickness())) + return true; + else if(card.isArtifact() || card.isGlobalEnchantment() || card.isLand()) + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/All.java b/src/All.java new file mode 100644 index 00000000000..5faa60f70bc --- /dev/null +++ b/src/All.java @@ -0,0 +1,21 @@ +public class All +{ + public Phase Phase = new Phase(); + public MagicStack Stack = new MagicStack(); + + public PlayerLife Human_Life = new PlayerLife(); + public PlayerLife Computer_Life = new PlayerLife(); + + //Human_Play, Computer_Play is different because Card.comesIntoPlay() is called when a card is added by PlayerZone.add(Card) + public PlayerZone Human_Play = new PlayerZone_ComesIntoPlay(Constant.Zone.Play, Constant.Player.Human); + public PlayerZone Human_Hand = new DefaultPlayerZone(Constant.Zone.Hand , Constant.Player.Human); + public PlayerZone Human_Graveyard = new DefaultPlayerZone(Constant.Zone.Graveyard , Constant.Player.Human); + public PlayerZone Human_Library = new DefaultPlayerZone(Constant.Zone.Library , Constant.Player.Human); + public PlayerZone Human_Removed = new DefaultPlayerZone(Constant.Zone.Removed_From_Play, Constant.Player.Human); + + public PlayerZone Computer_Play = new PlayerZone_ComesIntoPlay(Constant.Zone.Play , Constant.Player.Computer); + public PlayerZone Computer_Hand = new DefaultPlayerZone(Constant.Zone.Hand , Constant.Player.Computer); + public PlayerZone Computer_Graveyard = new DefaultPlayerZone(Constant.Zone.Graveyard , Constant.Player.Computer); + public PlayerZone Computer_Library = new DefaultPlayerZone(Constant.Zone.Library , Constant.Player.Computer); + public PlayerZone Computer_Removed = new DefaultPlayerZone(Constant.Zone.Removed_From_Play, Constant.Player.Computer); +} \ No newline at end of file diff --git a/src/AllZone.java b/src/AllZone.java new file mode 100644 index 00000000000..ef6057851ef --- /dev/null +++ b/src/AllZone.java @@ -0,0 +1,99 @@ + + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + +public class AllZone implements NewConstants { + //only for testing, should read decks from local directory +// public static final IO IO = new IO("all-decks"); + + public static QuestData QuestData = null; + public static final NameChanger NameChanger = new NameChanger(); + + public static EndOfTurn EndOfTurn = new EndOfTurn(); + public static final CardFactory CardFactory = new CardFactory(ForgeProps.getFile(CARDS)); + + public static final Phase Phase = new Phase(); + public static final MagicStack Stack = new MagicStack(); + public static final InputControl InputControl = new InputControl(); + public static final GameAction GameAction = new GameAction(); + public static final StateBasedEffects StateBasedEffects = new StateBasedEffects(); + + //initialized at Runtime since it has to be the last object constructed + + public static ComputerAI_Input Computer; + + //shared between Input_Attack , Input_Block, + // Input_CombatDamage , InputState_Computer + public static Combat Combat = new Combat(); + public static Combat pwCombat = new Combat();//for Planeswalker combat + + public static PlayerLife Human_Life = new PlayerLife(); + public static PlayerLife Computer_Life = new PlayerLife(); + + //Human_Play, Computer_Play is different because Card.comesIntoPlay() is called when a card is added by PlayerZone.add(Card) + public final static PlayerZone Human_Play = new PlayerZone_ComesIntoPlay(Constant.Zone.Play, Constant.Player.Human); + public final static PlayerZone Human_Hand = new DefaultPlayerZone(Constant.Zone.Hand , Constant.Player.Human); + public final static PlayerZone Human_Graveyard = new DefaultPlayerZone(Constant.Zone.Graveyard , Constant.Player.Human); + public final static PlayerZone Human_Library = new DefaultPlayerZone(Constant.Zone.Library , Constant.Player.Human); + public final static PlayerZone Human_Removed = new DefaultPlayerZone(Constant.Zone.Removed_From_Play, Constant.Player.Human); + + public final static PlayerZone Computer_Play = new PlayerZone_ComesIntoPlay(Constant.Zone.Play , Constant.Player.Computer); + public final static PlayerZone Computer_Hand = new DefaultPlayerZone(Constant.Zone.Hand , Constant.Player.Computer); + public final static PlayerZone Computer_Graveyard = new DefaultPlayerZone(Constant.Zone.Graveyard , Constant.Player.Computer); + public final static PlayerZone Computer_Library = new DefaultPlayerZone(Constant.Zone.Library , Constant.Player.Computer); + public final static PlayerZone Computer_Removed = new DefaultPlayerZone(Constant.Zone.Removed_From_Play, Constant.Player.Computer); + + public static final ManaPool ManaPool = new ManaPool(); + + public static Display Display = new GuiDisplay2(); + + + private final static Map map = new HashMap(); + + static + { + map.put(Constant.Zone.Graveyard + Constant.Player.Human, Human_Graveyard); + map.put(Constant.Zone.Hand + Constant.Player.Human, Human_Hand); + map.put(Constant.Zone.Library + Constant.Player.Human, Human_Library); + map.put(Constant.Zone.Play + Constant.Player.Human, Human_Play); + map.put(Constant.Zone.Removed_From_Play + Constant.Player.Human, Human_Removed); + + map.put(Constant.Zone.Graveyard + Constant.Player.Computer, Computer_Graveyard); + map.put(Constant.Zone.Hand + Constant.Player.Computer, Computer_Hand); + map.put(Constant.Zone.Library + Constant.Player.Computer, Computer_Library); + map.put(Constant.Zone.Play + Constant.Player.Computer, Computer_Play); + map.put(Constant.Zone.Removed_From_Play + Constant.Player.Computer, Computer_Removed); + } + public static PlayerZone getZone(Card c) + { + Iterator it = map.values().iterator(); + PlayerZone p; + while(it.hasNext()) + { + p = (PlayerZone)it.next(); + + if(GameAction.isCardInZone(c, p)) + return p; + } + return null; +// throw new RuntimeException("AllZone : getZone() error, card is not found, card is " +c); + } + public static PlayerZone getZone(String zone, String player) + { + if (player.equals("")) { //this is a really bad hack, to allow raging goblin to attack on turn 1 + player = "Human"; + System.out.println("Evil hack"); + } + Object o = map.get(zone + player); + if(o == null) + throw new RuntimeException("AllZone : getZone() invalid parameters " +zone +" " +player); + + return (PlayerZone)o; + } +}//AllZone \ No newline at end of file diff --git a/src/BackgroundPanel.java b/src/BackgroundPanel.java new file mode 100644 index 00000000000..5dd508b5ae1 --- /dev/null +++ b/src/BackgroundPanel.java @@ -0,0 +1,275 @@ +import java.awt.*; +import javax.swing.*; + +/* + * Support custom painting on a panel in the form of + * + * a) images - that can be scaled, tiled or painted at original size + * b) non solid painting - that can be done by using a Paint object + * + * Also, any component added directly to this panel will be made + * non-opaque so that the custom painting can show through. + */ +public class BackgroundPanel extends JPanel +{ + /** + * + */ + private static final long serialVersionUID = 1L; + public static final int SCALED = 0; + public static final int TILED = 1; + public static final int ACTUAL = 2; + + private Paint painter; + private Image image; + private int style = ACTUAL; + private float alignmentX = 0.5f; + private float alignmentY = 0.5f; + private boolean isTransparentAdd = true; + + /* + * Set image-string as the background with the SCALED style + */ + public BackgroundPanel(String s) + { + + ImageIcon imageIcon = new ImageIcon("pics\\" + s); + image = imageIcon.getImage(); + + setImage( image ); + setStyle( style ); + setLayout( new BorderLayout() ); + repaint(); + } + + public BackgroundPanel() + { + setStyle( style ); + setLayout( new BorderLayout() ); + repaint(); + } + + + /* + * Set image as the background with the SCALED style + */ + public BackgroundPanel(Image image) + { + this(image, SCALED); + + } + + /* + * Set image as the background with the specified style + */ + public BackgroundPanel(Image image, int style) + { + setImage( image ); + setStyle( style ); + setLayout( new BorderLayout() ); + } + + /* + * Set image as the backround with the specified style and alignment + */ + public BackgroundPanel(Image image, int style, float alignmentX, float alignmentY) + { + setImage( image ); + setStyle( style ); + setImageAlignmentX( alignmentX ); + setImageAlignmentY( alignmentY ); + setLayout( new BorderLayout() ); + } + + /* + * Use the Paint interface to paint a background + */ + public BackgroundPanel(Paint painter) + { + setPaint( painter ); + setLayout( new BorderLayout() ); + } + + /* + * Set the image used as the background + */ + public void setImage(Image image) + { + this.image = image; + repaint(); + } + + /* + * Set the style used to paint the background image + */ + public void setStyle(int style) + { + this.style = style; + repaint(); + } + + /* + * Set the Paint object used to paint the background + */ + public void setPaint(Paint painter) + { + this.painter = painter; + repaint(); + } + + /* + * Specify the horizontal alignment of the image when using ACTUAL style + */ + public void setImageAlignmentX(float alignmentX) + { + this.alignmentX = alignmentX > 1.0f ? 1.0f : alignmentX < 0.0f ? 0.0f : alignmentX; + repaint(); + } + + /* + * Specify the horizontal alignment of the image when using ACTUAL style + */ + public void setImageAlignmentY(float alignmentY) + { + this.alignmentY = alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f : alignmentY; + repaint(); + } + + /* + * Override method so we can make the component transparent + */ + public void add(JComponent component) + { + add(component, null); + } + + /* + * Override method so we can make the component transparent + */ + public void add(JComponent component, Object constraints) + { + if (isTransparentAdd) + { + makeComponentTransparent(component); + } + + super.add(component, constraints); + } + + /* + * Controls whether components added to this panel should automatically + * be made transparent. That is, setOpaque(false) will be invoked. + * The default is set to true. + */ + public void setTransparentAdd(boolean isTransparentAdd) + { + this.isTransparentAdd = isTransparentAdd; + } + + /* + * Try to make the component transparent. + * For components that use renderers, like JTable, you will also need to + * change the renderer to be transparent. An easy way to do this it to + * set the background of the table to a Color using an alpha value of 0. + */ + private void makeComponentTransparent(JComponent component) + { + component.setOpaque( false ); + + if (component instanceof JScrollPane) + { + JScrollPane scrollPane = (JScrollPane)component; + JViewport viewport = scrollPane.getViewport(); + viewport.setOpaque( false ); + Component c = viewport.getView(); + + if (c instanceof JComponent) + { + ((JComponent)c).setOpaque( false ); + } + } + } + + /* + * Add custom painting + */ + protected void paintComponent(Graphics g) + { + super.paintComponent(g); + + // Invoke the painter for the background + + if (painter != null) + { + Dimension d = getSize(); + Graphics2D g2 = (Graphics2D) g; + g2.setPaint(painter); + g2.fill( new Rectangle(0, 0, d.width, d.height) ); + } + + // Draw the image + + if (image == null ) return; + + switch (style) + { + case SCALED : + drawScaled(g); + break; + + case TILED : + drawTiled(g); + break; + + case ACTUAL : + drawActual(g); + break; + + default: + drawScaled(g); + } + } + + /* + * Custom painting code for drawing a SCALED image as the background + */ + private void drawScaled(Graphics g) + { + Dimension d = getSize(); + g.drawImage(image, 0, 0, d.width, d.height, null); + } + + /* + * Custom painting code for drawing TILED images as the background + */ + private void drawTiled(Graphics g) + { + Dimension d = getSize(); + int width = image.getWidth( null ); + int height = image.getHeight( null ); + + for (int x = 0; x < d.width; x += width) + { + for (int y = 0; y < d.height; y += height) + { + g.drawImage( image, x, y, null, null ); + } + } + } + + /* + * Custom painting code for drawing the ACTUAL image as the background. + * The image is positioned in the panel based on the horizontal and + * vertical alignments specified. + */ + private void drawActual(Graphics g) + { + Dimension d = getSize(); + Insets insets = getInsets(); + int width = d.width - insets.left - insets.right; + int height = d.height - insets.top - insets.left; + float x = (width - image.getWidth(null)) * alignmentX; + float y = (height - image.getHeight(null)) * alignmentY; + g.drawImage(image, (int)x + insets.left, (int)y + insets.top, this); + } +} diff --git a/src/BoosterDraft.java b/src/BoosterDraft.java new file mode 100644 index 00000000000..e11e6899d10 --- /dev/null +++ b/src/BoosterDraft.java @@ -0,0 +1,122 @@ + + +public interface BoosterDraft +{ + public CardList nextChoice(); + public void setChoice(Card c); + public boolean hasNextChoice(); + public Deck[] getDecks(); //size 7, all the computers decks +} + +class BoosterDraft_1 implements BoosterDraft +{ + private final BoosterDraftAI draftAI = new BoosterDraftAI(); + private final int nPlayers = 8; + private final int boosterPackSize = 15; + private final int stopCount = boosterPackSize * 3;//should total of 45 + + private int currentCount = 0; + private CardList[] pack;//size 8 + + //helps the computer choose which booster packs to pick from + //the first row says "pick from boosters 1-7, skip 0" since the players picks from 0 + //the second row says "pick from 0 and 2-7 boosters, skip 1" - player chooses from 1 + private final int computerChoose[][] = { + { 1,2,3,4,5,6,7}, + {0, 2,3,4,5,6,7}, + {0,1, 3,4,5,6,7}, + {0,1,2, 4,5,6,7}, + {0,1,2,3, 5,6,7}, + {0,1,2,3,4, 6,7}, + {0,1,2,3,4,5, 7}, + {0,1,2,3,4,5,6 } + }; + + public static void main(String[] args) + { + BoosterDraft_1 draft = new BoosterDraft_1(); + while(draft.hasNextChoice()) + { + CardList list = draft.nextChoice(); + System.out.println(list.size()); + draft.setChoice(list.get(0)); + } + } + BoosterDraft_1() {pack = get8BoosterPack();} + + public CardList nextChoice() + { + if(pack[getMod()].size() == 0) + pack = get8BoosterPack(); + + computerChoose(); + CardList list = pack[getMod()]; + return list; + } + public CardList[] get8BoosterPack() + { + CardList[] list = new CardList[] + {//nPlayers is 8 + new CardList(), + new CardList(), + new CardList(), + new CardList(), + + new CardList(), + new CardList(), + new CardList(), + new CardList(), + }; + ReadBoosterPack pack = new ReadBoosterPack(); + + for(int i = 0; i < list.length; i++) + list[i].addAll(pack.getBoosterPack().toArray()); + + return list; + }//get8BoosterPack() + + //size 7, all the computers decks + public Deck[] getDecks() {return draftAI.getDecks();} + + private void computerChoose() + { + int row[] = computerChoose[getMod()]; + + for(int i = 0; i < row.length; i++) + draftAI.choose(pack[row[i]]); + }//computerChoose() + + private int getMod() {return currentCount % nPlayers;} + public boolean hasNextChoice() {return currentCount < stopCount;} + + public void setChoice(Card c) + { + CardList list = pack[getMod()]; + currentCount++; + + if(! list.contains(c)) + throw new RuntimeException("BoosterDraft : setChoice() error - card not found - " +c +" - booster pack = " +list); + + list.remove(c); + }//setChoice() +} + +class BoosterDraftTest implements BoosterDraft +{ + int n = 3; + public Deck[] getDecks() {return null;} + + public CardList nextChoice() + { + n--; + ReadBoosterPack pack = new ReadBoosterPack(); + return pack.getBoosterPack(); + } + public void setChoice(Card c) {System.out.println(c.getName());} + public boolean hasNextChoice() + { + return n > 0; + } + public CardList getChosenCards() {return null;} + public CardList getUnchosenCards() {return null;} +} diff --git a/src/BoosterDraftAI.java b/src/BoosterDraftAI.java new file mode 100644 index 00000000000..7f10445c0bf --- /dev/null +++ b/src/BoosterDraftAI.java @@ -0,0 +1,302 @@ +import java.util.*; + +public class BoosterDraftAI +{ + //once a deck has this number of creatures the computer randomly + //picks a card, so the final computer deck has 12-20 creatures + //minimum of creatures per deck + private final int nCreatures = 16; + private final int nDecks = 7; + + //holds all the cards for each of the computer's decks + private CardList[] deck = new CardList[nDecks]; + private String[][] deckColor = new String[nDecks][]; + + private static Map colorToLand = new HashMap(); + + public static void main(String[] args) + { + BoosterDraftAI ai = new BoosterDraftAI(); + ai.runTestPrint(); + } + public void runTestPrint() + { + BoosterDraftAI ai = new BoosterDraftAI(); + ai.runTest(ai); + + Deck[] deck = ai.getDecks(); + + for(int outer = 0; outer < 7; outer++) + { + System.out.print(deck[outer].countMain() +" - "); + + for(int i = 0; i < 16; i++) + System.out.print(deck[outer].getMain(i) +", "); + + System.out.println(""); + + for(int i = 16; i < 22; i++) + System.out.print(deck[outer].getMain(i) +", "); + + System.out.println("\n"); + }//for outer + }//runTestPrint() + + //throws Exception if error + public void runTest(BoosterDraftAI ai) + { + ReadBoosterPack booster = new ReadBoosterPack(); + for(int outer = 0; outer < 1; outer++) + { + CardList allBooster = new CardList(); + for(int i = 0; i < 21; i++) + allBooster.addAll(booster.getBoosterPack().toArray()); + + int stop = allBooster.size(); + for(int i = 0; i < stop; i++) + { + ai.choose(allBooster); + } + //ai.checkDeckList(ai.deck); + } + }//runTest() + + //picks one Card from augment, removes that card, and returns the list + //returns the cards not picked + public CardList choose(final CardList in_choose) + { + //in_choose should ONLY be on the RIGHT side of any equal sign + //only 1 card should be removed from in_choose + + CardList list = new CardList(); + boolean hasPicked = false; + + //try to choose a creature that has one of the colors that are in the deck + for(int i = 0; i < nDecks; i++) + { + if(countCreatures(deck[i]) < nCreatures) + { + list.clear(); + + //get creature cards that match the decks 2 colors + list.addAll(CardListUtil.getColor(in_choose.getType("Creature"), deckColor[i][0]).toArray()); + list.addAll(CardListUtil.getColor(in_choose.getType("Creature"), deckColor[i][1]).toArray()); + + for(int j=0;j 1) + { + //TODO maybe keep in cards that have 2 colors, and match the colors + list.remove(list.get(j)); + } + } + + list.shuffle(); + + if(! list.isEmpty()) + { + + deck[i].add(list.get(0)); + hasPicked = true; + break; + } + }//if + }//for + + //no card was chosen + if(! hasPicked) + { + //TODO: remove cards that the computer can't play + //holds instants and sorceries + CardList spell = new CardList(); + spell.addAll(in_choose.getType("Instant").toArray()); + spell.addAll(in_choose.getType("Sorcery").toArray()); + + //choose any card that matches the decks color + for(int i = 0; i < nDecks; i++) + { + list.clear(); + + list.addAll(deck[i].getType("Instant").toArray()); + list.addAll(deck[i].getType("Sorcery").toArray()); + + //does the deck need more spells? + //16 creatures, 6 spells per deck + if(list.size() < 6) + { + list.clear(); + + //get any cards that match the decks 2 colors + list.addAll(CardListUtil.getColor(new CardList(spell.toArray()), deckColor[i][0]).toArray()); + list.addAll(CardListUtil.getColor(new CardList(spell.toArray()), deckColor[i][1]).toArray()); + + list.shuffle(); + + + + if(! list.isEmpty()) + { + deck[i].add(list.get(0)); + hasPicked = true; + break; + } + }//if - deck[i].size() < 22 + }//for + }//if - choose any card + + if(hasPicked) + in_choose.remove(list.get(0)); + else//computer didn't choose a card, just remove any card - all computer decks are done + { + in_choose.remove(0); + } + + return in_choose; + }//choose() + +/* + I get some wierd error when I have this method, I don't know whats wrong + + private void checkDeckList(CardList[] deck) + { + if(deck.length != nDecks) + throw new RuntimeException("BoosterDraftAI : checkDeckList() error, deck list size is not 7 - " +deck.length); + + for(int i = 0; i < nDecks; i++) + { + if(deck[i].size() != 22) + { + throw new RuntimeException("BoosterDraftAI : checkDeckList() error, deck list size is not 22 - " +deck[i].size() +" - " +deck.toString()); + } + if(countCreatures(deck[i]) < nCreatures) + throw new RuntimeException("BoosterDraftAI : checkDeckList() error, deck needs more creatures - " +countCreatures(deck[i])); + + for(int inner = 0; inner < 22; inner++) + if(! CardUtil.getColors(deck[i].getCard(inner)).contains(deckColor[i][0]) && + ! CardUtil.getColors(deck[i].getCard(inner)).contains(deckColor[i][1])) + throw new RuntimeException("BoosterDraftAI : checkDeckList() error, deck has different card colors"); + }//for + }//checkDeckList() +*/ + + private int countCreatures(CardList list) {return list.getType("Creature").size();} + + private void testColors(int[] n) + { + if(n.length != nDecks) + throw new RuntimeException("BoosterDraftAI : testColors error, numbers array length does not equal 7"); + + HashSet set = new HashSet(); + for(int i = 0; i < nDecks; i++) + set.add(new Integer(n[i])); + + if(set.size() != nDecks) + throw new RuntimeException("BoosterDraftAI : testColors error, numbers not unique"); + + for(int i = 0; i < nDecks; i++) + if(n[i] < 0 || deckColorChoices.length <= n[i]) + throw new RuntimeException("BoosterDraftAI : testColors error, index out of range - " +n[i]); + }//testColors() + + public Deck[] getDecks() + { + //check CardList[] deck for errors + //checkDeckList(deck); + + Deck[] out = new Deck[deck.length]; + + for(int i = 0; i < deck.length; i++) + { + addLand(deck[i], deckColor[i]); + out[i] = getDeck(deck[i]); + } + return out; + }//getDecks() + + private Deck getDeck(CardList list) + { + Deck out = new Deck(Constant.GameType.Draft); + for(int i = 0; i < list.size(); i++) + out.addMain(list.get(i).getName()); + + return out; + }//getDeck() + + //add Land to list argument + private void addLand(CardList list, String[] color) + { + Card land; + for(int i = 0; i < 9; i++) + { + land = AllZone.CardFactory.getCard(colorToLand.get(color[0]).toString(), Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(colorToLand.get(color[1]).toString(), Constant.Player.Computer); + list.add(land); + } + + if(list.getType("Land").size() != 18) + throw new RuntimeException("BoosterDraftAI : addLand() error, deck does not have 18 lands - " +list.getType("Land").size()); + + if(list.size() != 40) + throw new RuntimeException("BoosterDraftAI : addLand() error, deck is not 40 cards - " +list.size()); + }//addLand() + + + //returns 7 different ints, within the range of 0-9 + private int[] getDeckColors() + { + int[] out = new int[nDecks]; + int start = MyRandom.random.nextInt(); + start = Math.abs(start);//make number positive, stupid number generator + + for(int i = 0; i < out.length; i++) + { + //% to get an index between 0 and deckColorChoices.length + out[i] = start % deckColorChoices.length; + start++; + } + testColors(out); + + return out; + }//getDeckColors() + + public BoosterDraftAI() + { + //choose colors for decks + int[] n = getDeckColors(); + for(int i = 0; i < n.length; i++) + deckColor[i] = deckColorChoices[n[i]]; + + //initilize color map + colorToLand.put(Constant.Color.Black , "Swamp"); + colorToLand.put(Constant.Color.Blue , "Island"); + colorToLand.put(Constant.Color.Green , "Forest"); + colorToLand.put(Constant.Color.Red , "Mountain"); + colorToLand.put(Constant.Color.White , "Plains"); + + //initilize deck array + for(int i = 0; i < deck.length; i++) + deck[i] = new CardList(); + }//BoosterDraftAI() + + + //all 10 two color combinations + private String[][] deckColorChoices = + { + {Constant.Color.Black, Constant.Color.Blue}, + {Constant.Color.Black, Constant.Color.Green}, + {Constant.Color.Black, Constant.Color.Red}, + {Constant.Color.Black, Constant.Color.White}, + + {Constant.Color.Blue, Constant.Color.Green}, + {Constant.Color.Blue, Constant.Color.Red}, + {Constant.Color.Blue, Constant.Color.White}, + + {Constant.Color.Green, Constant.Color.Red}, + {Constant.Color.Green, Constant.Color.White}, + + {Constant.Color.Red, Constant.Color.White} + }; +}//BoosterDraftAI() \ No newline at end of file diff --git a/src/BoosterPack.java b/src/BoosterPack.java new file mode 100644 index 00000000000..9df679ed4e3 --- /dev/null +++ b/src/BoosterPack.java @@ -0,0 +1,27 @@ + + +public class BoosterPack +{ + public static CardList getBoosterPack(int number) + { + CardList all = new CardList(); + for(int i = 0; i < number; i++) + all.addAll(getBoosterPack().toArray()); + + return all; + } + + public static CardList getBoosterPack() + { + CardList all = AllZone.CardFactory.getAllCards(); + CardList pack = new CardList(); + + for(int i = 0; i < 10; i++) + pack.add(all.get(MyRandom.random.nextInt(all.size()))); + + for(int i = 0; i < 5; i++) + pack.add(AllZone.CardFactory.copyCard(pack.get(i))); + + return pack; + }//getBoosterPack() +} \ No newline at end of file diff --git a/src/ButtonUtil.java b/src/ButtonUtil.java new file mode 100644 index 00000000000..1debb07c8bf --- /dev/null +++ b/src/ButtonUtil.java @@ -0,0 +1,34 @@ +public class ButtonUtil +{ + public static void reset() + { + getOK().setText("OK"); + getCancel().setText("Cancel"); + + getOK().setSelectable(false); + getCancel().setSelectable(false); + } + public static void enableOnlyOK() + { + getOK().setSelectable(true); + getCancel().setSelectable(false); + } + public static void enableOnlyCancel() + { + getOK().setSelectable(false); + getCancel().setSelectable(true); + } + public static void disableAll() + { + getOK().setSelectable(false); + getCancel().setSelectable(false); + } + public static void enableAll() + { + getOK().setSelectable(true); + getCancel().setSelectable(true); + } + + private static MyButton getOK() {return AllZone.Display.getButtonOK();} + private static MyButton getCancel() {return AllZone.Display.getButtonCancel();} +} diff --git a/src/Card.java b/src/Card.java new file mode 100644 index 00000000000..c20bc00f7b8 --- /dev/null +++ b/src/Card.java @@ -0,0 +1,855 @@ +import java.util.*; + +enum Counters { + AGE, BLAZE, CHARGE, DIVINITY, FADE, HOOFPRINT, ICE, LOYALTY, M1M1, MANA, P0M1, P1P1, QUEST, SPORE +} + +public class Card extends MyObservable +{ + private static int nextUniqueNumber; + private int uniqueNumber = nextUniqueNumber++; + + + //private Collection keyword = new TreeSet(); + //private ArrayList keyword = new ArrayList(); + private ArrayList intrinsicKeyword = new ArrayList(); + private ArrayList extrinsicKeyword = new ArrayList(); + private ArrayList prevIntrinsicKeyword = new ArrayList(); + private ArrayList attached = new ArrayList(); + private ArrayList equippedBy = new ArrayList(); //which equipment cards are equipping this card? + //equipping size will always be 0 or 1 + private ArrayList equipping = new ArrayList(); //if this card is of the type equipment, what card is it currently equipping? + private ArrayList enchantedBy = new ArrayList(); //which auras enchanted this card? + //enchanting size will always be 0 or 1 + private ArrayList enchanting = new ArrayList(); //if this card is an Aura, what card is it enchanting? + private ArrayList type = new ArrayList(); + private ArrayList prevType = new ArrayList(); + private ArrayList spellAbility = new ArrayList(); + private ArrayList manaAbility = new ArrayList(); + + private HashMap receivedDamageFromThisTurn = new HashMap(); + + private boolean tapped; + private boolean sickness = true;//summoning sickness + private boolean token = false; + private boolean creatureAttackedThisTurn = false; + private boolean creatureBlockedThisTurn = false; + private boolean creatureGotBlockedThisTurn = false; + private boolean dealtCombatDmgToOppThisTurn = false; + private boolean dealtDmgToOppThisTurn = false; + private boolean exaltedBonus = false; + private boolean faceDown = false; + private boolean echoPaid = false; + private boolean sacrificeAtEOT = false; + + private boolean firstStrike = false; + private boolean doubleStrike = false; + + private boolean flashback = false; + + private int exaltedMagnitude = 0; + + private int baseAttack; + private int baseDefense; + + private int damage; + private int assignedDamage; + private int nShield; + private int turnInZone; + + private int tempAttackBoost = 0; + private int tempDefenseBoost = 0; + + private int semiPermanentAttackBoost = 0; + private int semiPermanentDefenseBoost = 0; + + private int otherAttackBoost = 0; + private int otherDefenseBoost = 0; + + private int randomPicture = 0; + + private int X = 0; + + private String owner = ""; + private String controller = ""; + private String name = ""; + private String imageName = ""; + private String rarity = ""; + private String text = ""; + private String manaCost = ""; + private String chosenType = ""; + + private ArrayList comesIntoPlayCommandList = new ArrayList(); + private ArrayList destroyCommandList = new ArrayList(); + private ArrayList leavesPlayCommandList = new ArrayList(); + private ArrayList turnFaceUpCommandList = new ArrayList(); + private ArrayList equipCommandList = new ArrayList(); + private ArrayList unEquipCommandList = new ArrayList(); + private ArrayList enchantCommandList = new ArrayList(); + private ArrayList unEnchantCommandList = new ArrayList(); + private ArrayList replaceMoveToGraveyardCommandList = new ArrayList(); + private ArrayList cycleCommandList = new ArrayList(); + + private Hashtable counters = new Hashtable(); + + //hacky code below, used to limit the number of times an ability + //can be used per turn like Vampire Bats + //should be put in SpellAbility, but it is put here for convienance + //this is make public just to make things easy + //this code presumes that each card only has one ability that can be + //used a limited number of times per turn + //CardFactory.SSP_canPlay(Card) uses these variables + + private int abilityTurnUsed; //What turn did this card last use this ability? + private int abilityUsed; //How many times has this ability been used? + + public void setAbilityTurnUsed(int i) {abilityTurnUsed = i; } + public int getAbilityTurnUsed() { return abilityTurnUsed; } + + public void setAbilityUsed(int i) {abilityUsed = i;} + public int getAbilityUsed() { return abilityUsed; } + + //****************TODO:Check + public void setX(int i){X = i;} + public int getX() { return X; } + //***************/ + + //used to see if an attacking creature with a triggering attack ability triggered this turn: + public void setCreatureAttackedThisTurn(boolean b) { creatureAttackedThisTurn = b; } + public boolean getCreatureAttackedThisTurn() { return creatureAttackedThisTurn; } + + public void setCreatureBlockedThisTurn(boolean b) { creatureBlockedThisTurn = b; } + public boolean getCreatureBlockedThisTurn() { return creatureBlockedThisTurn; } + + public void setCreatureGotBlockedThisTurn(boolean b) { creatureGotBlockedThisTurn = b; } + public boolean getCreatureGotBlockedThisTurn() { return creatureGotBlockedThisTurn; } + + public void setDealtCombatDmgToOppThisTurn(boolean b) { dealtCombatDmgToOppThisTurn = b; } + public boolean getDealtCombatDmgToOppThisTurn() { return dealtCombatDmgToOppThisTurn; } + + public void setDealtDmgToOppThisTurn(boolean b) { dealtDmgToOppThisTurn = b;} + public boolean getDealtDmgToOppThisTurn() { return dealtDmgToOppThisTurn; } + + public void addReceivedDamageFromThisTurn(Card c, int damage) { receivedDamageFromThisTurn.put(c, damage);} + public void setReceivedDamageFromThisTurn(HashMap receivedDamageFromThisTurn) { + this.receivedDamageFromThisTurn = receivedDamageFromThisTurn; + } + public HashMap getReceivedDamageFromThisTurn() { + return receivedDamageFromThisTurn; + } + + public void resetReceivedDamageFromThisTurn() { + receivedDamageFromThisTurn.clear(); + } + + + public boolean getSacrificeAtEOT() + { + return sacrificeAtEOT; + } + + public void setSacrificeAtEOT(boolean sacrificeAtEOT) + { + this.sacrificeAtEOT = sacrificeAtEOT; + } + + public boolean hasFirstStrike() { + return firstStrike || getKeyword().contains("First Strike"); + } + + public void setFirstStrike(boolean firstStrike){ + this.firstStrike = firstStrike; + } + + public void setDoubleStrike(boolean doubleStrike){ + this.doubleStrike = doubleStrike; + } + + public boolean hasDoubleStrike() { + return doubleStrike || getKeyword().contains("Double Strike"); + } + + public void addCounter(Counters counterName, int n) + { + if(counters.containsKey(counterName)) + { + Integer aux = counters.get(counterName) + n; + counters.put(counterName,aux); + } + else + { + counters.put(counterName, new Integer(n)); + } + this.updateObservers(); + } + + public void subtractCounter(Counters counterName, int n) + { + if(counters.containsKey(counterName)) + { + Integer aux = counters.get(counterName) - n; + counters.put(counterName,aux); + this.updateObservers(); + } + } + public int getCounters(Counters counterName) + { + if(counters.containsKey(counterName)) + { + return counters.get(counterName); + } + else + return 0; + } + + public void setCounter(Counters counterName, int n) { + counters.put(counterName,new Integer(n)); + this.updateObservers(); + } + + public int sumAllCounters() + { + Object[] values = counters.values().toArray(); + int count = 0; + int num = 0; + for(int i=0;i keyword = getKeyword(); + for(int i = 0; i < keyword.size(); i++) + { + if(i != 0) + s += ", "; + s += keyword.get(i).toString(); + } + + s += "\r\n" +text +"\r\n"; + + SpellAbility[] sa = getSpellAbility(); + for(int i = 0; i < sa.length; i++) + { + //presumes the first SpellAbility added to this card, is the "main" spell + //skip the first SpellAbility for creatures, since it says "Summon this creature" + //looks bad on the Gui card detail + if(isPermanent() && i != 0 && !(manaAbility.contains(sa[i]) && ((Ability_Mana) sa[i]).isBasic()))//prevent mana ability duplication + s += sa[i].toString() +"\r\n"; + } + + return s.trim(); + }//getText() + + /* private ArrayList addLandAbilities () + { + ArrayList res = new ArrayList(manaAbility); + if (!getType().contains("Land")) return res; + ArrayList types = getType(); + for(int i = 0; i < basics.length; i++) + if(types.contains(basics[i]) && !res.contains("tap: add "+ ManaPool.colors.charAt(i))) + res.add(new Ability_Mana(this, "tap: add "+ ManaPool.colors.charAt(i)){}); + return res; + }*/ + /*ArrayList addExtrinsicAbilities(ArrayList have) + { + try{ + if (AllZone.getZone(this).is(Constant.Zone.Play)) + { + for (Card c : AllZone.getZone(Constant.Zone.Play, getController()).getCards()) + if (c.getName().equals("Joiner Adept") && getType().contains("Land") || c.getName().equals("Gemhide Sliver") && getType().contains("Sliver")) + for (char ch : ManaPool.colors.toCharArray()) + have.add(new Ability_Mana(this, "tap: add " + ch){}); + }} + catch(NullPointerException ex){}//TODO: fix this to something more memory-efficient than catching 2000 NullPointer Exceptions every time you open deck editor + return have; + }*/ + public ArrayList getManaAbility(){return new ArrayList(manaAbility);} + public ArrayList getBasicMana() + { + ArrayList res = new ArrayList(); + for(Ability_Mana am : getManaAbility()) + if(am.isBasic() && !res.contains(am)) + res.add(am); + return res; + } + + public void clearSpellAbility() {spellAbility.clear(); manaAbility.clear();} + public void clearSpellKeepManaAbility() { spellAbility.clear(); } + public void clearManaAbility() { manaAbility.clear(); } + public void addSpellAbility(SpellAbility a) {a.setSourceCard(this); if (a instanceof Ability_Mana) manaAbility.add((Ability_Mana) a); else spellAbility.add(a);} + + public void removeSpellAbility(SpellAbility a) + { + if(a instanceof Ability_Mana) + //if (a.isExtrinsic()) //never remove intrinsic mana abilities, is this the way to go?? + manaAbility.remove((Ability_Mana)a); + else + spellAbility.remove(a); + + } + + + + public void removeAllExtrinsicManaAbilities() + { + //temp ArrayList, otherwise ConcurrentModificationExceptions occur: + ArrayList saList = new ArrayList(); + + for (SpellAbility var : manaAbility) + { + if(var.isExtrinsic()) + saList.add(var); + } + for (SpellAbility sa : saList) + { + removeSpellAbility(sa); + } + } + + public ArrayList getIntrinsicManaAbilitiesDescriptions() + { + ArrayList list = new ArrayList(); + for (SpellAbility var : manaAbility) + { + if (var.isIntrinsic()) + list.add(var.toString()); + } + return list; + } + + public SpellAbility[] getSpellAbility() + { + ArrayList res = new ArrayList(spellAbility); + res.addAll(getManaAbility()); + SpellAbility[] s = new SpellAbility[res.size()]; + res.toArray(s); + return s; + } + + //shield = regeneration + public void setShield(int n) {nShield = n;} + public int getShield() {return nShield;} + public void addShield() {nShield++;} + public void subtractShield() {nShield--;} + public void resetShield() {nShield = 0;} + + //is this "Card" supposed to be a token? + public void setToken(boolean b) {token = b;} + public boolean isToken() {return token;} + + public void setExaltedBonus(boolean b) {exaltedBonus = b;} + public boolean hasExaltedBonus() {return exaltedBonus;} + public void setExaltedMagnitude(int i) {exaltedMagnitude = i;} + public int getExaltedMagnitude() { return exaltedMagnitude; } + + public void setIsFaceDown(boolean b) { faceDown = b;} + public boolean isFaceDown() { return faceDown; } + + public void addComesIntoPlayCommand(Command c) {comesIntoPlayCommandList.add(c);} + public void removeComesIntoPlayCommand(Command c) { comesIntoPlayCommandList.remove(c);} + public void comesIntoPlay() { + for (Command var : comesIntoPlayCommandList) + var.execute(); + } + + public void addTurnFaceUpCommand(Command c) { turnFaceUpCommandList.add(c); } + public void removeTurnFaceUpCommand(Command c) { turnFaceUpCommandList.remove(c); } + public void turnFaceUp() { + for (Command var : turnFaceUpCommandList) + var.execute(); + } + + public void addDestroyCommand(Command c) {destroyCommandList.add(c);} + public void removeDestroyCommand(Command c) {destroyCommandList.remove(c); } + public void destroy() + { + for (Command var : destroyCommandList) + var.execute(); + } + + public void addLeavesPlayCommand(Command c) { leavesPlayCommandList.add(c);} + public void removeLeavesPlayCommand(Command c) { leavesPlayCommandList.remove(c); } + public void leavesPlay() { + for (Command var : leavesPlayCommandList) + var.execute(); + } + + public void addEquipCommand(Command c) {equipCommandList.add(c); } + public void removeEquipCommand(Command c) { equipCommandList.remove(c); } + public void equip() { + for (Command var : equipCommandList) + var.execute(); + } + + public void addUnEquipCommand(Command c) {unEquipCommandList.add(c); } + public void removeUnEquipCommand(Command c) { unEquipCommandList.remove(c); } + public void unEquip() { + for (Command var : unEquipCommandList) + var.execute(); + } + + public void addEnchantCommand(Command c) {enchantCommandList.add(c); } + public void removeEnchantCommand(Command c) {enchantCommandList.add(c); } + public void enchant() { + for (Command var : enchantCommandList) + var.execute(); + } + + public void addUnEnchantCommand(Command c) { unEnchantCommandList.add(c); } + public void unEnchant() { + for (Command var : unEnchantCommandList) + var.execute(); + } + + public ArrayList getReplaceMoveToGraveyard() { return replaceMoveToGraveyardCommandList; } + public void addReplaceMoveToGraveyardCommand(Command c) { replaceMoveToGraveyardCommandList.add(c);} + public void replaceMoveToGraveyard() + { + for (Command var : replaceMoveToGraveyardCommandList) + var.execute(); + } + + public void addCycleCommand(Command c) { cycleCommandList.add(c); } + public void cycle() { + for (Command var : cycleCommandList) + var.execute(); + } + + public void setSickness(boolean b) {sickness = b;} + public boolean hasSickness() + { + if(getKeyword().contains("Haste")) + return false; + + return sickness; + } + + public void setRarity(String s) {rarity = s;} + public String getRarity() {return rarity;} + + public void addDamage(int n) + { + if (this.getName().equals("Cho-Manno, Revolutionary")) + n = 0; + setDamage(getDamage() + n); + } + public void setDamage(int n) + { + if (this.getName().equals("Cho-Manno, Revolutionary")) + n = 0; + damage = n; + } + public int getDamage() {return damage;} + + public void setAssignedDamage(int n) {assignedDamage = n;} + public int getAssignedDamage() {return assignedDamage;} + + public void setImageName(String s) { imageName = s; } + public String getImageName() + { + if (!imageName.equals("")) + return imageName; + return name; + } + + public String getName() {return name;} + public String getOwner() {return owner;} + public String getController(){return controller;} + + public void setName(String s) {name = s; this.updateObservers();} + public void setOwner(String player) {owner = player;} + public void setController(String player){controller = player; this.updateObservers();} + + public ArrayList getEquippedBy() + { + return equippedBy; + } + + public void setEquippedBy(ArrayList list) + { + equippedBy = list; + } + + public ArrayList getEquipping() + { + return equipping; + } + + public void setEquipping(ArrayList list) + { + equipping = list; + } + + public boolean isEquipped() + { + Card c[] = new Card[equippedBy.size()]; + equippedBy.toArray(c); + return c.length != 0; + } + + public boolean isEquipping() + { + Card c[] = new Card[equipping.size()]; + equippedBy.toArray(); + return c.length != 0; + } + + public void addEquippedBy(Card c) + { + equippedBy.add(c); + this.updateObservers(); + } + + public void removeEquippedBy(Card c) + { + equippedBy.remove(c); + this.updateObservers(); + } + + public void addEquipping(Card c) + { + equipping.add(c); + this.updateObservers(); + } + + public void removeEquipping(Card c) + { + equipping.remove(c); + this.updateObservers(); + } + + public void equipCard(Card c) //equipment.equipCard(cardToBeEquipped); + { + equipping.add(c); + c.addEquippedBy(this); + this.equip(); + } + + public void unEquipCard(Card c) //equipment.unEquipCard(equippedCard); + { + this.unEquip(); + equipping.remove(c); + c.removeEquippedBy(this); + } + + public void unEquipAllCards() + { + for (int i=0; i getEnchantedBy() + { + return enchantedBy; + } + + public void setEnchantedBy(ArrayList list) + { + enchantedBy = list; + } + + public ArrayList getEnchanting() + { + return enchanting; + } + + public void setEnchanting(ArrayList list) + { + enchanting = list; + } + + public boolean isEnchanted() + { + Card c[] = new Card[enchantedBy.size()]; + enchantedBy.toArray(c); + return c.length != 0; + } + + public boolean isEnchanting() + { + Card c[] = new Card[enchanting.size()]; + enchantedBy.toArray(); + return c.length != 0; + } + + public void addEnchantedBy(Card c) + { + enchantedBy.add(c); + this.updateObservers(); + } + + public void removeEnchantedBy(Card c) + { + enchantedBy.remove(c); + this.updateObservers(); + } + + public void addEnchanting(Card c) + { + enchanting.add(c); + this.updateObservers(); + } + + public void removeEnchanting(Card c) + { + enchanting.remove(c); + this.updateObservers(); + } + + public void enchantCard(Card c) + { + enchanting.add(c); + c.addEnchantedBy(this); + this.enchant(); + } + + public void unEnchantCard(Card c) + { + this.unEnchant(); + enchanting.remove(c); + c.removeEnchantedBy(this); + } + + public void unEnchantAllCards() + { + for (int i=0; i a) {type = new ArrayList(a);} + public void addType(String a) {type.add(a); this.updateObservers();} + public void removeType(String a) {type.remove(a); this.updateObservers();} + public ArrayList getType() {return new ArrayList(type);} + + public void setPrevType(ArrayList a) {prevType = new ArrayList(a);} + public void addPrevType(String a) {prevType.add(a);} + public void removePrevType(String a) {prevType.remove(a);} + public ArrayList getPrevType() {return new ArrayList(prevType);} + + //values that are printed on card + public int getBaseAttack() {return baseAttack;} + public int getBaseDefense() {return baseDefense;} + + //values that are printed on card + public void setBaseAttack(int n) {baseAttack = n; this.updateObservers();} + public void setBaseDefense(int n) {baseDefense = n; this.updateObservers();} + + public int getNetAttack() + { + int total = getBaseAttack(); + total += getTempAttackBoost() + getSemiPermanentAttackBoost() + getOtherAttackBoost() + getCounters(Counters.P1P1) + - getCounters(Counters.M1M1); + return total; + } + public int getNetDefense() + { + int total = getBaseDefense(); + total += getTempDefenseBoost() + getSemiPermanentDefenseBoost() + getOtherDefenseBoost() + getCounters(Counters.P1P1) + - getCounters(Counters.M1M1) - getCounters(Counters.P0M1); + return total; + } + + public void setRandomPicture(int n) { randomPicture = n; } + public int getRandomPicture() { return randomPicture; } + + //public int getAttack(){return attack;} + + //for cards like Giant Growth, etc. + public int getTempAttackBoost() {return tempAttackBoost;} + public int getTempDefenseBoost() {return tempDefenseBoost;} + + public void addTempAttackBoost(int n) {tempAttackBoost += n; this.updateObservers();} + public void addTempDefenseBoost(int n) {tempDefenseBoost += n; this.updateObservers();} + public void setTempAttackBoost(int n) {tempAttackBoost = n; this.updateObservers();} + public void setTempDefenseBoost(int n) {tempDefenseBoost = n; this.updateObservers();} + + //for cards like Glorious Anthem, etc. + public int getSemiPermanentAttackBoost() {return semiPermanentAttackBoost;} + public int getSemiPermanentDefenseBoost() {return semiPermanentDefenseBoost;} + + public void addSemiPermanentAttackBoost(int n) { semiPermanentAttackBoost += n;} + public void addSemiPermanentDefenseBoost(int n){ semiPermanentDefenseBoost += n;} + public void setSemiPermanentAttackBoost(int n){ semiPermanentAttackBoost = n;} + public void setSemiPermanentDefenseBoost(int n) { semiPermanentDefenseBoost = n;} + + //for cards like Relentless Rats, Master of Etherium, etc. + public int getOtherAttackBoost() {return otherAttackBoost;} + public int getOtherDefenseBoost() {return otherDefenseBoost;} + + public void addOtherAttackBoost(int n) { otherAttackBoost += n;} + public void addOtherDefenseBoost(int n){ otherDefenseBoost += n;} + public void setOtherAttackBoost(int n){ otherAttackBoost = n;} + public void setOtherDefenseBoost(int n) { otherDefenseBoost = n;} + + //public void setAttack(int n) {attack = n; this.updateObservers();} + //public void setDefense(int n) {defense = n; this.updateObservers();} + + public boolean isUntapped() {return ! tapped;} + public boolean isTapped() {return tapped;} + public void setTapped(boolean b) {tapped = b; updateObservers();} + public void tap() {setTapped(true);} + public void untap() {setTapped(false);} + + //keywords are like flying, fear, first strike, etc... + public ArrayList getKeyword() + { + ArrayList a1 = new ArrayList(getIntrinsicKeyword()); + ArrayList a2 = new ArrayList(getExtrinsicKeyword()); + a1.addAll(a2); + + for(Ability_Mana sa : getManaAbility()) + if(sa.isBasic()) + a1.add(((Ability_Mana)sa).orig); + + return a1; + } + //public void setKeyword(ArrayList a) {keyword = new ArrayList(a); this.updateObservers();} + //public void addKeyword(String s) {keyword.add(s); this.updateObservers();} + //public void removeKeyword(String s) {keyword.remove(s); this.updateObservers();} + //public int getKeywordSize() {return keyword.size();} + + public String[] basics = {"Plains", "Island", "Swamp", "Mountain", "Forest"}; + + public ArrayList getIntrinsicKeyword() {return new ArrayList(intrinsicKeyword);} + public void setIntrinsicKeyword(ArrayList a) {intrinsicKeyword = new ArrayList(a); this.updateObservers();} + public void addIntrinsicKeyword(String s) {/*if (s.startsWith("tap: add")) manaAbility.add(new Ability_Mana(this, s){}); else*/ intrinsicKeyword.add(s);} + public void removeIntrinsicKeyword(String s) { intrinsicKeyword.remove(s); this.updateObservers();} + public int getIntrinsicKeywordSize() {return intrinsicKeyword.size(); } + + public ArrayList getExtrinsicKeyword() {return new ArrayList(extrinsicKeyword);} + public void setExtrinsicKeyword(ArrayList a) {extrinsicKeyword = new ArrayList(a); this.updateObservers();} + public void addExtrinsicKeyword(String s) { + if(!getKeyword().contains(s)){ + if (s.startsWith("tap: add")) manaAbility.add(new Ability_Mana(this, s) + { + private static final long serialVersionUID = 221124403788942412L; + }); + else extrinsicKeyword.add(s); + } + } + public void removeExtrinsicKeyword(String s) {extrinsicKeyword.remove(s); this.updateObservers();} + public int getExtrinsicKeywordSize() {return extrinsicKeyword.size(); } + + public ArrayList getPrevIntrinsicKeyword() { return new ArrayList(prevIntrinsicKeyword);} + public void setPrevIntrinsicKeyword(ArrayList a) { prevIntrinsicKeyword = new ArrayList(a); this.updateObservers();} + public void addPrevIntrinsicKeyword(String s) { prevIntrinsicKeyword.add(s);} + public void removePrevIntrinsicKeyword(String s) { prevIntrinsicKeyword.remove(s); this.updateObservers();} + public int getPrevIntrinsicKeywordSize() {return prevIntrinsicKeyword.size();} + + + public boolean isPermanent() {return !(isInstant() || isSorcery());} + + public boolean isCreature() {return type.contains("Creature");} + public boolean isBasicLand() {return type.contains("Basic");} + public boolean isLand() {return type.contains("Land");} + public boolean isSorcery() {return type.contains("Sorcery");} + public boolean isInstant() {return type.contains("Instant") /*|| getKeyword().contains("Flash")*/;} + public boolean isArtifact() {return type.contains("Artifact");} + + public boolean isEquipment() {return type.contains("Equipment");} + public boolean isPlaneswalker() {return type.contains("Planeswalker");} + public boolean isTribal() {return type.contains("Tribal");} + + //global and local enchantments + public boolean isEnchantment() {return typeContains("Enchantment"); } + public boolean isLocalEnchantment() {return typeContains("Aura"); } + public boolean isAura() {return typeContains("Aura"); } + public boolean isGlobalEnchantment() {return typeContains("Enchantment") && (! isLocalEnchantment());} + + private boolean typeContains(String s) + { + Iterator it = this.getType().iterator(); + while(it.hasNext()) + if(it.next().toString().startsWith(s)) + return true; + + return false; + } + + public void setUniqueNumber(int n) {uniqueNumber = n; this.updateObservers();} + public int getUniqueNumber() {return uniqueNumber;} + + public boolean equals(Object o) + { + if(o instanceof Card) + { + Card c = (Card)o; + int a = getUniqueNumber(); + int b = c.getUniqueNumber(); + return (a == b); + } + return false; + } + public int hashCode() + { + return getUniqueNumber(); + } + public String toString() + { + return this.getName() +" (" +this.getUniqueNumber() +")"; + } + public boolean hasFlashback() { + return flashback; + } + public void setFlashback(boolean b) + { + flashback = b; + } +} diff --git a/src/CardDetailUtil.java b/src/CardDetailUtil.java new file mode 100644 index 00000000000..10e1eb87086 --- /dev/null +++ b/src/CardDetailUtil.java @@ -0,0 +1,48 @@ +import javax.swing.*; + +interface CardDetail +{ + public void updateCardDetail(Card c); +} + +public class CardDetailUtil +{ + public static void updateCardDetail(Card card, JTextArea area, JPanel cardDetailPanel, JPanel picturePanel, JLabel label[]) + { + if(card == null) + return; + //System.out.println("label length: " + label.length); + for(int i = 0; i < label.length; i++) + label[i].setText(""); + + area.setText(""); + + if(card.isLand()) + label[0].setText(card.getName()); + else + label[0].setText(card.getName() +" - " +card.getManaCost()); + + label[1].setText(GuiDisplayUtil.formatCardType(card)); + + if(card.isCreature()) + { + String stats = "" +card.getNetAttack() +" / " +card.getNetDefense(); + label[2].setText(stats); + } + + if(card.isCreature()) + label[3].setText("Damage: " +card.getDamage() +" Assigned Damage: " +card.getAssignedDamage()); + + String uniqueID = card.getUniqueNumber() +" "; + label[4].setText("Card ID " +uniqueID); + + area.setText(card.getText()); + + cardDetailPanel.setBorder(GuiDisplayUtil.getBorder(card)); + + //picture + picturePanel.removeAll(); + picturePanel.add(GuiDisplayUtil.getPicture(card)); + picturePanel.revalidate(); + }//updateCardDetail +} \ No newline at end of file diff --git a/src/CardFactory.java b/src/CardFactory.java new file mode 100644 index 00000000000..6f881d07a43 --- /dev/null +++ b/src/CardFactory.java @@ -0,0 +1,41235 @@ +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Random; +import java.util.Vector; + +import javax.swing.JOptionPane; + +import forge.error.ErrorViewer; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + +public class CardFactory implements NewConstants { + // String cardname is the key, Card is the value + private Map map = new HashMap(); + @SuppressWarnings("unused") + // random + private Random random = new Random(); + private CardList allCards = new CardList(); + + private HashSet removedCardList; + private Card blankCard = new Card(); //new code + + public CardFactory(String filename) { + this(new File(filename)); + } + + public CardFactory(File file) { + SpellAbility spell = new SpellAbility(SpellAbility.Spell, blankCard) { + //neither computer nor human play can play this card + @Override + public boolean canPlay() { + return false; + } + + @Override + public void resolve() {} + }; + blankCard.addSpellAbility(spell); + spell.setManaCost("1"); + blankCard.setName("Removed Card"); + + //owner and controller will be wrong sometimes + //but I don't think it will matter + //theoretically blankCard will go to the wrong graveyard + blankCard.setOwner(Constant.Player.Human); + blankCard.setController(Constant.Player.Human); + + removedCardList = new HashSet(FileUtil.readFile(ForgeProps.getFile(REMOVED))); + + + try { + readCards(file); + + // initialize CardList allCards + Iterator it = map.keySet().iterator(); + Card c; + while(it.hasNext()) { + c = getCard(it.next().toString(), Constant.Player.Human); + allCards.add(c); + //System.out.println("cardName: " + c.getName()); + + } + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + }// constructor + + public CardList getAllCards() { + return new CardList(allCards.toArray()); + }// getAllCards() + + private void readCards(File file) { + map.clear(); + + ReadCard read = new ReadCard(ForgeProps.getFile(CARDS)); + try { + read.run(); + // javax.swing.SwingUtilities.invokeAndWait(read); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("CardFactory : readCards() thread error - " + ex.getMessage()); + } + + ArrayList simpleList = read.getCards(); + Card s; + Iterator it = simpleList.iterator(); + while(it.hasNext()) { + s = it.next(); + map.put(s.getName(), s); + //System.out.println("cardName: " + s.getName()); + } + }// readCard() + + final public Card copyCard(Card in) { + Card out = getCard(in.getName(), in.getOwner()); + out.setUniqueNumber(in.getUniqueNumber()); + return out; + } + + /* + final public Card getCard(String cardName, String owner) { + cardName = AllZone.NameChanger.getOriginalName(cardName); + return getCard2(cardName, owner); + } + */ + + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + //this is the new getCard() method, you have to remove the old getCard() + final public Card getCard(String cardName, String owner) { + if(removedCardList.contains(cardName) || cardName.equals(blankCard.getName())) return blankCard; + + return getCard2(cardName, owner); + } + + //self-targeted power and/or toughness pumping abilities + //-1 means "PTPump" is not found + //any other int means that "PTPump" was found in the Card keyword + private final int shouldPTPumpCard(Card c) + { + ArrayList a = c.getKeyword(); + for(int i = 0; i < a.size(); i++) + if(a.get(i).toString().startsWith("PTPump")) + return i; + + return -1; + } + //same thing, for "KPump" - self-targeted keyword adding abilities + private final int shouldKPumpCard(Card c) + { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if(a.get(i).toString().startsWith("KPump")) + return i; + + return -1; + } + //same thing, for "PTKPump" - self-targeted power and/or toughness pumping + //plus keyword adding abilities + private final int shouldPTKPumpCard(Card c) + { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if(a.get(i).toString().startsWith("PTKPump")) + return i; + + return -1; + } + + //"TgtKPump" - targeted keyword adding abilities + private final int shouldTgtKPumpCard(Card c) + { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if(a.get(i).toString().startsWith("TgtKPump")) + return i; + + return -1; + } + + // Check for self-regenerate ability + private final int shouldRegenerateMe(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("RegenerateMe")) + return i; + + return -1; + } + + // Check for Cycling ability + private final int shouldCycle(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("Cycling")) + return i; + + return -1; + } + + private final int shouldSporeSaproling(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("Remove three spore counters")) + return i; + + return -1; + } + + private final int shouldSpDamageTgt(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + { + if (a.get(i).toString().startsWith("spDamageTgt")) + return i; + } + return -1; + } + + private final int shouldSpDamageCP(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + { + if (a.get(i).toString().startsWith("spDamageCP")) + return i; + } + return -1; + } + + private final int shouldSpDamageP(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + { + if (a.get(i).toString().startsWith("spDamageP")) + return i; + } + return -1; + } + + private final int shouldRebelSearch(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("SearchRebel")) + return i; + return -1; + } + + private final int shouldMercSearch(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("SearchMerc")) + return i; + return -1; + } + + private final int shouldMorph(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("Morph")) + return i; + + return -1; + } + + private final int shouldDevour(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("Devour")) + return i; + + return -1; + } + + private final int shouldSpellbomb(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("1, Sacrifice"))// + if(a.get(i).equals("1, Sacrifice "+c.getName()+": Draw a card.")) + return i; + return -1; + } + + private final int shouldModular(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + { + if (a.get(i).toString().startsWith("Modular")) + return i; + } + return -1; + } + + private final int shouldUntap(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("Untap")) + return i; + + return -1; + } + + private final int shouldFlashback(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("Flashback")) + return i; + + return -1; + } + + private final int shouldAbDamageCP(Card c) { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + { + if (a.get(i).toString().startsWith("abDamageCP")) + return i; + } + return -1; + } + + private final int shouldAbTgtPTPumpCard(Card c) + { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("abTgtPTPump")) + return i; + + return -1; + } + + private final int shouldSpPumpTgt(Card c){ + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("spPumpTgt")) + return i; + + return -1; + } + + private final int shouldSpDestroyTgt(Card c){ + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("spDestroyTgt:")) + return i; + + return -1; + } + + private final int shouldSpDrawCards(Card c){ + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("spDrawCards")) + return i; + + return -1; + } + + // spLoseLifeGainLife + private final int shouldSpLoseLifeGainLife(Card c){ + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith("spLoseLifeGainLife")) + return i; + + return -1; + } + + private final int shouldManaAbility(Card c){ + ArrayList a = c.getIntrinsicKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().contains(": add ")) + return i; + + return -1; + } + + + final private Card getCard2(final String cardName, final String owner) + { + //o should be Card object + Object o = map.get(cardName); + if(o == null) + throw new RuntimeException("CardFactory : getCard() invalid card name - " +cardName); + + final Card card = copyStats(o); + card.setOwner(owner); + card.setController(owner); + //may have to change the spell + //this is so permanents like creatures and artifacts have a "default" spell + if(! card.isLand()) + card.addSpellAbility(new Spell_Permanent(card)); + + //look for "Comes into play tapped." in the "no text" line + //of card.txt and add the appropriate code to make that happen + if(card.getKeyword().contains("Comes into play tapped.")) + { + card.addComesIntoPlayCommand(new Command() + { + private static final long serialVersionUID = 203335252453049234L; + + public void execute() + { + card.tap(); + } + }); + }//if "Comes into play tapped." + + //Creatures with simple, self-targeted mana-activated keyword adding abilities + //-1 means not found + while(shouldKPumpCard(card) != -1) + { + int n = shouldKPumpCard(card); + if(n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + + final String manaCost = k[0].substring(6); + final String keyword = k[1]; + + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -2904643243256352517L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.removeIntrinsicKeyword(keyword); + } + } + }; + + SpellAbility ability = new Ability_Activated(card, manaCost) + { + private static final long serialVersionUID = -630655617339584299L; + + public boolean canPlayAI() + { + //in case if a lifelink pump, allow multiple pumps + if (CardFactoryUtil.AI_doesCreatureAttack(card) && + !card.getKeyword().contains(keyword)) + { + Random r = new Random(); + if (r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed())) + return true; + else + return false; + } + else + return false; + } + public boolean canPlay() + { + if (CardFactoryUtil.canUseAbility(card) && AllZone.GameAction.isCardInPlay(card)) + return true; + else + return false; + } + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addIntrinsicKeyword(keyword); + + card.setAbilityUsed(card.getAbilityUsed()+1); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + } + }; + + String Desc = new String(); + Desc = cardName + " gains " + keyword + " until end of turn."; + + ability.setDescription(manaCost + " : " + Desc); + ability.setStackDescription(Desc); + + card.addSpellAbility(ability); + }//if (should pump card) + }//while - card has more pump keywords - Blistering Dieflyn has two pump keywords + + + //Creatures with simple, self-targeted mana-activated power and/or toughness + //pumping abilities + //is the card "self pumper" like Furnace Whelp - this card gets +1/+1 until end of turn? + //-1 means not found + while(shouldPTPumpCard(card) != -1) + { + int n = shouldPTPumpCard(card); + if(n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + final int attack[] = new int[1]; + final int defense[] = new int[1]; + + String k[] = parse.split(":"); + String pt[] = k[1].split("/"); + + final String manaCost = k[0].substring(7); + + + Integer na = card.getNetAttack(); + Integer nd = card.getNetDefense(); + + pt[0].replace("p", na.toString()); + pt[0].replace("t", nd.toString()); + + pt[1].replace("p", na.toString()); + pt[1].replace("t", nd.toString()); + + attack[0] = Integer.parseInt(pt[0].replace("+", "")); + defense[0] = Integer.parseInt(pt[1].replace("+", "")); + + + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -4518618729662470596L; + public void execute() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addTempAttackBoost(-attack[0]); + card.addTempDefenseBoost(-defense[0]); + } + } + }; + + SpellAbility ability = new Ability_Activated(card, manaCost) + { + private static final long serialVersionUID = -5718931378326228534L; + + public boolean canPlayAI() + { + if (card.getNetDefense() + defense[0] < 1) // no point if it would kill the creature outright + return false; + return CardFactoryUtil.AI_doesCreatureAttack(card); + } + public boolean canPlay() + { + if (CardFactoryUtil.canUseAbility(card) && AllZone.GameAction.isCardInPlay(card) && + !card.isFaceDown()) + return true; + else + return false; + } + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addTempAttackBoost(attack[0]); + card.addTempDefenseBoost(defense[0]); + + card.setAbilityUsed(card.getAbilityUsed()+1); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + } + }; + + String Desc = new String(); + Desc = cardName + " gets "; + if (attack[0] > 0) + Desc = Desc + "+" + attack[0]; + else + Desc = Desc + attack[0]; + Desc = Desc + "/"; + if (defense[0] > 0) + Desc = Desc + "+" + defense[0]; + else + Desc = Desc + defense[0]; + Desc = Desc + " until end of turn."; + + ability.setDescription(manaCost + " : " + Desc); + ability.setStackDescription(Desc); + + card.addSpellAbility(ability); + }//if (should pump card) + }//while - card has more pump keywords - Blistering Dieflyn has two pump keywords + + //Creatures with simple, self-targeted mana-activated power and/or toughness + //pumping plus keyword adding abilities + //is the card "self pumper" like Furnance Whelp - this card gets +1/+1 until end of turn? + //-1 means not found + while(shouldPTKPumpCard(card) != -1) + { + int n = shouldPTKPumpCard(card); + if(n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + final int attack[] = new int[1]; + final int defense[] = new int[1]; + + String k[] = parse.split(":"); + String ptk[] = k[1].split("/"); + + final String manaCost = k[0].substring(8); + + attack[0] = Integer.parseInt(ptk[0].replace("+", "")); + defense[0] = Integer.parseInt(ptk[1].replace("+", "")); + final String keyword = ptk[2]; + + + + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -3554196069508466753L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.removeIntrinsicKeyword(keyword); + card.addTempAttackBoost(-attack[0]); + card.addTempDefenseBoost(-defense[0]); + + } + } + }; + + SpellAbility ability = new Ability_Activated(card, manaCost) + { + private static final long serialVersionUID = 4196412133232530875L; + + public boolean canPlayAI() + { + if (card.getNetDefense() + defense[0] < 1) // no point if it would kill the creature outright + return false; + + if (card.getKeyword().contains(keyword)) + return false; + + return CardFactoryUtil.AI_doesCreatureAttack(card); + } + public boolean canPlay() + { + if (CardFactoryUtil.canUseAbility(card) && AllZone.GameAction.isCardInPlay(card) && + !card.isFaceDown()) + return true; + else + return false; + } + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addIntrinsicKeyword(keyword); + card.addTempAttackBoost(attack[0]); + card.addTempDefenseBoost(defense[0]); + + card.setAbilityUsed(card.getAbilityUsed()+1); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + } + }; + + + String Desc = new String(); + Desc = cardName + " gets "; + if (attack[0] > 0) + Desc = Desc + "+" + attack[0]; + else + Desc = Desc + attack[0]; + Desc = Desc + "/"; + if (defense[0] > 0) + Desc = Desc + "+" + defense[0]; + else + Desc = Desc + defense[0]; + Desc = Desc + " and gains " + keyword + " until end of turn."; + + ability.setDescription(manaCost + " : " + Desc); + ability.setStackDescription(Desc); + + card.addSpellAbility(ability); + }//if (should pump card) + }//while - card has more pump keywords - Blistering Dieflyn has two pump keywords + + //Creatures with simple, targeted keyword adding abilities + // costs may include "T" to indicate a tap cost + //-1 means not found + while(shouldTgtKPumpCard(card) != -1) + { + int n = shouldTgtKPumpCard(card); + if(n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + + String tmpCost = k[0].substring(9); + final String keyword = k[1]; + + boolean tapCost = false; + boolean tapOnlyCost = false; + + if (tmpCost.contains("T")) + { + tapCost = true; + tmpCost = tmpCost.replace("T", ""); + tmpCost = tmpCost.trim(); + if (tmpCost.length() == 0) + tapOnlyCost = true; + } + + final String manaCost = tmpCost; + + String tempDesc = new String(); + tempDesc = "Target creature gains " + keyword + " until end of turn."; + final String Desc = tempDesc; + + if (! tapCost) + { + final SpellAbility ability = new Ability_Activated(card, manaCost) + { + + private static final long serialVersionUID = -1118592153328758083L; + + public boolean canPlayAI() + { + //if(CardFactoryUtil.AI_doesCreatureAttack(card)) + // return false; + CardList list = getCreature(); + if (list.isEmpty()) + return false; + else + { + Random r = new Random(); + if (r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed())) + return true; + else + return false; + } + } + + + public boolean canPlay() + { + + if (CardFactoryUtil.canUseAbility(card) && AllZone.GameAction.isCardInPlay(card)&& + !card.isFaceDown()) + return true; + else + return false; + } + public void chooseTargetAI() + { + Card target = CardFactoryUtil.AI_getBestCreature(getCreature()); + setTargetCard(target); + } + CardList getCreature() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && + (!CardFactoryUtil.AI_doesCreatureAttack(c)) && CardFactoryUtil.canTarget(card, c) && + (! c.getKeyword().contains(keyword)) && + (! c.getKeyword().contains("Defender")) && + (! c.hasSickness() && keyword.equals("Haste")); + } + }); + // list.remove(card); // if mana-only cost, allow self-target + return list; + }//getCreature() + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + final Card[] creature = new Card[1]; + final Command EOT = new Command() + { + private static final long serialVersionUID = -8840812331316327448L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(creature[0])) + creature[0].removeExtrinsicKeyword(keyword); + } + }; + creature[0] = getTargetCard(); + creature[0].addExtrinsicKeyword(keyword); + card.setAbilityUsed(card.getAbilityUsed()+1); + AllZone.EndOfTurn.addUntil(EOT); + }//if (card is in play) + }//resolve() + };//SpellAbility + + ability.setDescription(manaCost + ":" + Desc); + ability.setStackDescription(Desc); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + card.addSpellAbility(ability); + } + if (tapOnlyCost) + { + final SpellAbility ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 5252594757468128739L; + + public boolean canPlayAI() + { + if(CardFactoryUtil.AI_doesCreatureAttack(card)) + return false; + + return getCreature().size() != 0; + } + public boolean canPlay() + { + boolean sick = true; + + if (!card.hasSickness() || !card.isCreature()) + sick = false; + + if (card.isUntapped() && CardFactoryUtil.canUseAbility(card) && AllZone.GameAction.isCardInPlay(card) + && !sick && !card.isFaceDown()) + return true; + else + return false; + } + public void chooseTargetAI() + { + card.tap(); + Card target = CardFactoryUtil.AI_getBestCreature(getCreature()); + setTargetCard(target); + } + CardList getCreature() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && + (!CardFactoryUtil.AI_doesCreatureAttack(c)) && + (! c.getKeyword().contains(keyword)) && + (! c.getKeyword().contains("Defender")) && + (! c.hasSickness() && keyword.equals("Haste")); + } + }); + list.remove(card); + return list; + }//getCreature() + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + final Card[] creature = new Card[1]; + final Command EOT = new Command() + { + private static final long serialVersionUID = 2134353417588894452L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(creature[0])) + creature[0].removeExtrinsicKeyword(keyword); + } + }; + creature[0] = getTargetCard(); + creature[0].addExtrinsicKeyword(keyword); + AllZone.EndOfTurn.addUntil(EOT); + }//if (card is in play) + }//resolve() + };//SpellAbility + + ability.setDescription("tap:" + Desc); + ability.setStackDescription(Desc); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + card.addSpellAbility(ability); + } + if (! tapOnlyCost && tapCost) + { + final SpellAbility ability = new Ability_Tap(card, manaCost) + { + private static final long serialVersionUID = 7593387152288440603L; + + public boolean canPlayAI() + { + if(CardFactoryUtil.AI_doesCreatureAttack(card)) + return false; + + return getCreature().size() != 0; + } + public boolean canPlay() + { + boolean sick = true; + + if (!card.hasSickness() || !card.isCreature()) + sick = false; + + if (card.isUntapped() && CardFactoryUtil.canUseAbility(card) && AllZone.GameAction.isCardInPlay(card) && + !sick && !card.isFaceDown()) + return true; + else + return false; + } + public void chooseTargetAI() + { + card.tap(); + Card target = CardFactoryUtil.AI_getBestCreature(getCreature()); + setTargetCard(target); + } + CardList getCreature() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && + (!CardFactoryUtil.AI_doesCreatureAttack(c)) && + (! c.getKeyword().contains(keyword)) && + (! c.getKeyword().contains("Defender")) && + (! c.hasSickness() && keyword.equals("Haste")); + } + }); + list.remove(card); + return list; + }//getCreature() + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card ,getTargetCard())) + { + final Card[] creature = new Card[1]; + final Command EOT = new Command() + { + private static final long serialVersionUID = 3532917180149273560L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(creature[0])) + creature[0].removeExtrinsicKeyword(keyword); + } + }; + creature[0] = getTargetCard(); + creature[0].addExtrinsicKeyword(keyword); + AllZone.EndOfTurn.addUntil(EOT); + }//if (card is in play) + }//resolve() + };//SpellAbility + + ability.setDescription(manaCost + ", tap:" + Desc); + ability.setStackDescription(Desc); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + card.addSpellAbility(ability); + } + } + }//while + + + //Creatures with self-regenerate abilities + //-1 means keyword "RegenerateMe" not found + while (shouldRegenerateMe(card) != -1) + { + int n = shouldRegenerateMe(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + final String manacost = k[1]; + + final Command untilEOT = new Command() { + private static final long serialVersionUID = -7619842476705984912L; + + public void execute() + { + card.setShield(0); + + } + }; + + final SpellAbility a1 = new Ability(card, manacost) { + public boolean canPlayAI() + { + if (CardFactoryUtil.AI_isMainPhase()) + { + if (CardFactoryUtil.AI_doesCreatureAttack(card)) + { + //"Fuzzy logic" to determine if using a regenerate ability might be helpful because + //we can't wait to decide to play this ability during combat, like the human can + //weight[] is a set of probability percentages to be averaged later + int weight[] = new int[3]; + + // cards with real keywords (flying, trample, etc) are probably more desireable + if (card.getKeyword().size() > 0) + weight[0] = 75; + else + weight[0] = 0; + + // if there are many cards in hand, then maybe it's not such a great idea to waste mana + CardList HandList = new CardList(AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer).getCards()); + + if (HandList.size() >= 4) + weight[1] = 25; + else + weight[1] = 75; + + // compare the highest converted mana cost of cards in hand to the number of lands + // if there's spare mana, then regeneration might be viable + int hCMC = 0; + for (int i = 0; i < HandList.size(); i++) + if (CardUtil.getConvertedManaCost(HandList.getCard(i).getManaCost()) > hCMC) + hCMC = CardUtil.getConvertedManaCost(HandList.getCard(i).getManaCost()); + + CardList LandList = new CardList(AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer).getCards()); + LandList = LandList.getType("Land"); + + //most regenerate abilities cost 2 or less + if (hCMC + 2 >= LandList.size()) + weight[2] = 50; + else + weight[2] = 0; + + // ultimately, it's random fate that dictates if this was the right play + int aw = (weight[0] + weight[1] + weight[2]) / 3; + Random r = new Random(); + if (r.nextInt(100) <= aw) + return true; + } + } + return false; + } + + public void resolve() + { + card.addShield(); + AllZone.EndOfTurn.addUntil(untilEOT); + } + }; //SpellAbility + + card.addSpellAbility(a1); + + String Desc = new String(); + Desc = "Regenerate " + cardName; + + a1.setDescription(manacost + " : " + Desc); + a1.setStackDescription(Desc); + + a1.setBeforePayMana(new Input_PayManaCost(a1)); + } //if (should RegenerateMe) + } //while - card has more RegenerateMe - Jungle Troll has two Regenerate keywords + + + if (shouldUntap(card) != -1) + { + int n = shouldUntap(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + final String manacost = k[1]; + + card.addSpellAbility(CardFactoryUtil.ability_Untap(card, manacost)); + } + } + + if (shouldSporeSaproling(card) != -1) + { + int n = shouldSporeSaproling(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + card.addSpellAbility(CardFactoryUtil.ability_Spore_Saproling(card)); + } + }//Spore Saproling + + if (shouldSpDamageTgt(card) != -1) + { + int n = shouldSpDamageTgt(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + card.clearSpellAbility(); + + String k[] = parse.split(":"); + + final boolean TgtCreature[] = {false}; + final boolean TgtPlayer[] = {false}; + final boolean TgtCP[] = {false}; + + if (k[0].contains("CP")) + TgtCP[0] = true; + else if (k[0].contains("P")) + TgtPlayer[0] = true; + else if (k[0].contains("C")) + TgtCreature[0] = true; + + // how much damage + final int NumDmg[] = {-1}; + final String NumDmgX[] = {"none"}; + + if (k[1].length() <= 2) // numeric + NumDmg[0] = Integer.parseInt(k[1]); + else // result of some sort of function + { + if (k[1].startsWith("Count$")) + { + String kk[] = k[1].split("\\$"); + NumDmgX[0] = kk[1]; + } + } + + //drawbacks and descriptions + final String DrawBack[] = {"none"}; + final String spDesc[] = {"none"}; + final String stDesc[] = {"none"}; + if (k.length > 2) + { + if (k[2].contains("Drawback$")) + { + String kk[] = k[2].split("\\$"); + DrawBack[0] = kk[1]; + if (k.length > 3) + spDesc[0] = k[3]; + if (k.length > 4) + stDesc[0] = k[4]; + } + else + { + if (k.length > 2) + spDesc[0] = k[2]; + if (k.length > 3) + stDesc[0] = k[3]; + } + } + + final SpellAbility DamageTgt = new Spell(card) + { + private static final long serialVersionUID = 7239608350643325111L; + private int damage; + + public int getNumDamage() + { + if (NumDmg[0] != -1) + return NumDmg[0]; + + if (! NumDmgX[0].equals("none")) + return CardFactoryUtil.xCount(card, NumDmgX[0]); + + return 0; + } + + boolean shouldTgtP() + { + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if (hand.size() >= 7) // anti-discard-at-EOT + return true; + + if(AllZone.Human_Life.getLife() < (10 - damage)) // if damage from this spell would drop the human to less than 10 life + return true; + + return false; + } + + Card chooseTgtC() + { + // Combo alert!! + PlayerZone compy = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList cPlay = new CardList(compy.getCards()); + if (cPlay.size() > 0) + for (int i = 0; i < cPlay.size(); i++) + if (cPlay.get(i).getName().equals("Stuffy Doll")) + return cPlay.get(i); + + PlayerZone human = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList hPlay = new CardList(human.getCards()); + hPlay = hPlay.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + // will include creatures already dealt damage + return c.isCreature() && ((c.getNetDefense() + c.getDamage()) <= damage) && CardFactoryUtil.canTarget(card, c); + } + } + ); + + if (hPlay.size() > 0) + { + Card best = hPlay.get(0); + + if (hPlay.size() > 1) + { + for (int i = 1; i < hPlay.size(); i++) + { + Card b = hPlay.get(i); + // choose best overall creature? + if (b.getSpellAbility().length > best.getSpellAbility().length || + b.getKeyword().size() > best.getKeyword().size() || + b.getNetAttack() > best.getNetAttack()) + best = b; + } + } + + return best; + } + + return null; + } + + public boolean canPlayAI() + { + damage = getNumDamage(); + + if (TgtCP[0] == true) + { + if (shouldTgtP() == true) + { + setTargetPlayer(Constant.Player.Human); + return true; + } + + Card c = chooseTgtC(); + if (c != null) + { + setTargetCard(c); + return true; + } + } + + if (TgtPlayer[0] == true) + { + setTargetPlayer(Constant.Player.Human); + return shouldTgtP(); + } + + if (TgtCreature[0] == true) + { + Card c = chooseTgtC(); + if (c != null) + { + setTargetCard(c); + return c != null; + } + } + + return false; + } + + public void resolve() + { + damage = getNumDamage(); + String tgtP = new String(); + + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + Card c = getTargetCard(); + //c.addDamage(damage); + AllZone.GameAction.addDamage(c, damage); + tgtP = c.getController(); + } + } + else + { + AllZone.GameAction.addDamage(getTargetPlayer(), damage); + tgtP = getTargetPlayer(); + } + + if (! DrawBack[0].equals("none")) + CardFactoryUtil.doDrawBack(DrawBack[0], damage, card.getController(), AllZone.GameAction.getOpponent(card.getController()), tgtP, card, getTargetCard()); + }// resolove + }; //spellAbility + if (! spDesc[0].equals("none")) + DamageTgt.setDescription(spDesc[0]); + else + { + String s; + s = card.getName() + " deals " + NumDmg[0] + " damage to target"; + if (TgtCP[0]) + s = s + " creature or player."; + else if (TgtCreature[0]) + s = s + " creature."; + else if (TgtPlayer[0]) + s = s + " player."; + DamageTgt.setDescription(s); + } + + if (! stDesc[0].equals("none")) + DamageTgt.setStackDescription(stDesc[0]); + else + DamageTgt.setStackDescription(card.getName() + " - deals " + NumDmg[0] + " damage."); + + if (TgtCP[0]) + DamageTgt.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(DamageTgt, true)); + else if (TgtCreature[0]) + DamageTgt.setBeforePayMana(CardFactoryUtil.input_targetCreature(DamageTgt)); + else if (TgtPlayer[0]) + DamageTgt.setBeforePayMana(CardFactoryUtil.input_targetPlayer(DamageTgt)); + + card.addSpellAbility(DamageTgt); + } + }// spDamageTgt + + + //Spell damage cards CP means Computer and Player (like shock, Lightning Bolt) + if (shouldSpDamageCP(card) != -1) + { + int n = shouldSpDamageCP(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + //System.out.println("parse: " + parse); + card.removeIntrinsicKeyword(parse); + + card.clearSpellAbility(); + + String k[] = parse.split(":"); + final String dmg = k[1]; + + card.addSpellAbility(CardFactoryUtil.spellability_spDamageCP(card, dmg)); + } + } + + if (shouldSpDamageP(card) != -1) + { + int n = shouldSpDamageP(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removePrevIntrinsicKeyword(parse); + + card.clearSpellAbility(); + + String k[] = parse.split(":"); + final String dmg = k[1]; + + card.addSpellAbility(CardFactoryUtil.spellability_spDamageP(card, dmg)); + } + }//SpDamageP + + if (shouldAbDamageCP(card) != -1) + { + int n = shouldAbDamageCP(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + + String tmpCost = k[0].substring(11); + + final int dmg[] = new int[1]; + dmg[0] = Integer.parseInt(k[1]); + + boolean tapCost = false; + boolean tapOnlyCost = false; + + if (tmpCost.contains("T")) + { + tapCost = true; + tmpCost = tmpCost.replace("T", ""); + tmpCost = tmpCost.trim(); + if (tmpCost.length() == 0) + tapOnlyCost = true; + } + + final String manaCost = tmpCost; + + String tempDesc = new String(); + tempDesc = cardName + " deals " + dmg[0] + " damage to target creature or player."; + final String Desc = tempDesc; + + if (! tapCost) + { + final SpellAbility ability = new Ability_Activated(card, manaCost) + { + private static final long serialVersionUID = -7560349014757367722L; + + public boolean canPlayAI() + { + Random r = new Random(); + if (r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed())) + return true; + else + return false; + } + + public void chooseTargetAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(dmg[0], card, true); + list.shuffle(); + + if(list.isEmpty() || AllZone.Human_Life.getLife() < 5 + dmg[0]) + setTargetPlayer(Constant.Player.Human); + else + setTargetCard(list.get(0)); + }//chooseTargetAI + + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) { + getTargetCard().addDamage(dmg[0]); + if (card.getKeyword().contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(card, dmg[0]); + for(int i=0; i < CardFactoryUtil.hasNumberEnchantments(card, "Guilty Conscience"); i++) + GameActionUtil.executeGuiltyConscienceEffects(card, dmg[0]); + } + } + else { + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(dmg[0]); + if (card.getKeyword().contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(card, dmg[0]); + for(int i=0; i < CardFactoryUtil.hasNumberEnchantments(card, "Guilty Conscience"); i++) + GameActionUtil.executeGuiltyConscienceEffects(card, dmg[0]); + } + }//resolve() + };//Ability_Activated + + ability.setDescription(manaCost + ": " + Desc); + ability.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(ability, true)); + card.addSpellAbility(ability); + }//!tapCost + + if (tapOnlyCost == true) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = -7560349014757367722L; + + public void chooseTargetAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(1, card, true); + list.shuffle(); + + if(list.isEmpty() || AllZone.Human_Life.getLife() < 5 + dmg[0]) + setTargetPlayer(Constant.Player.Human); + else + setTargetCard(list.get(0)); + }//chooseTargetAI + + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + getTargetCard().addDamage(dmg[0]); + if (card.getKeyword().contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(card, dmg[0]); + for(int i=0; i < CardFactoryUtil.hasNumberEnchantments(card, "Guilty Conscience"); i++) + GameActionUtil.executeGuiltyConscienceEffects(card, dmg[0]); + + } + } + else { + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(dmg[0]); + if (card.getKeyword().contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(card, dmg[0]); + for(int i=0; i < CardFactoryUtil.hasNumberEnchantments(card, "Guilty Conscience"); i++) + GameActionUtil.executeGuiltyConscienceEffects(card, dmg[0]); + + card.setDealtDmgToOppThisTurn(true); + } + }//resolve() + };//Ability_Tap + + ability.setDescription("tap: " + Desc); + ability.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(ability, true)); + card.addSpellAbility(ability); + }//tapOnlyCost + + if (! tapOnlyCost && tapCost) + { + final SpellAbility ability = new Ability_Tap(card, manaCost) + { + private static final long serialVersionUID = -7560349014757367722L; + + public void chooseTargetAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(1, card, true); + list.shuffle(); + + if(list.isEmpty() || AllZone.Human_Life.getLife() < 5 + dmg[0]) + setTargetPlayer(Constant.Player.Human); + else + setTargetCard(list.get(0)); + }//chooseTargetAI + + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) { + getTargetCard().addDamage(dmg[0]); + if (card.getKeyword().contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(card, dmg[0]); + for(int i=0; i < CardFactoryUtil.hasNumberEnchantments(card, "Guilty Conscience"); i++) + GameActionUtil.executeGuiltyConscienceEffects(card, dmg[0]); + } + } + else { + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(dmg[0]); + if (card.getKeyword().contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(card, dmg[0]); + for(int i=0; i < CardFactoryUtil.hasNumberEnchantments(card, "Guilty Conscience"); i++) + GameActionUtil.executeGuiltyConscienceEffects(card, dmg[0]); + + card.setDealtDmgToOppThisTurn(true); + } + }//resolve() + };//Ability_Tap + + ability.setDescription(manaCost + ", tap: " + Desc); + ability.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(ability, true)); + card.addSpellAbility(ability); + }//!tapOnlyCost && tapCost + }//n + }//AbDamageCP + + + while (shouldAbTgtPTPumpCard(card) != -1) + { + int n = shouldAbTgtPTPumpCard(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + String pt[] = k[1].split("/"); + + final int attack[] = new int[1]; + final int defense[] = new int[1]; + + attack[0] = Integer.parseInt(pt[0].replace("+", "")); + defense[0] = Integer.parseInt(pt[1].replace("+", "")); + + String tmpCost = k[0].substring(11); + boolean tapCost = false; + boolean tapOnlyCost = false; + + if (tmpCost.contains("T")) + { + tapCost = true; + tmpCost = tmpCost.replace("T", ""); + tmpCost = tmpCost.trim(); + if (tmpCost.length() == 0) + tapOnlyCost = true; + } + + final String manaCost = tmpCost; + //System.out.println("manaCost is " + manaCost + " for " + card.getName()); + + String tmpDesc = new String(); + tmpDesc = "Target creature gets "; + if (attack[0] > 0) + tmpDesc = tmpDesc + "+" + attack[0]; + else + tmpDesc = tmpDesc + attack[0]; + tmpDesc = tmpDesc + "/"; + if (defense[0] > 0) + tmpDesc = tmpDesc + "+" + defense[0]; + else + tmpDesc = tmpDesc + defense[0]; + tmpDesc = tmpDesc + " until end of turn."; + final String Desc = tmpDesc; + + if (!tapCost) + { + final SpellAbility ability = new Ability_Activated(card, manaCost) + { + private static final long serialVersionUID = -845173064437485113L; + + public boolean canPlay() + { + if (CardFactoryUtil.canUseAbility(card) && AllZone.GameAction.isCardInPlay(card) && + !card.isFaceDown()) + return true; + else + return false; + } + public boolean canPlayAI() + { + CardList list = getAttackers(); + if (list.isEmpty()) + return false; + else + { + if (list.get(0).getNetDefense() + defense[0] < 1) + return false; + Random r = new Random(); + if (r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed())) + { + setTargetCard(list.get(0)); + return true; + } + else + return false; + } + }//canPlayAI + public CardList getAttackers() + { + Card[] c = ComputerUtil.getAttackers().getAttackers(); + CardList list = new CardList(c); + + return list; + }//getAttacker + public void resolve() + { + if (AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + final Card[] creature = new Card[1]; + + creature[0] = getTargetCard(); + creature[0].addTempAttackBoost(attack[0]); + creature[0].addTempDefenseBoost(defense[0]); + + card.setAbilityUsed(card.getAbilityUsed()+1); + + final Command EOT = new Command() + { + private static final long serialVersionUID = 122944434978198700L; + + public void execute() + { + if (AllZone.GameAction.isCardInPlay(creature[0])) + { + creature[0].addTempAttackBoost(-attack[0]); + creature[0].addTempDefenseBoost(-defense[0]); + } + } + };//EOT + AllZone.EndOfTurn.addUntil(EOT); + } + }//resolve + };//ability + ability.setDescription(manaCost+": "+Desc); + ability.setStackDescription(Desc); + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + card.addSpellAbility(ability); + }//!tapCost + + if (tapOnlyCost) + { + final SpellAbility ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 6723777240105966031L; + + public boolean canPlay() + { + boolean sick = true; + if (!card.hasSickness() || !card.isCreature()) + sick = false; + if (card.isUntapped() && CardFactoryUtil.canUseAbility(card) && + AllZone.GameAction.isCardInPlay(card) && !sick && !card.isFaceDown()) + return true; + else + return false; + }//canPlay + public boolean canPlayAI() + { + CardList list = getAttackers(); + if (list.isEmpty()) + return false; + else + if (list.get(0).getNetDefense() + defense[0] < 1) + return false; + if (CardFactoryUtil.AI_doesCreatureAttack(card)) + return false; + setTargetCard(list.get(0)); + return true; + }//canPlayAI + public CardList getAttackers() + { + Card[] c = ComputerUtil.getAttackers().getAttackers(); + CardList list = new CardList(c); + list.remove(card); + return list; + } + public void resolve() + { + if (AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + final Card[] creature = new Card[1]; + + creature[0] = getTargetCard(); + creature[0].addTempAttackBoost(attack[0]); + creature[0].addTempDefenseBoost(defense[0]); + + final Command EOT = new Command() + { + private static final long serialVersionUID = -852905560563053752L; + + public void execute() + { + if (AllZone.GameAction.isCardInPlay(creature[0])) + { + creature[0].addTempAttackBoost(-attack[0]); + creature[0].addTempDefenseBoost(-defense[0]); + } + } + };//EOT + AllZone.EndOfTurn.addUntil(EOT); + } + }//resolve + };//ability + ability.setDescription("tap: "+Desc); + ability.setStackDescription(Desc); + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature_NoCost_TapAbility((Ability_Tap)ability)); + card.addSpellAbility(ability); + }//tapOnlyCost + + if (!tapOnlyCost && tapCost) + { + final SpellAbility ability = new Ability_Tap(card, manaCost) + { + private static final long serialVersionUID = 2749576299299014851L; + + public boolean canPlay() + { + boolean sick = true; + if (!card.hasSickness() || !card.isCreature()) + sick = false; + if (card.isUntapped() && CardFactoryUtil.canUseAbility(card) && + AllZone.GameAction.isCardInPlay(card) && !sick && !card.isFaceDown()) + return true; + else + return false; + }//canPlay + public boolean canPlayAI() + { + CardList list = getAttackers(); + if (list.isEmpty()) + return false; + else + if (list.get(0).getNetDefense() + defense[0] < 1) + return false; + if (CardFactoryUtil.AI_doesCreatureAttack(card)) + return false; + setTargetCard(list.get(0)); + return true; + }//canPlayAI + public CardList getAttackers() + { + Card[] c = ComputerUtil.getAttackers().getAttackers(); + CardList list = new CardList(c); + list.remove(card); + return list; + }//getAttackers + public void resolve() + { + if (AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + final Card[] creature = new Card[1]; + + creature[0] = getTargetCard(); + creature[0].addTempAttackBoost(attack[0]); + creature[0].addTempDefenseBoost(defense[0]); + + final Command EOT = new Command() + { + private static final long serialVersionUID = 8179097336678296338L; + + public void execute() + { + if (AllZone.GameAction.isCardInPlay(creature[0])) + { + creature[0].addTempAttackBoost(-attack[0]); + creature[0].addTempDefenseBoost(-defense[0]); + } + } + };//EOT + AllZone.EndOfTurn.addUntil(EOT); + } + }//resolve + };//ability + ability.setDescription(manaCost+ ", tap: "+Desc); + ability.setStackDescription(Desc); + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + card.addSpellAbility(ability); + }//!tapCost + } + }//while + + // Generic destroy target card + if (shouldSpDestroyTgt(card) != -1) + { + int n = shouldSpDestroyTgt(card); + + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + String Targets = k[1]; // Artifact, Creature, Enchantment, Land, Permanent, White, Blue, Black, Red, Green, Colorless, MultiColor + // non-Artifact, non-Creature, non-Enchantment, non-Land, non-Permanent, + //non-White, non-Blue, non-Black, non-Red, non-Green, non-Colorless, non-MultiColor + final String Tgts[] = Targets.split(","); + + String tmpDesc = card.getText().substring(15); + int i = tmpDesc.indexOf("."); + tmpDesc = tmpDesc.substring(0, i); + final String Selec = new String("Select target " + tmpDesc + " to destroy."); + + final boolean NoRegen = (k.length == 3); + + card.clearSpellAbility(); + + final SpellAbility spDstryTgt = new Spell(card) + { + private static final long serialVersionUID = 142142142142L; + + public boolean canPlayAI() + { + CardList results = new CardList(); + CardList choices = getTargets(); + + if (choices.size() > 0) + { + for (int i = 0; i < Tgts.length; i++) + { + if (Tgts[i].equals("Artifact")) { + if (CardFactoryUtil.AI_getBestArtifact(choices) != null) + results.add(CardFactoryUtil.AI_getBestArtifact(choices)); + } + else if (Tgts[i].equals("Creature")) { + if (CardFactoryUtil.AI_getBestCreature(choices) != null) + results.add(CardFactoryUtil.AI_getBestCreature(choices)); + } + else if (Tgts[i].equals("Enchantment")) { + if (CardFactoryUtil.AI_getBestEnchantment(choices, card, true) != null) + results.add(CardFactoryUtil.AI_getBestEnchantment(choices, card, true)); + } + else if (Tgts[i].equals("Land")) { + if (CardFactoryUtil.AI_getBestLand(choices) != null) + results.add(CardFactoryUtil.AI_getBestLand(choices)); + } + else if (Tgts[i].equals("Permanent")){ + if (CardFactoryUtil.AI_getMostExpensivePermanent(choices, card, true) != null) + results.add(CardFactoryUtil.AI_getMostExpensivePermanent(choices, card, true)); + } + } + } + + + if (results.size() > 0) + { + results.shuffle(); + setTargetCard(results.get(0)); + return true; + } + return false; + } + CardList getTargets() + { + CardList tmpList = new CardList(); + tmpList.addAll(AllZone.Human_Play.getCards()); + tmpList.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (CardFactoryUtil.canTarget(card, c)); + } + }); + + return tmpList.getValidCards(Tgts); + } + public void resolve() + { + if (AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + if (NoRegen) + AllZone.GameAction.destroyNoRegeneration(getTargetCard()); + else + AllZone.GameAction.destroy(getTargetCard()); + + } + }; //SpDstryTgt + + Input InGetTarget = new Input() + { + private static final long serialVersionUID = -142142142142L; + + public void showMessage() + { + CardList allCards = new CardList(); + allCards.addAll(AllZone.Human_Play.getCards()); + allCards.addAll(AllZone.Computer_Play.getCards()); + allCards.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (CardFactoryUtil.canTarget(card, c)); + } + }); + + CardList choices = allCards.getValidCards(Tgts); + stopSetNext(CardFactoryUtil.input_targetSpecific(spDstryTgt, choices, Selec, true)); + } + };//InGetTarget + + //card.clearSpellAbility(); + spDstryTgt.setBeforePayMana(InGetTarget); + spDstryTgt.setDescription(card.getText()); + card.setText(""); + card.addSpellAbility(spDstryTgt); + }//spDestroyTgt + + if (shouldSpDrawCards(card) != -1) + { + int n = shouldSpDrawCards(card); + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + + final boolean Tgt[] = {false}; + Tgt[0] = k[0].contains("Tgt"); + + final int NumCards[] = {-1}; + final String NumCardsType[] = {"none"}; + final boolean NumCardsTypeYouCtrl[] = {false}; + final boolean NumCardsTypeInPlay[] = {false}; + final boolean NumCardsTypeInYourYard[] = {false}; + final boolean NumCardsTypeInAllYards[] = {false}; + final boolean NumCardsDomain[] = {false}; + if (k[1].length() == 1) + NumCards[0] = Integer.parseInt(k[1]); + else + { + if (k[1].startsWith("NumCardsType")) + { + String kk[] = k[1].split("/"); + NumCardsType[0] = kk[1]; + NumCardsTypeYouCtrl[0] = kk[2].equals("YouCtrl"); + NumCardsTypeInPlay[0] = kk[2].equals("InPlay"); + NumCardsTypeInYourYard[0] = kk[2].equals("InYourYard"); + NumCardsTypeInAllYards[0] = kk[2].equals("InAllYards"); + } + NumCardsDomain[0] = k[1].equals("Domain"); + } + + final int NumDiscard[] = {0}; + final String UnlessDiscardType[] = {"none"}; + final boolean AtRandom[] = {false}; + + final int NumLoseLife[] = {0}; + + final int NumToLibrary[] = {0}; + final String LibraryPosition[] = {"none"}; + + final int NumOppDraw[] = {0}; + + if (k.length > 2) + { + if (k[2].contains("Discard")) + { + String kk[] = k[2].split("/"); + if (kk[1].equals("X")) + NumDiscard[0] = -1; + else + NumDiscard[0] = Integer.parseInt(kk[1]); + + if (kk.length > 2) + { + if (kk[2].equals("UnlessDiscardType")) + UnlessDiscardType[0] = kk[3]; + + AtRandom[0] = kk[2].equals("AtRandom"); + } + } + + if (k[2].contains("LoseLife")) + { + String kk[] = k[2].split("/"); + if (kk[1].equals("X")) + NumLoseLife[0] = -1; + else + NumLoseLife[0] = Integer.parseInt(kk[1]); + } + + if (k[2].contains("NumToLibrary")) + { + String kk[] = k[2].split("/"); + if (kk[1].equals("X")) + NumToLibrary[0] = -1; + else + NumToLibrary[0] = Integer.parseInt(kk[1]); + LibraryPosition[0] = kk[2]; + } + + if (k[2].contains("NumOppDraw")) + { + String kk[] = k[2].split("/"); + if (kk[1].equals("X")) + NumOppDraw[0] = -1; + else + NumOppDraw[0] = Integer.parseInt(kk[1]); + } + } + + final SpellAbility spDraw = new Spell(card) + { + private static final long serialVersionUID = -7049779241008089696L; + + public int getNumCards() + { + if (NumCards[0] != -1) + return NumCards[0]; + + int n = 0; + + String cardController = card.getController(); + PlayerZone myPlay = AllZone.getZone(Constant.Zone.Play, cardController); + PlayerZone opPlay = AllZone.getZone(Constant.Zone.Play, AllZone.GameAction.getOpponent(cardController)); + + PlayerZone myYard = AllZone.getZone(Constant.Zone.Graveyard, cardController); + PlayerZone opYard = AllZone.getZone(Constant.Zone.Graveyard, AllZone.GameAction.getOpponent(cardController)); + + CardList AllCards = new CardList(); + + if (! NumCardsType[0].equals("none")) + { + if (NumCardsTypeInYourYard[0] == false) + AllCards.addAll(myYard.getCards()); + + if (NumCardsTypeInAllYards[0] == false) + { + AllCards.addAll(myYard.getCards()); + AllCards.addAll(opYard.getCards()); + } + + if (NumCardsTypeYouCtrl[0] == true) + AllCards.addAll(myPlay.getCards()); + + if (NumCardsTypeInPlay[0] == true) + { + AllCards.addAll(myPlay.getCards()); + AllCards.addAll(opPlay.getCards()); + } + + AllCards = AllCards.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if (c.getType().contains(NumCardsType[0])) + return true; + + return false; + } + }); + + n = AllCards.size(); + } + if (NumCardsDomain[0] == true) + { + AllCards.addAll(myPlay.getCards()); + String basic[] = {"Forest", "Plains", "Mountain", "Island", "Swamp"}; + + for(int i = 0; i < basic.length; i++) + if (! AllCards.getType(basic[i]).isEmpty()) + n++; + } + + if (NumDiscard[0] == -1) + NumDiscard[0] = n; + if (NumLoseLife[0] == -1) + NumLoseLife[0] = n; + if (NumToLibrary[0] == -1) + NumToLibrary[0] = n; + if (NumOppDraw[0] == -1) + NumOppDraw[0] = n; + + return n; + } + + public boolean canPlayAI() + { + int n = getNumCards(); + int h = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer).size(); + Random r = new Random(); + + if (((h + n) - (NumDiscard[0] + NumToLibrary[0]) <= 7) + && (AllZone.GameAction.getPlayerLife(Constant.Player.Computer).getLife() - NumLoseLife[0]) >= 8 + && (r.nextInt(10) > 4)) + { + setTargetPlayer(Constant.Player.Computer); + return true; + } + + return false; + } + + public void resolve() + { + int n = getNumCards(); + + String TgtPlayer = card.getController(); + if (Tgt[0]) + TgtPlayer = getTargetPlayer(); + + for (int i=0; i < n; i++) + AllZone.GameAction.drawCard(TgtPlayer); + + if (NumDiscard[0] > 0) + { + if (!UnlessDiscardType[0].equals("none")) + AllZone.GameAction.discardUnless(TgtPlayer, NumDiscard[0], UnlessDiscardType[0]); + else if (AtRandom[0] == true) + AllZone.GameAction.discardRandom(TgtPlayer, NumDiscard[0]); + else + AllZone.GameAction.discard(TgtPlayer, NumDiscard[0]); + } + + if (NumLoseLife[0] > 0) + AllZone.GameAction.getPlayerLife(TgtPlayer).subtractLife(NumLoseLife[0]); + + if (NumToLibrary[0] > 0) + AllZone.GameAction.handToLibrary(TgtPlayer, NumToLibrary[0], LibraryPosition[0]); + + if (NumOppDraw[0] > 0) + for (int i = 0; i < NumOppDraw[0]; i++) + AllZone.GameAction.drawCard(AllZone.GameAction.getOpponent(TgtPlayer)); + } + }; + + if (Tgt[0]) + spDraw.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spDraw)); + + spDraw.setDescription(card.getText()); + card.setText(""); + card.clearSpellAbility(); + card.addSpellAbility(spDraw); + }//spDrawCards + + //Spell gain life lose life cards (like Soul Feast) + if (shouldSpLoseLifeGainLife(card) != -1) + { + int n = shouldSpLoseLifeGainLife(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + card.clearSpellAbility(); + + String k[] = parse.split(":"); + final String lfdmg = k[1]; + + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -8277174319360648715L; + + public void resolve() + { + final int n = Integer.parseInt(lfdmg); + + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(n); + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.addLife(n); + }//resolve() + };//SpellAbility + + spell.setChooseTargetAI(CardFactoryUtil.AI_targetHuman()); + spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell)); + + card.clearSpellAbility(); + card.addSpellAbility(spell); + + return card; + } + }// spLoseLifeGainLife + + if (shouldRebelSearch(card) != -1) + { + int n = shouldRebelSearch(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + final String manacost = k[1]; + + card.addSpellAbility(CardFactoryUtil.ability_Rebel_Search(card, manacost)); + } + }//Rebel search + + if (shouldMercSearch(card) != -1) + { + int n = shouldMercSearch(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + final String manacost = k[1]; + + card.addSpellAbility(CardFactoryUtil.ability_Merc_Search(card, manacost)); + } + }//Merc search + + if (shouldMorph(card) != -1) + { + int n = shouldMorph(card); + if (n != -1) + { + card.setPrevIntrinsicKeyword(card.getIntrinsicKeyword()); + card.setPrevType(card.getType()); + + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + final String manacost = k[1]; + + int attack = card.getBaseAttack(); + int defense = card.getBaseDefense(); + + String orgManaCost = card.getManaCost(); + + card.addSpellAbility(CardFactoryUtil.ability_Morph_Up(card, manacost, orgManaCost, attack, defense)); + card.addSpellAbility(CardFactoryUtil.ability_Morph_Down(card)); + } + }//Morph + + if (shouldFlashback(card) != -1) + { + int n = shouldFlashback(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + //card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + + final String manacost = k[1]; + + card.addSpellAbility(CardFactoryUtil.ability_Flashback(card, manacost,"0")); + } + }//flashback + + + + + if (shouldDevour(card) != -1) + { + int n = shouldDevour(card); + if (n != -1) + { + + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + final String magnitude = k[1]; + + + final int multiplier = Integer.parseInt(magnitude); + //final String player = card.getController(); + final int[] numCreatures = new int[1]; + + + final SpellAbility devour = new Spell(card) + { + private static final long serialVersionUID = 4888189840817163900L; + + public void resolve() + { + int totalCounters = numCreatures[0] * multiplier; + card.addCounter(Counters.P1P1, totalCounters); + + if(card.getName().equals("Skullmulcher")) + { + for(int i=0;i= 2) + { + attack[0] = Integer.parseInt(ptk[0].replace("+", "")); + defense[0] = Integer.parseInt(ptk[1].replace("+", "")); + } + + if (ptk.length == 3) + keyword[0] = ptk[2]; + +/* String Desc = new String(); + Desc = "Target creature "; + if (attack[0] != 0 || defense[0] != 0) + { + Desc = Desc + "gets "; + if (attack[0] > 0) + Desc = Desc + "+" + attack[0]; + else + Desc = Desc + attack[0]; + Desc = Desc + "/"; + if (defense[0] > 0) + Desc = Desc + "+" + defense[0]; + else + Desc = Desc + defense[0]; + + if (! keyword[0].equals("none")) + Desc = Desc + " and "; + } + if (! keyword[0].equals("none")) + Desc = Desc + "gains " + keyword; + + Desc = Desc + " until end of turn."; +*/ + SpellAbility spPump = new Spell(card) + { + private static final long serialVersionUID = 42244224L; + + public boolean canPlayAI() + { + Card c = getAttacker(); + if (c != null) + { + setTargetCard(c); + return true; + } + else + return false; + } + + public Card getAttacker() + { + Combat c = ComputerUtil.getAttackers(); + + CardList list = new CardList(c.getAttackers()); + CardListUtil.sortFlying(list); + + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (CardFactoryUtil.canTarget(card, c)) && + (! c.getKeyword().contains(keyword[0])) && + (! c.hasSickness() && keyword[0].equals("Haste")); + } + }); + + if (list.size() > 0) + return list.get(0); + else + return null; + } + + public void resolve() + { + final Card[] target = new Card[1]; + + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -42244224L; + + public void execute() + { + if (AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-attack[0]); + target[0].addTempDefenseBoost(-defense[0]); + + if (!keyword[0].equals("none")) + target[0].removeExtrinsicKeyword(keyword[0]); + } + } + }; + + target[0] = getTargetCard(); + if (AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0])) + { + target[0].addTempAttackBoost(attack[0]); + target[0].addTempDefenseBoost(defense[0]); + if (!keyword[0].equals("none")) + target[0].addExtrinsicKeyword(keyword[0]); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + } + }; + + spPump.setBeforePayMana(CardFactoryUtil.input_targetCreature(spPump)); + //spPump.setDescription(Desc); + card.clearSpellAbility(); + card.addSpellAbility(spPump); + } + + + while (shouldManaAbility(card) != -1) + { + int n = shouldManaAbility(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + final Ability_Mana ability = new Ability_Mana(card, parse) + { + private static final long serialVersionUID = -113811381138L; + + public boolean canPlayAI() + { + return false; + } + }; + //ability.setDescription(parse); + card.addSpellAbility(ability); + } + } + + //////////////////////////////////////////////////////////////// + + if(card.getKeyword().contains("When this card comes into play, draw a card.")) + { + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + }//resolve() + };//SpellAbility + Command intoPlay = new Command() + { + + private static final long serialVersionUID = 1707519783018941582L; + + public void execute() + { + ability.setStackDescription(card.getName() + " - " +card.getController() +" draws a card."); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + }//end if + + + //*************** START *********** START ************************** + if( cardName.equals("Burst of Speed") || + cardName.equals("Chorus of Woe") || + cardName.equals("Dance of Shadows") || + cardName.equals("Desperate Charge") || + cardName.equals("Glorious Charge") || + cardName.equals("Kjeldoran War Cry") || + cardName.equals("Magnify") || + cardName.equals("Nature's Cloak") || + cardName.equals("Nocturnal Raid") || + cardName.equals("Overrun") || + cardName.equals("Path of Anger's Flame") || + cardName.equals("Resuscitate") || + cardName.equals("Righteous Charge") || + cardName.equals("Scare Tactics") || + cardName.equals("Shield Wall") || + cardName.equals("Solidarity") || + cardName.equals("Steadfastness") || + cardName.equals("Tortoise Formation") || + cardName.equals("Tromp the Domains") || + cardName.equals("Valorous Charge") || + cardName.equals("Virtuous Charge") || + cardName.equals("Vitalizing Wind") || + cardName.equals("Warrior's Charge") || + cardName.equals("Warrior's Honor")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -5844664906503221006L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public Card getAttacker() + { + //target creatures that is going to attack + Combat c = ComputerUtil.getAttackers(); + Card[] att = c.getAttackers(); + if(cardName.equals("Dance of Shadows") || + cardName.equals("Overrun") || + cardName.equals("Tromp the Domains")) + { + if (att.length > 2) // Effect best used with a few creatures + return att[0]; + else + return null; + } + if(cardName.equals("Burst of Speed") || + cardName.equals("Chorus of Woe") || + cardName.equals("Desperate Charge") || + cardName.equals("Glorious Charge") || + cardName.equals("Kjeldoran War Cry") || + cardName.equals("Magnify") || + cardName.equals("Nature's Cloak") || + cardName.equals("Nocturnal Raid") || + cardName.equals("Path of Anger's Flame") || + cardName.equals("Resuscitate") || + cardName.equals("Righteous Charge") || + cardName.equals("Scare Tactics") || + cardName.equals("Shield Wall") || + cardName.equals("Solidarity") || + cardName.equals("Steadfastness") || + cardName.equals("Tortoise Formation") || + cardName.equals("Valorous Charge") || + cardName.equals("Vitalizing Wind") || + cardName.equals("Virtuous Charge") || + cardName.equals("Warrior's Charge") || + cardName.equals("Warrior's Honor")) + { + if (att.length > 1) // Effect best used on at least a couple creatures + return att[0]; + else + return null; + } + return null; + }//getAttacker() + + int getPowerBoost() + { + if(cardName.equals("Tromp the Domains")) + return getTtDBoost(); + + if(cardName.equals("Kjeldoran War Cry")) + return getKWCBoost(); + + if(cardName.equals("Chorus of Woe") || + cardName.equals("Dance of Shadows") || + cardName.equals("Glorious Charge") || + cardName.equals("Magnify") || + cardName.equals("Scare Tactics") || + cardName.equals("Virtuous Charge") || + cardName.equals("Warrior's Charge") || + cardName.equals("Warrior's Honor")) + return 1; + + if(cardName.equals("Desperate Charge") || + cardName.equals("Nocturnal Raid") || + cardName.equals("Path of Anger's Flame") || + cardName.equals("Righteous Charge") || + cardName.equals("Valorous Charge")) + return 2; + + if(cardName.equals("Overrun")) + return 3; + + if(cardName.equals("Vitalizing Wind")) + return 7; + + return 0; + }//getPowerBoost() + + int getToughBoost() + { + if(cardName.equals("Tromp the Domains")) + return getTtDBoost(); + + if(cardName.equals("Kjeldoran War Cry")) + return getKWCBoost(); + + if(cardName.equals("Glorious Charge") || + cardName.equals("Magnify") || + cardName.equals("Virtuous Charge") || + cardName.equals("Warrior's Charge") || + cardName.equals("Warrior's Honor")) + return 1; + + if(cardName.equals("Righteous Charge") || + cardName.equals("Shield Wall")) + return 2; + + if(cardName.equals("Overrun") || + cardName.equals("Steadfastness")) + return 3; + + if(cardName.equals("Solidarity")) + return 5; + + if(cardName.equals("Vitalizing Wind")) + return 7; + + return 0; + }//getToughBoost() + + String getKeywordBoost() + { + if(cardName.equals("Burst of Speed")) + return "Haste"; + + if(cardName.equals("Overrun") || + cardName.equals("Tromp the Domains")) + return "Trample"; + + if(cardName.equals("Dance of Shadows")) + return "Fear"; + + if(cardName.equals("Nature's Cloak")) + return "Forestwalk"; + + if(cardName.equals("Resuscitate")) + return "RegenerateMe:1"; + + if(cardName.equals("Tortoise Formation")) + return "Shroud"; + + return "None"; + }//getKeywordBoost() + + int getTtDBoost() // Tromp the Domains - +1/+1 for each basic land you control + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList land = new CardList(play.getCards()); + + String basic[] = {"Forest", "Plains", "Mountain", "Island", "Swamp"}; + int count = 0; + + for (int i = 0; i < basic.length; i++) + { + CardList c = land.getType(basic[i]); + if (!c.isEmpty()) + count++; + } + return count; + }//getTtDBoost + + int getKWCBoost() // Kjeldoran War Cry - +X/+X, X = 1 + Num(KWC in All Graveyards) + { + PlayerZone hYard = AllZone.getZone(Constant.Zone.Graveyard, Constant.Player.Human); + PlayerZone cYard = AllZone.getZone(Constant.Zone.Graveyard, Constant.Player.Computer); + CardList allYards = new CardList(); + + allYards.addAll(hYard.getCards()); + allYards.addAll(cYard.getCards()); + allYards = allYards.getName("Kjeldoran War Cry"); + + return allYards.size() + 1; + }//getKWCBoost + + public void resolve() + { + + final int pboost = getPowerBoost(); + final int tboost = getToughBoost(); + final String kboost = getKeywordBoost(); + + CardList list = new CardList(); + + if (cardName.equals("Burst of Speed") || // Creatures "you" Control + cardName.equals("Chorus of Woe") || + cardName.equals("Dance of Shadows") || + cardName.equals("Desperate Charge") || + cardName.equals("Glorious Charge") || + cardName.equals("Kjeldoran War Cry") || + cardName.equals("Nature's Cloak") || + cardName.equals("Overrun") || + cardName.equals("Path of Anger's Flame") || + cardName.equals("Resuscitate") || + cardName.equals("Righteous Charge") || + cardName.equals("Scare Tactics") || + cardName.equals("Shield Wall") || + cardName.equals("Solidarity") || + cardName.equals("Steadfastness") || + cardName.equals("Tortoise Formation") || + cardName.equals("Virtuous Charge") || + cardName.equals("Vitalizing Wind") || + cardName.equals("Warrior's Charge") || + cardName.equals("Warrior's Honor")) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + list.addAll(play.getCards()); + + if(cardName.equals("Nature's Cloak")) + list = list.getColor("G"); + } + + if (cardName.equals("Magnify") || // All Creatures in Play + cardName.equals("Nocturnal Raid") || // All Black Creatures in Play + cardName.equals("Valorous Charge")) // All White Creatures in Play + { + PlayerZone human = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + PlayerZone comp = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + + list.addAll(human.getCards()); + list.addAll(comp.getCards()); + + if(cardName.equals("Nocturnal Raid")) + list = list.getColor("B"); + + if(cardName.equals("Valorous Charge")) + list = list.getColor("W"); + } + + for(int i = 0; i < list.size(); i++) + { + final Card[] target = new Card[1]; + target[0] = list.get(i); + + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 5063161656920609389L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-pboost); + target[0].addTempDefenseBoost(-tboost); + + if(!kboost.equals("None")) + target[0].removeExtrinsicKeyword(kboost); + } + } + };//Command + + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(pboost); + target[0].addTempDefenseBoost(tboost); + + if(!kboost.equals("None")) + target[0].addExtrinsicKeyword(kboost); + + AllZone.EndOfTurn.addUntil(untilEOT); + }//if + }//for + }//resolve() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Elspeth, Knight-Errant")) + { + //computer only plays ability 1 and 3, gain life and put X\X token into play + final int turn[] = new int[1]; + turn[0] = -1; + + final Card card2 = new Card() + { + public void addDamage(int n) + { + subtractCounter(Counters.LOYALTY, n); + AllZone.GameAction.checkStateEffects(); + } + }; + card2.addCounter(Counters.LOYALTY, 4); + + card2.setOwner(owner); + card2.setController(owner); + + card2.setName(card.getName()); + card2.setType(card.getType()); + card2.setManaCost(card.getManaCost()); + card2.addSpellAbility(new Spell_Permanent(card2)); + + //ability2: target creature gets +3/+3 and flying until EOT + final SpellAbility ability2 = new Ability(card2, "0") + { + + public void resolve() + { + + card2.addCounter(Counters.LOYALTY, 1); + + turn[0] = AllZone.Phase.getTurn(); + + final Command eot = new Command() + { + private static final long serialVersionUID = 94488363210770877L; + + public void execute() + { + Card c = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(c)) + { + c.addTempAttackBoost(-3); + c.addTempDefenseBoost(-3); + c.removeExtrinsicKeyword("Flying"); + } + }//execute() + };//Command + + Card c = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card2, c)) + { + c.addTempAttackBoost(3); + c.addTempDefenseBoost(3); + c.addExtrinsicKeyword("Flying"); + + AllZone.EndOfTurn.addUntil(eot); + } + }//resolve() + + public boolean canPlayAI() + { + return false; + } + + public boolean canPlay() + { + @SuppressWarnings("unused") // library + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card2.getController()); + + return 0 < card2.getCounters(Counters.LOYALTY) && + AllZone.getZone(card2).is(Constant.Zone.Play) && + turn[0] != AllZone.Phase.getTurn() && + AllZone.Phase.getActivePlayer().equals(card2.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn"); + + }//canPlay() + };//SpellAbility ability2 + + ability2.setBeforePayMana(new Input() + { + private static final long serialVersionUID = 9062830120519820799L; + + int check = -1; + public void showMessage() + { + if(check != AllZone.Phase.getTurn()) + { + check = AllZone.Phase.getTurn(); + turn[0] = AllZone.Phase.getTurn(); + + + AllZone.Stack.push(ability2); + } + stop(); + }//showMessage() + }); + + + + //ability3 + final SpellAbility ability3 = new Ability(card2, "0") + { + public void resolve() + { + card2.subtractCounter(Counters.LOYALTY, 8); + turn[0] = AllZone.Phase.getTurn(); + + //make all permanents in play/hand/library and graveyard + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + + CardList list = new CardList(); + list.addAll(play.getCards()); + list.addAll(hand.getCards()); + list.addAll(library.getCards()); + list.addAll(grave.getCards()); + + + for (int i=0;i < list.size(); i++) + { + Card c = list.get(i); + if (c.isPermanent() && !c.isPlaneswalker()) + { + c.addExtrinsicKeyword("Indestructible"); + } + + } + + } + public boolean canPlay() + { + return 8 <= card2.getCounters(Counters.LOYALTY) && AllZone.getZone(card2).is(Constant.Zone.Play) && + turn[0] != AllZone.Phase.getTurn() && + AllZone.Phase.getActivePlayer().equals(card2.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn"); + }//canPlay() + public boolean canPlayAI() + { + return true; + } + }; + ability3.setBeforePayMana(new Input() + { + private static final long serialVersionUID = -2054686425541429389L; + + int check = -1; + public void showMessage() + { + if(check != AllZone.Phase.getTurn()) + { + check = AllZone.Phase.getTurn(); + turn[0] = AllZone.Phase.getTurn(); + AllZone.Stack.push(ability3); + } + stop(); + }//showMessage() + }); + + //ability 1: create white 1/1 token + final SpellAbility ability1 = new Ability(card2, "0") + { + public void resolve() + { + card2.addCounter(Counters.LOYALTY, 1); + turn[0] = AllZone.Phase.getTurn(); + + Card c = new Card(); + + c.setOwner(card2.getController()); + c.setController(card2.getController()); + + c.setManaCost("W"); + c.setToken(true); + + c.setImageName("W 1 1 Soldier"); + c.setName("Soldier"); + c.addType("Creature"); + c.addType("Soldier"); + c.setBaseAttack(1); + c.setBaseDefense(1); + //AllZone.GameAction.getPlayerLife(card.getController()).addLife(2); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card2.getController()); + play.add(c); + } + public boolean canPlayAI() + { + if(ability3.canPlay() && ability3.canPlayAI()) { + return false; + } else + { + return true; + } + } + public boolean canPlay() + { + return 0 < card2.getCounters(Counters.LOYALTY) && AllZone.getZone(card2).is(Constant.Zone.Play) && + turn[0] != AllZone.Phase.getTurn() && + AllZone.Phase.getActivePlayer().equals(card2.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn"); + }//canPlay() + };//SpellAbility ability1 + + ability1.setBeforePayMana(new Input() + { + private static final long serialVersionUID = -7892114885686285881L; + + int check = -1; + public void showMessage() + { + if(check != AllZone.Phase.getTurn()) + { + check = AllZone.Phase.getTurn(); + turn[0] = AllZone.Phase.getTurn(); + AllZone.Stack.push(ability1); + } + stop(); + }//showMessage() + }); + + ability1.setDescription("+1: Put a white 1/1 Soldier creature token into play."); + ability1.setStackDescription("Elspeth, Knight-Errant - put 1/1 token into play."); + card2.addSpellAbility(ability1); + + ability2.setDescription("+1: Target creature gets +3/+3 and gains flying until end of turn."); + ability2.setStackDescription("Elspeth, Knight-Errant - creature gets +3/+3 and Flying until EOT."); + ability2.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability2)); + + card2.addSpellAbility(ability2); + + ability3.setDescription("-8: For the rest of the game, artifacts, creatures, enchantments, and lands you control are indestructible."); + ability3.setStackDescription("Elspeth, Knight-Errant - Make everything indestructible."); + card2.addSpellAbility(ability3); + + return card2; + } + //*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Nissa Revane")) + { + final int turn[] = new int[1]; + turn[0] = -1; + + final Card card2 = new Card() + { + public void addDamage(int n) + { + subtractCounter(Counters.LOYALTY, n); + AllZone.GameAction.checkStateEffects(); + } + }; + card2.addCounter(Counters.LOYALTY, 2); + + card2.setOwner(owner); + card2.setController(owner); + + card2.setName(card.getName()); + card2.setType(card.getType()); + card2.setManaCost(card.getManaCost()); + card2.addSpellAbility(new Spell_Permanent(card2)); + + //ability2: gain 2 life for each elf controlled + final SpellAbility ability2 = new Ability(card2, "0") + { + + public void resolve() + { + + card2.addCounter(Counters.LOYALTY, 1); + + turn[0] = AllZone.Phase.getTurn(); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card2.getController()); + CardList elves = new CardList(play.getCards()); + elves = elves.getType("Elf"); + + AllZone.GameAction.getPlayerLife(card.getController()).addLife(2*elves.size()); + + }//resolve() + + public boolean canPlayAI() + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, Constant.Player.Computer); + + CardList chosens = new CardList(lib.getCards()); + chosens = chosens.getName("Nissa's Chosen"); + + if (chosens.size() > 0) + return false; + + return true; + } + + public boolean canPlay() + { + @SuppressWarnings("unused") // library + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card2.getController()); + + return 0 < card2.getCounters(Counters.LOYALTY) && + AllZone.getZone(card2).is(Constant.Zone.Play) && + turn[0] != AllZone.Phase.getTurn() && + AllZone.Phase.getActivePlayer().equals(card2.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn"); + + }//canPlay() + };//SpellAbility ability2 + + ability2.setBeforePayMana(new Input() + { + + + private static final long serialVersionUID = 2828718386226165026L; + int check = -1; + public void showMessage() + { + if(check != AllZone.Phase.getTurn()) + { + check = AllZone.Phase.getTurn(); + turn[0] = AllZone.Phase.getTurn(); + + + AllZone.Stack.push(ability2); + } + stop(); + }//showMessage() + }); + + + //ability3 + final SpellAbility ability3 = new Ability(card2, "0") + { + public void resolve() + { + card2.subtractCounter(Counters.LOYALTY, 7); + turn[0] = AllZone.Phase.getTurn(); + + //make all permanents in play/hand/library and graveyard + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + + CardList list = new CardList();; + list.addAll(library.getCards()); + list = list.getType("Elf"); + + //currently, just adds all elves into play. + for (int i=0;i < list.size(); i++) + { + Card c = list.get(i); + if (c.isCreature() ) + { + library.remove(c); + play.add(c); + } + } + } + public boolean canPlay() + { + return 7 <= card2.getCounters(Counters.LOYALTY) && AllZone.getZone(card2).is(Constant.Zone.Play) && + turn[0] != AllZone.Phase.getTurn() && + AllZone.Phase.getActivePlayer().equals(card2.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn"); + }//canPlay() + public boolean canPlayAI() + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, Constant.Player.Computer); + + CardList elves = new CardList(lib.getCards()); + elves = elves.getType("Elf"); + + return elves.size() > 3; + } + }; + ability3.setBeforePayMana(new Input() + { + + private static final long serialVersionUID = -7189927522150479572L; + int check = -1; + public void showMessage() + { + if(check != AllZone.Phase.getTurn()) + { + check = AllZone.Phase.getTurn(); + turn[0] = AllZone.Phase.getTurn(); + AllZone.Stack.push(ability3); + } + stop(); + }//showMessage() + }); + + //ability 1: search for Nessa's Chosen + final SpellAbility ability1 = new Ability(card2, "0") + { + public void resolve() + { + card2.addCounter(Counters.LOYALTY, 1); + turn[0] = AllZone.Phase.getTurn(); + + if (card2.getController().equals(Constant.Player.Human)){ + Object check = AllZone.Display.getChoiceOptional("Search for Nissa's Chosen", AllZone.Human_Library.getCards()); + if(check != null) + { + Card c = (Card)check; + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card2.getController()); + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card2.getController()); + + if (c.getName().equals("Nissa's Chosen")) + { + lib.remove(c); + play.add(c); + } + } + AllZone.GameAction.shuffle(Constant.Player.Human); + }//human + else + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card2.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card2.getController()); + CardList nissas = new CardList(lib.getCards()); + nissas = nissas.getName("Nissa's Chosen"); + + if (nissas.size() > 0) + { + Card nissa = nissas.get(0); + lib.remove(nissa); + play.add(nissa); + } + AllZone.GameAction.shuffle(Constant.Player.Computer); + } + + } + public boolean canPlayAI() + { + if(ability3.canPlay() && ability3.canPlayAI()) { + return false; + } else + { + return true; + } + } + public boolean canPlay() + { + return 0 < card2.getCounters(Counters.LOYALTY) && AllZone.getZone(card2).is(Constant.Zone.Play) && + turn[0] != AllZone.Phase.getTurn() && + AllZone.Phase.getActivePlayer().equals(card2.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn"); + }//canPlay() + };//SpellAbility ability1 + + ability1.setBeforePayMana(new Input() + { + + private static final long serialVersionUID = 7668642820407492396L; + int check = -1; + public void showMessage() + { + if(check != AllZone.Phase.getTurn()) + { + check = AllZone.Phase.getTurn(); + turn[0] = AllZone.Phase.getTurn(); + AllZone.Stack.push(ability1); + } + stop(); + }//showMessage() + }); + + ability1.setDescription("+1: Search your library for a card named Nissa's Chosen and put it onto the battlefield. Then shuffle your library."); + ability1.setStackDescription("Nissa Revane - Search for a card named Nissa's Chosen and put it onto the battlefield."); + card2.addSpellAbility(ability1); + + ability2.setDescription("+1: You gain 2 life for each Elf you control."); + ability2.setStackDescription("Nissa Revane - You gain 2 life for each Elf you control."); + + card2.addSpellAbility(ability2); + + ability3.setDescription("-7: Search your library for any number of Elf creature cards and put them onto the battlefield. Then shuffle your library."); + ability3.setStackDescription("Nissa Revane - Search your library for any number of Elf creature cards and put them onto the battlefield. Then shuffle your library."); + card2.addSpellAbility(ability3); + + return card2; + } + //*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Nicol Bolas, Planeswalker")) + { + + final int turn[] = new int[1]; + turn[0] = -1; + + final Card card2 = new Card() + { + public void addDamage(int n) + { + subtractCounter(Counters.LOYALTY, n); + AllZone.GameAction.checkStateEffects(); + } + }; + card2.addCounter(Counters.LOYALTY, 5); + + card2.setOwner(owner); + card2.setController(owner); + + card2.setName(card.getName()); + card2.setType(card.getType()); + card2.setManaCost(card.getManaCost()); + card2.addSpellAbility(new Spell_Permanent(card2)); + + //ability3 + final SpellAbility ability3 = new Ability(card2, "0") + { + public void resolve() + { + card2.subtractCounter(Counters.LOYALTY, 9); + turn[0] = AllZone.Phase.getTurn(); + + String player = card2.getController(); + String opponent = AllZone.GameAction.getOpponent(player); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, opponent); + CardList oppPerms = new CardList(play.getCards()); + + PlayerLife life = AllZone.GameAction.getPlayerLife(opponent); + life.subtractLife(7); + + for (int j=0; j<7; j++) + { + //will not actually let human choose which cards to discard + AllZone.GameAction.discardRandom(opponent); + } + + CardList permsToSac = new CardList(); + CardList oppPermTempList = new CardList(play.getCards()); + + if (player.equals("Human")) + { + for(int k=0; k < oppPerms.size(); k++) + { + Card c = oppPerms.get(k); + + permsToSac.add(c); + + if (k == 6) + break; + } + } + + else //computer + { + Object o = null; + for(int k=0; k < oppPerms.size(); k++) + { + o = AllZone.Display.getChoiceOptional("Select Card to sacrifice", oppPermTempList.toArray()); + Card c = (Card)o; + //AllZone.GameAction.sacrifice(c); + permsToSac.add(c); + oppPermTempList.remove(c); + + + if (k == 6) + break; + } + } + for(int m=0;m highestCost) + { + highestCost = CardUtil.getConvertedManaCost(nonCreaturePermanents.get(i).getManaCost()); + bestCard = nonCreaturePermanents.get(i); + } + } + if (bestCard == null && nonCreaturePermanents.size() > 0) + { + bestCard = nonCreaturePermanents.get(0); + return bestCard; + } + + return null; + } + };//SpellAbility ability1 + + ability1.setBeforePayMana(new Input() + { + private static final long serialVersionUID = 9167121234861249451L; + + int check = -1; + public void showMessage() + { + if(check != AllZone.Phase.getTurn()) + { + check = AllZone.Phase.getTurn(); + turn[0] = AllZone.Phase.getTurn(); + AllZone.Stack.push(ability1); + } + stop(); + }//showMessage() + }); + + ability1.setDescription("+3: Destroy target noncreature permanent."); + ability1.setStackDescription("Nicol Bolas - Destroy target noncreature permanent."); + ability1.setBeforePayMana(CardFactoryUtil.input_targetNonCreaturePermanent(ability1, Command.Blank)); + + card2.addSpellAbility(ability1); + + ability2.setDescription("-2: Gain control of target creature."); + ability2.setStackDescription("Nicol Bolas - Gain control of target creature."); + ability2.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability2)); + + card2.addSpellAbility(ability2); + + ability3.setDescription("-9: Nicol Bolas deals 7 damage to target player. That player discards 7 cards, then sacrifices 7 permanents."); + ability3.setStackDescription("Nicol Bolas - deals 7 damage to target player. That player discards 7 cards, then sacrifices 7 permanents."); + card2.addSpellAbility(ability3); + + return card2; + } + //*************** END ************ END ************************** + + + + + +//*************** START *********** START ************************** + if(cardName.equals("Ajani Goldmane")) + { + //computer only plays ability 1 and 3, gain life and put X\X token into play + final int turn[] = new int[1]; + turn[0] = -1; + + final Card card2 = new Card() + { + public void addDamage(int n) + { + subtractCounter(Counters.LOYALTY,n); + AllZone.GameAction.checkStateEffects(); + } + }; + card2.addCounter(Counters.LOYALTY, 4); + + card2.setOwner(owner); + card2.setController(owner); + + card2.setName(card.getName()); + card2.setType(card.getType()); + card2.setManaCost(card.getManaCost()); + card2.addSpellAbility(new Spell_Permanent(card2)); + + //ability2: all controller's creatures get +1\+1 and vigilance until EOT + final SpellAbility ability2 = new Ability(card2, "0") + { + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -5436621445704076988L; + + public void execute() + { + String player = card2.getController(); + CardList creatures; + if(player.equals(Constant.Player.Human)) { + creatures = new CardList(AllZone.Human_Play.getCards()); + } else { + creatures = new CardList(AllZone.Computer_Play.getCards()); + } + + creatures = creatures.getType("Creature"); + + for (int i = 0; i < creatures.size(); i++) { + Card card = creatures.get(i); + //card.setAttack(card.getAttack() - 1); + //card.setDefense(card.getDefense() - 1); + card.removeExtrinsicKeyword("Vigilance"); + } + } + }; + + public void resolve() + { + card2.subtractCounter(Counters.LOYALTY,1); + turn[0] = AllZone.Phase.getTurn(); + + String player = card2.getController(); + CardList creatures; + if(player.equals(Constant.Player.Human)) { + creatures = new CardList(AllZone.Human_Play.getCards()); + } else { + creatures = new CardList(AllZone.Computer_Play.getCards()); + } + + creatures = creatures.getType("Creature"); + + for (int i = 0; i < creatures.size(); i++) { + Card card = creatures.get(i); + card.addCounter(Counters.P1P1,1); + card.addExtrinsicKeyword("Vigilance"); + } + + AllZone.EndOfTurn.addUntil(untilEOT); + } + + public boolean canPlayAI() + { + return false; + } + + public boolean canPlay() + { + @SuppressWarnings("unused") // library + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card2.getController()); + + return 0 < card2.getCounters(Counters.LOYALTY) && + AllZone.getZone(card2).is(Constant.Zone.Play) && + turn[0] != AllZone.Phase.getTurn() && + AllZone.Phase.getActivePlayer().equals(card2.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn"); + + }//canPlay() + };//SpellAbility ability2 + + ability2.setBeforePayMana(new Input() + { + private static final long serialVersionUID = 6373573398967821630L; + int check = -1; + public void showMessage() + { + if(check != AllZone.Phase.getTurn()) + { + check = AllZone.Phase.getTurn(); + turn[0] = AllZone.Phase.getTurn(); + AllZone.Stack.push(ability2); + } + stop(); + }//showMessage() + }); + + //ability3 + final SpellAbility ability3 = new Ability(card2, "0") + { + public void resolve() + { + card2.subtractCounter(Counters.LOYALTY, 6); + turn[0] = AllZone.Phase.getTurn(); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + + //Create token + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setImageName("W N N Avatar"); + c.setName("Avatar"); + c.setManaCost("W"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Avatar"); + c.setBaseAttack(AllZone.GameAction.getPlayerLife(card.getController()).getLife()); + c.setBaseDefense(AllZone.GameAction.getPlayerLife(card.getController()).getLife()); + + c.addIntrinsicKeyword("This creature's power and toughness are each equal to your life total."); + + play.add(c); + } + public boolean canPlay() + { + return 6 <= card2.getCounters(Counters.LOYALTY) && AllZone.getZone(card2).is(Constant.Zone.Play) && + turn[0] != AllZone.Phase.getTurn() && + AllZone.Phase.getActivePlayer().equals(card2.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn"); + }//canPlay() + public boolean canPlayAI() + { + // may be it's better to put only if you have less than 5 life + return true; + } + }; + ability3.setBeforePayMana(new Input() + { + private static final long serialVersionUID = 7530960428366291386L; + + int check = -1; + public void showMessage() + { + if(check != AllZone.Phase.getTurn()) + { + check = AllZone.Phase.getTurn(); + turn[0] = AllZone.Phase.getTurn(); + AllZone.Stack.push(ability3); + } + stop(); + }//showMessage() + }); + + //ability 1: gain 2 life + final SpellAbility ability1 = new Ability(card2, "0") + { + public void resolve() + { + card2.addCounter(Counters.LOYALTY, 1); + turn[0] = AllZone.Phase.getTurn(); + + + AllZone.GameAction.getPlayerLife(card.getController()).addLife(2); + System.out.println("current phase: " +AllZone.Phase.getPhase()); + } + public boolean canPlayAI() + { + if(ability3.canPlay() && ability3.canPlayAI()) { + return false; + } else + { + return true; + } + } + public boolean canPlay() + { + return 0 < card2.getCounters(Counters.LOYALTY) && AllZone.getZone(card2).is(Constant.Zone.Play) && + turn[0] != AllZone.Phase.getTurn() && + AllZone.Phase.getActivePlayer().equals(card2.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn"); + }//canPlay() + };//SpellAbility ability1 + + ability1.setBeforePayMana(new Input() + { + private static final long serialVersionUID = -7969603493514210825L; + + int check = -1; + public void showMessage() + { + if(check != AllZone.Phase.getTurn()) + { + check = AllZone.Phase.getTurn(); + turn[0] = AllZone.Phase.getTurn(); + AllZone.Stack.push(ability1); + } + stop(); + }//showMessage() + }); + + ability1.setDescription("+1: You gain 2 life."); + ability1.setStackDescription("Ajani Goldmane - " + card2.getController() + " gains 2 life"); + card2.addSpellAbility(ability1); + + ability2.setDescription("-1: Put a +1/+1 counter on each creature you control. Those creatures gain vigilance until end of turn."); + ability2.setStackDescription("Ajani Goldmane - Put a +1/+1 counter on each creature you control. They get vigilance."); + card2.addSpellAbility(ability2); + + ability3.setDescription("-6: Put a white Avatar creature token into play with \"This creature's power and toughness are each equal to your life total.\""); + ability3.setStackDescription("Ajani Goldmane - Put X\\X white Avatar creature token into play."); + card2.addSpellAbility(ability3); + + return card2; + } + //*************** END ************ END ************************** + + + //contributed code + //*************** START *********** START ************************** + if(cardName.equals("Dark Banishing")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -5621665629586583879L; + + Card check; + + public boolean canPlayAI() + { + check = getNonBlackCreature(); + return check != null; + } + + public void chooseTargetAI() + { + Card c = getNonBlackCreature(); + if((c == null) || (! check.equals(c))) + throw new RuntimeException(card +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + setTargetCard(c); + }//chooseTargetAI() + + Card getNonBlackCreature() + { + int maxAttack = 0; + Card bestCard = null; + CardList nonBlackCards = CardFactoryUtil.AI_getHumanCreature(card, true); + + for(int i = 0; i < nonBlackCards.size(); i++) + if(!CardUtil.getColors(nonBlackCards.get(i)).contains(Constant.Color.Black)) + if(nonBlackCards.get (i).getNetAttack() > maxAttack) + { + maxAttack = nonBlackCards.get(i).getNetAttack(); + bestCard = nonBlackCards.get(i); + } + + return bestCard; + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card,getTargetCard())) + { + AllZone.GameAction.destroyNoRegeneration(getTargetCard()); + } + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + //target + Input target = new Input() + { + private static final long serialVersionUID = -3155643868640376193L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target non-black creature for " +spell.getSourceCard()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + if (!CardFactoryUtil.canTarget(card, c)) + { + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + else if((!CardUtil.getColors(c).contains(Constant.Color.Black)) + && c.isCreature() + && zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(c); + stopSetNext(new Input_PayManaCost(spell)); + } + } + };//SpellAbility - target + + spell.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Filthy Cur")) + { + final Card newCard = new Card() + { + public void addDamage(final int n) + { + super.addDamage(n); + SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(getController()).subtractLife(n); + } + }; + ability.setStackDescription("Filthy Cur - causes " +n +" damage to " +getController()); + AllZone.Stack.add(ability); + }//addDamage() + };//Card + + newCard.setOwner(card.getOwner()); + newCard.setController(card.getController()); + + newCard.setManaCost(card.getManaCost()); + newCard.setName(card.getName()); + newCard.addType("Creature"); + newCard.addType("Hound"); + newCard.setText(card.getSpellText()); + newCard.setBaseAttack(card.getBaseAttack()); + newCard.setBaseDefense(card.getBaseDefense()); + + newCard.addSpellAbility(new Spell_Permanent(newCard)); + + return newCard; + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Shinka Gatekeeper")) + { + final Card newCard = new Card() + { + public void addDamage(final int n) + { + super.addDamage(n); + SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(getController()).subtractLife(n); + } + }; + ability.setStackDescription("Shinka Gatekeeper - causes " +n +" damage to " +getController()); + AllZone.Stack.add(ability); + }//addDamage() + };//Card + + newCard.setOwner(card.getOwner()); + newCard.setController(card.getController()); + + newCard.setManaCost(card.getManaCost()); + newCard.setName(card.getName()); + newCard.addType("Creature"); + newCard.addType("Ogre"); + newCard.addType("Warrior"); + newCard.setText(card.getSpellText()); + newCard.setBaseAttack(card.getBaseAttack()); + newCard.setBaseDefense(card.getBaseDefense()); + + newCard.addSpellAbility(new Spell_Permanent(newCard)); + + return newCard; + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Jackal Pup")) + { + final Card newCard = new Card() + { + public void addDamage(final int n) + { + super.addDamage(n); + SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(getController()).subtractLife(n); + } + }; + ability.setStackDescription("Jackal Pup - causes " +n +" damage to " +getController()); + AllZone.Stack.add(ability); + }//addDamage() + };//Card + + newCard.setOwner(card.getOwner()); + newCard.setController(card.getController()); + + newCard.setManaCost(card.getManaCost()); + newCard.setName(card.getName()); + newCard.addType("Creature"); + newCard.addType("Hound"); + newCard.setText(card.getSpellText()); + newCard.setBaseAttack(card.getBaseAttack()); + newCard.setBaseDefense(card.getBaseDefense()); + + newCard.addSpellAbility(new Spell_Permanent(newCard)); + + return newCard; + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Stuffy Doll")) + { + final Card newCard = new Card() + { + Card c = this; + public void addDamage(final int n) + { + super.addDamage(n); + final String opponent = AllZone.GameAction.getOpponent(owner); + + SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(opponent).subtractLife(n); + + if (c.getKeyword().contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(c,n); + for(int i=0; i < CardFactoryUtil.hasNumberEnchantments(c, "Guilty Conscience"); i++) + GameActionUtil.executeGuiltyConscienceEffects(c, n); + } + }; + ability.setStackDescription("Stuffy Doll - causes " +n +" damage to " +opponent); + AllZone.Stack.add(ability); + }//addDamage() + };//Card + + newCard.setOwner(card.getOwner()); + newCard.setController(card.getController()); + + newCard.setManaCost(card.getManaCost()); + newCard.setName(card.getName()); + newCard.addType("Artifact"); + newCard.addType("Creature"); + newCard.addType("Construct"); + newCard.setText("Whenever damage is dealt to Stuffy Doll, it deals that much damage to your opponent."); + newCard.setBaseAttack(0); + newCard.setBaseDefense(1); + + newCard.addIntrinsicKeyword("Indestructible"); + + final Ability_Tap ability = new Ability_Tap(newCard) + { + private static final long serialVersionUID = 577739727089395613L; + + public void resolve() + { + newCard.addDamage(1); + + if (newCard.getKeyword().contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(newCard, 1); + for(int i=0; i < CardFactoryUtil.hasNumberEnchantments(newCard, "Guilty Conscience"); i++) + GameActionUtil.executeGuiltyConscienceEffects(newCard, 1); + } + };//SpellAbility + ability.setDescription("tap: Stuffy Doll deals 1 damage to itself."); + ability.setStackDescription("Stuffy Doll - deals 1 damage to itself."); + ability.setBeforePayMana(new Input_NoCost_TapAbility(ability)); + +// card.addSpellAbility(ability); +// return card; +///* + newCard.addSpellAbility(new Spell_Permanent(newCard)); + newCard.addSpellAbility(ability); + + return newCard; +//*/ + }//*************** END ************ END ************************** + + +// computer plays 2 land of these type instead of just 1 per turn + + //*************** START *********** START ************************** + //Ravinca Duel Lands + if(cardName.equals("Blood Crypt") || cardName.equals("Breeding Pool") || cardName.equals("Godless Shrine") || cardName.equals("Hallowed Fountain") || cardName.equals("Overgrown Tomb") || cardName.equals("Sacred Foundry") || cardName.equals("Steam Vents") || cardName.equals("Stomping Ground") || cardName.equals("Temple Garden") || cardName.equals("Watery Grave")) + { + //if this isn't done, computer plays more than 1 copy + //card.clearSpellAbility(); + card.clearSpellKeepManaAbility(); + + card.addComesIntoPlayCommand(new Command() + { + private static final long serialVersionUID = 7352127748114888255L; + + public void execute() + { + if(card.getController().equals(Constant.Player.Human)) + humanExecute(); + else + computerExecute(); + } + public void computerExecute() + { + boolean pay = false; + + if(AllZone.Computer_Life.getLife() > 9) + pay = MyRandom.random.nextBoolean(); + + if(pay) + AllZone.Computer_Life.subtractLife(2); + else + card.tap(); + } + public void humanExecute() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + if(2 < life.getLife()) + { + String[] choices = {"Yes", "No"}; + Object o = AllZone.Display.getChoice("Pay 2 life?", choices); + if(o.equals("Yes")) + life.subtractLife(2); + else + tapCard(); + }//if + else + tapCard(); + }//execute() + private void tapCard() + { + card.tap(); + } + }); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Kabira Crossroads")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + Card c = card; + PlayerLife life = AllZone.GameAction.getPlayerLife(c.getController()); + life.addLife(2); + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = -4550013855602477643L; + + public void execute() + { + card.tap(); + ability.setStackDescription(card.getName() + " - " +card.getController() +" gains 2 life"); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Graypelt Refuge")|| cardName.equals("Sejiri Refuge")|| cardName.equals("Jwar Isle Refuge") || + cardName.equals("Akoum Refuge")|| cardName.equals("Kazandu Refuge")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + Card c = card; + c.tap(); + PlayerLife life = AllZone.GameAction.getPlayerLife(c.getController()); + life.addLife(1); + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = 5055232386220487221L; + + public void execute() + { + card.tap(); + ability.setStackDescription(card.getName() + " - " +card.getController() +" gains 1 life"); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Faerie Conclave")) + { + card.addComesIntoPlayCommand(new Command() + { + private static final long serialVersionUID = 2792041290726604698L; + + public void execute() + { + card.tap(); + } + }); + + final Command eot1 = new Command() + { + private static final long serialVersionUID = 5106629534549783845L; + + public void execute() + { + Card c = card; + + c.setBaseAttack(0); + c.setBaseDefense(0); + c.removeIntrinsicKeyword("Flying"); + c.removeType("Creature"); + c.removeType("Faerie"); + } + }; + + final SpellAbility a1 = new Ability(card, "1 U") + { + public boolean canPlayAI() + { + return false; + } + public void resolve() + { + Card c = card; + + c.setBaseAttack(2); + c.setBaseDefense(1); + + //to prevent like duplication like "Flying Flying Creature Creature" + if(! c.getIntrinsicKeyword().contains("Flying")) + { + c.addIntrinsicKeyword("Flying"); + c.addType("Creature"); + c.addType("Faerie"); + } + AllZone.EndOfTurn.addUntil(eot1); + } + };//SpellAbility + card.setManaCost("U"); + + card.clearSpellKeepManaAbility(); + card.addSpellAbility(a1); + a1.setDescription("1U: Faerie Conclave becomes a 2/1 blue Faerie creature with flying until end of turn. It's still a land."); + a1.setStackDescription(card +" becomes a 2/1 creature with flying until EOT"); + + Command paid1 = new Command() { + private static final long serialVersionUID = -601119544294387668L; + public void execute() {AllZone.Stack.add(a1);} + }; + + a1.setBeforePayMana(new Input_PayManaCost_Ability(a1.getManaCost(), paid1)); + + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Forbidding Watchtower")) + { + card.addComesIntoPlayCommand(new Command() + { + private static final long serialVersionUID = 5212793782060828409L; + + public void execute() + { + card.tap(); + } + }); + + final Command eot1 = new Command() + { + private static final long serialVersionUID = 8806880921707550181L; + + public void execute() + { + Card c = card; + + c.setBaseAttack(0); + c.setBaseDefense(0); + c.removeType("Creature"); + c.removeType("Soldier"); + } + }; + + final SpellAbility a1 = new Ability(card, "1 W") + { + public boolean canPlayAI() + { + return false; + } + public void resolve() + { + Card c = card; + + c.setBaseAttack(1); + c.setBaseDefense(5); + + //to prevent like duplication like "Creature Creature" + if(! c.getType().contains("Creature")) + { + c.addType("Creature"); + c.addType("Soldier"); + } + AllZone.EndOfTurn.addUntil(eot1); + } + };//SpellAbility + + card.clearSpellKeepManaAbility(); + card.addSpellAbility(a1); + a1.setStackDescription(card +" becomes a 1/5 creature until EOT"); + + Command paid1 = new Command() { + private static final long serialVersionUID = -7211256926392695778L; + public void execute() {AllZone.Stack.add(a1);} + }; + + a1.setBeforePayMana(new Input_PayManaCost_Ability(a1.getManaCost(), paid1)); + + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Treetop Village")) + { + card.addComesIntoPlayCommand(new Command() + { + private static final long serialVersionUID = -2246560994818997231L; + + public void execute() + { + card.tap(); + } + }); + + final Command eot1 = new Command() + { + private static final long serialVersionUID = -8535770979347971863L; + + public void execute() + { + Card c = card; + + c.setBaseAttack(0); + c.setBaseDefense(0); + c.removeType("Creature"); + c.removeType("Ape"); + c.removeIntrinsicKeyword("Trample"); + } + }; + + final SpellAbility a1 = new Ability(card, "1 G") + { + public boolean canPlayAI() + { + return ! card.getType().contains("Creature"); + } + public void resolve() + { + Card c = card; + + c.setBaseAttack(3); + c.setBaseDefense(3); + + //to prevent like duplication like "Creature Creature" + if(! c.getIntrinsicKeyword().contains("Trample")) + { + c.addType("Creature"); + c.addType("Ape"); + c.addIntrinsicKeyword("Trample"); + } + AllZone.EndOfTurn.addUntil(eot1); + } + };//SpellAbility + + card.clearSpellKeepManaAbility(); + card.addSpellAbility(a1); + a1.setStackDescription(card +" becomes a 3/3 creature with trample until EOT"); + + Command paid1 = new Command() { + private static final long serialVersionUID = -6800983290478844750L; + + public void execute() {AllZone.Stack.add(a1);} + }; + + a1.setBeforePayMana(new Input_PayManaCost_Ability(a1.getManaCost(), paid1)); + + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Serra Avenger")) + { + SpellAbility spell = new Spell_Permanent(card) + { + private static final long serialVersionUID = -1148518222979323313L; + + public boolean canPlay() + { + return super.canPlay() && 6 < AllZone.Phase.getTurn(); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + } + //*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Force of Savagery")) + { + SpellAbility spell = new Spell_Permanent(card) + { + private static final long serialVersionUID = 1603238129819160467L; + + public boolean canPlayAI() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + + return list.containsName("Glorious Anthem") || list.containsName("Gaea's Anthem"); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + } + //*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Pyrohemia")) + { + SpellAbility ability = new Ability(card, "R") + { + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Creature"); + computer = computer.getType("Creature"); + + return AllZone.Computer_Life.getLife() > 2 && !(human.size() == 0 && 0 < computer.size()); + } + public void resolve() + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + for(int i = 0; i < list.size(); i++){ + if (CardFactoryUtil.canDamage(card, list.get(i))) + list.get(i).addDamage(1); + } + + AllZone.Human_Life.subtractLife(1); + AllZone.Computer_Life.subtractLife(1); + }//resolve() + };//SpellAbility + ability.setDescription("R: Pyrohemia deals 1 damage to each creature and each player."); + ability.setStackDescription(card +" deals 1 damage to each creature and each player."); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = 5596915641671666843L; + + public boolean canPlayAI() + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + return 0 < list.size(); + } + }); + + card.addSpellAbility(ability); + } + //*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Pestilence")) + { + SpellAbility ability = new Ability(card, "B") + { + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Creature"); + computer = computer.getType("Creature"); + + return AllZone.Computer_Life.getLife() > 2 && !(human.size() == 0 && 0 < computer.size()); + } + public void resolve() + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + for(int i = 0; i < list.size(); i++) { + if (CardFactoryUtil.canDamage(card, list.get(i))) + list.get(i).addDamage(1); + } + + AllZone.Human_Life.subtractLife(1); + AllZone.Computer_Life.subtractLife(1); + }//resolve() + };//SpellAbility + ability.setDescription("B: Pestilence deals 1 damage to each creature and each player."); + ability.setStackDescription(card +" deals 1 damage to each creature and each player."); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = -4163089323122672307L; + + public boolean canPlayAI() + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + return 0 < list.size(); + } + }); + + card.addSpellAbility(ability); + } + //*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Greater Forgeling")) + { + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -4569751606008597903L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addTempAttackBoost(-3); + card.addTempDefenseBoost(3); + } + } + }; + + SpellAbility ability = new Ability(card, "1 R") + { + public boolean canPlayAI() + { + return MyRandom.random.nextBoolean() && CardFactoryUtil.AI_doesCreatureAttack(card) && + 3 < card.getNetDefense(); + } + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addTempAttackBoost(3); + card.addTempDefenseBoost(-3); + AllZone.EndOfTurn.addUntil(untilEOT); + } + } + }; + + ability.setDescription("1 R: Greater Forgeling gets +3/-3 until end of turn."); + ability.setStackDescription(card +" gets +3/-3 until end of turn."); + card.addSpellAbility(ability); + } + //*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Liliana Vess")) + { + //computer only plays ability 1 and 3, discard and return creature from graveyard to play + final int turn[] = new int[1]; + turn[0] = -1; + + final Card card2 = new Card() + { + public void addDamage(int n) + { + subtractCounter(Counters.LOYALTY,n); + AllZone.GameAction.checkStateEffects(); + } + }; + card2.addCounter(Counters.LOYALTY, 5); + + card2.setOwner(owner); + card2.setController(owner); + + card2.setName(card.getName()); + card2.setType(card.getType()); + card2.setManaCost(card.getManaCost()); + card2.addSpellAbility(new Spell_Permanent(card2)); + + //ability2 + final SpellAbility ability2 = new Ability(card2, "0") + { + public void resolve() + { + card2.subtractCounter(Counters.LOYALTY, 2); + turn[0] = AllZone.Phase.getTurn(); + + String player = card2.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void computerResolve() + { + CardList creature = new CardList(AllZone.Computer_Library.getCards()); + creature = creature.getType("Creature"); + if(creature.size() != 0) + { + Card c = creature.get(0); + AllZone.GameAction.shuffle(card2.getController()); + + //move to top of library + AllZone.Computer_Library.remove(c); + AllZone.Computer_Library.add(c, 0); + } + }//computerResolve() + public void humanResolve() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card2.getController()); + + CardList list = new CardList(library.getCards()); + + if(list.size() != 0) + { + Object o = AllZone.Display.getChoiceOptional("Select any card", list.toArray()); + + AllZone.GameAction.shuffle(card2.getController()); + if(o != null) + { + //put creature on top of library + library.remove(o); + library.add((Card)o, 0); + } + }//if + }//resolve() + public boolean canPlayAI() + { + return false; + } + + public boolean canPlay() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card2.getController()); + + return 2 <= card2.getCounters(Counters.LOYALTY) && + AllZone.getZone(card2).is(Constant.Zone.Play) && + 1 < library.size() && + turn[0] != AllZone.Phase.getTurn() && + AllZone.Phase.getActivePlayer().equals(card2.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn"); + }//canPlay() + };//SpellAbility ability2 + + ability2.setBeforePayMana(new Input() + { + private static final long serialVersionUID = 5726590384281714755L; + + int check = -1; + public void showMessage() + { + if(check != AllZone.Phase.getTurn()) + { + check = AllZone.Phase.getTurn(); + turn[0] = AllZone.Phase.getTurn(); + AllZone.Stack.push(ability2); + } + stop(); + }//showMessage() + }); + + //ability3 + final SpellAbility ability3 = new Ability(card2, "0") + { + public void resolve() + { + card2.subtractCounter(Counters.LOYALTY, 8); + turn[0] = AllZone.Phase.getTurn(); + + //get all graveyard creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Graveyard.getCards()); + list.addAll(AllZone.Computer_Graveyard.getCards()); + list = list.getType("Creature"); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card2.getController()); + PlayerZone grave = null; + Card c = null; + for(int i = 0; i < list.size(); i++) + { + //this is a rough hack, but no one will ever see this code anyways, lol ;+) + c = list.get(i); + c.setController(card.getController()); + + grave = AllZone.getZone(c); + if(grave != null) + grave.remove(c); + + play.add(c); + } + } + public boolean canPlay() + { + return 8 <= card2.getCounters(Counters.LOYALTY) && AllZone.getZone(card2).is(Constant.Zone.Play) && + turn[0] != AllZone.Phase.getTurn() && + AllZone.Phase.getActivePlayer().equals(card2.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn"); + }//canPlay() + public boolean canPlayAI() + { + CardList list = new CardList(); + list.addAll(AllZone.Human_Graveyard.getCards()); + list.addAll(AllZone.Computer_Graveyard.getCards()); + list = list.getType("Creature"); + + return 3 < list.size(); + } + }; + ability3.setBeforePayMana(new Input() + { + private static final long serialVersionUID = -3297439284172874241L; + + int check = -1; + public void showMessage() + { + if(check != AllZone.Phase.getTurn()) + { + check = AllZone.Phase.getTurn(); + turn[0] = AllZone.Phase.getTurn(); + AllZone.Stack.push(ability3); + } + stop(); + }//showMessage() + }); + + //ability 1 + final SpellAbility ability1 = new Ability(card2, "0") + { + public void resolve() + { + card2.addCounter(Counters.LOYALTY,1); + turn[0] = AllZone.Phase.getTurn(); + + String s = getTargetPlayer(); + setStackDescription("Liliana Vess - " +s +" discards a card"); + + if(s.equals(Constant.Player.Human)) + AllZone.InputControl.setInput(CardFactoryUtil.input_discard()); + else + AllZone.GameAction.discardRandom(Constant.Player.Computer); + } + public boolean canPlayAI() + { + if(ability3.canPlay() && ability3.canPlayAI()) + return false; + else + { + setTargetPlayer(Constant.Player.Human); + return true; + } + } + public boolean canPlay() + { + return 0 < card2.getCounters(Counters.LOYALTY) && AllZone.getZone(card2).is(Constant.Zone.Play) && + turn[0] != AllZone.Phase.getTurn() && + AllZone.Phase.getActivePlayer().equals(card2.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn"); + }//canPlay() + };//SpellAbility ability1 + + Input target = new Input() + { + private static final long serialVersionUID = 4997055112713151705L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target player"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectPlayer(String player) + { + turn[0] = AllZone.Phase.getTurn(); + ability1.setTargetPlayer(player); + AllZone.Stack.add(ability1); + stop(); + } + };//Input target + ability1.setBeforePayMana(target); + ability1.setDescription("+1: Target player discards a card."); + card2.addSpellAbility(ability1); + + ability2.setDescription("-2: Search your library for a card, then shuffle your library and put that card on top of it."); + ability2.setStackDescription("Liliana Vess - Search your library for a card, then shuffle your library and put that card on top of it."); + card2.addSpellAbility(ability2); + + ability3.setDescription("-8: Put all creature cards in all graveyards into play under your control."); + ability3.setStackDescription("Liliana Vess - Put all creature cards in all graveyards into play under your control."); + card2.addSpellAbility(ability3); + + return card2; + } + //*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Chandra Nalaar")) + { + //computer only plays ability 1 and 3, discard and return creature from graveyard to play + final int turn[] = new int[1]; + turn[0] = -1; + + final Card card2 = new Card() + { + public void addDamage(int n) + { + subtractCounter(Counters.LOYALTY, n); + AllZone.GameAction.checkStateEffects(); + } + }; + card2.addCounter(Counters.LOYALTY, 6); + + card2.setOwner(owner); + card2.setController(owner); + + card2.setName(card.getName()); + card2.setType(card.getType()); + card2.setManaCost(card.getManaCost()); + card2.addSpellAbility(new Spell_Permanent(card2)); + + //ability 1 + final SpellAbility ability1 = new Ability(card2, "0") + { + public void resolve() + { + card2.addCounter(Counters.LOYALTY, 1); + turn[0] = AllZone.Phase.getTurn(); + + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card2,getTargetCard())) + { + Card c = getTargetCard(); + if (CardFactoryUtil.canDamage(card2, c)) + c.addDamage(1); + } + } + + else + { + PlayerLife life = AllZone.GameAction.getPlayerLife(getTargetPlayer()); + life.subtractLife(1); + } + } + public boolean canPlay() + { + SpellAbility sa; + for (int i=0; i= 4 && AllZone.Phase.getPhase().equals(Constant.Phase.Main1) && + AllZone.Phase.getActivePlayer().equals(card2.getController()); + } + };//SpellAbility ability3 + Input runtime3 = new Input() + { + private static final long serialVersionUID = 7697504647440222302L; + + int check = -1; + public void showMessage() + { + if(check != AllZone.Phase.getTurn()) + { + check = AllZone.Phase.getTurn(); + turn[0] = AllZone.Phase.getTurn(); + + AllZone.Stack.push(ability3); + stop(); + } + } + };//Input + ability3.setStackDescription(card2.getName() +" - Creatures you control get +3/+3 and trample until end of turn."); + ability3.setDescription("-4: Creatures you control get +3/+3 and trample until end of turn."); + ability3.setBeforePayMana(runtime3); + card2.addSpellAbility(ability3); + //end ability 3 + + return card2; + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Caller of the Claw")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + int stop = countGraveyard(); + for(int i = 0; i < stop; i++) + makeToken(); + }//resolve() + int countGraveyard() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + CardList list = new CardList(grave.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && (c.getTurnInZone() == AllZone.Phase.getTurn()); + } + }); + return list.size(); + }//countGraveyard() + void makeToken() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setImageName("G 2 2 Bear"); + c.setName("Bear"); + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Bear"); + c.setBaseAttack(2); + c.setBaseDefense(2); + + play.add(c); + }//makeToken() + };//SpellAbility + + Command comesIntoPlay = new Command() + { + private static final long serialVersionUID = 8485080996453793968L; + + public void execute() + { + AllZone.Stack.add(ability); + } + };//Command + ability.setStackDescription("Caller of the Claw - Put a 2/2 green Bear creature token into play for each nontoken creature put into your graveyard from play this turn."); + card.addComesIntoPlayCommand(comesIntoPlay); + + SpellAbility spell = new Spell_Permanent(card) + { + private static final long serialVersionUID = 6946020026681536710L; + + public boolean canPlayAI() {return super.canPlay();} + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Kiki-Jiki, Mirror Breaker")) + { + final SpellAbility ability = new Ability_Tap(card) + { + private static final long serialVersionUID = -943706942500499644L; + + public boolean canPlayAI() {return getCreature().size() != 0;} + public void chooseTargetAI() + { + setTargetCard(getCreature().get(0)); + } + CardList getCreature() + { + CardList list = null; + if(card.getController().equals(Constant.Player.Human)){ + list = new CardList(AllZone.Human_Play.getCards()); + } + else{ + list = new CardList(AllZone.Computer_Play.getCards()); + } + + list = list.getType("Creature"); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (!c.getType().contains("Legendary") ); + } + }); + CardListUtil.sortAttack(list); + return list; + }//getCreature() + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && getTargetCard().getController().equals(card.getController()) + && CardFactoryUtil.canTarget(card,getTargetCard()) ) + { + Card copy; + if (!getTargetCard().isToken()) + { + //copy creature and put it into play + copy = getCard(getTargetCard().getName(), card.getController()); + copy.setToken(true); + + if (getTargetCard().isFaceDown()) { + copy.setIsFaceDown(true); + copy.setManaCost(""); + copy.setBaseAttack(2); + copy.setBaseDefense(2); + copy.setIntrinsicKeyword(new ArrayList()); //remove all keywords + copy.setType(new ArrayList()); //remove all types + copy.addType("Creature"); + copy.clearSpellAbility(); //disallow "morph_up" + } + copy.addIntrinsicKeyword("Haste"); + } + else //isToken() + { + Card c = getTargetCard(); + copy = new Card(); + + copy.setName(c.getName()); + + copy.setOwner(c.getController()); + copy.setController(c.getController()); + + copy.setManaCost(c.getManaCost()); + copy.setToken(true); + + copy.setType(c.getType()); + + copy.setBaseAttack(c.getBaseAttack()); + copy.setBaseDefense(c.getBaseDefense()); + copy.addIntrinsicKeyword("Haste"); + } + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(copy); + + + //have to do this since getTargetCard() might change + //if Kiki-Jiki somehow gets untapped again + final Card[] target = new Card[1]; + target[0] = copy; + Command atEOT = new Command() + { + private static final long serialVersionUID = 7803915905490565557L; + public void execute() + { + //technically your opponent could steal the token + //and the token shouldn't be sacrificed + if(AllZone.GameAction.isCardInPlay(target[0])) + AllZone.GameAction.sacrifice(target[0]); //maybe do a setSacrificeAtEOT, but probably not. + } + };//Command + AllZone.EndOfTurn.addAt(atEOT); + }//is card in play? + }//resolve() + };//SpellAbility + + Input runtime = new Input() + { + private static final long serialVersionUID = 7171284831370490875L; + + public void showMessage() + { + //get all non-legendary creatures you control + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && + (!c.getType().contains("Legendary")); + } + }); + stopSetNext(CardFactoryUtil.input_targetSpecific(ability, list, "Select target creature to copy that is not legendary.", true)); + } + };//Input + ability.setStackDescription("Kiki-Jiki - copy card."); + ability.setDescription("tap: Put a token into play that's a copy of target nonlegendary creature you control. That creature token has haste. Sacrifice it at end of turn."); + ability.setBeforePayMana(runtime); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Nevinyrral's Disk")) + { + SpellAbility summoningSpell = new Spell_Permanent(card) + { + private static final long serialVersionUID = -8859376851358601934L; + + public boolean canPlayAI() + { + boolean nevinyrralInPlay = false; + + CardList inPlay = new CardList(); + inPlay.addAll(AllZone.Computer_Play.getCards()); + for(int i=0; i 0 && + (AllZone.Phase.getPhase().equals(Constant.Phase.Main2) || AllZone.Phase.getPhase().equals(Constant.Phase.Main1)) + && AllZone.GameAction.isCardInPlay(card) && CardFactoryUtil.canUseAbility(card); + } + public void resolve() + { + + String player = card.getController(); + + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + + CardList lands = new CardList(hand.getCards()); + lands = lands.getType("Land"); + + if (lands.size() > 0) + { + if (player.equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Select land to play", lands.toArray()); + if (o!=null) + { + Card c = (Card)o; + hand.remove(c); + play.add(c); + } + } + else + { + Card c = lands.get(0); + hand.remove(c); + play.add(c); + } + card.setAbilityUsed(card.getAbilityUsed()+1); + } + } + }; + + card.addSpellAbility(ability); + ability.setDescription("You may play two additional lands on each of your turns."); + ability.setStackDescription(card.getName() + " - " + card.getController() + " plays an additional land."); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Exploration")) + { + final int turn[] = new int[1]; + turn[0] = -1; + + final Ability ability = new Ability(card, "0") + { + public boolean canPlay() + { + SpellAbility sa; + for (int i=0; i 0 && + (AllZone.Phase.getPhase().equals(Constant.Phase.Main2) || AllZone.Phase.getPhase().equals(Constant.Phase.Main1)) + && AllZone.GameAction.isCardInPlay(card) && turn[0] != AllZone.Phase.getTurn(); + } + public void resolve() + { + turn[0] = AllZone.Phase.getTurn(); + String player = card.getController(); + + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + + CardList lands = new CardList(hand.getCards()); + lands = lands.getType("Land"); + + if (lands.size() > 0) + { + if (player.equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Select land to play", lands.toArray()); + if (o!=null) + { + Card c = (Card)o; + hand.remove(c); + play.add(c); + } + } + else + { + Card c = lands.get(0); + hand.remove(c); + play.add(c); + } + } + } + }; + + card.addSpellAbility(ability); + ability.setDescription("You may play an additional land each of your turns."); + ability.setStackDescription(card.getName() + " - " + card.getController() + " plays an additional land."); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Fastbond")) + { + final Ability ability = new Ability(card, "0") + { + public boolean canPlayAI() + { + if(AllZone.GameAction.getPlayerLife(Constant.Player.Computer).getLife() > 4) + return true; + else + return false; + } + public boolean canPlay() + { + SpellAbility sa; + for (int i=0; i 0 && + (AllZone.Phase.getPhase().equals(Constant.Phase.Main2) || AllZone.Phase.getPhase().equals(Constant.Phase.Main1)) + && AllZone.GameAction.isCardInPlay(card); + } + public void resolve() + { + String player = card.getController(); + + + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + CardList fastbonds = new CardList(play.getCards()); + fastbonds = fastbonds.getName("Fastbond"); //do this, because if there are more in play, fastbond will deal more damage per land + + AllZone.GameAction.getPlayerLife(player).subtractLife(fastbonds.size()); + + CardList lands = new CardList(hand.getCards()); + lands = lands.getType("Land"); + + if (lands.size() > 0) + { + if (player.equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Select land to play", lands.toArray()); + if (o!=null) + { + Card c = (Card)o; + hand.remove(c); + play.add(c); + } + } + else + { + Card c = lands.get(0); + hand.remove(c); + play.add(c); + + } + } + } + }; + + card.addSpellAbility(ability); + ability.setDescription("You may play as many lands as you choose on your turn. Whenever you play a land other than the first land of the turn, Fastbond deals 1 damage to you."); + ability.setStackDescription(card.getName() + " - deals damage to " + card.getController() + ", plays another land."); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Wellwisher")) + { + final SpellAbility ability = new Ability_Tap(card, "0") + { + private static final long serialVersionUID = 1446529067071763247L; + + public boolean canPlay() + { + setStackDescription(card.getName() +" - " +card.getController() +" gains " +countElf() +" life."); + + return super.canPlay(); + } + public void resolve() + { + AllZone.GameAction.getPlayerLife(card.getController()).addLife(countElf()); + } + int countElf() + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Elf"); + return list.size(); + } + };//SpellAbility + ability.setDescription("tap: You gain 1 life for each Elf in play."); + ability.setBeforePayMana(new Input_NoCost_TapAbility((Ability_Tap) ability)); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Sliver Overlord")) + { + //final String player = card.getController(); + final SpellAbility ability = new Ability(card, "3") + { + public boolean canPlay() + { + SpellAbility sa; + for (int i=0; i 0) + return true; + else + return false; + + } + + + public void resolve() + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + String player = card.getController(); + + CardList list = new CardList(lib.getCards()); + list = list.getType("Sliver"); + + if (list.size()==0) + return; + + if (player.equals(Constant.Player.Computer)) + { + Card sliver = CardFactoryUtil.AI_getBestCreature(list); + lib.remove(sliver); + hand.add(sliver); + } + else //human + { + Object o = AllZone.Display.getChoiceOptional("Select target Sliver", list.toArray()); + Card sliver = (Card)o; + lib.remove(sliver); + hand.add(sliver); + } + AllZone.GameAction.shuffle(player); + } + }; + + final SpellAbility ability2 = new Ability(card, "3") + { + + public void resolve() + { + + + Card c = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(c) && (c.getType().contains("Sliver") || c.getKeyword().contains("Changeling") ) + && CardFactoryUtil.canTarget(card,c) ) + { + //set summoning sickness + if(c.getKeyword().contains("Haste")){ + c.setSickness(false); + } + else{ + c.setSickness(true); + } + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(false); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(false); + + PlayerZone from = AllZone.getZone(c); + from.remove(c); + + c.setController(card.getController()); + + PlayerZone to = AllZone.getZone(Constant.Zone.Play, card.getController()); + to.add(c); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(true); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(true); + }//if + + + }//resolve() + + public boolean canPlayAI() + { + + CardList c = CardFactoryUtil.AI_getHumanCreature(card, true); + CardListUtil.sortAttack(c); + CardListUtil.sortFlying(c); + c = c.filter(new CardListFilter(){ + + public boolean addCard(Card c) { + return c.getType().contains("Sliver") || c.getKeyword().contains("Changeling"); + } + + }); + + if(c.isEmpty()) + return false; + + if(2 <= c.get(0).getNetAttack() && c.get(0).getKeyword().contains("Flying") && + c.get(0).getKeyword().contains("Sliver")) + { + setTargetCard(c.get(0)); + return true; + } + + CardListUtil.sortAttack(c); + if(4 <= c.get(0).getNetAttack() && c.get(0).getKeyword().contains("Sliver")) + { + setTargetCard(c.get(0)); + return true; + } + + return false; + }//canPlayAI() + + public boolean canPlay() + { + return AllZone.GameAction.isCardInPlay(card); + + }//canPlay() + };//SpellAbility ability2 + + ability2.setBeforePayMana(new Input() + { + private static final long serialVersionUID = 1489433384490805477L; + + public void showMessage() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + CardList slivers = new CardList(AllZone.getZone(Constant.Zone.Play, opponent).getCards()); + slivers = slivers.getType("Sliver"); + + stopSetNext(CardFactoryUtil.input_targetSpecific(ability2, slivers, "Select a Sliver", true)); + } + }); + + ability.setDescription("3:Search your library for a Sliver card, reveal that card, and put it into your hand. Then shuffle your library."); + ability.setStackDescription(card.getName() +" - search for a Sliver card and put it into your hand."); + + ability2.setDescription("3:Gain control of target Sliver."); + ability.setStackDescription(card.getName() +" - Gain control of target Sliver."); + + card.addSpellAbility(ability); + card.addSpellAbility(ability2); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Sliver Queen")) + { + final SpellAbility a1 = new Ability(card, "2") + { + + public boolean canPlay() + { + SpellAbility sa; + //this is a hack, check the stack to see if this card has an ability on the stack + //if so, we can't use the ability + for (int i=0; i 0 && CardFactoryUtil.canTarget(card, c); + } + }); + perms.shuffle(); + setTargetCard(perms.get(0)); //TODO: improve this. + } + + public boolean canPlayAI() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList perms = new CardList(play.getCards()); + perms = perms.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.sumAllCounters() > 0; + } + }); + return perms.size() > 0; + } + };//SpellAbility + + Input runtime = new Input() + { + private static final long serialVersionUID = 1571239319226728848L; + + public void showMessage() + { + PlayerZone human = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + PlayerZone comp = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList perms = new CardList(); + perms.addAll(human.getCards()); + perms.addAll(comp.getCards()); + + stopSetNext(CardFactoryUtil.input_targetSpecific(a1, perms, "Select target permanent.", true)); + } + }; + + card.addSpellAbility(a1); + a1.setDescription("2 GU, Untap: For each counter on target permanent, put another of those counters on that permanent."); + + a1.setBeforePayMana(runtime); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Order of Whiteclay")) + { + final SpellAbility a1 = new Ability(card,"1 W W") + { + public void resolve() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList creats = new CardList(grave.getCards()); + creats = creats.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return CardUtil.getConvertedManaCost(c.getManaCost()) <= 3; + } + + }); + + if (card.getController().equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Choose a creature", creats.toArray()); + if (o!=null) + { + Card c = (Card)o; + grave.remove(c); + play.add(c); + card.untap(); + } + } + else //Computer + { + Card c = creats.get(0); + grave.remove(c); + play.add(c); + card.untap(); + } + + } + + public boolean canPlay() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + CardList creats = new CardList(grave.getCards()); + creats = creats.filter(new CardListFilter() + { + + public boolean addCard(Card c) + { + return CardUtil.getConvertedManaCost(c.getManaCost()) <= 3; + } + + }); + if (card.isTapped() && !card.hasSickness() && creats.size() > 0) + return true; + else + return false; + } + + public boolean canPlayAI() + { + return true; + } + };//SpellAbility + card.addSpellAbility(a1); + a1.setDescription("1 W W, Untap: Return target creature card with converted mana cost 3 or less from your graveyard to play."); + a1.setStackDescription(card.getName() + " - return target creature card with converted mana cost 3 or less from your graveyard to play."); + + a1.setBeforePayMana(new Input_PayManaCost(a1)); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Patrol Signaler")) + { + final SpellAbility a1 = new Ability(card,"1 W") + { + public void resolve() + { + card.untap(); + makeToken(); + } + void makeToken() + { + Card c = new Card(); + + c.setName("Kithkin Soldier"); + c.setImageName("W 1 1 Kithkin Soldier"); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("W"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Kithkin"); + c.addType("Soldier"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//makeToken() + public boolean canPlay() + { + SpellAbility sa; + for (int i=0; i3; + } + }; + card.clearSpellAbility(); + card.addSpellAbility(summoningSpell); + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + + AllZone.GameAction.getPlayerLife(card.getController()).subtractLife(3); + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = 2334517567512130479L; + + public void execute() + { + ability.setStackDescription("Serpent Warrior - " + +card.getController() +" loses 3 life"); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Eviscerator")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(card.getController()).subtractLife(5); + } + public boolean canPlayAI() + { + return 8 < AllZone.Computer_Life.getLife(); + } + }; + Command intoPlay = new Command() + { + + private static final long serialVersionUID = -221296021551561668L; + + public void execute() + { + ability.setStackDescription("Eviscerator - " +card.getController() +" loses 5 life"); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Foul Imp")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(card.getController()).subtractLife(2); + } + public boolean canPlayAI() + { + return 4 < AllZone.Computer_Life.getLife(); + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = -5371716833341661084L; + + public void execute() + { + ability.setStackDescription("Foul Imp - " +card.getController() +" loses 2 life"); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Drekavac")) + { + final Input discard = new Input() + { + private static final long serialVersionUID = -6392468000100283596L; + + public void showMessage() + { + AllZone.Display.showMessage("Discard from your hand a non-creature card"); + ButtonUtil.disableAll(); + } + public void selectCard(Card c, PlayerZone zone) + { + if(zone.is(Constant.Zone.Hand)) + { + AllZone.GameAction.discard(c); + if(c.isCreature()) + AllZone.GameAction.sacrifice(card); + stop(); + } + } + };//Input + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + if(card.getController().equals(Constant.Player.Human)) + { + if(AllZone.Human_Hand.getCards().length == 0) + AllZone.GameAction.sacrifice(card); + else + AllZone.InputControl.setInput(discard); + } + else + { + CardList list = new CardList(AllZone.Computer_Hand.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (!c.isCreature()); + } + }); + AllZone.GameAction.discard(list.get(0)); + }//else + }//resolve() + };//SpellAbility + Command intoPlay = new Command() + { + private static final long serialVersionUID = 9202753910259054021L; + + public void execute() + { + ability.setStackDescription(card.getController() +" sacrifices Drekavac unless he discards a non-creature card"); + AllZone.Stack.add(ability); + } + }; + SpellAbility spell = new Spell_Permanent(card) + { + private static final long serialVersionUID = -2940969025405788931L; + + //could never get the AI to work correctly + //it always played the same card 2 or 3 times + public boolean canPlayAI() {return false;} + + public boolean canPlay() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + CardList list = new CardList(hand.getCards()); + list.remove(card); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (!c.isCreature()); + } + }); + return list.size() != 0; + }//canPlay() + }; + card.addComesIntoPlayCommand(intoPlay); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Minotaur Explorer")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + if(hand.getCards().length == 0) + AllZone.GameAction.sacrifice(card); + else + AllZone.GameAction.discardRandom(card.getController()); + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = 4986114285467649619L; + + public void execute() + { + ability.setStackDescription(card.getController() +" - discards at random or sacrifices Minotaur Explorer"); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Goretusk Firebeast")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + AllZone.GameAction.getPlayerLife(opponent).subtractLife(4); + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = 2977308349468915040L; + + public void execute() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + ability.setStackDescription("Goretusk Firebeast - deals 4 damage to " +opponent); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Goblin Ringleader")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone libraryZone = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand , card.getController()); + + //get top 4 cards of the library + CardList top = new CardList(); + Card[] library = libraryZone.getCards(); + for(int i = 0; i < 4 && i < library.length; i++) + top.add(library[i]); + + //put top 4 cards on bottom of library + for(int i = 0; i < top.size(); i++) + { + libraryZone.remove(top.get(i)); + libraryZone.add(top.get(i)); + } + + CardList goblin = top.getType("Goblin"); + + for(int i = 0; i < goblin.size(); i++) + AllZone.GameAction.moveTo(hand, goblin.get(i)); + }//resolve() + };//SpellAbility + Command intoPlay = new Command() + { + private static final long serialVersionUID = -7538870520237796620L; + + public void execute() + { + AllZone.Stack.add(ability); + } + }; + ability.setStackDescription("Goblin Ringleader - reveal the top four cards of your library. Put all Goblin cards revealed this way into your hand and the rest on the bottom of your library."); + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Sylvan Messenger")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone libraryZone = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand , card.getController()); + + //get top 4 cards of the library + CardList top = new CardList(); + Card[] library = libraryZone.getCards(); + for(int i = 0; i < 4 && i < library.length; i++) + top.add(library[i]); + + //put top 4 cards on bottom of library + for(int i = 0; i < top.size(); i++) + { + libraryZone.remove(top.get(i)); + libraryZone.add(top.get(i)); + } + + CardList goblin = top.getType("Elf"); + + for(int i = 0; i < goblin.size(); i++) + AllZone.GameAction.moveTo(hand, goblin.get(i)); + }//resolve() + };//SpellAbility + Command intoPlay = new Command() + { + private static final long serialVersionUID = 4757054648163014149L; + + public void execute() + { + AllZone.Stack.add(ability); + } + }; + ability.setStackDescription("Sylvan Messenger - reveal the top four cards of your library. Put all Elf cards revealed this way into your hand and the rest on the bottom of your library."); + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Child of Alara")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + + + for(int i = 0; i < list.size(); i++) + if(!list.get(i).getType().contains("Land")) + { + Card c = list.get(i); + AllZone.GameAction.destroyNoRegeneration(c); + } + } + }; + Command destroy = new Command() + { + private static final long serialVersionUID = -2937565366066183385L; + + public void execute() + { + AllZone.Stack.add(ability); + } + }; + ability.setStackDescription("Child of Alara - Destroy all non-land permanents, they can't be regenerated"); + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Ryusei, the Falling Star")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + for(int i = 0; i < list.size(); i++) + if(! list.get(i).getKeyword().contains("Flying") && CardFactoryUtil.canDamage(card, list.get(i))) + list.get(i).addDamage(5); + } + }; + Command destroy = new Command() + { + private static final long serialVersionUID = -6585074939675844265L; + + public void execute() + { + AllZone.Stack.add(ability); + } + }; + ability.setStackDescription("Ryusei, the Falling Star - deals 5 damage to each creature without flying"); + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Sleeper Agent")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve(){ + @SuppressWarnings("unused") // opponent + String opponent = card.getController(); + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(false); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(false); + + PlayerZone from = AllZone.getZone(card); + from.remove(card); + + card.setController(AllZone.GameAction.getOpponent(card.getOwner())); + + PlayerZone to = AllZone.getZone(Constant.Zone.Play, AllZone.GameAction.getOpponent(card.getOwner())); + to.add(card); + System.out.println("cards controller = " + card.getController()); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(true); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(true); + } + }; + + ability.setStackDescription("When Sleeper Agent comes into play, target opponent gains control of it."); + Command intoPlay = new Command() + { + private static final long serialVersionUID = -3934471871041458847L; + + public void execute() + { + AllZone.Stack.add(ability); + + }//execute() + }; + card.addComesIntoPlayCommand(intoPlay); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Flametongue Kavu")) + { + final CommandReturn getCreature = new CommandReturn() + { + //get target card, may be null + public Object execute() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(4, card, true); + CardListUtil.sortAttack(list); + CardListUtil.sortFlying(list); + + if(list.size() != 0) + { + Card c = list.get(0); + if(3 <= c.getNetAttack() || + (2 <= c.getNetAttack() && c.getKeyword().contains("Flying"))) + return c; + } + if((AllZone.Computer_Life.getLife() < 10) && + (CardFactoryUtil.AI_getHumanCreature(card, true).size() != 0)) + { + list = CardFactoryUtil.AI_getHumanCreature(card, true); + CardListUtil.sortAttack(list); + CardListUtil.sortFlying(list); + + return list.get(0); + } + return null; + }//execute() + };//CommandReturn + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canDamage(card, getTargetCard()) && CardFactoryUtil.canTarget(card,getTargetCard()) ) + AllZone.GameAction.addDamage(getTargetCard(), 4); + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = -1920425335456952853L; + + public void execute() + { + if(card.getController().equals(Constant.Player.Human)) + { + AllZone.InputControl.setInput(CardFactoryUtil.input_targetCreature(ability)); + ButtonUtil.disableAll(); + } + else//computer + { + Object o = getCreature.execute(); + if(o != null)//should never happen, but just in case + { + ability.setTargetCard((Card)o); + AllZone.Stack.add(ability); + } + else { + ability.setTargetCard(card); + AllZone.Stack.add(ability); + } + }//else + }//execute() + }; + card.addComesIntoPlayCommand(intoPlay); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = 5741146386242415357L; + + public boolean canPlayAI() + { + Object o = getCreature.execute(); + + return (o != null) && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Shriekmaw")) + { + final CommandReturn getCreature = new CommandReturn() + { + //get target card, may be null + public Object execute() + { + CardList nonblack = CardFactoryUtil.AI_getHumanCreature(card, true); + nonblack = nonblack.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return(!c.isArtifact() && !CardUtil.getColors(c).contains(Constant.Color.Black)); + } + }); + + CardList list = new CardList(nonblack.toArray()); + CardListUtil.sortAttack(list); + CardListUtil.sortFlying(list); + + if(list.size() != 0) + { + Card c = list.get(0); + if(2 <= c.getNetAttack() && c.getKeyword().contains("Flying")) + return c; + } + + if((AllZone.Computer_Life.getLife() < 10) && list.size() != 0) + { + CardListUtil.sortAttack(list); + + if(MyRandom.percentTrue(50)) + CardListUtil.sortFlying(list); + + return list.get(0); + } + return null; + }//execute() + };//CommandReturn + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card,c) && + !CardUtil.getColors(c).contains(Constant.Color.Black) && + !c.isArtifact()) + { + AllZone.GameAction.destroy(c); + } + }//resolve() + };//SpellAbility + Command intoPlay = new Command() + { + private static final long serialVersionUID = -70141932446179740L; + + public void execute() + { + Input target = new Input() + { + private static final long serialVersionUID = 2634600975568025031L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target nonartifact, nonblack creature to destroy"); + ButtonUtil.disableAll(); + } + public void selectCard(Card card, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(ability, card)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + else if(card.isCreature() && zone.is(Constant.Zone.Play) && + !card.isArtifact() && !CardUtil.getColors(card).contains(Constant.Color.Black)) + { + ability.setTargetCard(card); + AllZone.Stack.add(ability); + stop(); + } + } + };//Input target + + + if(card.getController().equals(Constant.Player.Human)) + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return(!c.isArtifact() && !CardUtil.getColors(c).contains(Constant.Color.Black)); + } + }); + + if(list.size() != 0) + AllZone.InputControl.setInput(target); +// AllZone.InputControl.setInput(CardFactoryUtil.input_targetCreature(ability)); + } + else//computer + { + Object o = getCreature.execute(); + if(o != null)//should never happen, but just in case + { + ability.setTargetCard((Card)o); + AllZone.Stack.add(ability); + } + }//else + }//execute() + }; + card.addComesIntoPlayCommand(intoPlay); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = -7508374608705757486L; + + public boolean canPlayAI() + { + Object o = getCreature.execute(); + + return (o != null) && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + + card.addSpellAbility(new Spell_Evoke(card, "1 B") + { + private static final long serialVersionUID = 6838065487515852527L; + + public boolean canPlayAI() + { + Object o = getCreature.execute(); + + return (o != null) && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Briarhorn")) + { + final CommandReturn getCreature = new CommandReturn() + { + //get target card, may be null + public Object execute() + { + Combat combat = ComputerUtil.getAttackers(); + Card[] c = combat.getAttackers(); + + if(c.length == 0) + { + CardList list = new CardList(); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return(c.isCreature() && !c.hasSickness()); + } + }); + + if(list.size() == 0) + return card; + else + { + CardListUtil.sortAttack(list); + CardListUtil.sortFlying(list); + + for(int i = 0; i < list.size(); i++) + if(list.get(i).isUntapped()) + return list.get(i); + + return list.get(0); + } + + } + + return c[0]; + }//execute() + };//CommandReturn + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + final Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card,c)) + { + c.addTempAttackBoost(3); + c.addTempDefenseBoost(3); + + AllZone.EndOfTurn.addUntil(new Command() + { + private static final long serialVersionUID = -5417966443737481535L; + + public void execute() + { + c.addTempAttackBoost(-3); + c.addTempDefenseBoost(-3); + } + }); + }//if + }//resolve() + };//SpellAbility + Command intoPlay = new Command() + { + private static final long serialVersionUID = -5497111036332352337L; + + public void execute() + { + if(card.getController().equals(Constant.Player.Human)) + { + AllZone.InputControl.setInput(CardFactoryUtil.input_targetCreature(ability)); + } + else//computer + { + Object o = getCreature.execute(); + if(o != null)//should never happen, but just in case + { + ability.setTargetCard((Card)o); + AllZone.Stack.add(ability); + } + }//else + }//execute() + }; + card.addComesIntoPlayCommand(intoPlay); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = -681505091538444209L; + + public boolean canPlayAI() + { + Object o = getCreature.execute(); + + return (o != null) && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + + card.addSpellAbility(new Spell_Evoke(card, "1 G") + { + private static final long serialVersionUID = 8565746177492779899L; + + public boolean canPlayAI() + { + return false; + } + //because this card has Flash + public boolean canPlay() + { + if (!AllZone.GameAction.isCardInPlay(card)) + return true; + else + return false; + } + }); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Inner-Flame Acolyte")) + { + final CommandReturn getCreature = new CommandReturn() + { + //get target card, may be null + public Object execute() + { + Combat combat = ComputerUtil.getAttackers(); + Card[] c = combat.getAttackers(); + CardList list = new CardList(); + + if(c.length == 0) + { + list.addAll(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature(); + } + }); + + if(list.size() == 0) + return card; + else + { + CardListUtil.sortAttack(list); + CardListUtil.sortFlying(list); + + for(int i = 0; i < list.size(); i++) + if(list.get(i).isUntapped()) + return list.get(i); + + return list.get(0); + } + } + + return c[0]; + }//execute() + };//CommandReturn + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + final Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card,c) ) + { + c.addTempAttackBoost(2); + c.addExtrinsicKeyword("Haste"); + + AllZone.EndOfTurn.addUntil(new Command() + { + private static final long serialVersionUID = -6478147896119509688L; + + public void execute() + { + c.addTempAttackBoost(-2); + c.removeExtrinsicKeyword("Haste"); + } + }); + }//if + }//resolve() + };//SpellAbility + Command intoPlay = new Command() + { + private static final long serialVersionUID = -4514610171270596654L; + + public void execute() + { + if(card.getController().equals(Constant.Player.Human)) + { + AllZone.InputControl.setInput(CardFactoryUtil.input_targetCreature(ability)); + } + else//computer + { + Object o = getCreature.execute(); + if(o != null)//should never happen, but just in case + { + ability.setTargetCard((Card)o); + AllZone.Stack.add(ability); + } + }//else + }//execute() + }; + card.addComesIntoPlayCommand(intoPlay); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = 7153795935713327863L; + + public boolean canPlayAI() + { + Object o = getCreature.execute(); + + return (o != null) && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + + card.addSpellAbility(new Spell_Evoke(card, "R") + { + private static final long serialVersionUID = 8173305091293824506L; + + public boolean canPlayAI() + { + return false; + } + }); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Timetwister")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 505983020365091226L; + + public void resolve() + { + discardDraw7(Constant.Player.Human); + discardDraw7(Constant.Player.Computer); + }//resolve() + + void discardDraw7(String player) + { + // Discard hand into graveyard + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player); + Card[] c = hand.getCards(); + for(int i = 0; i < c.length; i++) + AllZone.GameAction.discard(c[i]); + + // Move graveyard into library + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + Card[] g = grave.getCards(); + for (int i = 0; i < g.length; i++) + { + grave.remove(g[i]); + library.add(g[i],0); + } + + // Shuffle library + AllZone.GameAction.shuffle(player); + + // Draw seven cards + for(int i = 0; i < 7; i++) + AllZone.GameAction.drawCard(player); + + library.remove(card); + grave.add(card); + } + + // Simple, If computer has two or less playable cards remaining in hand play Timetwister + public boolean canPlayAI() + { + Card[] c = removeLand(AllZone.Computer_Hand.getCards()); + return 2 >= c.length; + } + Card[] removeLand(Card[] in) + { + CardList c = new CardList(in); + c = c.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return !c.isLand(); + } + }); + return c.toArray(); + }//removeLand() + + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Slaughterhouse Bouncer")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canDamage(card, getTargetCard()) && CardFactoryUtil.canTarget(card,getTargetCard()) ) + getTargetCard().addDamage(3); + } + }; + Command destroy = new Command() + { + private static final long serialVersionUID = 1619442728548153928L; + + public void execute() + { + //check to see if any other creatures in play + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + //check to see if any cards in hand + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + if(hand.getCards().length == 0 && list.size() != 0) + { + if(card.getController().equals(Constant.Player.Human)) + { + AllZone.InputControl.setInput(CardFactoryUtil.input_targetCreature(ability)); + ButtonUtil.disableAll(); + } + else//computer + { + //1.try to get human creature with defense of 3 + list = CardFactoryUtil.AI_getHumanCreature(card, true); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) {return c.getNetDefense() == 3;} + }); + //2.try to get human creature with defense of 2 or less + if(list.isEmpty()) + list = CardFactoryUtil.AI_getHumanCreature(2, card, true); + //3.get any computer creature + if(list.isEmpty()) + { + list = new CardList(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + } + list.shuffle(); + ability.setTargetCard(list.get(0)); + AllZone.Stack.add(ability); + } + }//if ok to play + }//execute() + };//Command + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Undying Beast")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + card.setDamage(0); + card.setAssignedDamage(0); + card.untap(); + + //moves card to top of library + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getOwner()); + library.add(card, 0); + } + }; + Command destroy = new Command() + { + private static final long serialVersionUID = -318081458847722674L; + + public void execute() + { + if(card.isToken()) + return; + + //remove from graveyard + PlayerZone grave = AllZone.getZone(card); + grave.remove(card); + + ability.setStackDescription("Put Undying Beast on top of its owner's library."); + AllZone.Stack.add(ability); + } + }; + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Fire Imp") || cardName.equals("Corrupt Eunuchs")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canDamage(card, getTargetCard()) && CardFactoryUtil.canTarget(card,getTargetCard()) ) + getTargetCard().addDamage(2); + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = -7639628386947162984L; + + public void execute() + { + if(card.getController().equals(Constant.Player.Human)) + { + AllZone.InputControl.setInput(CardFactoryUtil.input_targetCreature(ability)); + ButtonUtil.disableAll(); + } + else//computer + { + CardList list = CardFactoryUtil.AI_getHumanCreature(2, card, true); + CardListUtil.sortAttack(list); + CardListUtil.sortFlying(list); + + if(list.isEmpty()) + { + list = CardFactoryUtil.AI_getHumanCreature(card, true); + list.shuffle(); + } + + if (list.size() > 0) + ability.setTargetCard(list.get(0)); + else + ability.setTargetCard(card); + + AllZone.Stack.add(ability); + }//else + }//execute() + };//Command + card.addComesIntoPlayCommand(intoPlay); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = 1731831041621831246L; + + public boolean canPlayAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(card, true); + + return (list.size() > 0) && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Man-o'-War") || cardName.equals("Sun Ce, Young Conquerer")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + Card c = getTargetCard(); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, c.getOwner()); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card,getTargetCard()) ) + { + AllZone.getZone(c).remove(c); + + if(! c.isToken()) + { + Card newCard = AllZone.CardFactory.getCard(c.getName(), c.getOwner()); + hand.add(newCard); + } + } + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = -7628289586347295144L; + + public void execute() + { + if(card.getController().equals(Constant.Player.Human)) + { + AllZone.InputControl.setInput(CardFactoryUtil.input_targetCreature(ability)); + ButtonUtil.disableAll(); + } + else//computer + { + Card human = CardFactoryUtil.AI_getBestCreature(CardFactoryUtil.AI_getHumanCreature(card, true)); + ability.setTargetCard(human); + + + if (human == null) + ability.setTargetCard(card); + + AllZone.Stack.add(ability); + }//else + }//execute() + };//Command + card.addComesIntoPlayCommand(intoPlay); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = 2458286917800051358L; + + public boolean canPlayAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(card, true); + + return (list.size() > 0) && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Keening Banshee")) + { + + final SpellAbility ability = new Ability(card, "0") + { + + public void resolve() + { + final Card c = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card,c) ) + { + c.addTempAttackBoost(-2); + c.addTempDefenseBoost(-2); + + AllZone.EndOfTurn.addUntil(new Command() + { + private static final long serialVersionUID = 8479364459667467780L; + + public void execute() + { + c.addTempAttackBoost(2); + c.addTempDefenseBoost(2); + } + }); + } + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = 6283666887577455663L; + + public void execute() + { + if(card.getController().equals(Constant.Player.Human)) + { + AllZone.InputControl.setInput(CardFactoryUtil.input_targetCreature(ability)); + ButtonUtil.disableAll(); + } + else//computer + { + CardList list = CardFactoryUtil.AI_getHumanCreature(2, card, true); + CardListUtil.sortAttack(list); + CardListUtil.sortFlying(list); + + if(list.isEmpty()) + { + list = CardFactoryUtil.AI_getHumanCreature(card, true); + list.shuffle(); + } + + ability.setTargetCard(list.get(0)); + AllZone.Stack.add(ability); + }//else + }//execute() + };//Command + card.addComesIntoPlayCommand(intoPlay); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = -1893090545602255371L; + + public boolean canPlayAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(card, true); + + return (list.size() > 0) && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Dragon Roost")) + { + final SpellAbility ability = new Ability(card, "5 R R") + { + public void resolve() + { + Card c = new Card(); + + c.setName("Dragon"); + c.setImageName("R 5 5 Dragon"); + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("R"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Dragon"); + c.setBaseAttack(5); + c.setBaseDefense(5); + c.addIntrinsicKeyword("Flying"); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//resolve() + }; + ability.setDescription("5RR: Put a 5/5 red Dragon creature token with flying into play."); + ability.setStackDescription("Dragon Roost - Put a 5/5 red Dragon creature token with flying into play."); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("The Hive")) + { + final SpellAbility ability = new Ability_Tap(card, "5") + { + private static final long serialVersionUID = -1091111822316858416L; + + public void resolve() + { + Card c = new Card(); + c.setName("Wasp"); + c.setImageName("C 1 1 Wasp"); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost(""); + c.setToken(true); + + c.addType("Artifact"); + c.addType("Creature"); + c.addType("Insect"); + + c.setBaseAttack(1); + c.setBaseDefense(1); + c.addIntrinsicKeyword("Flying"); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//resolve() + }; + ability.setDescription("5, tap: Put a 1/1 Insect artifact creature token with flying named Wasp into play."); + ability.setStackDescription("The Hive - Put a 1/1 token with flying into play."); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Mobilization")) + { + final SpellAbility ability = new Ability(card, "2 W") + { + public void resolve() + { + Card c = new Card(); + c.setName("Soldier"); + c.setImageName("W 1 1 Soldier"); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("W"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Soldier"); + + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//resolve() + }; + ability.setDescription("2W: Put a 1/1 white Soldier creature token into play."); + ability.setStackDescription("Mobilization - Put a 1/1 Soldier token into play."); + card.addSpellAbility(ability); + + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Ant Queen")) + { + final SpellAbility ability = new Ability(card, "1 G") + { + public void resolve() + { + Card c = new Card(); + c.setName("Insect"); + c.setImageName("G 1 1 Insect"); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Insect"); + + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//resolve() + }; + ability.setDescription("1 G: Put a 1/1 green Insect creature token onto the battlefield."); + ability.setStackDescription(card.getName() + " - Put a 1/1 green Insect token onto the battlefield."); + card.addSpellAbility(ability); + + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Centaur Glade")) + { + final SpellAbility ability = new Ability(card, "2 G G") + { + public void resolve() + { + Card c = new Card(); + c.setName("Centaur"); + c.setImageName("G 3 3 Centaur"); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Centaur"); + + c.setBaseAttack(3); + c.setBaseDefense(3); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//resolve() + }; + ability.setDescription("2GG: Put a 3/3 green Centaur creature token into play."); + ability.setStackDescription("Centaur Glade - Put a 3/3 token into play."); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Eternal Witness")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + if(AllZone.GameAction.isCardInZone(getTargetCard(), grave)) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, getTargetCard()); + } + }//resolve() + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = 1658050744890095441L; + + public void execute() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + + if(grave.getCards().length == 0) + return; + + if(card.getController().equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Select target card", grave.getCards()); + if(o != null) + { + ability.setTargetCard((Card)o); + AllZone.Stack.add(ability); + } + } + else//computer + { + CardList list = new CardList(grave.getCards()); + Card best = CardFactoryUtil.AI_getBestCreature(list); + + if(best == null) + { + list.shuffle(); + best = list.get(0); + } + ability.setTargetCard(best); + AllZone.Stack.add(ability); + } + }//execute() + };//Command + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Gravedigger")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + if(AllZone.GameAction.isCardInZone(getTargetCard(), grave)) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, getTargetCard()); + } + }//resolve() + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = -7433708170033536384L; + + public void execute() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + CardList list = new CardList(grave.getCards()); + list = list.getType("Creature"); + + if(list.isEmpty()) + return; + + if(card.getController().equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Select target card", list.toArray()); + if(o != null) + { + ability.setTargetCard((Card)o); + AllZone.Stack.add(ability); + } + }//if + else//computer + { + Card best = CardFactoryUtil.AI_getBestCreature(list); + ability.setTargetCard(best); + AllZone.Stack.add(ability); + } + }//execute() + };//Command + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Strongarm Thug")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + if(AllZone.GameAction.isCardInZone(getTargetCard(), grave)) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, getTargetCard()); + } + }//resolve() + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = 4519970074391756730L; + + public void execute() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + CardList list = new CardList(grave.getCards()); + list = list.getType("Mercenary"); + + if(list.isEmpty()) + return; + + if(card.getController().equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Select target card", list.toArray()); + if(o != null) + { + ability.setTargetCard((Card)o); + AllZone.Stack.add(ability); + } + }//if + else//computer + { + Card best = CardFactoryUtil.AI_getBestCreature(list); + ability.setTargetCard(best); + AllZone.Stack.add(ability); + } + }//execute() + };//Command + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************ + if (cardName.equals("Aedun Oakenshield")) + { + final Ability_Tap ability = new Ability_Tap(card, "B R G") + { + private static final long serialVersionUID = -7913968639880781838L; + public boolean canPlayAI() {return getGraveCreatures().size() != 0;} + + public void chooseTargetAI() + { + CardList grave = getGraveCreatures(); + Card target = CardFactoryUtil.AI_getBestCreature(grave); + setTargetCard(target); + } + + public void resolve() + { + if(card.getController().equals(Constant.Player.Human)) + { + Card c = (Card) AllZone.Display.getChoice("Select card", getGraveCreatures().toArray()); + setTargetCard(c); + } + + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + + if(AllZone.GameAction.isCardInZone(getTargetCard(), grave)) + AllZone.GameAction.moveTo(hand, getTargetCard()); + }//resolve() + public boolean canPlay() + { + return getGraveCreatures().size() != 0; + } + CardList getGraveCreatures() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + CardList list = new CardList(grave.getCards()); + list = list.getType("Creature"); + return list; + } + };//SpellAbility + ability.setDescription("B R G, Tap: Return target creature card from your graveyard to your hand."); + ability.setStackDescription(cardName + " - return target creature from your graveyard to your hand."); + + card.clearSpellAbility(); + card.addSpellAbility(ability); + + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Raise Dead") || cardName.equals("Disentomb") || cardName.equals("Return to Battle") || + cardName.equals("Recover")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -5822375745105110975L; + public boolean canPlayAI() {return getGraveCreatures().size() != 0;} + + public void chooseTargetAI() + { + CardList grave = getGraveCreatures(); + Card target = CardFactoryUtil.AI_getBestCreature(grave); + setTargetCard(target); + } + + public void resolve() + { + if(card.getController().equals(Constant.Player.Human)) + { + Card c = (Card) AllZone.Display.getChoice("Select card", getGraveCreatures().toArray()); + setTargetCard(c); + } + + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + + if(AllZone.GameAction.isCardInZone(getTargetCard(), grave)) + AllZone.GameAction.moveTo(hand, getTargetCard()); + }//resolve() + public boolean canPlay() + { + return getGraveCreatures().size() != 0; + } + CardList getGraveCreatures() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + CardList list = new CardList(grave.getCards()); + list = list.getType("Creature"); + return list; + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Anarchist")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + if(AllZone.GameAction.isCardInZone(getTargetCard(), grave)) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, getTargetCard()); + } + }//resolve() + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = -7459412502903144952L; + + public void execute() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + CardList sorcery = new CardList(grave.getCards()); + sorcery = sorcery.getType("Sorcery"); + + String controller = card.getController(); + + if(sorcery.size() == 0) + return; + + if(controller.equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Select target card", sorcery.toArray()); + if(o != null) + { + ability.setTargetCard((Card)o); + AllZone.Stack.add(ability); + } + } + else //computer + { + sorcery.shuffle(); + ability.setTargetCard(sorcery.get(0)); + AllZone.Stack.add(ability); + } + + }//execute() + };//Command + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Penumbra Kavu")) + { + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Kavu"); + c.setImageName("B 3 3 Kavu"); + c.setManaCost("B"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Kavu"); + c.setBaseAttack(3); + c.setBaseDefense(3); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//resolve() + };//Ability + + Command destroy = new Command() + { + private static final long serialVersionUID = 1281791927604583468L; + + public void execute() + { + ability.setStackDescription(card.getController() +" puts a 3/3 creature into play from Penumbra Kavu"); + AllZone.Stack.add(ability); + } + }; + + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Penumbra Bobcat")) + { + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Cat"); + c.setImageName("B 2 1 Cat"); + c.setManaCost("B"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Cat"); + c.setBaseAttack(2); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//resolve() + };//Ability + + Command destroy = new Command() + { + private static final long serialVersionUID = -8057009255325020247L; + + public void execute() + { + ability.setStackDescription(card.getController() +" puts a 2/1 creature into play from Penumbra Bobcat"); + AllZone.Stack.add(ability); + } + }; + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Penumbra Spider")) + { + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Spider"); + c.setImageName("B 2 4 Spider"); + c.setManaCost("B"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Spider"); + c.setBaseAttack(2); + c.setBaseDefense(4); + c.addIntrinsicKeyword("Reach"); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//resolve() + };//Ability + + Command destroy = new Command() + { + private static final long serialVersionUID = 9186718803540678064L; + + public void execute() + { + ability.setStackDescription(card.getController() +" puts a 2/4 Black Spider creature into play from Penumbra Spider"); + AllZone.Stack.add(ability); + } + }; + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Penumbra Wurm")) + { + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Wurm"); + c.setImageName("B 6 6 Wurm"); + c.setManaCost("B"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Wurm"); + c.setBaseAttack(6); + c.setBaseDefense(6); + c.addIntrinsicKeyword("Trample"); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//resolve() + };//Ability + + Command destroy = new Command() + { + private static final long serialVersionUID = -8819664543962631239L; + + public void execute() + { + ability.setStackDescription(card.getController() +" puts a 6/6 Black Wurm creature with trample into play from Penumbra Wurm"); + AllZone.Stack.add(ability); + } + }; + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Aven Fisher") || cardName.equals("Riptide Crab")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + } + }; + Command destroy = new Command() + { + private static final long serialVersionUID = -2786138225183288814L; + + public void execute() + { + ability.setStackDescription(card.getName() + " - " + card.getController() +" draws a card"); + AllZone.Stack.add(ability); + } + }; + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Peregrine Drake")) + { + final Input untap = new Input() + { + private static final long serialVersionUID = 2287264826189281795L; + + int stop = 5; + int count = 0; + + public void showMessage() + { + AllZone.Display.showMessage("Select a land to untap"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(card.isLand() && zone.is(Constant.Zone.Play)) + { + card.untap(); + count++; + if(count == stop) + stop(); + } + }//selectCard() + }; + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + if(card.getController().equals("Human")) + AllZone.InputControl.setInput(untap); + else + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isLand() && c.isTapped(); + } + }); + for(int i = 0; i < 5 && i < list.size(); i++) + list.get(i).untap(); + }//else + }//resolve() + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = 3208277692165539396L; + + public void execute() + { + ability.setStackDescription(card.getController() +" untaps up to 5 lands."); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Cloud of Faeries")) + { + final Input untap = new Input() + { + private static final long serialVersionUID = -2167059918040912025L; + + int stop = 2; + int count = 0; + + public void showMessage() + { + AllZone.Display.showMessage("Select a land to untap"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(card.isLand() && zone.is(Constant.Zone.Play)) + { + card.untap(); + count++; + if(count == stop) + stop(); + } + }//selectCard() + }; + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + if(card.getController().equals("Human")) + AllZone.InputControl.setInput(untap); + else + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isLand() && c.isTapped(); + } + }); + for(int i = 0; i < 2 && i < list.size(); i++) + { + list.get(i).untap(); + } + }//else + }//resolve() + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = 7222997838166323277L; + + public void execute() + { + ability.setStackDescription(card.getController() +" untaps up to 2 lands."); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + + //add cycling + card.addSpellAbility(CardFactoryUtil.ability_cycle(card, "2")); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Vodalian Merchant")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + + if(card.getController().equals("Human")) + AllZone.InputControl.setInput(CardFactoryUtil.input_discard()); + else + AllZone.GameAction.discardRandom("Computer"); + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = -8924243774757009091L; + + public void execute() + { + ability.setStackDescription(card.getController() +" draws a card, then discards a card"); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Whirlpool Rider")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + //shuffle hand into library, then shuffle library + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand , card.getController()); + Card c[] = hand.getCards(); + for(int i = 0; i < c.length; i++) + AllZone.GameAction.moveTo(library, c[i]); + AllZone.GameAction.shuffle(card.getController()); + + //draw same number of cards as before + for(int i = 0; i < c.length; i++) + AllZone.GameAction.drawCard(card.getController()); + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = 6290392806910817877L; + + public void execute() + { + ability.setStackDescription(card.getController() +" shuffles the cards from his hand into his library, then draws that many cards."); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Sky Swallower")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + String opp = AllZone.GameAction.getOpponent(card.getController()); + PlayerZone oppPlay = AllZone.getZone(Constant.Zone.Play, opp); + PlayerZone myPlay = AllZone.getZone(Constant.Zone.Play, card.getController()); + + CardList list = new CardList(myPlay.getCards()); + list.remove(card);//doesn't move Sky Swallower + while(! list.isEmpty()) + { + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(false); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(false); + //so "comes into play" abilities don't trigger + ///list.get(0).addComesIntoPlayCommand(Command.Blank); + + oppPlay.add(list.get(0)); + myPlay.remove(list.get(0)); + + list.get(0).setController(opp); + list.remove(0); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(true); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(true); + } + }//resolve() + }; + + Command intoPlay = new Command() + { + private static final long serialVersionUID = -453410206437839334L; + + public void execute() + { + ability.setStackDescription(AllZone.GameAction.getOpponent(card.getController()) +" gains control of all other permanents you control"); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Terror")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 8809370679594989382L; + + public boolean canPlayAI() + { + return (getCreature().size() != 0) && (AllZone.Phase.getTurn() > 4); + } + public void chooseTargetAI() + { + Card best = CardFactoryUtil.AI_getBestCreature(getCreature()); + setTargetCard(best); + } + CardList getCreature() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(card, true); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (! CardUtil.getColors(c).contains(Constant.Color.Black)) && + (! c.getType().contains("Artifact")) && + (2 < c.getNetAttack()); + } + }); + return list; + }//getCreature() + public void resolve() + { + if (AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + AllZone.GameAction.destroyNoRegeneration(getTargetCard()); + }//resolve() + }; + + Input runtime = new Input() + { + private static final long serialVersionUID = -1750678113925588670L; + + public void showMessage() + { + CardList choice = new CardList(); + choice.addAll(AllZone.Human_Play.getCards()); + choice.addAll(AllZone.Computer_Play.getCards()); + + choice = choice.getType("Creature"); + choice = choice.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (! CardUtil.getColors(c).contains(Constant.Color.Black)) && + (! c.getType().contains("Artifact")); + } + }); + + stopSetNext(CardFactoryUtil.input_targetSpecific(spell, choice, "Select target non-artifact, non-black creature to destroy.", true)); + } + }; + + card.clearSpellAbility(); + spell.setBeforePayMana(runtime); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Expunge")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 5773953475935635628L; + + public boolean canPlayAI() + { + return (getCreature().size() != 0) && (AllZone.Phase.getTurn() > 4); + } + public void chooseTargetAI() + { + Card best = CardFactoryUtil.AI_getBestCreature(getCreature()); + setTargetCard(best); + } + CardList getCreature() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(card, true); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (! CardUtil.getColors(c).contains(Constant.Color.Black)) && + (! c.getType().contains("Artifact")) && + (2 < c.getNetAttack()); + } + }); + return list; + }//getCreature() + public void resolve() + { + AllZone.GameAction.destroyNoRegeneration(getTargetCard()); + }//resolve() + }; + + Input runtime = new Input() + { + private static final long serialVersionUID = 3015711791310250186L; + + public void showMessage() + { + CardList choice = new CardList(); + choice.addAll(AllZone.Human_Play.getCards()); + choice.addAll(AllZone.Computer_Play.getCards()); + + choice = choice.getType("Creature"); + choice = choice.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (! CardUtil.getColors(c).contains(Constant.Color.Black)) && + (! c.getType().contains("Artifact")); + } + }); + + stopSetNext(CardFactoryUtil.input_targetSpecific(spell, choice, "Select target non-artifact, non-black creature to destroy.", true)); + } + }; + + card.clearSpellAbility(); + spell.setBeforePayMana(runtime); + + spell.setDescription(card.getText()); + card.addSpellAbility(spell); + + + card.addSpellAbility(CardFactoryUtil.ability_cycle(card, "2")); + }//*************** END ************ END ************************** + + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Pongify")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -7657135492744577568L; + + public boolean canPlayAI() + { + return (getCreature().size() != 0) && (AllZone.Phase.getTurn() > 4); + } + public void chooseTargetAI() + { + Card best = CardFactoryUtil.AI_getBestCreature(getCreature()); + setTargetCard(best); + } + CardList getCreature() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(card, true); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (3 < c.getNetAttack()); + } + }); + return list; + }//getCreature() + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card,getTargetCard()) ) + { + PlayerZone play = AllZone.getZone(getTargetCard()); + makeToken(play, getTargetCard().getController()); + + AllZone.GameAction.destroyNoRegeneration(getTargetCard()); + } + }//resolve() + void makeToken(PlayerZone play, String controller) + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(controller); + + c.setName("Ape"); + c.setImageName("G 3 3 Ape"); + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Ape"); + c.setBaseAttack(3); + c.setBaseDefense(3); + + play.add(c); + } + };//SpellAbility + + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Devour in Shadow")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 215990562522519924L; + + public boolean canPlayAI() + { + return (getCreature().size() != 0) && (AllZone.Phase.getTurn() > 4); + } + public void chooseTargetAI() + { + Card best = CardFactoryUtil.AI_getBestCreature(getCreature()); + setTargetCard(best); + + if(AllZone.Computer_Life.getLife() <= best.getNetDefense()) + { + CardList human = CardFactoryUtil.AI_getHumanCreature(AllZone.Computer_Life.getLife() - 1, card, true); + CardListUtil.sortAttack(human); + + if(0 < human.size()) + setTargetCard(human.get(0)); + } + } + CardList getCreature() + { + return CardFactoryUtil.AI_getHumanCreature(card, true); + }//getCreature() + public void resolve() + { + if (AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + AllZone.GameAction.destroyNoRegeneration(getTargetCard()); + + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.subtractLife(getTargetCard().getNetDefense()); + } + }//resolve() + }; + + card.clearSpellAbility(); + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Terminate")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 3334967250557638367L; + + public boolean canPlayAI() + { + return (getCreature().size() != 0) && (AllZone.Phase.getTurn() > 4); + } + public void chooseTargetAI() + { + Card best = CardFactoryUtil.AI_getBestCreature(getCreature()); + setTargetCard(best); + + CardList human = CardFactoryUtil.AI_getHumanCreature(AllZone.Computer_Life.getLife() - 1, card, true); + CardListUtil.sortAttack(human); + + if(0 < human.size()) + setTargetCard(human.get(0)); + + } + CardList getCreature() + { + return CardFactoryUtil.AI_getHumanCreature(card, true); + }//getCreature() + public void resolve() + { + if (AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + AllZone.GameAction.destroyNoRegeneration(getTargetCard()); + }//resolve() + }; + + card.clearSpellAbility(); + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Kinsbaile Borderguard")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + card.addCounter(Counters.P1P1, countKithkin()); + //System.out.println("all counters: " +card.sumAllCounters()); + }//resolve() + + public int countKithkin() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList kithkin = new CardList(play.getCards()); + kithkin = kithkin.filter(new CardListFilter() + { + + public boolean addCard(Card c) + { + return (c.getType().contains("Kithkin") || c.getKeyword().contains("Changeling"))&& !c.equals(card); + } + + }); + return kithkin.size(); + + } + @SuppressWarnings("unused") // makeToken + public void makeToken() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Kithkin Soldier"); + c.setImageName("W 1 1 Kithkin Soldier"); + c.setManaCost("W"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Kithkin"); + c.addType("Soldier"); + + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = -7067218066522935060L; + + public void execute() + { + ability.setStackDescription("Kinsbaile Borderguard comes into play with a +1/+1 counter on it for each other Kithkin you control."); + AllZone.Stack.add(ability); + } + }; + + final SpellAbility ability2 = new Ability(card, "0") + { + public void resolve() + { + for (int i=0;i 0 && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Wren's Run Packmaster")) + { + final CommandReturn getCreature = new CommandReturn() + { + public Object execute() + { + //get all creatures + CardList list = new CardList(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + list.addAll(play.getCards()); + + list = list.filter(new CardListFilter(){ + public boolean addCard(Card c) { + return c.getType().contains("Elf") || c.getKeyword().contains("Changeling"); + } + }); + + return list; + } + };//CommandReturn + + final SpellAbility abilityComes = new Ability(card, "0") + { + public void resolve() + { + if (getTargetCard() == null || getTargetCard() == card) + AllZone.GameAction.sacrifice(card); + + else if(AllZone.GameAction.isCardInPlay(getTargetCard())) + { + /* + PlayerZone play = AllZone.getZone(getTargetCard()); + PlayerZone removed = AllZone.getZone(Constant.Zone.Removed_From_Play, getTargetCard().getController()); + play.remove(getTargetCard()); + removed.add(getTargetCard()); + */ + AllZone.GameAction.removeFromGame(getTargetCard()); + } + }//resolve() + }; + + final Input inputComes = new Input() + { + private static final long serialVersionUID = 5210700665533271691L; + + public void showMessage() + { + CardList choice = (CardList)getCreature.execute(); + + stopSetNext(CardFactoryUtil.input_targetSpecific(abilityComes, choice, "Select Elf to remove from the game", false)); + ButtonUtil.disableAll(); //target this card means: sacrifice this card + } + }; + Command commandComes = new Command() + { + + private static final long serialVersionUID = -3580408066322945328L; + + public void execute() + { + CardList creature = (CardList)getCreature.execute(); + String s = card.getController(); + if(creature.size() == 0) { + AllZone.GameAction.sacrifice(card); + return; + } + else if(s.equals(Constant.Player.Human)) + AllZone.InputControl.setInput(inputComes); + else //computer + { + Card target; + //must target computer creature + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + computer = computer.getType("Elf"); + computer.remove(card); + + computer.shuffle(); + if (computer.size()!= 0) { + target = computer.get(0); + abilityComes.setTargetCard(target); + AllZone.Stack.add(abilityComes); + } + }//else + }//execute() + };//CommandComes + Command commandLeavesPlay = new Command() + { + + private static final long serialVersionUID = -5903638227914705191L; + + public void execute() + { + //System.out.println(abilityComes.getTargetCard().getName()); + Object o = abilityComes.getTargetCard(); + + if(o == null || ((Card)o).isToken()|| !AllZone.GameAction.isCardRemovedFromGame((Card)o) ) + return; + + SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + //copy card to reset card attributes like attack and defense + Card c = abilityComes.getTargetCard(); + if(! c.isToken()) + { + c = AllZone.CardFactory.copyCard(c); + c.setController(c.getOwner()); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getOwner()); + PlayerZone removed = AllZone.getZone(Constant.Zone.Removed_From_Play, c.getOwner()); + removed.remove(c); + play.add(c); + + } + }//resolve() + };//SpellAbility + ability.setStackDescription(card.getName() + " - returning creature to play"); + AllZone.Stack.add(ability); + }//execute() + };//Command + + + final SpellAbility a1 = new Ability(card, "2 G") + { + public boolean canPlayAI() + { + return MyRandom.random.nextBoolean(); + } + public boolean canPlay() + { + SpellAbility sa; + //this is a hack, check the stack to see if this card has an ability on the stack + //if so, we can't use the ability + for (int i=0; i 0 && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + + card.addSpellAbility(a1); + a1.setBeforePayMana(new Input_PayManaCost(a1)); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Changeling Berserker") || cardName.equals("Changeling Hero") || cardName.equals("Changeling Titan")) + { + final CommandReturn getCreature = new CommandReturn() + { + public Object execute() + { + //get all creatures + CardList list = new CardList(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + list.addAll(play.getCards()); + + list = list.filter(new CardListFilter(){ + public boolean addCard(Card c) { + return c.getType().contains("Creature"); + } + }); + + return list; + } + };//CommandReturn + + final SpellAbility abilityComes = new Ability(card, "0") + { + public void resolve() + { + if (getTargetCard() == null || getTargetCard() == card) + AllZone.GameAction.sacrifice(card); + + else if(AllZone.GameAction.isCardInPlay(getTargetCard()) ) + { + /* + PlayerZone play = AllZone.getZone(getTargetCard()); + PlayerZone removed = AllZone.getZone(Constant.Zone.Removed_From_Play, getTargetCard().getController()); + play.remove(getTargetCard()); + removed.add(getTargetCard()); + */ + AllZone.GameAction.removeFromGame(getTargetCard()); + } + }//resolve() + }; + + final Input inputComes = new Input() + { + + private static final long serialVersionUID = 5210700665533271691L; + + public void showMessage() + { + CardList choice = (CardList)getCreature.execute(); + + stopSetNext(CardFactoryUtil.input_targetSpecific(abilityComes, choice, "Select creature to remove from the game", false)); + ButtonUtil.disableAll(); + } + }; + Command commandComes = new Command() + { + + private static final long serialVersionUID = -3580408066322945328L; + + public void execute() + { + CardList creature = (CardList)getCreature.execute(); + String s = card.getController(); + if(creature.size() == 0) { + AllZone.GameAction.sacrifice(card); + return; + } + else if(s.equals(Constant.Player.Human)) + AllZone.InputControl.setInput(inputComes); + else //computer + { + Card target; + //must target computer creature + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + computer = computer.getType("Creature"); + computer.remove(card); + + computer.shuffle(); + if (computer.size()!= 0) { + target = computer.get(0); + abilityComes.setTargetCard(target); + AllZone.Stack.add(abilityComes); + } + }//else + }//execute() + };//CommandComes + Command commandLeavesPlay = new Command() + { + + private static final long serialVersionUID = -5903638227914705191L; + + public void execute() + { + //System.out.println(abilityComes.getTargetCard().getName()); + Object o = abilityComes.getTargetCard(); + + if(o == null || ((Card)o).isToken()|| !AllZone.GameAction.isCardRemovedFromGame((Card)o) ) + return; + + SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + //copy card to reset card attributes like attack and defense + Card c = abilityComes.getTargetCard(); + if(! c.isToken()) + { + c = AllZone.CardFactory.copyCard(c); + c.setController(c.getOwner()); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getOwner()); + PlayerZone removed = AllZone.getZone(Constant.Zone.Removed_From_Play, c.getOwner()); + removed.remove(c); + play.add(c); + + } + }//resolve() + };//SpellAbility + ability.setStackDescription(card.getName() + " - returning creature to play"); + AllZone.Stack.add(ability); + }//execute() + };//Command + + card.addComesIntoPlayCommand(commandComes); + card.addLeavesPlayCommand(commandLeavesPlay); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + + private static final long serialVersionUID = 2583297503017070549L; + + public boolean canPlayAI() + { + Object o = getCreature.execute(); + if (o == null) + return false; + + CardList cl = (CardList)getCreature.execute(); + return (o != null) && cl.size() > 0 && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Devout Lightcaster")) + { + final CommandReturn getBlackPerm = new CommandReturn() + { + public Object execute() + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter(){ + public boolean addCard(Card c) { + return c.isPermanent() && CardFactoryUtil.canTarget(card,c) && CardUtil.getColor(c).equals(Constant.Color.Black); + } + }); + + return list; + } + };//CommandReturn + + final SpellAbility abilityComes = new Ability(card, "0") + { + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card,getTargetCard()) ) + { + + AllZone.GameAction.removeFromGame(getTargetCard()); + } + }//resolve() + }; + + final Input inputComes = new Input() + { + private static final long serialVersionUID = 3762167908738465100L; + + public void showMessage() + { + CardList choice = (CardList)getBlackPerm.execute(); + + stopSetNext(CardFactoryUtil.input_targetSpecific(abilityComes, choice, "Select target black permanent to remove from the game", true)); + ButtonUtil.disableAll();//to disable the Cancel button + } + }; + Command commandComes = new Command() + { + + private static final long serialVersionUID = 3878683618127503416L; + + public void execute() + { + CardList creature = (CardList)getBlackPerm.execute(); + String s = card.getController(); + if(creature.size() == 0) + return; + else if(s.equals(Constant.Player.Human)) + AllZone.InputControl.setInput(inputComes); + else //computer + { + Card target; + + //try to target human permanent + PlayerZone hum = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList human = new CardList(hum.getCards()); + human = human.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.isPermanent() && CardUtil.getColor(c).equals(Constant.Color.Black); + } + + }); + //target = CardFactoryUtil.AI_getBestCreature(human);//returns null if list is empty + human.shuffle(); + target = null; + if (human.size()!=0) + target = human.get(0); + + if(target == null) + { + //must target computer creature + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + computer = computer.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.isPermanent() && CardUtil.getColor(c).equals(Constant.Color.Black); + } + + }); + + computer.shuffle(); + if (computer.size()!= 0) + target = computer.get(0); + } + abilityComes.setTargetCard(target); + AllZone.Stack.add(abilityComes); + }//else + }//execute() + };//CommandComes + + card.addComesIntoPlayCommand(commandComes); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + + private static final long serialVersionUID = -9059177006257139430L; + + public boolean canPlayAI() + { + Object o = getBlackPerm.execute(); + if (o == null) + return false; + + CardList cl = (CardList)getBlackPerm.execute(); + return (o != null) && cl.size() > 0 && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Faceless Butcher")) + { + final CommandReturn getCreature = new CommandReturn() + { + public Object execute() + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter(){ + public boolean addCard(Card c) { + return c.isCreature() && CardFactoryUtil.canTarget(card,c); + } + }); + + //remove "this card" + list.remove(card); + + return list; + } + };//CommandReturn + + final SpellAbility abilityComes = new Ability(card, "0") + { + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card,getTargetCard()) ) + { + /* + PlayerZone play = AllZone.getZone(getTargetCard()); + PlayerZone removed = AllZone.getZone(Constant.Zone.Removed_From_Play, getTargetCard().getController()); + play.remove(getTargetCard()); + removed.add(getTargetCard()); + */ + AllZone.GameAction.removeFromGame(getTargetCard()); + } + }//resolve() + }; + + final Input inputComes = new Input() + { + private static final long serialVersionUID = -1932054059769056049L; + + public void showMessage() + { + CardList choice = (CardList)getCreature.execute(); + + stopSetNext(CardFactoryUtil.input_targetSpecific(abilityComes, choice, "Select target creature to remove from the game", true)); + ButtonUtil.disableAll();//to disable the Cancel button + } + }; + Command commandComes = new Command() + { + private static final long serialVersionUID = -5675532512302863456L; + + public void execute() + { + CardList creature = (CardList)getCreature.execute(); + String s = card.getController(); + if(creature.size() == 0) + return; + else if(s.equals(Constant.Player.Human)) + AllZone.InputControl.setInput(inputComes); + else //computer + { + Card target; + + //try to target human creature + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + target = CardFactoryUtil.AI_getBestCreature(human);//returns null if list is empty + + if(target == null) + { + //must target computer creature + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + computer = computer.getType("Creature"); + computer.remove(card); + + computer.shuffle(); + if (computer.size()!= 0) + target = computer.get(0); + } + abilityComes.setTargetCard(target); + AllZone.Stack.add(abilityComes); + }//else + }//execute() + };//CommandComes + Command commandLeavesPlay = new Command() + { + private static final long serialVersionUID = 5518706316791622193L; + + public void execute() + { + //System.out.println(abilityComes.getTargetCard().getName()); + Object o = abilityComes.getTargetCard(); + + if(o == null || ((Card)o).isToken()|| !AllZone.GameAction.isCardRemovedFromGame((Card)o) ) + return; + + SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + //copy card to reset card attributes like attack and defense + Card c = abilityComes.getTargetCard(); + if(! c.isToken()) + { + c = AllZone.CardFactory.copyCard(c); + c.setController(c.getOwner()); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getOwner()); + PlayerZone removed = AllZone.getZone(Constant.Zone.Removed_From_Play, c.getOwner()); + removed.remove(c); + play.add(c); + + } + }//resolve() + };//SpellAbility + ability.setStackDescription("Faceless Butcher - returning creature to play"); + AllZone.Stack.add(ability); + }//execute() + };//Command + + card.addComesIntoPlayCommand(commandComes); + card.addLeavesPlayCommand(commandLeavesPlay); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + + private static final long serialVersionUID = -62128538015338896L; + + public boolean canPlayAI() + { + Object o = getCreature.execute(); + if (o == null) + return false; + + CardList cl = (CardList)getCreature.execute(); + return (o != null) && cl.size() > 0 && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Oblivion Ring")) + { + final CommandReturn getPerm = new CommandReturn() + { + public Object execute() + { + //get all creatures + CardList tempList = new CardList(); + tempList.addAll(AllZone.Human_Play.getCards()); + tempList.addAll(AllZone.Computer_Play.getCards()); + + CardList list = new CardList(); + + for(int i=0;i < tempList.size(); i++) + { + if(tempList.get(i).isPermanent() && !tempList.get(i).isLand() && CardFactoryUtil.canTarget(card, tempList.get(i)) ) + list.add(tempList.get(i)); + } + + //remove "this card" + list.remove(card); + + return list; + } + };//CommandReturn + + final SpellAbility abilityComes = new Ability(card, "0") + { + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card,getTargetCard()) ) + { + AllZone.GameAction.removeFromGame(getTargetCard()); + } + }//resolve() + }; + + final Input inputComes = new Input() + { + private static final long serialVersionUID = -3613946694360326887L; + + public void showMessage() + { + CardList choice = (CardList)getPerm.execute(); + + stopSetNext(CardFactoryUtil.input_targetSpecific(abilityComes, choice, "Select target permanent to remove from the game", true)); + ButtonUtil.disableAll();//to disable the Cancel button + } + }; + Command commandComes = new Command() + { + private static final long serialVersionUID = -6250376920501373535L; + + public void execute() + { + CardList perm = (CardList)getPerm.execute(); + String s = card.getController(); + if(perm.size() == 0) + return; + else if(s.equals(Constant.Player.Human)) + AllZone.InputControl.setInput(inputComes); + else //computer + { + Card target; + + //try to target human creature + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + target = CardFactoryUtil.AI_getBestCreature(human);//returns null if list is empty + + // try to target human permanent + if (target == null) + { + int convertedCost = 0; + CardList tempList = new CardList(); + tempList.addAll(AllZone.Human_Play.getCards()); + + @SuppressWarnings("unused") // list + CardList list = new CardList(); + for (int i=0;i convertedCost)) + { + target = tempList.get(i); + convertedCost = CardUtil.getConvertedManaCost(tempList.get(i).getManaCost()); + } + } + } + + //target something cheaper (manacost 0?) instead: + if (target == null) + { + CardList humanPerms = new CardList(); + humanPerms.addAll(AllZone.Human_Play.getCards()); + humanPerms = humanPerms.filter(new CardListFilter() { + public boolean addCard(Card c) { + return c.isPermanent() && !c.isLand() && CardFactoryUtil.canTarget(card, c); + } + }); + + if (humanPerms.size()>0) + target = humanPerms.get(0); + } + + if(target == null) + { + //must target computer creature + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + computer = computer.getType("Creature"); + computer.remove(card); + + computer.shuffle(); + if (computer.size() != 0) + target = computer.get(0); + else + target = card; + } + abilityComes.setTargetCard(target); + AllZone.Stack.add(abilityComes); + }//else + }//execute() + };//CommandComes + Command commandLeavesPlay = new Command() + { + private static final long serialVersionUID = 6997038208952910355L; + + public void execute() + { + Object o = abilityComes.getTargetCard(); + if(o == null || ((Card)o).isToken() || !AllZone.GameAction.isCardRemovedFromGame((Card)o) ) + return; + + SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + //copy card to reset card attributes like attack and defense + Card c = abilityComes.getTargetCard(); + if(! c.isToken()) + { + c = AllZone.CardFactory.copyCard(c); + c.setController(c.getOwner()); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getOwner()); + play.add(c); + } + }//resolve() + };//SpellAbility + ability.setStackDescription("Oblivion Ring - returning permanent to play."); + AllZone.Stack.add(ability); + }//execute() + };//Command + + card.addComesIntoPlayCommand(commandComes); + card.addLeavesPlayCommand(commandLeavesPlay); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = -3250095291930182087L; + + public boolean canPlayAI() + { + Object o = getPerm.execute(); + if (o == null) + return false; + + CardList cl = (CardList)getPerm.execute(); + return (o != null) && cl.size() > 0 && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + + }//*************** END ************ END ************************** + + + + /* + //*************** START *********** START ************************** + else if(cardName.equals("Oblivion Ring")) + { + final SpellAbility enchantment = new Spell(card) + { + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard())) + { + PlayerZone play = AllZone.getZone(getTargetCard()); + play.remove(getTargetCard()); + + //put permanent into play + Card c = getSourceCard(); + AllZone.getZone(Constant.Zone.Play, c.getController()).add(c); + } + }//resolve() + + public boolean canPlayAI() + { + //try to target human creature + CardList human = CardFactoryUtil.AI_getHumanCreature(); + Card target = CardFactoryUtil.AI_getBestCreature(human);//returns null if list is empty + + if(target == null) + return false; + else + { + setTargetCard(target); + return true; + } + }//canPlayAI() + };//SpellAbility enchantment + + + final Input target = new Input() + { + //showMessage() is always the first method called + public void showMessage() + { + AllZone.Display.showMessage("Select non-land to remove from the game."); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + + public void selectCard(Card c, PlayerZone zone) + { + if(zone.is(Constant.Zone.Play) && !c.isLand()) + { + enchantment.setTargetCard(c); + + stopSetNext(new Input_PayManaCost(enchantment)); + } + } + };//Input target + + Command commandDestroy = new Command() + { + public void execute() + { + Object o = enchantment.getTargetCard(); + if(o == null || ((Card)o).isToken()) + return; + + SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + //copy card to reset card attributes like attack and defense + Card c = enchantment.getTargetCard(); + if(! c.isToken()) + { + c = AllZone.CardFactory.copyCard(c); + c.setController(c.getOwner()); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getOwner()); + play.add(c); + } + }//resolve() + };//SpellAbility + ability.setStackDescription(card.getName() +" - returning creature to play"); + AllZone.Stack.add(ability); + }//execute() + };//Command + card.setDestroy(commandDestroy); + + card.clearSpellAbility(); + card.addSpellAbility(enchantment); + + enchantment.setBeforePayMana(target); + }//*************** END ************ END ************************** + + */ + + //*************** START *********** START ************************** + else if(cardName.equals("Oubliette")) + { + final SpellAbility enchantment = new Spell(card) + { + private static final long serialVersionUID = -6751177094537759827L; + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card,getTargetCard())) + { + AllZone.GameAction.removeFromGame(getTargetCard()); + + //put permanent into play + Card c = getSourceCard(); + AllZone.getZone(Constant.Zone.Play, c.getController()).add(c); + } + }//resolve() + + public boolean canPlayAI() + { + //try to target human creature + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + Card target = CardFactoryUtil.AI_getBestCreature(human);//returns null if list is empty + + if(target == null) + return false; + else + { + setTargetCard(target); + return true; + } + }//canPlayAI() + };//SpellAbility enchantment + + + @SuppressWarnings("unused") // target + final Input target = new Input() + { + private static final long serialVersionUID = -251660220889858176L; + + //showMessage() is always the first method called + public void showMessage() + { + AllZone.Display.showMessage("Select creature to remove from the game (sorry no phasing yet)."); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + + public void selectCard(Card c, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(enchantment, c)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + else if(zone.is(Constant.Zone.Play) && c.isCreature()) + { + enchantment.setTargetCard(c); + + stopSetNext(new Input_PayManaCost(enchantment)); + } + } + };//Input target + + Command commandLeavesPlay = new Command() + { + private static final long serialVersionUID = -2535098005246027777L; + + public void execute() + { + Object o = enchantment.getTargetCard(); + if(o == null || ((Card)o).isToken() || !AllZone.GameAction.isCardRemovedFromGame((Card)o) ) + return; + + SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + //copy card to reset card attributes like attack and defense + Card c = enchantment.getTargetCard(); + if(! c.isToken()) + { + c = AllZone.CardFactory.copyCard(c); + c.setController(c.getOwner()); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getOwner()); + play.add(c); + } + }//resolve() + };//SpellAbility + ability.setStackDescription(card.getName() +" - returning creature to play"); + AllZone.Stack.add(ability); + }//execute() + };//Command + card.addLeavesPlayCommand(commandLeavesPlay); + + card.clearSpellAbility(); + card.addSpellAbility(enchantment); + + enchantment.setBeforePayMana(CardFactoryUtil.input_targetCreature(enchantment)); + }//*************** END ************ END ************************** + + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Test Destroy")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 6637283804612570910L; + + public boolean canPlayAI() {return false;} + + public void resolve() + { + AllZone.GameAction.destroy(getTargetCard()); + }//resolve() + }; + + card.clearSpellAbility(); + spell.setBeforePayMana(CardFactoryUtil.input_targetType(spell, "All")); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Take Possession")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -7359291736123492910L; + + public boolean canPlayAI() {return 0 < CardFactoryUtil.AI_getHumanCreature(card, true).size();} + + public void chooseTargetAI() + { + Card best = CardFactoryUtil.AI_getBestCreature(CardFactoryUtil.AI_getHumanCreature(card, true)); + setTargetCard(best); + } + + public void resolve() + { + Card c = getTargetCard(); + c.setController(card.getController()); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(false); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(false); + + PlayerZone from = AllZone.getZone(c); + PlayerZone to = AllZone.getZone(Constant.Zone.Play, card.getController()); + + from.remove(c); + to.add(c); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(true); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(true); + + }//resolve() + }; + + card.clearSpellAbility(); + spell.setBeforePayMana(CardFactoryUtil.input_targetType(spell, "All")); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Night's Whisper")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -8594340516961923197L; + + public boolean canPlayAI() + { + return AllZone.Computer_Life.getLife()>2; + } + public void resolve() + { + //draw 2 cards, subtract 2 life + String player = card.getController(); + AllZone.GameAction.drawCard(player); + AllZone.GameAction.drawCard(player); + + AllZone.GameAction.getPlayerLife(player).subtractLife(2); + }//resolve() + }; + + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Infest")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4970294125917784048L; + + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Creature"); + computer = computer.getType("Creature"); + + human = CardListUtil.filterToughness(human, 2); + computer = CardListUtil.filterToughness(computer, 2); + + //the computer will at least destroy 2 more human creatures + return computer.size() < human.size()-1; + }//canPlayAI() + + public void resolve() + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + for(int i = 0; i < list.size(); i++) + list.get(i).addDamage(2); + }//resolve() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Ember-Fist Zubera")) + { + //counts Zubera in all graveyards for this turn + final CommandReturn countZubera = new CommandReturn() + { + public Object execute() + { + CardList list = new CardList(); + list.addAll(AllZone.Human_Graveyard.getCards()); + list.addAll(AllZone.Computer_Graveyard.getCards()); + + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (c.getTurnInZone() == AllZone.Phase.getTurn()) && + (c.getType().contains("Zubera") || c.getKeyword().contains("Changeling") ); + } + });//CardListFilter() + + return new Integer(list.size()); + } + }; + + final Input[] input = new Input[1]; + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + //human chooses target on resolve, + //computer chooses target in Command destroy + if(Constant.Player.Human.equals(card.getController())) + AllZone.InputControl.setInput(input[0]); + else + { + int damage = ((Integer)countZubera.execute()).intValue(); + + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canDamage(card, getTargetCard()) + && CardFactoryUtil.canTarget(card,getTargetCard()) ) + { + Card c = getTargetCard(); + c.addDamage(damage); + } + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage); + } + }//resolve() + };//SpellAbility + + input[0] = new Input() + { + private static final long serialVersionUID = 1899925898843297992L; + + public void showMessage() + { + int damage = ((Integer)countZubera.execute()).intValue(); + AllZone.Display.showMessage("Select target Creature, Planeswalker or Player - " + damage +" damage "); + ButtonUtil.disableAll(); + } + public void selectCard(Card card, PlayerZone zone) + { + if((card.isCreature() || card.isPlaneswalker()) && zone.is(Constant.Zone.Play)) + { + int damage = ((Integer)countZubera.execute()).intValue(); + card.addDamage(damage); + + //have to do this since state effects aren't checked + //after this "Input" class is done + //basically this makes everything work right + //Ember-Fist Zubera can destroy a 2/2 creature + AllZone.GameAction.checkStateEffects(); + stop(); + } + }//selectCard() + public void selectPlayer(String player) + { + int damage = ((Integer)countZubera.execute()).intValue(); + AllZone.GameAction.getPlayerLife(player).subtractLife(damage); + stop(); + }//selectPlayer() + };//Input + + Command destroy = new Command() + { + private static final long serialVersionUID = -1889425992069348304L; + + public void execute() + { + ability.setStackDescription(card +" causes damage to creature or player"); + + @SuppressWarnings("unused") // damage + int damage = ((Integer)countZubera.execute()).intValue(); + + String con = card.getController(); + + //human chooses target on resolve, + //computer chooses target in Command destroy + if(con.equals(Constant.Player.Computer)) + ability.setTargetPlayer(Constant.Player.Human); + + AllZone.Stack.add(ability); + }//execute() + }; + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Ashen-Skin Zubera")) + { + //counts Zubera in all graveyards for this turn + final CommandReturn countZubera = new CommandReturn() + { + public Object execute() + { + CardList list = new CardList(); + list.addAll(AllZone.Human_Graveyard.getCards()); + list.addAll(AllZone.Computer_Graveyard.getCards()); + + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (c.getTurnInZone() == AllZone.Phase.getTurn()) && + (c.getType().contains("Zubera") || c.getKeyword().contains("Changeling") ); + } + });//CardListFilter() + return new Integer(list.size()); + } + };//CommandReturn + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + int discard = ((Integer)countZubera.execute()).intValue(); + + if(Constant.Player.Human.equals(getTargetPlayer())) + AllZone.InputControl.setInput(CardFactoryUtil.input_discard(discard)); + else + { + for(int i = 0; i < discard; i++) + AllZone.GameAction.discardRandom(Constant.Player.Computer); + } + }//resolve() + };//SpellAbility + + Command destroy = new Command() + { + private static final long serialVersionUID = -7494691537986218546L; + + public void execute() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + ability.setTargetPlayer(opponent); + ability.setStackDescription(card +" - " + opponent +" discards cards"); + + AllZone.Stack.add(ability); + }//execute() + }; + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Floating-Dream Zubera")) + { + //counts Zubera in all graveyards for this turn + final CommandReturn countZubera = new CommandReturn() + { + public Object execute() + { + CardList list = new CardList(); + list.addAll(AllZone.Human_Graveyard.getCards()); + list.addAll(AllZone.Computer_Graveyard.getCards()); + + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (c.getTurnInZone() == AllZone.Phase.getTurn()) && + (c.getType().contains("Zubera") || c.getKeyword().contains("Changeling") ); + } + });//CardListFilter() + return new Integer(list.size()); + } + };//CommandReturn + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + int number = ((Integer)countZubera.execute()).intValue(); + + for(int i = 0; i < number; i++) + AllZone.GameAction.drawCard(getTargetPlayer()); + }//resolve() + };//SpellAbility + + Command destroy = new Command() + { + private static final long serialVersionUID = -5814070329854975419L; + + public void execute() + { + ability.setTargetPlayer(card.getController()); + ability.setStackDescription(card +" - " +card.getController() +" draws cards"); + AllZone.Stack.add(ability); + + }//execute() + }; + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Silent-Chant Zubera")) + { + //counts Zubera in all graveyards for this turn + final CommandReturn countZubera = new CommandReturn() + { + public Object execute() + { + CardList list = new CardList(); + list.addAll(AllZone.Human_Graveyard.getCards()); + list.addAll(AllZone.Computer_Graveyard.getCards()); + + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (c.getTurnInZone() == AllZone.Phase.getTurn()) && + (c.getType().contains("Zubera") || c.getKeyword().contains("Changeling") ); + } + });//CardListFilter() + return new Integer(list.size()); + } + };//CommandReturn + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + int number = ((Integer)countZubera.execute()).intValue(); + + PlayerLife life = AllZone.GameAction.getPlayerLife(getTargetPlayer()); + life.addLife(number * 2); + }//resolve() + };//SpellAbility + + Command destroy = new Command() + { + private static final long serialVersionUID = -2327085948421343657L; + + public void execute() + { + ability.setTargetPlayer(card.getController()); + ability.setStackDescription(card +" - " +card.getController() +" gains life"); + AllZone.Stack.add(ability); + + }//execute() + }; + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Dripping-Tongue Zubera")) + { + //counts Zubera in all graveyards for this turn + final CommandReturn countZubera = new CommandReturn() + { + public Object execute() + { + CardList list = new CardList(); + list.addAll(AllZone.Human_Graveyard.getCards()); + list.addAll(AllZone.Computer_Graveyard.getCards()); + + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (c.getTurnInZone() == AllZone.Phase.getTurn()) && + (c.getType().contains("Zubera") || c.getKeyword().contains("Changeling") ); + } + });//CardListFilter() + return new Integer(list.size()); + } + };//CommandReturn + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + int count = ((Integer)countZubera.execute()).intValue(); + for(int i = 0; i < count; i++) + makeToken(); + }//resolve() + void makeToken() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Spirit"); + c.setImageName("C 1 1 Spirit"); + c.setManaCost(""); + c.setToken(true); + + c.addType("Creature"); + c.addType("Spirit"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + play.add(c); + }//makeToken() + + };//SpellAbility + + Command destroy = new Command() + { + private static final long serialVersionUID = 8362692868619919330L; + public void execute() + { + ability.setTargetPlayer(card.getController()); + ability.setStackDescription(card +" - " +card.getController() +" puts tokens into play"); + AllZone.Stack.add(ability); + }//execute() + }; + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Keiga, the Tide Star")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + PlayerZone oldPlay = AllZone.getZone(getTargetCard()); + + //so "comes into play" abilities don't trigger + //getTargetCard().addComesIntoPlayCommand(Command.Blank); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(false); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(false); + + play.add(getTargetCard()); + oldPlay.remove(getTargetCard()); + + getTargetCard().setController(card.getController()); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(true); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(true); + } + }//resolve() + }; + + final Input targetInput = new Input() + { + private static final long serialVersionUID = -8727869672234802473L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target creature"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(card, c)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + else if(c.isCreature() && zone.is(Constant.Zone.Play)) + { + ability.setTargetCard(c); + ability.setStackDescription("Gain control of " +ability.getTargetCard()); + AllZone.Stack.add(ability); + stop(); + } + } + };//Input + Command destroy = new Command() + { + private static final long serialVersionUID = -3868616119471172026L; + + public void execute() + { + String con = card.getController(); + CardList list = CardFactoryUtil.AI_getHumanCreature(card, true); + + if(con.equals(Constant.Player.Human)) + AllZone.InputControl.setInput(targetInput); + else if(list.size() != 0) + { + Card target = CardFactoryUtil.AI_getBestCreature(list); + ability.setTargetCard(target); + AllZone.Stack.add(ability); + } + }//execute() + }; + card.addDestroyCommand(destroy); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Angelic Blessing")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 6906094867912276636L; + + public void resolve() + { + final Command eot = new Command() + { + private static final long serialVersionUID = 4672991308703961180L; + + public void execute() + { + Card c = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(c) ) + { + c.addTempAttackBoost(-3); + c.addTempDefenseBoost(-3); + c.removeExtrinsicKeyword("Flying"); + } + }//execute() + };//Command + + Card c = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) ) + { + c.addTempAttackBoost(3); + c.addTempDefenseBoost(3); + c.addExtrinsicKeyword("Flying"); + + AllZone.EndOfTurn.addUntil(eot); + } + }//resolve() + public boolean canPlayAI() + { + Combat combat = ComputerUtil.getAttackers(); + return (0 != combat.getAttackers().length); + } + public void chooseTargetAI() + { + Combat combat = ComputerUtil.getAttackers(); + Card[] attacker = combat.getAttackers(); + if(attacker.length != 0) + setTargetCard(attacker[0]); + else + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + Card best = CardFactoryUtil.AI_getBestCreature(list); + setTargetCard(best); + } + }//chooseTargetAI() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + }//*************** END ************ END ************************** + + +/* + + //*************** START *********** START ************************** + if(cardName.equals("Molten Rain")) + { + final SpellAbility spell = new Spell(card) + { + public boolean canPlayAI() + { + CardList land = new CardList(AllZone.Human_Play.getCards()); + land = land.getType("Basic"); + return land.size() != 0; + } + + public void chooseTargetAI() + { + //target basic land that Human only has 1 or 2 in play + CardList land = new CardList(AllZone.Human_Play.getCards()); + land = land.getType("Basic"); + + Card target = null; + + String[] name = {"Forest", "Swamp", "Plains", "Mountain", "Island"}; + for(int i = 0; i < name.length; i++) + if(land.getName(name[i]).size() == 1) + { + target = land.getName(name[i]).get(0); + break; + } + + //see if there are only 2 lands of the same type + if(target == null) + { + for(int i = 0; i < name.length; i++) + if(land.getName(name[i]).size() == 2) + { + target = land.getName(name[i]).get(0); + break; + } + }//if + if(target == null) + { + land.shuffle(); + target = land.get(0); + } + setTargetCard(target); + }//chooseTargetAI() + + public void resolve() + { + Card c = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(c)) + { + AllZone.GameAction.destroy(c); + + if(! c.getType().contains("Basic")) + AllZone.GameAction.getPlayerLife(c.getController()).subtractLife(2); + } + }//resolve() + + };//Spell + card.clearSpellAbility(); + card.addSpellAbility(spell); + + Input target = new Input() + { + public void showMessage() + { + AllZone.Display.showMessage("Select target Land"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(card.isLand() && zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + }//selectCard() + }; + spell.setBeforePayMana(target); + }//*************** END ************ END ************************** + +*/ + + +//*************** START *********** START ************************** + if (cardName.equals("Molten Rain")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 8855786097956610090L; + + public void resolve() + { + Card c = getTargetCard(); + if (AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c)) { + if(! c.getType().contains("Basic")) + AllZone.GameAction.getPlayerLife(c.getController()).subtractLife(2); + AllZone.GameAction.destroy(c); + } + + }// resolve() + + };// Spell + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setChooseTargetAI(CardFactoryUtil.AI_targetType("Land", AllZone.Human_Play)); + spell.setBeforePayMana(CardFactoryUtil.input_targetType(spell,"Land")); + }// *************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Elvish Piper")) + { + final SpellAbility ability = new Ability_Tap(card, "G") + { + private static final long serialVersionUID = 8788555124182810249L; + + public boolean canPlayAI() {return getCreature().size() != 0;} + public void chooseTargetAI() + { + card.tap(); + Card target = CardFactoryUtil.AI_getBestCreature(getCreature()); + setTargetCard(target); + } + CardList getCreature() + { + CardList list = new CardList(AllZone.Computer_Hand.getCards()); + list = list.getType("Creature"); + return list; + } + + public void resolve() + { + Card c = getTargetCard(); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + + if(AllZone.GameAction.isCardInZone(c, hand)) + { + hand.remove(c); + play.add(c); + } + } + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("G, tap: Put a creature card from your hand into play."); + + final Command paid = new Command() + { + private static final long serialVersionUID = 6859737530872573139L; + public void execute() + { + AllZone.InputControl.resetInput(); + AllZone.Stack.add(ability); + } + }; + final Command unpaid = new Command() + { + private static final long serialVersionUID = -257927480355704167L; + + public void execute() + { + card.untap(); + } + }; + final Input target = new Input() + { + private static final long serialVersionUID = -1041198540673942649L; + + public void showMessage() + { + ButtonUtil.enableOnlyCancel(); + AllZone.Display.showMessage("Select creature from your hand to put into play"); + } + public void selectCard(Card c, PlayerZone zone) + { + if(c.isCreature() && zone.is(Constant.Zone.Hand, Constant.Player.Human)) + { + card.tap(); + + ability.setTargetCard(c);//since setTargetCard() changes stack description + ability.setStackDescription("Put into play " +c); + + AllZone.InputControl.setInput(new Input_PayManaCost_Ability(ability.getManaCost(), paid, unpaid)); + } + } + public void selectButtonCancel() + { + card.untap(); + stop(); + } + };//Input target + ability.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Belbe's Portal")) + { + final SpellAbility ability = new Ability_Tap(card, "3") + { + private static final long serialVersionUID = 3790805878629855813L; + + public boolean canPlayAI() {return getCreature().size() != 0;} + public void chooseTargetAI() + { + card.tap(); + Card target = CardFactoryUtil.AI_getBestCreature(getCreature()); + setTargetCard(target); + } + CardList getCreature() + { + CardList list = new CardList(AllZone.Computer_Hand.getCards()); + list = list.getType(card.getChosenType()); + return list; + } + + public void resolve() + { + Card c = getTargetCard(); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + + if(AllZone.GameAction.isCardInZone(c, hand)) + { + hand.remove(c); + play.add(c); + } + } + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("3, tap: Put a creature card of the chosen type from your hand into play."); + + final Command paid = new Command() + { + private static final long serialVersionUID = 4258139342966165260L; + + public void execute() + { + AllZone.InputControl.resetInput(); + AllZone.Stack.add(ability); + } + }; + final Command unpaid = new Command() + { + private static final long serialVersionUID = 5792270994683837097L; + + public void execute() + { + card.untap(); + } + }; + final Input target = new Input() + { + private static final long serialVersionUID = -3180364352114242238L; + + public void showMessage() + { + ButtonUtil.enableOnlyCancel(); + AllZone.Display.showMessage("Select creature from your hand to put into play"); + } + public void selectCard(Card c, PlayerZone zone) + { + if(c.isCreature() && zone.is(Constant.Zone.Hand, Constant.Player.Human) && c.getType().contains(card.getChosenType())) + { + card.tap(); + + ability.setTargetCard(c);//since setTargetCard() changes stack description + ability.setStackDescription("Put into play " +c); + + AllZone.InputControl.setInput(new Input_PayManaCost_Ability(ability.getManaCost(), paid, unpaid)); + } + } + public void selectButtonCancel() + { + card.untap(); + stop(); + } + };//Input target + ability.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Weathered Wayfarer")) + { + final SpellAbility ability = new Ability_Tap(card, "W") + { + private static final long serialVersionUID = 2902408879239353813L; + + public void resolve() + { + //getTargetCard() will NEVER be null + + //checks to see if card is still in the library + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + if(AllZone.GameAction.isCardInZone(getTargetCard(), library)) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, getTargetCard()); + } + }//resolve() + public boolean canPlay() + { + String oppPlayer = AllZone.GameAction.getOpponent(card.getController()); + + PlayerZone selfZone = AllZone.getZone(Constant.Zone.Play, card.getController()); + PlayerZone oppZone = AllZone.getZone(Constant.Zone.Play, oppPlayer); + + CardList self = new CardList(selfZone.getCards()); + CardList opp = new CardList(oppZone.getCards()); + + self = self.getType("Land"); + opp = opp.getType("Land"); + + //checks to see if any land in library + PlayerZone selfLibrary = AllZone.getZone(Constant.Zone.Library, card.getController()); + CardList library = new CardList(selfLibrary.getCards()); + library = library.getType("Land"); + + return (self.size() < opp.size()) && (library.size() != 0) && super.canPlay(); + } + public void chooseTargetAI() + { + PlayerZone selfLibrary = AllZone.getZone(Constant.Zone.Library, card.getController()); + CardList library = new CardList(selfLibrary.getCards()); + library = library.getType("Land"); + + setTargetCard(library.get(0)); + } + };//SpellAbility + + Input target = new Input() + { + private static final long serialVersionUID = 3492362297282622857L; + + public void showMessage() + { + CardList land = new CardList(AllZone.Human_Library.getCards()); + land = land.getType("Land"); + Object o = AllZone.Display.getChoiceOptional("Select a Land", land.toArray()); + + //techincally not correct, but correct enough + //this allows players to look at their decks without paying anything + if(o == null) + stop(); + else + { + AllZone.GameAction.shuffle("Human"); + ability.setTargetCard((Card)o); + stopSetNext(new Input_PayManaCost(ability)); + } + }//showMessage() + };//Input - target + + card.addSpellAbility(ability); + ability.setDescription("W, tap: Search your library for a land card, reveal it, and put it into your hand. Then shuffle your library. Play this ability only if an opponent controls more lands than you."); + ability.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Disciple of Kangee")) + { + final SpellAbility ability = new Ability_Tap(card, "U") + { + private static final long serialVersionUID = -5169389637917649036L; + public boolean canPlayAI() + { + if(CardFactoryUtil.AI_doesCreatureAttack(card)) + return false; + + return CardFactoryUtil.AI_getHumanCreature("Flying", card, false).isEmpty() && + (getCreature().size() != 0); + } + public void chooseTargetAI() + { + card.tap(); + Card target = CardFactoryUtil.AI_getBestCreature(getCreature()); + setTargetCard(target); + } + CardList getCreature() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && (!CardFactoryUtil.AI_doesCreatureAttack(c)) && + (! c.getKeyword().contains("Flying")) && CardFactoryUtil.canTarget(card, c); + } + }); + list.remove(card); + return list; + }//getCreature() + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + final Card[] creature = new Card[1]; + final Command EOT = new Command() + { + private static final long serialVersionUID = -1899153704584793548L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(creature[0])) + creature[0].removeExtrinsicKeyword("Flying"); + } + }; + creature[0] = getTargetCard(); + creature[0].addExtrinsicKeyword("Flying"); + AllZone.EndOfTurn.addUntil(EOT); + }//if (card is in play) + }//resolve() + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("U, tap: Target creature gains flying."); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Puppeteer")) + { + //tap - target creature + final SpellAbility ability = new Ability_Tap(card, "U") + { + private static final long serialVersionUID = 7698358771800336470L; + public boolean canPlayAI() {return getTapped().size() != 0;} + public void chooseTargetAI() + { + card.tap(); + Card target = CardFactoryUtil.AI_getBestCreature(getTapped()); + setTargetCard(target); + } + CardList getTapped() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && c.isTapped(); + } + }); + return list; + }//getTapped() + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + Card c = getTargetCard(); + if(c.isTapped()) + c.untap(); + else + c.tap(); + } + }//resolve() + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("U, tap: Tap or untap target creature."); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Sorceress Queen")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = -6853184726011448677L; + public boolean canPlayAI() + { + Card c = getCreature(); + if(c == null) + return false; + else + { + setTargetCard(c); + return true; + } + }//canPlayAI() + //may return null + public Card getCreature() + { + CardList untapped = CardFactoryUtil.AI_getHumanCreature(card, true); + untapped = untapped.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isUntapped() && 2 < c.getNetDefense() && c != card; + } + }); + if(untapped.isEmpty()) + return null; + + Card big = CardFactoryUtil.AI_getBestCreature(untapped); + return big; + } + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + final Card[] creature = new Card[1]; + + creature[0] = getTargetCard(); + final int[] originalAttack = {creature[0].getBaseAttack()}; + final int[] originalDefense = {creature[0].getBaseDefense()}; + + creature[0].setBaseAttack(0); + creature[0].setBaseDefense(2); + + final Command EOT = new Command() + { + private static final long serialVersionUID = 6437463765161964445L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(creature[0])) + { + creature[0].setBaseAttack(originalAttack[0]); + creature[0].setBaseDefense(originalDefense[0]); + } + } + }; + AllZone.EndOfTurn.addUntil(EOT); + }//is card in play? + }//resolve() + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: Target creature other than Sorceress Queen becomes 0/2 until end of turn."); + //this ability can target "this card" when it shouldn't be able to + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature_NoCost_TapAbility_NoTargetSelf(ability)); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Immaculate Magistrate")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 8976980151320100343L; + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + PlayerZone zone = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList list = new CardList(zone.getCards()); + int nElf = list.getType("Elf").size(); + + Card c = getTargetCard(); + c.addCounter(Counters.P1P1, nElf); + + }//is card in play? + }//resolve() + public boolean canPlayAI() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isUntapped() && !c.equals(card) && c.isCreature(); + } + }); + + if(list.isEmpty()) + return false; + + list.shuffle(); + + setTargetCard(list.get(0)); + return true; + }//canPlayAI() + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: Put a +1/+1 counter on target creature for each Elf you control."); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature_NoCost_TapAbility(ability)); + }//*************** END ************ END ************************** + + /* + //*************** START *********** START ************************** + if(cardName.equals("Prodigal Sorcerer") || cardName.equals("Prodigal Pyromancer") + || cardName.equals("Razorfin Hunter") || cardName.equals("Vulshok Sorcerer") + || cardName.equals("Viashino Fangtail") || cardName.equals("Jeska, Warrior Adept")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = -7560349014757367722L; + public void chooseTargetAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(1, card, true); + list.shuffle(); + + if(list.isEmpty() || AllZone.Human_Life.getLife() < 5) + setTargetPlayer(Constant.Player.Human); + else + setTargetCard(list.get(0)); + } + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + getTargetCard().addDamage(1); + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(1); + }//resolve() + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: " +card.getName() +" deals 1 damage to target creature or player."); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(ability, true)); + + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if (cardName.equals("Anaba Shaman")) + { + final Ability_Tap ability = new Ability_Tap(card, "R") + { + private static final long serialVersionUID = -3954988810589187088L; + public void chooseTargetAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(1, card, true); + list.shuffle(); + + if(list.isEmpty() || AllZone.Human_Life.getLife() < 5) + setTargetPlayer(Constant.Player.Human); + else + setTargetCard(list.get(0)); + } + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + getTargetCard().addDamage(1); + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(1); + }//resolve() + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("R, tap: " +card.getName() +" deals 1 damage to target creature or player."); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(ability, true)); + + + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Kamahl, Pit Fighter")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 6922727343642792543L; + public boolean canPlayAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(card, true); + + boolean b = true; + + //use ability only if no human creatures can block + for(int i = 0; i < list.size(); i++) + if(list.get(i).isUntapped()) + b = false; + + return b || AllZone.Phase.getPhase().equals(Constant.Phase.Main2); + } + + public void chooseTargetAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(3, card, true); + list.shuffle(); + + if(list.isEmpty() || AllZone.Human_Life.getLife() < 17) + setTargetPlayer(Constant.Player.Human); + else + setTargetCard(list.get(0)); + } + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + getTargetCard().addDamage(3); + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(3); + }//resolve() + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: " +card.getName() +" deals 3 damage to target creature or player."); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(ability, true)); + }//*************** END ************ END ************************** + + */ + + //*************** START *********** START ************************** + if(cardName.equals("Mawcor")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 6238678956434079L; + public boolean canPlayAI() + { + return AllZone.Phase.getPhase().equals(Constant.Phase.Main2); + } + + public void chooseTargetAI() + { + setTargetPlayer(Constant.Player.Human); + } + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + getTargetCard().addDamage(1); + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(1); + }//resolve() + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: Mawcor deals 1 damage to target creature or player."); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(ability, true)); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Orcish Artillery") || cardName.equals("Goblin Artillery") + || cardName.equals("Orcish Cannoneers")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = -305363091630642003L; + public boolean canPlayAI() + { + return AllZone.Computer_Life.getLife() > 6; + } + + public void chooseTargetAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(2, card, true); + list.shuffle(); + + if(list.isEmpty() || AllZone.Human_Life.getLife() < 5) + setTargetPlayer(Constant.Player.Human); + else + setTargetCard(list.get(0)); + } + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + getTargetCard().addDamage(2); + //3 damage to self + AllZone.GameAction.getPlayerLife(card.getController()).subtractLife(3); + + if (card.getKeyword().contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(card, 5); + for(int i=0; i < CardFactoryUtil.hasNumberEnchantments(card, "Guilty Conscience"); i++) + GameActionUtil.executeGuiltyConscienceEffects(card, 5); + + } + } + else + { + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(2); + //3 damage to self + AllZone.GameAction.getPlayerLife(card.getController()).subtractLife(3); + + if (card.getKeyword().contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(card, 5); + for(int i=0; i < CardFactoryUtil.hasNumberEnchantments(card, "Guilty Conscience"); i++) + GameActionUtil.executeGuiltyConscienceEffects(card, 5); + } + + }//resolve() + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: " +cardName + " deals 2 damage to target creature or player and 3 damage to you."); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(ability,true)); + }//*************** END ************ END ************************** + + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Sparksmith")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 681102636956052363L; + public boolean canPlayAI() + { + int n = countGoblins(); + return (AllZone.Computer_Life.getLife() > n) && + (CardFactoryUtil.AI_getHumanCreature(n, card, true).size() != 0); + } + public void chooseTargetAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(countGoblins(), card, true); + list.shuffle(); + setTargetCard(list.get(0)); + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.subtractLife(countGoblins()); + + getTargetCard().addDamage(countGoblins()); + + if (card.getKeyword().contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(card, 2*countGoblins()); + for(int i=0; i < CardFactoryUtil.hasNumberEnchantments(card, "Guilty Conscience"); i++) + GameActionUtil.executeGuiltyConscienceEffects(card, 2*countGoblins()); + } + }//resolve() + int countGoblins() + { + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Goblin"); + return list.size(); + } + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: Sparksmith deals X damage to target creature and X damage to you, where X is the number of Goblins in play."); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Rathi Assassin")) + { + final Ability_Tap ability = new Ability_Tap(card, "1 B B") + { + private static final long serialVersionUID = 1117792059002738977L; + public boolean canPlay() + { + return AllZone.GameAction.isCardInPlay(card) && !card.isTapped() && !card.hasSickness(); + } + public boolean canPlayAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + human = human.filter(new CardListFilter() + { + public boolean addCard(Card c) {return c.isTapped() && !CardUtil.getColor(c).equals(Constant.Color.Black);} + }); + + CardListUtil.sortAttack(human); + CardListUtil.sortFlying(human); + + if(0 < human.size()) + setTargetCard(human.get(0)); + + return 0 < human.size(); + } + public void resolve() + { + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && c.isTapped() && CardFactoryUtil.canTarget(card, c) && !CardUtil.getColor(c).equals(Constant.Color.Black) ) + { + AllZone.GameAction.destroy(c); + } + }//resolve() + };//SpellAbility + + /* + Input target = new Input() + { + public void showMessage() + { + AllZone.Display.showMessage("Select target tapped nonblack creature to destroy"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + if(c.isCreature() && zone.is(Constant.Zone.Play) && c.isTapped() && ! CardUtil.getColor(c).equals(Constant.Color.Black) ) + { + //tap ability + card.tap(); + + ability.setTargetCard(c); + AllZone.Stack.add(ability); + stop(); + } + }//selectCard() + };//Input + */ + + ability.setBeforePayMana(new Input() + { + private static final long serialVersionUID = -7903295056497483023L; + + public void showMessage() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + CardList slivers = new CardList(AllZone.getZone(Constant.Zone.Play, opponent).getCards()); + slivers = slivers.filter(new CardListFilter() + { + + public boolean addCard(Card c) + { + PlayerZone zone = AllZone.getZone(c); + return c.isCreature() && zone.is(Constant.Zone.Play) && c.isTapped() && ! CardUtil.getColor(c).equals(Constant.Color.Black); + } + + }); + + stopSetNext(CardFactoryUtil.input_targetSpecific(ability, slivers, "Select a tapped non-black creature", true)); + } + }); + + card.addSpellAbility(ability); + ability.setDescription("1 B B, tap: Destroy target tapped nonblack creature."); + //ability.setBeforePayMana(target); + //ability.setAfterPayMana(target); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Royal Assassin")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 1974437552336643722L; + public boolean canPlayAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + human = human.filter(new CardListFilter() + { + public boolean addCard(Card c) {return c.isTapped();} + }); + + CardListUtil.sortAttack(human); + CardListUtil.sortFlying(human); + + if(0 < human.size()) + setTargetCard(human.get(0)); + + return 0 < human.size(); + } + public void resolve() + { + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && c.isTapped() && CardFactoryUtil.canTarget(card, c) ) + { + AllZone.GameAction.destroy(c); + } + }//resolve() + };//SpellAbility + + Input target = new Input() + { + private static final long serialVersionUID = -5894703805950364923L; + public void showMessage() + { + AllZone.Display.showMessage("Select target tapped creature to destroy"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(card, c)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + else if(c.isCreature() && zone.is(Constant.Zone.Play) && c.isTapped()) + { + //tap ability + card.tap(); + + ability.setTargetCard(c); + AllZone.Stack.add(ability); + stop(); + } + }//selectCard() + };//Input + + card.addSpellAbility(ability); + ability.setDescription("tap: Destroy target tapped creature."); + ability.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Giltspire Avenger")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = -1117719063688165635L; + + public boolean canPlayAI() + { + return false; + } + + public boolean canPlay() + { + System.out.println("phase =" + AllZone.Phase.getPhase()); + if ((AllZone.Phase.getPhase().equals(Constant.Phase.Main2) || + AllZone.Phase.getPhase().equals(Constant.Phase.End_Of_Turn)) && + !card.hasSickness() && card.isUntapped()) + return true; + else + return false; + + } + + public void resolve() + { + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && (c.getDealtCombatDmgToOppThisTurn() || c.getDealtDmgToOppThisTurn()) + && CardFactoryUtil.canTarget(card, c) ) + { + AllZone.GameAction.destroy(c); + } + }//resolve() + };//SpellAbility + + Input target = new Input() + { + private static final long serialVersionUID = -4946540988877576202L; + public void showMessage() + { + AllZone.Display.showMessage("Select target creature to destroy"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(card, c)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + else if(c.isCreature() && zone.is(Constant.Zone.Play) && (c.getDealtCombatDmgToOppThisTurn() || + c.getDealtDmgToOppThisTurn()) ) + { + //tap ability + card.tap(); + + ability.setTargetCard(c); + AllZone.Stack.add(ability); + stop(); + } + }//selectCard() + };//Input + + card.addSpellAbility(ability); + ability.setDescription("tap: Destroy target creature that dealt damage to you this turn."); + ability.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Hex")) + { + final Card[] target = new Card[6]; + final int[] index = new int[1]; + + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -1880229743741157304L; + public boolean canPlayAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + + CardListUtil.sortAttack(human); + CardListUtil.sortFlying(human); + + if(6 <= human.size()) + { + for(int i = 0; i < 6; i++) //should check to make sure none of these creatures have protection or cannot be the target of spells. + target[i] = human.get(i); + } + + return 6 <= human.size(); + } + public void resolve() + { + for(int i = 0; i < target.length; i++) + if(AllZone.GameAction.isCardInPlay(target[i]) && CardFactoryUtil.canTarget(card, target[i]) ) + AllZone.GameAction.destroy(target[i]); + }//resolve() + };//SpellAbility + + + final Input input = new Input() + { + private static final long serialVersionUID = 5792813689927185739L; + public void showMessage() + { + int count = 6 - index[0]; + AllZone.Display.showMessage("Select target " + count +" creatures to destroy"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + for(int i=0;i 0){ + Card target = CardFactoryUtil.AI_getBestCreature(creature); + setTargetCard(target); + } + else + { + CardList enchantment = CardFactoryUtil.AI_getHumanEnchantment(card, true); + if (enchantment.size() > 0) + { + Card target = CardFactoryUtil.AI_getBestEnchantment(enchantment, card, true); + setTargetCard(target); + } + } + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + AllZone.GameAction.destroy(getTargetCard()); + } + }//resolve() + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap, 1 W B: Destroy target creature or enchantment."); + + //ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + + Input runtime = new Input() + { + private static final long serialVersionUID = -8099713981623158814L; + + public void showMessage() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + all = all.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return (c.isEnchantment() || c.isCreature() ) && CardFactoryUtil.canTarget(card, c); + } + }); + + stopSetNext(CardFactoryUtil.input_targetSpecific(ability, all, "Destroy target creature or enchantment.", true)); + } + }; + ability.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Wojek Embermage")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = -1208482961653326721L; + public boolean canPlayAI() + { + return (CardFactoryUtil.AI_getHumanCreature(1, card, true).size() != 0) && + (AllZone.Phase.getPhase().equals(Constant.Phase.Main2)); + } + + public void chooseTargetAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(1, card, true); + list.shuffle(); + setTargetCard(list.get(0)); + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + CardList list = getRadiance(getTargetCard()); + for(int i = 0; i < list.size(); i++) + list.get(i).addDamage(1); + } + }//resolve() + //parameter Card c, is included in CardList + //no multi-colored cards + CardList getRadiance(Card c) + { + String color = CardUtil.getColor(c); + if(color.equals(Constant.Color.Colorless)) + { + CardList list = new CardList(); + list.add(c); + return list; + } + + CardList sameColor = new CardList(); + + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + for(int i = 0; i < list.size(); i++) + if(CardUtil.getColor(list.get(i)).equals(color)) + sameColor.add(list.get(i)); + + return sameColor; + } + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("Radiance - tap: Wojek Embermage deals 1 damage to target creature and each other creature that shares a color with it."); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Timberwatch Elf")) + { + final Card[] creature = new Card[1]; + final int[] pump = new int[1]; + final Command EOT = new Command() + { + private static final long serialVersionUID = -2764970883655205904L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(creature[0])) + { + creature[0].addTempAttackBoost(-pump[0]); + creature[0].addTempDefenseBoost(-pump[0]); + } + } + }; + + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = -7536296719726210357L; + public boolean canPlayAI() + { + CardList c = getAttackers(); + if(c.isEmpty()) + return false; + else + { + setTargetCard(c.get(0)); + return true; + } + }//canPlayAI() + CardList getAttackers() + { + Card[] c = ComputerUtil.getAttackers().getAttackers(); + CardList list = new CardList(c); + list = list.filter(new CardListFilter(){ + + public boolean addCard(Card c) { + return CardFactoryUtil.canTarget(card, c); + } + + }); + + //remove "this card" from attackers, if it is there + list.remove(card); + list.shuffle(); + return list; + }//getAttackers() + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + creature[0] = getTargetCard(); + pump[0] = countElves(); + + creature[0].addTempAttackBoost(pump[0]); + creature[0].addTempDefenseBoost(pump[0]); + + AllZone.EndOfTurn.addUntil(EOT); + } + }//resolve() + int countElves() + { + CardList elf = new CardList(); + elf.addAll(AllZone.Human_Play.getCards()); + elf.addAll(AllZone.Computer_Play.getCards()); + + elf = elf.getType("Elf"); + return elf.size(); + } + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: Target creature gets +X/+X until end of turn, where X is the number of Elves in play."); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature_NoCost_TapAbility(ability)); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Mad Auntie")) + { + final Card[] creature = new Card[1]; + final Command EOT = new Command() + { + private static final long serialVersionUID = -5143708900761432510L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(creature[0])) + { + creature[0].setShield(0); + } + } + }; + + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = -1280855188535819509L; + public boolean canPlayAI() + { + return false; + }//canPlayAI() + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + getTargetCard().addShield(); + AllZone.EndOfTurn.addUntil(EOT); + } + }//resolve() + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: Regenerate another target Goblin."); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature_NoCost_TapAbility(ability)); + }//*************** END ************ END ************************** + + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Intrepid Hero")) + { + //tap ability - no cost - target creature + + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = -7825416464364928117L; + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) && + getTargetCard().getNetAttack() >= 4) + { + AllZone.GameAction.destroy(getTargetCard()); + } + }//resolve() + public boolean canPlayAI() + { + return getHumanCreatures().size() != 0; + } + public void chooseTargetAI() + { + CardList human = getHumanCreatures(); + human.shuffle(); + setTargetCard(human.get(0)); + } + CardList getHumanCreatures() + { + CardList list = new CardList(AllZone.Human_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && 3 < c.getNetAttack(); + } + }); + return list; + } + };//SpellAbility + + Input target = new Input() + { + private static final long serialVersionUID = -7024383930124942288L; + public void showMessage() + { + AllZone.Display.showMessage("Select target creature with power 4 or greater"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(card.isCreature() && zone.is(Constant.Zone.Play) && 3 < card.getNetAttack()) + { + ability.setTargetCard(card); + stopSetNext(new Input_NoCost_TapAbility(ability)); + } + } + }; + + card.addSpellAbility(ability); + ability.setDescription("tap: Destroy target creature with power 4 or greater."); + + ability.setBeforePayMana(target); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Tetsuo Umezawa")) + { + //tap ability - no cost - target creature + + final Ability_Tap ability = new Ability_Tap(card) + { + + private static final long serialVersionUID = -8034678094689484203L; + public void resolve() + { + CardList blockers = AllZone.Combat.getAllBlockers(); + + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) && + (blockers.contains(getTargetCard()) || getTargetCard().isTapped()) ) + { + AllZone.GameAction.destroy(getTargetCard()); + } + }//resolve() + public boolean canPlayAI() + { + return false; + } + };//SpellAbility + + Input target = new Input() + { + + private static final long serialVersionUID = -1939019440028116051L; + public void showMessage() + { + AllZone.Display.showMessage("Select target tapped or blocking creature."); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + CardList blockers = AllZone.Combat.getAllBlockers(); + if(card.isCreature() && zone.is(Constant.Zone.Play) && + (blockers.contains(card) || card.isTapped()) ) + { + ability.setTargetCard(card); + stopSetNext(new Input_NoCost_TapAbility(ability)); + } + } + }; + + card.addSpellAbility(ability); + ability.setDescription("U B B R, Tap: Destroy target tapped or blocking creature."); + + ability.setBeforePayMana(target); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Tor Wauki")) + { + //tap ability - no cost - target creature + + final Ability_Tap ability = new Ability_Tap(card) + { + + private static final long serialVersionUID = -8034678094689484203L; + public void resolve() + { + CardList attackers = new CardList(AllZone.Combat.getAttackers()); + CardList blockers = AllZone.Combat.getAllBlockers(); + + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) && + (attackers.contains(getTargetCard()) || blockers.contains(getTargetCard()) ) ) + { + getTargetCard().addDamage(2); + } + }//resolve() + public boolean canPlayAI() + { + return false; + } + };//SpellAbility + + Input target = new Input() + { + + private static final long serialVersionUID = -1939019440028116051L; + public void showMessage() + { + AllZone.Display.showMessage("Select target attacking or blocking creature."); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + CardList attackers = new CardList(AllZone.Combat.getAttackers()); + CardList blockers = AllZone.Combat.getAllBlockers(); + if(card.isCreature() && zone.is(Constant.Zone.Play) && + (attackers.contains(card) || blockers.contains(card) ) ) + { + ability.setTargetCard(card); + stopSetNext(new Input_NoCost_TapAbility(ability)); + } + } + }; + + card.addSpellAbility(ability); + ability.setDescription("tap: Tor Wauki deals 2 damage to target attacking or blocking creature."); + + ability.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Lady Caleria")) + { + //tap ability - no cost - target creature + + final Ability_Tap ability = new Ability_Tap(card) + { + + private static final long serialVersionUID = -8034678094689484203L; + public void resolve() + { + CardList attackers = new CardList(AllZone.Combat.getAttackers()); + CardList blockers = AllZone.Combat.getAllBlockers(); + + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) && + (attackers.contains(getTargetCard()) || blockers.contains(getTargetCard()) ) ) + { + getTargetCard().addDamage(3); + } + }//resolve() + public boolean canPlayAI() + { + return false; + } + };//SpellAbility + + Input target = new Input() + { + + private static final long serialVersionUID = -1939019440028116051L; + public void showMessage() + { + AllZone.Display.showMessage("Select target attacking or blocking creature."); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + CardList attackers = new CardList(AllZone.Combat.getAttackers()); + CardList blockers = AllZone.Combat.getAllBlockers(); + if(card.isCreature() && zone.is(Constant.Zone.Play) && + (attackers.contains(card) || blockers.contains(card) ) ) + { + ability.setTargetCard(card); + stopSetNext(new Input_NoCost_TapAbility(ability)); + } + } + }; + + card.addSpellAbility(ability); + ability.setDescription("tap: Lady Caleria deals 3 damage to target attacking or blocking creature."); + + ability.setBeforePayMana(target); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Femeref Archers")) + { + //tap ability - no cost - target creature + + final Ability_Tap ability = new Ability_Tap(card) + { + + private static final long serialVersionUID = -4369831076920644547L; + public void resolve() + { + CardList attackers = new CardList(AllZone.Combat.getAttackers()); + + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) && + attackers.contains(getTargetCard()) && getTargetCard().getKeyword().contains("Flying")) + { + getTargetCard().addDamage(4); + } + }//resolve() + public boolean canPlayAI() + { + return false; + } + };//SpellAbility + + Input target = new Input() + { + + private static final long serialVersionUID = 3455890565752527632L; + public void showMessage() + { + AllZone.Display.showMessage("Select target attacking creature with flying."); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + CardList attackers = new CardList(AllZone.Combat.getAttackers()); + if(card.isCreature() && zone.is(Constant.Zone.Play) && card.getKeyword().contains("Flying") && + attackers.contains(card)) + { + ability.setTargetCard(card); + stopSetNext(new Input_NoCost_TapAbility(ability)); + } + } + }; + + card.addSpellAbility(ability); + ability.setDescription("tap: Femeref Archers deals 4 damage to target attacking creature with flying."); + + ability.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Adarkar Valkyrie")) + { + //tap ability - no cost - target creature - EOT + + final Card[] target = new Card[1]; + + final Command destroy = new Command() + { + private static final long serialVersionUID = -2433442359225521472L; + + public void execute() + { + AllZone.Stack.add(new Ability(card, "0", "Return " +target[0] +" from graveyard to play") + { + public void resolve() + { + PlayerZone grave = AllZone.getZone(target[0]); + //checks to see if card is still in the graveyard + if(AllZone.GameAction.isCardInZone(target[0], grave)) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + AllZone.GameAction.moveTo(play, target[0]); + target[0].setController(card.getController()); + } + } + }); + }//execute() + }; + + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 2777978927867867610L; + + public void execute() + { + //resets the Card destroy Command + //target[0].addDestroy(Command.Blank); + target[0].removeDestroyCommand(destroy); + + } + }; + + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = -8454685126878522607L; + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard())) + { + target[0] = getTargetCard(); + AllZone.EndOfTurn.addUntil(untilEOT); + + //when destroyed, return to play + //add triggered ability to target card + target[0].addDestroyCommand(destroy); + }//if + }//resolve() + public boolean canPlayAI() + { + return false; + } + };//SpellAbility + + Input targetInput = new Input() + { + private static final long serialVersionUID = 913860087744941946L; + public void showMessage() + { + AllZone.Display.showMessage("Select target non-token creature other than this card"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + //must target non-token creature, and cannot target itself + if(c.isCreature() && (!c.isToken()) && (!c.equals(card))) + { + ability.setTargetCard(c); + stopSetNext(new Input_NoCost_TapAbility(ability)); + } + } + }; + + card.addSpellAbility(ability); + ability.setDescription("tap: When target creature other than Adarkar Valkyrie is put into a graveyard this turn, return that card to play under your control."); + + ability.setBeforePayMana(targetInput); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Imperious Perfect")) + { + //mana tap ability + final Ability_Tap ability = new Ability_Tap(card, "G") + { + private static final long serialVersionUID = -3266607637871879336L; + + public boolean canPlayAI() + { + String phase = AllZone.Phase.getPhase(); + return phase.equals(Constant.Phase.Main2); + } + public void chooseTargetAI() {card.tap();} + + public void resolve() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Elf Warrior"); + c.setImageName("G 1 1 Elf Warrior"); + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Elf"); + c.addType("Warrior"); + + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//resolve() + };//SpellAbility + + card.addSpellAbility(ability); + + ability.setDescription("G, tap: Put a 1/1 green Elf Warrior creature token into play."); + ability.setStackDescription("Imperious Perfect - Put a 1/1 green Elf Warrior creature token into play."); + ability.setBeforePayMana(new Input_PayManaCost(ability)); + }//*************** END ************ END ************************** + + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Wall of Kelp")) + { + //mana tap ability + final Ability_Tap ability = new Ability_Tap(card, "U U") + { + private static final long serialVersionUID = 2893813929304858905L; + + public boolean canPlayAI() + { + String phase = AllZone.Phase.getPhase(); + return phase.equals(Constant.Phase.Main2); + } + public void chooseTargetAI() {card.tap();} + + public void resolve() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Kelp"); + c.setManaCost("U"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Plant"); + c.addType("Wall"); + c.addIntrinsicKeyword("Defender"); + + c.setBaseAttack(0); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//resolve() + };//SpellAbility + + card.addSpellAbility(ability); + + ability.setDescription("UU, tap: Put a 0/1 blue Kelp Wall creature token with defender into play."); + ability.setStackDescription("Wall of Kelp - Put a 0/1 blue Kelp Wall creature token with defender into play"); + ability.setBeforePayMana(new Input_PayManaCost(ability)); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Vedalken Mastermind")) + { + //mana tap ability + final Ability_Tap ability = new Ability_Tap(card, "U") + { + private static final long serialVersionUID = -6131368241135911606L; + + public boolean canPlayAI() {return false;} + + public void resolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, getTargetCard().getOwner()); + AllZone.GameAction.moveTo(hand, getTargetCard()); + + if (getTargetCard().isToken()) + hand.remove(getTargetCard()); + }//resolve() + };//SpellAbility + + + Input runtime = new Input() + { + private static final long serialVersionUID = -5218098811060156481L; + + public void showMessage() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList choice = new CardList(play.getCards()); + stopSetNext(CardFactoryUtil.input_targetSpecific(ability, choice, "Select a permanent you control.", true)); + } + }; + card.addSpellAbility(ability); + ability.setDescription("U, tap: Return target permanent you control to its owner's hand."); + ability.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Helldozer")) + { + //mana tap ability + final Ability_Tap ability = new Ability_Tap(card, "B B B") + { + private static final long serialVersionUID = 6426884086364885861L; + + public boolean canPlayAI() + { + if(CardFactoryUtil.AI_doesCreatureAttack(card)) + return false; + + CardList land = new CardList(AllZone.Human_Play.getCards()); + land = land.getType("Land"); + return land.size() != 0; + } + + public void chooseTargetAI() + { + card.tap(); + + //target basic land that Human only has 1 or 2 in play + CardList land = new CardList(AllZone.Human_Play.getCards()); + land = land.getType("Land"); + + Card target = null; + + String[] name = {"Forest", "Swamp", "Plains", "Mountain", "Island"}; + for(int i = 0; i < name.length; i++) + if(land.getName(name[i]).size() == 1) + { + target = land.getName(name[i]).get(0); + break; + } + + //see if there are only 2 lands of the same type + if(target == null) + { + for(int i = 0; i < name.length; i++) + if(land.getName(name[i]).size() == 2) + { + target = land.getName(name[i]).get(0); + break; + } + }//if + if(target == null) + { + land.shuffle(); + target = land.get(0); + } + setTargetCard(target); + }//chooseTargetAI() + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + AllZone.GameAction.destroy(getTargetCard()); + + //if non-basic, untap Helldozer + if(! getTargetCard().getType().contains("Basic")) + card.untap(); + } + }//resolve() + };//SpellAbility + + card.addSpellAbility(ability); + ability.setDescription("BBB, tap: Destroy target land. If that land is nonbasic, untap Helldozer."); + ability.setBeforePayMana(CardFactoryUtil.input_targetType(ability, "Land")); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Cao Cao, Lord of Wei")) + { + //mana tap ability + final Ability_Tap ability = new Ability_Tap(card, "0") + { + private static final long serialVersionUID = 6760838700101179614L; + public void chooseTargetAI() {card.tap();} + public boolean canPlayAI() + { + int hand = AllZone.Human_Hand.getCards().length; + if((! CardFactoryUtil.AI_doesCreatureAttack(card)) && hand != 0) + return true; + + return 2 <= hand; + } + + public void resolve() + { + String player = AllZone.GameAction.getOpponent(card.getController()); + + if(player.equals(Constant.Player.Human)) + AllZone.InputControl.setInput(CardFactoryUtil.input_discard(2)); + else + { + AllZone.GameAction.discardRandom(player); + AllZone.GameAction.discardRandom(player); + } + }//resolve() + public boolean canPlay() + { + String opp = AllZone.GameAction.getOpponent(card.getController()); + setStackDescription(card.getName() +" - " +opp +" discards 2 cards"); + + String phase = AllZone.Phase.getPhase(); + String activePlayer = AllZone.Phase.getActivePlayer(); + + return super.canPlay() && + phase.equals(Constant.Phase.Main1) && + card.getController().equals(activePlayer); + } + };//SpellAbility + + ability.setChooseTargetAI(CardFactoryUtil.AI_targetHuman()); + ability.setDescription("tap: Target opponent discards two cards. Play this ability only during your turn, before the combat phase."); + ability.setBeforePayMana(new Input_NoCost_TapAbility(ability)); + + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Gwendlyn Di Corci")) + { + //mana tap ability + final Ability_Tap ability = new Ability_Tap(card, "0") + { + + private static final long serialVersionUID = -4211234606012596777L; + public void chooseTargetAI() {setTargetPlayer(Constant.Player.Human); } + public boolean canPlayAI() + { + int hand = AllZone.Human_Hand.getCards().length; + return hand > 0; + } + + public void resolve() + { + String player = getTargetPlayer(); + + AllZone.GameAction.discardRandom(player); + + }//resolve() + public boolean canPlay() + { + setStackDescription(card.getName() +" - " +getTargetPlayer() +" discards a card at random."); + + String activePlayer = AllZone.Phase.getActivePlayer(); + + return super.canPlay() && + card.getController().equals(activePlayer); + } + };//SpellAbility + + Input input = new Input() + { + private static final long serialVersionUID = 3312693459353844120L; + + public void showMessage() + { + //prevents this from running multiple times, which it is for some reason + if(ability.getSourceCard().isUntapped()) + { + ability.getSourceCard().tap(); + stopSetNext(CardFactoryUtil.input_targetPlayer(ability)); + } + } + }; + + ability.setDescription("Tap: Target player discards a card at random. Activate this ability only during your turn."); + ability.setBeforePayMana(input); + //ability.setBeforePayMana(CardFactoryUtil.input_targetPlayer(ability)); + + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Xira Arien")) + { + //mana tap ability + final Ability_Tap ability = new Ability_Tap(card, "G R B") + { + + private static final long serialVersionUID = 5373361883064666451L; + public void chooseTargetAI() {setTargetPlayer(Constant.Player.Computer);} + public boolean canPlayAI() + { + int hand = AllZone.Computer_Hand.getCards().length; + int lib = AllZone.Computer_Library.getCards().length; + return hand < 6 && lib > 0; + } + + public void resolve() + { + String player = getTargetPlayer(); + + AllZone.GameAction.drawCard(player); + + }//resolve() + public boolean canPlay() + { + + setStackDescription(card.getName() +" - " +getTargetPlayer() +" discards a card at random."); + + return super.canPlay(); + } + };//SpellAbility + + ability.setDescription("Tap: Target player draws a card."); + //ability.setBeforePayMana(new Input_NoCost_TapAbility(ability)); + ability.setBeforePayMana(CardFactoryUtil.input_targetPlayer(ability)); + + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Wayward Soul")) + { + //mana ability + final Ability ability = new Ability(card, "U") + { + public boolean canPlayAI() {return false;} + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card) ) + { + card.setBaseAttack(3); + card.setBaseDefense(2); + card.setIntrinsicKeyword(new ArrayList()); + card.addIntrinsicKeyword("Flying"); + + card.setAssignedDamage(0); + card.setDamage(0); + card.untap(); + AllZone.getZone(card).remove(card); + + //put card on top of library + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getOwner()); + library.add(card, 0); + } + }//resolve() + };//SpellAbility + + Input runtime = new Input() + { + private static final long serialVersionUID = 1469011418219527227L; + + public void showMessage() + { + ability.setStackDescription("Put " +card +" on top of its owner's library"); + + stopSetNext(new Input_PayManaCost(ability)); + } + }; + ability.setDescription("U: Put Wayward Soul on top of its owner's library."); + ability.setStackDescription("Put Wayward Soul on top of its owner's library."); + card.addSpellAbility(ability); + ability.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Coastal Hornclaw")) + { + //sacrifice ability - targets itself - until EOT + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 7538741250040204529L; + + public void execute() + { + card.removeIntrinsicKeyword("Flying"); + } + }; + + //mana tap ability + final Ability ability = new Ability(card, "0") + { + public boolean canPlayAI() + { + CardList land = new CardList(AllZone.Computer_Play.getCards()); + land = land.getType("Land"); + + CardList canBlock = CardFactoryUtil.AI_getHumanCreature(card, true); + canBlock = canBlock.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isUntapped(); + } + }); + + return (land.size() != 0) && + (! card.getKeyword().contains("Flying")) && + CardFactoryUtil.AI_getHumanCreature("Flying", card, false).isEmpty() && + (! card.hasSickness()) && + (AllZone.Phase.getPhase().equals(Constant.Phase.Main1)); + } + + public void chooseTargetAI() + { + CardList land = new CardList(AllZone.Computer_Play.getCards()); + land = land.getType("Land"); + land.shuffle(); + AllZone.GameAction.sacrifice(land.get(0)); + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addIntrinsicKeyword("Flying"); + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + };//SpellAbility + + + Input runtime = new Input() + { + private static final long serialVersionUID = 4874019210748846864L; + + public void showMessage() + { + ability.setStackDescription(card +" gains flying until EOT."); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList choice = new CardList(play.getCards()); + choice = choice.getType("Land"); + stopSetNext(CardFactoryUtil.input_sacrifice(ability, choice, "Select a land to sacrifice.")); + } + }; + ability.setStackDescription(card +" gains flying until end of turn."); + ability.setDescription("Sacrifice a land: Coastal Hornclaw gains flying until end of turn."); + card.addSpellAbility(ability); + ability.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Spitting Spider")) + { + final Ability ability = new Ability(card, "0") + { + public boolean canPlayAI() + { + return false; + } + public void resolve() + { + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && c.getKeyword().contains("Flying"); + } + }); + + for(int i = 0; i < list.size(); i++) + list.get(i).addDamage(1); + }//resolve() + };//SpellAbility + + Input runtime = new Input() + { + private static final long serialVersionUID = 2004031367305867525L; + + public void showMessage() + { + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList choice = new CardList(play.getCards()); + choice = choice.getType("Land"); + stopSetNext(CardFactoryUtil.input_sacrifice(ability, choice, "Select a land to sacrifice.")); + } + }; + ability.setStackDescription(card +" deals 1 damage to each creature with flying."); + ability.setDescription("Sacrifice a land: Spitting Spider deals 1 damage to each creature with flying."); + card.addSpellAbility(ability); + ability.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Killer Whale")) + { + final Ability ability = new Ability(card, "U") + { + public boolean canPlayAI() + { + return false; + } + public void resolve() + { + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -8494294720368074013L; + + public void execute() + { + card.removeIntrinsicKeyword("Flying"); + } + }; + + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addIntrinsicKeyword("Flying"); + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + };//SpellAbility + + ability.setStackDescription(card +" gains flying until end of turn."); + ability.setDescription("U: Killer Whale gains flying until end of turn."); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + // *************** START *********** START ************************** + if (cardName.equals("Lay Waste") || cardName.equals("Stone Rain") + || cardName.equals("Ice Storm") || cardName.equals("Sinkhole")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4973311759179228894L; + public boolean canPlayAI() + { + CardList land = new CardList(AllZone.Human_Play.getCards()); + land = land.getType("Basic"); + return land.size() != 0; + } + public void chooseTargetAI() + { + // target basic land that Human only has 1 or 2 in play + CardList land = new CardList(AllZone.Human_Play.getCards()); + land = land.getType("Basic"); + Card target = null; + String[] name = + { "Forest", "Swamp", "Plains", "Mountain", "Island" }; + for (int i = 0; i < name.length; i++) + if (land.getName(name[i]).size() == 1) + { + target = land.getName(name[i]).get(0); + break; + } + // see if there are only 2 lands of the same type + if (target == null) + { + for (int i = 0; i < name.length; i++) + if (land.getName(name[i]).size() == 2) + { + target = land.getName(name[i]).get(0); + break; + } + }// if + if (target == null) + { + land.shuffle(); + target = land.get(0); + } + setTargetCard(target); + }// chooseTargetAI() + public void resolve() + { + if (AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + AllZone.GameAction.destroy(getTargetCard()); + }// resolve() + };// SpellAbility + card.clearSpellAbility(); + spell.setBeforePayMana(CardFactoryUtil.input_targetType(spell, + "Land")); + card.addSpellAbility(spell); + if (cardName.equals("Lay Waste")) + { + card.addSpellAbility(CardFactoryUtil.ability_cycle(card, "2")); + spell.setDescription("Destroy target land"); + } + return card; + }// *************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Obsidian Fireheart")) + { + final Ability ability = new Ability(card, "1 R R") + { + public void resolve() { + Card c = getTargetCard(); + + if (AllZone.GameAction.isCardInPlay(c) && c.isLand() && (c.getCounters(Counters.BLAZE)==0) ) + c.addCounter(Counters.BLAZE, 1); + + } + public boolean canPlayAI() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList land = new CardList(play.getCards()); + land = land.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.isLand() && c.getCounters(Counters.BLAZE) < 1; + } + }); + + if (land.size() > 0) + setTargetCard(land.get(0)); + + return land.size() > 0; + } + + }; + + ability.setDescription("1 R R: Put a blaze counter on target land without a blaze counter on it. For as long as that land has a blaze counter on it, it has \"At the beginning of your upkeep, this land deals 1 damage to you.\" (The land continues to burn after Obsidian Fireheart has left the battlefield.)"); + ability.setBeforePayMana(CardFactoryUtil.input_targetType(ability, "Land")); + card.addSpellAbility(ability); + + }// *************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Glint-Eye Nephilim")) + { + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 5790680475821014099L; + + public void execute() + { + card.addTempAttackBoost(-1); + card.addTempDefenseBoost(-1); + } + }; + + final Ability ability = new Ability(card, "1") + { + public boolean canPlayAI() + { + Card[] hand = AllZone.Computer_Hand.getCards(); + return CardFactoryUtil.AI_doesCreatureAttack(card) && (hand.length != 0); + } + public void chooseTargetAI() {AllZone.GameAction.discardRandom(Constant.Player.Computer);} + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card) ) + { + card.addTempAttackBoost(1); + card.addTempDefenseBoost(1); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + };//SpellAbility + + + Input runtime = new Input() + { + private static final long serialVersionUID = -4302110760957471033L; + + public void showMessage() + { + ability.setStackDescription(card +" gets +1/+1 until EOT."); + //stopSetNext(CardFactoryUtil.input_sacrifice(ability, choice, "Select a card to discard.")); + stopSetNext(CardFactoryUtil.input_discard(ability, 1)); + + } + }; + ability.setStackDescription(card +" gets +1/+1 until end of turn."); + ability.setDescription("1, Discard a card: Glint-Eye Nephilim gets +1/+1 until end of turn."); + card.addSpellAbility(ability); + ability.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Wild Mongrel")) + { + //sacrifice ability - targets itself - until EOT + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -5563743272875711445L; + + public void execute() + { + card.addTempAttackBoost(-1); + card.addTempDefenseBoost(-1); + } + }; + + //mana tap ability + final Ability ability = new Ability(card, "0") + { + public boolean canPlayAI() + { + Card[] hand = AllZone.Computer_Hand.getCards(); + return CardFactoryUtil.AI_doesCreatureAttack(card) && (hand.length > 3); + } + public void chooseTargetAI() {AllZone.GameAction.discardRandom(Constant.Player.Computer);} + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addTempAttackBoost(1); + card.addTempDefenseBoost(1); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + };//SpellAbility + + + Input runtime = new Input() + { + private static final long serialVersionUID = -4209163355325441624L; + + public void showMessage() + { + ability.setStackDescription(card +" gets +1/+1 until EOT."); + //stopSetNext(CardFactoryUtil.input_sacrifice(ability, choice, "Select a card to discard.")); + stopSetNext(CardFactoryUtil.input_discard(ability, 1)); + //AllZone.InputControl.setInput(CardFactoryUtil.input_discard()); + } + }; + ability.setStackDescription(card +" gets +1/+1 until end of turn."); + ability.setDescription("Discard a card: Wild Mongrel gets +1/+1 until end of turn."); + card.addSpellAbility(ability); + ability.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Hell-Bent Raider")) + { + final Command untilEOT = new Command() + { + + private static final long serialVersionUID = -2693050198371979012L; + + public void execute() + { + card.removeIntrinsicKeyword("Protection from white"); + } + }; + + //mana tap ability + final Ability ability = new Ability(card, "0") + { + public boolean canPlayAI() + { + return false; + } + + public void resolve() + { + AllZone.GameAction.discardRandom(card.getController()); + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addIntrinsicKeyword("Protection from white"); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + };//SpellAbility + + + ability.setStackDescription(card +" gets Protection from white until end of turn."); + ability.setDescription("Discard a card at random: Hell-Bent Raider gets protection from white until end of turn."); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Whiptongue Frog")) + { + //mana ability - targets itself - until EOT + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -2693050198371979012L; + + public void execute() + { + card.removeIntrinsicKeyword("Flying"); + } + }; + + //mana tap ability + final Ability ability = new Ability(card, "U") + { + public boolean canPlayAI() + { + return (! card.hasSickness()) && + (! card.getKeyword().contains("Flying")) && + (AllZone.Phase.getPhase().equals(Constant.Phase.Main1)); + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addIntrinsicKeyword("Flying"); + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + };//SpellAbility + + + Input runtime = new Input() + { + private static final long serialVersionUID = 1268037036474796569L; + + public void showMessage() + { + ability.setStackDescription(card +" gains flying until EOT."); + stopSetNext(new Input_PayManaCost(ability)); + } + }; + ability.setStackDescription("Whiptongue Frog gains flying until EOT."); + ability.setDescription("U: Whiptongue Frog gains flying until end of turn."); + card.addSpellAbility(ability); + ability.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Sarcomite Myr")) + { + //mana ability - targets itself - until EOT + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -1726670429352834671L; + + public void execute() + { + card.removeIntrinsicKeyword("Flying"); + } + }; + + //mana tap ability + final Ability ability = new Ability(card, "2") + { + public boolean canPlayAI() + { + return (! card.hasSickness()) && + (! card.getKeyword().contains("Flying")) && + (AllZone.Phase.getPhase().equals(Constant.Phase.Main1)); + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addIntrinsicKeyword("Flying"); + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + };//SpellAbility + + + Input runtime = new Input() + { + private static final long serialVersionUID = -685958984421033465L; + + public void showMessage() + { + ability.setStackDescription(card +" gains flying until EOT."); + stopSetNext(new Input_PayManaCost(ability)); + } + }; + ability.setStackDescription(card +" - gains flying until EOT."); + ability.setDescription("2: Sarcomite Myr gains flying until end of turn."); + card.addSpellAbility(ability); + ability.setBeforePayMana(runtime); + + //ability 2 + final Ability ability2 = new Ability(card, "2") + { + public boolean canPlayAI() + { + return false; + } + + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + }//resolve() + };//SpellAbility + + card.addSpellAbility(ability2); + ability2.setDescription("2, Sacrifice Sarcomite Myr: Draw a card."); + ability2.setStackDescription("Sarcomite Myr - draw a card"); + ability2.setBeforePayMana(new Input_PayManaCost_Ability(ability2.getManaCost(), new Command() + { + private static final long serialVersionUID = -4357239016463815380L; + + public void execute() + { + AllZone.GameAction.sacrifice(card); + AllZone.Stack.add(ability2); + } + })); + + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Goblin Balloon Brigade")) + { + //mana ability - targets itself - until EOT + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 3574792977266468264L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(card)) + card.removeIntrinsicKeyword("Flying"); + } + }; + + //mana tap ability + final Ability ability = new Ability(card, "R") + { + public boolean canPlayAI() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, false); + return flying.isEmpty() && + (! card.hasSickness()) && + (! card.getKeyword().contains("Flying")) && + (! CardFactoryUtil.AI_getHumanCreature(card, true).isEmpty()); + } + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addIntrinsicKeyword("Flying"); + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + };//SpellAbility + + + Input runtime = new Input() + { + private static final long serialVersionUID = 7757347395564372034L; + + public void showMessage() + { + ability.setStackDescription(card +" gains flying until EOT."); + stopSetNext(new Input_PayManaCost(ability)); + } + }; + ability.setStackDescription("Goblin Balloon Brigade gains flying until EOT."); + ability.setDescription("R: Goblin Balloon Brigade gains flying until end of turn."); + card.addSpellAbility(ability); + ability.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Manta Riders")) + { + //mana ability - targets itself - until EOT + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -8732007889935536106L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(card)) + card.removeIntrinsicKeyword("Flying"); + } + }; + + //mana tap ability + final Ability ability = new Ability(card, "U") + { + public boolean canPlayAI() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, false); + return flying.isEmpty() && + (! card.hasSickness()) && + (! card.getKeyword().contains("Flying")) && + (! CardFactoryUtil.AI_getHumanCreature(card, true).isEmpty()); + } + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.addIntrinsicKeyword("Flying"); + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + };//SpellAbility + + + Input runtime = new Input() + { + private static final long serialVersionUID = -3889041123558196949L; + + public void showMessage() + { + ability.setStackDescription(card +" gains flying until EOT."); + stopSetNext(new Input_PayManaCost(ability)); + } + }; + ability.setStackDescription(card.getName() +" gains flying until EOT."); + ability.setDescription("U: Manta Riders gains flying until end of turn."); + card.addSpellAbility(ability); + ability.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Turtleshell Changeling")) + { + //mana ability - targets itself - until EOT + //mana ability + final Ability ability = new Ability(card, "1 U") + { + public boolean canPlayAI() + { + return CardFactoryUtil.AI_doesCreatureAttack(card) && card.getNetAttack() == 1; + } + public void resolve() + { + //in case ability is played twice + final int[] oldAttack = new int[1]; + final int[] oldDefense = new int[1]; + + oldAttack[0] = card.getBaseAttack(); + oldDefense[0] = card.getBaseDefense(); + + card.setBaseAttack(oldDefense[0]); + card.setBaseDefense(oldAttack[0]); + + //EOT + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -5494886974452901728L; + + public void execute() + { + card.setBaseAttack(oldAttack[0]); + card.setBaseDefense(oldDefense[0]); + } + }; + + AllZone.EndOfTurn.addUntil(untilEOT); + }//resolve() + };//SpellAbility + + + ability.setStackDescription(card +" - switch power and toughness until EOT."); + ability.setDescription("1 U: Switch Turtleshell Changeling's power and toughness until end of turn."); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Wings of Velis Vel")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -5744842090293912606L; + public boolean canPlayAI() + { + Combat combat = ComputerUtil.getAttackers(); + @SuppressWarnings("unused") // attack + Card[] attack = combat.getAttackers(); + + CardList small = new CardList(AllZone.Computer_Play.getCards()); + small = small.getType("Creature"); + + //try to make a good attacker + if(0 < small.size()) + { + CardListUtil.sortAttackLowFirst(small); + setTargetCard(small.get(0)); + + return true && AllZone.Phase.getPhase().equals(Constant.Phase.Main1); + } + + return false; + }//canPlayAI() + public void resolve() + { + //in case ability is played twice + final int[] oldAttack = new int[1]; + final int[] oldDefense = new int[1]; + + final Card card[] = new Card[1]; + card[0] = getTargetCard(); + + oldAttack[0] = card[0].getBaseAttack(); + oldDefense[0] = card[0].getBaseDefense(); + + card[0].setBaseAttack(4); + card[0].setBaseDefense(4); + card[0].addExtrinsicKeyword("Flying"); + + //EOT + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 7236360479349324099L; + + public void execute() + { + card[0].setBaseAttack(oldAttack[0]); + card[0].setBaseDefense(oldDefense[0]); + + card[0].removeExtrinsicKeyword("Flying"); + } + }; + + AllZone.EndOfTurn.addUntil(untilEOT); + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + }//*************** END ************ END ************************** + + + +/* + //*************** START *********** START ************************** +if(cardName.equals("Epic Proportions")) +{ + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 358340213887424783L; + public boolean canPlayAI() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + if(list.isEmpty()) + return false; + + //else + CardListUtil.sortAttack(list); + CardListUtil.sortFlying(list); + + setTargetCard(list.get(0)); + return true; + }//canPlayAI() + public void resolve() + { + Card c = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + c.addSemiPermanentAttackBoost(5); + c.addSemiPermanentDefenseBoost(5); + c.addExtrinsicKeyword("Trample"); + } + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); +}//*************** END ************ END ************************** + +*/ + + + + +//*************** START *********** START ************************** +if(cardName.equals("Epic Proportions")) +{ + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 358340213887424783L; + + public boolean canPlay() + { + return true; // for flash, which is not working through the keyword for some reason + } + + public boolean canPlayAI() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + if(list.isEmpty()) + return false; + + //else + CardListUtil.sortAttack(list); + CardListUtil.sortFlying(list); + + setTargetCard(list.get(0)); + return true; + }//canPlayAI() + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(card); + + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) ) + { + card.enchantCard(c); + System.out.println("Enchanted: " +getTargetCard()); + } + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + Command onEnchant = new Command() + { + private static final long serialVersionUID = 5133552158526053493L; + + public void execute() + { + if (card.isEnchanting()) + { + Card crd = card.getEnchanting().get(0); + crd.addExtrinsicKeyword("Trample"); + crd.addSemiPermanentAttackBoost(5); + crd.addSemiPermanentDefenseBoost(5); + } + }//execute() + };//Command + + + Command onUnEnchant = new Command() + { + private static final long serialVersionUID = -2404250578944336031L; + + public void execute() + { + if (card.isEnchanting()) + { + Card crd = card.getEnchanting().get(0); + crd.removeExtrinsicKeyword("Trample"); + crd.addSemiPermanentAttackBoost(-5); + crd.addSemiPermanentDefenseBoost(-5); + } + + }//execute() + };//Command + + Command onLeavesPlay = new Command() + { + private static final long serialVersionUID = -6076263565995301138L; + + public void execute() + { + if (card.isEnchanting()) + { + Card crd = card.getEnchanting().get(0); + card.unEnchantCard(crd); + } + } + }; + + card.addEnchantCommand(onEnchant); + card.addUnEnchantCommand(onUnEnchant); + card.addLeavesPlayCommand(onLeavesPlay); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); +}//*************** END ************ END ************************** + +//*************** START *********** START ************************** +if(cardName.equals("Mythic Proportions")) +{ + final SpellAbility spell = new Spell(card) + { + + private static final long serialVersionUID = 4227124619270545652L; + public boolean canPlayAI() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + if(list.isEmpty()) + return false; + + //else + CardListUtil.sortAttack(list); + CardListUtil.sortFlying(list); + + setTargetCard(list.get(0)); + return true; + }//canPlayAI() + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(card); + + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) ) + { + card.enchantCard(c); + System.out.println("Enchanted: " +getTargetCard()); + } + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + Command onEnchant = new Command() + { + private static final long serialVersionUID = -6642467768059387172L; + + public void execute() + { + if (card.isEnchanting()) + { + Card crd = card.getEnchanting().get(0); + crd.addExtrinsicKeyword("Trample"); + crd.addSemiPermanentAttackBoost(8); + crd.addSemiPermanentDefenseBoost(8); + } + }//execute() + };//Command + + + Command onUnEnchant = new Command() + { + + private static final long serialVersionUID = 3550678810412528973L; + + public void execute() + { + if (card.isEnchanting()) + { + Card crd = card.getEnchanting().get(0); + crd.removeExtrinsicKeyword("Trample"); + crd.addSemiPermanentAttackBoost(-8); + crd.addSemiPermanentDefenseBoost(-8); + } + + }//execute() + };//Command + + Command onLeavesPlay = new Command() + { + private static final long serialVersionUID = -8590925715809196436L; + + public void execute() + { + if (card.isEnchanting()) + { + Card crd = card.getEnchanting().get(0); + card.unEnchantCard(crd); + } + } + }; + + card.addEnchantCommand(onEnchant); + card.addUnEnchantCommand(onUnEnchant); + card.addLeavesPlayCommand(onLeavesPlay); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); +}//*************** END ************ END ************************** + +//*************** START *********** START ************************** +if(cardName.equals("Nimbus Wings")) +{ + final SpellAbility spell = new Spell(card) + { + + + private static final long serialVersionUID = -4759884801420518565L; + public boolean canPlayAI() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + if(list.isEmpty()) + return false; + + //else + CardListUtil.sortAttack(list); + CardListUtil.sortFlying(list); + + for (int i=0;i 0) + { + setTargetCard(stuffy.get(0)); + return true; + } + else + { + CardList list = new CardList(AllZone.Human_Play.getCards()); + list = list.getType("Creature"); + + if(list.isEmpty()) + return false; + + //else + CardListUtil.sortAttack(list); + CardListUtil.sortFlying(list); + + for (int i=0;i= list.get(i).getNetDefense()) && list.get(i).getNetAttack() >= 3) + { + setTargetCard(list.get(i)); + return true; + } + } + } + return false; + + }//canPlayAI() + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(card); + + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) ) + card.enchantCard(c); + + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); +}//*************** END ************ END ************************** + +//*************** START *********** START ************************** +if(cardName.equals("Cessation")) +{ + final SpellAbility spell = new Spell(card) + { + + private static final long serialVersionUID = 3681531440398159146L; + public boolean canPlayAI() + { + CardList list = new CardList(AllZone.Human_Play.getCards()); + list = list.getType("Creature"); + + if(list.isEmpty()) + return false; + + //else + CardListUtil.sortAttack(list); + CardListUtil.sortFlying(list); + + for (int i=0;i()); + c.addType("Creature"); + c.addType("Treefolk"); + + c.setIntrinsicKeyword(new ArrayList()); + + c.clearSpellAbility(); + } + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Control Magic")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 7359753772138233155L; + public boolean canPlayAI() + { + CardList c = CardFactoryUtil.AI_getHumanCreature(card, true); + CardListUtil.sortAttack(c); + CardListUtil.sortFlying(c); + + if(c.isEmpty()) + return false; + + if(2 <= c.get(0).getNetAttack() && c.get(0).getKeyword().contains("Flying")) + { + setTargetCard(c.get(0)); + return true; + } + + CardListUtil.sortAttack(c); + if(4 <= c.get(0).getNetAttack()) + { + setTargetCard(c.get(0)); + return true; + } + + return false; + }//canPlayAI() + public void resolve() + { + + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(card); + + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) ) + card.enchantCard(c); + + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + Command onEnchant = new Command() + { + + private static final long serialVersionUID = -3423649303706656587L; + + public void execute() + { + if (card.isEnchanting()) + { + Card crd = card.getEnchanting().get(0); + //set summoning sickness + if(crd.getKeyword().contains("Haste")){ + crd.setSickness(false); + } + else{ + crd.setSickness(true); + } + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(false); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(false); + + PlayerZone from = AllZone.getZone(crd); + from.remove(crd); + + crd.setController(card.getController()); + + PlayerZone to = AllZone.getZone(Constant.Zone.Play, card.getController()); + to.add(crd); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(true); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(true); + } + }//execute() + };//Command + + Command onUnEnchant = new Command() + { + + private static final long serialVersionUID = -2365466450520529652L; + + public void execute() + { + if (card.isEnchanting()) + { + Card crd = card.getEnchanting().get(0); + if (AllZone.GameAction.isCardInPlay(crd)) + { + if(crd.getKeyword().contains("Haste")){ + crd.setSickness(false); + } + else{ + crd.setSickness(true); + } + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(false); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(false); + + PlayerZone from = AllZone.getZone(crd); + from.remove(crd); + + String opp = AllZone.GameAction.getOpponent(crd.getController()); + crd.setController(opp); + + PlayerZone to = AllZone.getZone(Constant.Zone.Play, opp); + to.add(crd); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(true); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(true); + } + } + + }//execute() + };//Command + + Command onLeavesPlay = new Command() + { + + + private static final long serialVersionUID = 8144460293841806556L; + + public void execute() + { + if (card.isEnchanting()) + { + Card crd = card.getEnchanting().get(0); + card.unEnchantCard(crd); + } + } + }; + + card.addEnchantCommand(onEnchant); + card.addUnEnchantCommand(onUnEnchant); + card.addLeavesPlayCommand(onLeavesPlay); + + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + //destroy doesn't work + if(cardName.equals("Sower of Temptation")) + { + final Card moveCreature[] = new Card[1]; + + final SpellAbility spell = new Spell_Permanent(card) + { + private static final long serialVersionUID = -6432280175218503718L; + public boolean canPlayAI() + { + CardList c = CardFactoryUtil.AI_getHumanCreature(card, true); + CardListUtil.sortAttack(c); + CardListUtil.sortFlying(c); + + if(c.isEmpty()) + return false; + + if(2 <= c.get(0).getNetAttack() && c.get(0).getKeyword().contains("Flying")) + { + setTargetCard(c.get(0)); + return true; + } + + CardListUtil.sortAttack(c); + if(4 <= c.get(0).getNetAttack()) + { + setTargetCard(c.get(0)); + return true; + } + + return false; + }//canPlayAI() + public void resolve() + { + super.resolve(); + + Card c = getTargetCard(); + moveCreature[0] = c; + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) ) + { + + //set summoning sickness + if(c.getKeyword().contains("Haste")){ + c.setSickness(false); + } + else{ + c.setSickness(true); + } + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(false); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(false); + + c.setSickness(true); + c.setController(card.getController()); + + PlayerZone from = AllZone.getZone(c); + from.remove(c); + + PlayerZone to = AllZone.getZone(Constant.Zone.Play, card.getController()); + to.add(c); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(true); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(true); + } + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + + card.addLeavesPlayCommand(new Command() + { + private static final long serialVersionUID = -8961588142846220965L; + + public void execute() + { + Card c = moveCreature[0]; + + if(AllZone.GameAction.isCardInPlay(c)) + { + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(false); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(false); + + c.setSickness(true); + c.setController(AllZone.GameAction.getOpponent(c.getController())); + + PlayerZone from = AllZone.getZone(c); + from.remove(c); + + PlayerZone to = AllZone.getZone(Constant.Zone.Play, c.getOwner()); + to.add(c); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(true); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(true); + }//if + }//execute() + });//Command + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Terramorphic Expanse")) + { + //tap sacrifice + final Ability_Tap ability = new Ability_Tap(card, "0") + { + private static final long serialVersionUID = 5441740362881917927L; + + public boolean canPlayAI() + { + return false; + /* + //sacrifice Sakura-Tribe Elder if Human has any creatures + CardList list = new CardList(AllZone.Human_Play.getCards()); + list = list.getType("Creature"); + return list.size() != 0 && card.isUntapped(); + */ + } + public void chooseTargetAI() + { + AllZone.GameAction.sacrifice(card); + } + public boolean canPlay() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + CardList list = new CardList(library.getCards()); + list = list.getType("Basic"); + if (list.size() > 0 && AllZone.GameAction.isCardInPlay(card)) + return true; + else + return false; + + }//canPlay() + public void resolve() + { + if(owner.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void computerResolve() + { + CardList play = new CardList(AllZone.Computer_Play.getCards()); + play = play.getType("Basic"); + + CardList library = new CardList(AllZone.Computer_Library.getCards()); + library = library.getType("Basic"); + + //this shouldn't happen, but it is defensive programming, haha + if(library.isEmpty()) + return; + + Card land = null; + + //try to find a basic land that isn't in play + for(int i = 0; i < library.size(); i++) + if(! play.containsName(library.get(i))) + { + land = library.get(i); + break; + } + + //if not found + //library will have at least 1 basic land because canPlay() checks that + if(land == null) + land = library.get(0); + + land.tap(); + AllZone.Computer_Library.remove(land); + AllZone.Computer_Play.add(land); + + AllZone.GameAction.shuffle(Constant.Player.Computer); + }//computerResolve() + + public void humanResolve() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play , card.getController()); + + CardList basicLand = new CardList(library.getCards()); + basicLand = basicLand.getType("Basic"); + + Object o = AllZone.Display.getChoiceOptional("Choose a basic land", basicLand.toArray()); + if(o != null) + { + Card land = (Card)o; + land.tap(); + + library.remove(land); + play.add(land); + } + AllZone.GameAction.shuffle(card.getController()); + }//resolve() + };//SpellAbility + + Input runtime = new Input() + { + private static final long serialVersionUID = -4379321114820908030L; + boolean once = true; + public void showMessage() + { + //this is necessary in order not to have a StackOverflowException + //because this updates a card, it creates a circular loop of observers + if(once) + { + once = false; + AllZone.GameAction.sacrifice(card); + + ability.setStackDescription(card.getController() +" - Search your library for a basic land card and put it into play tapped. Then shuffle your library."); + AllZone.Stack.add(ability); + + stop(); + } + }//showMessage() + }; + card.addSpellAbility(ability); + ability.setDescription("tap, Sacrifice Terramorphic Expanse: Search your library for a basic land card and put it into play tapped. Then shuffle your library."); + ability.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Frostling")) + { + final Ability ability = new Ability(card, "0") + { + public boolean canPlayAI() {return getCreature().size() != 0;} + + public void chooseTargetAI() + { + CardList list = getCreature(); + list.shuffle(); + setTargetCard(list.get(0)); + + AllZone.GameAction.sacrifice(card); + } + CardList getCreature() + { + //toughness of 1 + CardList list = CardFactoryUtil.AI_getHumanCreature(1, card, true); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + //only get 1/1 flyers or 2/1 creatures + return (2 <= c.getNetAttack()) || c.getKeyword().contains("Flying"); + } + }); + return list; + }//getCreature() + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + getTargetCard().addDamage(1); + }//resolve() + };//SpellAbility + + card.addSpellAbility(ability); + ability.setDescription("Sacrifice Frostling: Frostling deals 1 damage to target creature."); + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability, new Command() + { + private static final long serialVersionUID = 3482118508536148313L; + + public void execute() + { + AllZone.GameAction.sacrifice(card); + } + })); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Bottle Gnomes")) + { + final Ability ability = new Ability(card, "0") + { + public boolean canPlayAI() + { + return AllZone.Computer_Life.getLife() < 3; + + } + + public boolean canPlay() + { + SpellAbility sa; + for (int i=0; i 0 && super.canPlay(); + }//canPlay() + public void resolve() + { + if(owner.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void computerResolve() + { + CardList play = new CardList(AllZone.Computer_Play.getCards()); + play = play.getType("Basic"); + + CardList library = new CardList(AllZone.Computer_Library.getCards()); + library = library.getType("Basic"); + + //this shouldn't happen, but it is defensive programming, haha + if(library.isEmpty()) + return; + + Card land = null; + + //try to find a basic land that isn't in play + for(int i = 0; i < library.size(); i++) + if(! play.containsName(library.get(i))) + { + land = library.get(i); + break; + } + + //if not found + //library will have at least 1 basic land because canPlay() checks that + if(land == null) + land = library.get(0); + + land.tap(); + AllZone.Computer_Library.remove(land); + AllZone.Computer_Play.add(land); + + AllZone.GameAction.shuffle(Constant.Player.Computer); + }//computerResolve() + public void humanResolve() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play , card.getController()); + + CardList basicLand = new CardList(library.getCards()); + basicLand = basicLand.getType("Basic"); + if(basicLand.isEmpty()) + return; + + Object o = AllZone.Display.getChoiceOptional("Choose a basic land", basicLand.toArray()); + if(o != null) + { + Card land = (Card)o; + land.tap(); + + library.remove(land); + play.add(land); + } + + AllZone.GameAction.shuffle(card.getController()); + }//resolve() + };//SpellAbility + + Input runtime = new Input() + { + private static final long serialVersionUID = 1959709104655340395L; + boolean once = true; + public void showMessage() + { + //this is necessary in order not to have a StackOverflowException + //because this updates a card, it creates a circular loop of observers + if(once) + { + once = false; + AllZone.GameAction.sacrifice(card); + AllZone.Stack.add(ability); + + stop(); + } + }//showMessage() + }; + card.addSpellAbility(ability); + ability.setBeforePayMana(runtime); + ability.setDescription("Sacrifice Sakura-Tribe Elder: Search your library for a basic land card, put that card into play tapped, then shuffle your library."); + ability.setStackDescription("Search your library for a basic land card, put that card into play tapped, then shuffle your library."); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Transluminant")) + { + final Command atEOT = new Command() + { + private static final long serialVersionUID = -5126793112740563180L; + + public void execute() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Spirit"); + c.setImageName("W 1 1 Spirit"); + c.setManaCost("W"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Spirit"); + c.setBaseAttack(1); + c.setBaseDefense(1); + c.addIntrinsicKeyword("Flying"); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play , card.getController()); + play.add(c); + }//execute() + };//Command + + final Ability ability = new Ability(card, "W") + { + public boolean canPlayAI() + { /* + CardList list = new CardList(AllZone.Human_Play.getCards()); + list = list.getType("Creature"); + + String phase = AllZone.Phase.getPhase(); + return phase.equals(Constant.Phase.Main2) && list.size() != 0; + */ + return false; + } + public void chooseTargetAI() + { + AllZone.GameAction.sacrifice(card); + } + + public void resolve() + { + AllZone.EndOfTurn.addAt(atEOT); + }//resolve() + };//SpellAbility + + card.addSpellAbility(ability); + ability.setDescription("W, Sacrifice Transluminant: Put a 1/1 white Spirit creature token with flying into play at end of turn."); + ability.setStackDescription("Put a 1/1 white Spirit creature token with flying into play at end of turn."); + ability.setBeforePayMana(new Input_PayManaCost_Ability(ability.getManaCost(), new Command() + { + private static final long serialVersionUID = -6553009833190713980L; + + public void execute() + { + AllZone.GameAction.sacrifice(card); + AllZone.Stack.add(ability); + } + })); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Llanowar Behemoth")) + { + final Ability ability = new Ability(card, "0") + { + public boolean canPlayAI() + { + return (getUntapped().size() != 0) && CardFactoryUtil.AI_doesCreatureAttack(card); + } + public void chooseTargetAI() + { + Card c = getUntapped().get(0); + c.tap(); + setTargetCard(c); + } + CardList getUntapped() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && c.isUntapped() && (!CardFactoryUtil.AI_doesCreatureAttack(c)); + } + }); + return list; + }//getUntapped() + + public void resolve() + { + card.addTempAttackBoost(1); + card.addTempDefenseBoost(1); + + Command untilEOT = new Command() + { + private static final long serialVersionUID = 6445782721494547172L; + + public void execute() + { + card.addTempAttackBoost(-1); + card.addTempDefenseBoost(-1); + }//execute() + };//Command + + AllZone.EndOfTurn.addUntil(untilEOT); + }//resolve() + };//SpellAbility + + Input target = new Input() + { + private static final long serialVersionUID = 7721637420366357272L; + public void showMessage() + { + AllZone.Display.showMessage("Select an untapped creature you control"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + if(c.isCreature() && zone.is(Constant.Zone.Play, card.getController()) && c.isUntapped()) + { + ability.setStackDescription(card +" gets +1/+1 until end of turn."); + c.tap(); + AllZone.Stack.add(ability); + stop(); + } + } + };//Input + ability.setBeforePayMana(target); + ability.setDescription("Tap an untapped creature you control: Llanowar Behemoth gets +1/+1 until end of turn."); + + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Memnarch")) + { + //has 2 non-tap abilities that effects itself + final SpellAbility ability1 = new Ability(card, "1 U U") + { + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + getTargetCard().addType("Artifact"); + } + }//resolve() + public boolean canPlayAI() + { + CardList list = getCreature(); + return list.size() != 0; + } + public void chooseTargetAI() + { + Card target = CardFactoryUtil.AI_getBestCreature(getCreature()); + setTargetCard(target); + }//chooseTargetAI() + CardList getCreature() + { + CardList list = new CardList(AllZone.Human_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && (!c.isArtifact()); + } + }); + return list; + }//getCreature() + };//SpellAbility + + //**** start of ability2 + final SpellAbility ability2 = new Ability(card, "3 U") + { + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + //gain control of target artifact + PlayerZone from = AllZone.getZone(Constant.Zone.Play, getTargetCard().getController()); + from.remove(getTargetCard()); + + + getTargetCard().setController(card.getController()); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(false); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(false); + + PlayerZone to = AllZone.getZone(Constant.Zone.Play, card.getController()); + to.add(getTargetCard()); + to.setUpdate(true); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(true); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(true); + + +// AllZone.GameAction.moveTo(play, getTargetCard()); + + //TODO: controller probably is not set correctly + //TODO: when you take control, the creature looses type "Artifact" since + // GameAction.moveTo() makes a new card object + } + }//resolve() + public boolean canPlayAI() + { + CardList list = getArtifactCreatures(); + return list.size() != 0; + } + public void chooseTargetAI() + { + CardList list = getArtifactCreatures(); + Card target = CardFactoryUtil.AI_getBestCreature(list); + if(target == null) + target = AllZone.Human_Play.get(0); + + setTargetCard(target); + } + CardList getArtifactCreatures() + { + CardList list = new CardList(AllZone.Human_Play.getCards()); + list = list.getType("Artifact"); + list = list.getType("Creature"); + return list; + } + };//SpellAbility + card.addSpellAbility(ability1); + card.addSpellAbility(ability2); + + ability1.setDescription("1UU: Target permanent becomes an artifact in addition to its other types.(This effect doesn't end at end of turn.)"); + ability2.setDescription("3U: Gain control of target artifact.(This effect doesn't end at end of turn.)"); + + ability1.setBeforePayMana(CardFactoryUtil.input_targetType(ability1, "All")); + ability2.setBeforePayMana(CardFactoryUtil.input_targetType(ability2, "Artifact")); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Meloku the Clouded Mirror")) + { + final SpellAbility ability = new Ability(card, "1") + { + public void resolve() + { + Card c = new Card(); + c.setToken(true); + c.setImageName("U 1 1 Illusion"); + c.setName("Illusion"); + + c.setManaCost("U"); + c.setBaseAttack(1); + c.setBaseDefense(1); + c.addIntrinsicKeyword("Flying"); + c.addType("Creature"); + c.addType("Illusion"); + c.setOwner(card.getController()); + c.setController(card.getController()); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + + //TODO: the "bounced" land should be chosen by the user + //instead of "automatically" done for him + CardList island = new CardList(play.getCards()); + island = island.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.getType().contains("Land") && c.isTapped(); + } + }); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + + if(! island.isEmpty()) + AllZone.GameAction.moveTo(hand, island.get(0)); + }//resolve() + + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("1, Return a land you control to its owner's hand: Put a 1/1 blue Illusion creature token with flying into play."); + ability.setStackDescription("Put 1/1 token with flying into play"); + ability.setBeforePayMana(new Input_PayManaCost(ability)); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Squall Drifter")) + { + final SpellAbility ability = new Ability_Tap(card, "W") + { + private static final long serialVersionUID = 3862705592994953819L; + public void resolve() + { + Card c = getTargetCard(); + c.tap(); + } + public boolean canPlayAI() {return false;} + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("W, tap: Tap target creature."); + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("That Which Was Taken")) + { + final SpellAbility ability = new Ability_Tap(card, "4") + { + private static final long serialVersionUID = -8996435083734446340L; + public void resolve() + { + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) ) + c.addExtrinsicKeyword("Indestructible"); + } + public boolean canPlayAI() + { + CardList creatures = getCreatures(); + + for (int i = 0; i < creatures.size(); i++) + { + if (!creatures.get(i).getKeyword().contains("Indestructible")) + { + return true; + } + } + + return false; + } + public void chooseTargetAI() + { + //Card c = CardFactoryUtil.AI_getBestCreature(getCreatures()); + CardList a = getCreatures(); + CardListUtil.sortAttack(a); + CardListUtil.sortFlying(a); + + Card c = null; + + for (int i = 0; i < a.size(); i++) + { + if (!a.get(i).getKeyword().contains("Indestructible")) + { + c = a.get(i); + break; + } + } + + setTargetCard(c); + } + CardList getCreatures() + { + CardList list = new CardList(); + list.addAll(AllZone.Computer_Play.getCards()); + return list.getType("Creature"); + } + };//SpellAbility + + Input target = new Input() + { + private static final long serialVersionUID = 137806881250205274L; + public void showMessage() + { + AllZone.Display.showMessage("Select target permanent"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + if(zone.is(Constant.Zone.Play) && c != card)//cannot target self + { + ability.setTargetCard(c); + stopSetNext(new Input_PayManaCost(ability)); + } + } + };//Input -- target + + ability.setBeforePayMana(target); + ability.setDescription("4, tap: Tap a divinity counter on target permanent other than That Which Was Taken."); + + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Stern Judge")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 3059547795996737707L; + public void resolve() + { + AllZone.Human_Life.subtractLife(countSwamps("Human")); + AllZone.Computer_Life.subtractLife(countSwamps("Computer")); + } + int countSwamps(String player) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + CardList swamps = new CardList(play.getCards()); + swamps = swamps.getType("Swamp"); + return swamps.size(); + } + public boolean canPlayAI() + { + int computer = countSwamps(Constant.Player.Computer); + int human = countSwamps(Constant.Player.Human); + + if((computer >= AllZone.Computer_Life.getLife()) || (human == 0)) + return false; + + return computer <= human; + } + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: Each player loses 1 life for each Swamp he or she controls."); + ability.setStackDescription("Stern Judge - Each player loses 1 life for each Swamp he or she controls"); + ability.setBeforePayMana(new Input_NoCost_TapAbility(ability)); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Cackling Imp") || cardName.equals("Blightspeaker")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = -8034678094689484203L; + public void resolve() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + AllZone.GameAction.getPlayerLife(opponent).subtractLife(1); + } + public boolean canPlayAI() + { + //computer should play ability if this creature doesn't attack + Combat c = ComputerUtil.getAttackers(); + CardList list = new CardList(c.getAttackers()); + + //could this creature attack?, if attacks, do not use ability + return (! list.contains(card)); + } + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: Target player loses 1 life."); + ability.setStackDescription(card.getName() + " - Opponent loses 1 life."); + ability.setBeforePayMana(new Input_NoCost_TapAbility(ability)); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Sea Gate Loremaster")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + + private static final long serialVersionUID = -1701216509507402535L; + public boolean canPlayAI() {return false;} + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList list = new CardList(play.getCards()); + list = list.filter(new CardListFilter() + { + + public boolean addCard(Card c) { + return c.getType().contains("Ally") || c.getKeyword().contains("Changeling"); + } + + }); + + for (int i=0;i 3 && 6 < AllZone.Computer_Life.getLife(); + }//canPlayAI() + public void resolve() + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return ! c.getKeyword().contains("Flying") && CardFactoryUtil.canDamage(card, c); + } + }); + for(int i = 0; i < list.size(); i++) + list.get(i).addDamage(4); + + AllZone.Human_Life.subtractLife(4); + AllZone.Computer_Life.subtractLife(4); + }//resolve() + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: Hammerfist Giant deals 4 damage to each creature without flying and each player."); + ability.setStackDescription("Hammerfist Giant - deals 4 damage to each creature without flying and each player."); + ability.setBeforePayMana(new Input_NoCost_TapAbility(ability)); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Urborg Syphon-Mage")) + { + final Ability_Tap ability = new Ability_Tap(card, "2 B") + { + private static final long serialVersionUID = -1965170715774280112L; + + public void resolve() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + AllZone.GameAction.getPlayerLife(opponent).subtractLife(2); + + AllZone.GameAction.getPlayerLife(card.getController()).addLife(2); + + //computer discards here, todo: should discard when ability put on stack + if(card.getController().equals(Constant.Player.Computer)) + AllZone.GameAction.discardRandom(Constant.Player.Computer); + } + public boolean canPlay() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + return super.canPlay() && hand.getCards().length != 0; + } + public boolean canPlayAI() + { + int life = AllZone.Human_Life.getLife(); + Card[] hand = AllZone.Computer_Hand.getCards(); + return ((life < 11) || (5 < AllZone.Phase.getTurn())) && + hand.length > 0; + } + };//SpellAbility + + card.addSpellAbility(ability); + ability.setDescription("2B, tap, Discard a card: Each other player loses 2 life. You gain life equal to the life lost this way."); + ability.setStackDescription("Urborg Syphon-Mage - Opponent loses 2 life, and you gain 2 life"); + ability.setBeforePayMana(new Input_PayManaCost_Ability("2 B", new Command() + { + private static final long serialVersionUID = 1186455545951390853L; + + public void execute() + { + card.tap(); + AllZone.InputControl.setInput(CardFactoryUtil.input_discard()); + AllZone.Stack.add(ability); + } + })); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Spectral Procession")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 6118842682065463016L; + public void resolve() + { + makeToken(); + makeToken(); + makeToken(); + } + void makeToken() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("W"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Spirit"); + c.setBaseAttack(1); + c.setBaseDefense(1); + c.addIntrinsicKeyword("Flying"); + + c.setName("Spirit"); + c.setImageName("W 1 1 Spirit"); + + play.add(c); + } + }; + + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Stangg")){ + + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + Card c = new Card(); + + c.setName("Stangg Twin"); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("R G"); + c.setToken(true); + + c.addType("Legendary"); + c.addType("Creature"); + c.addType("Human"); + c.addType("Warrior"); + c.setBaseAttack(3); + c.setBaseDefense(4); + + c.addLeavesPlayCommand(new Command() + { + private static final long serialVersionUID = 3367390368512271319L; + + public void execute() { + if (AllZone.GameAction.isCardInPlay(card)) + AllZone.GameAction.sacrifice(card); + } + + }); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + + } + }; + ability.setStackDescription("When Stangg enters the battlefield, if Stangg is on the battlefield, put a legendary 3/4 red and green Human Warrior creature token named Stangg Twin onto the battlefield."); + + card.addComesIntoPlayCommand(new Command() + { + private static final long serialVersionUID = 6667896040611028600L; + + public void execute() { + AllZone.Stack.add(ability); + } + }); + + card.addLeavesPlayCommand(new Command() + { + private static final long serialVersionUID = 1786900359843939456L; + + public void execute() { + CardList list = new CardList(); + list.addAll(AllZone.Computer_Play.getCards()); + list.addAll(AllZone.Human_Play.getCards()); + list = list.getName("Stangg Twin"); + + if (list.size() == 1) + AllZone.GameAction.removeFromGame(list.get(0)); + } + }); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Llanowar Mentor")) + { + final Ability_Tap ability = new Ability_Tap(card, "G") + { + private static final long serialVersionUID = 752280918226277729L; + + public void resolve() + { + makeToken(); + + //computer discards here, todo: should discard when ability put on stack + if(card.getController().equals(Constant.Player.Computer)) + AllZone.GameAction.discardRandom(Constant.Player.Computer); + } + void makeToken() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Elf"); + c.addType("Druid"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + + //custom settings + c.setName("Llanowar Elves"); + c.setImageName("G 1 1 Llanowar Elves"); + //c.addIntrinsicKeyword("tap: add G"); + c.addSpellAbility(new Ability_Mana(card, "tap: add G") + { + private static final long serialVersionUID = 7871036527184588884L; + }); + + + play.add(c); + }//makeToken() + + public boolean canPlay() + { + Card c[] = AllZone.getZone(Constant.Zone.Hand, card.getController()).getCards(); + + return super.canPlay() && (0 < c.length); + } + + public boolean canPlayAI() + { + boolean canDiscard = 0 < AllZone.Computer_Hand.getCards().length; + return canPlay() && canDiscard && AllZone.Phase.getPhase().equals(Constant.Phase.Main2); + } + };//SpellAbility + + card.addSpellAbility(ability); + ability.setDescription("G, tap, Discard a card: Put a 1/1 green Elf Druid creature token named Llanowar Elves into play with \"tap: add G\" "); + ability.setStackDescription("Llanowar Mentor - Put a 1/1 token into play"); + ability.setBeforePayMana(new Input_PayManaCost_Ability("G", new Command() + { + private static final long serialVersionUID = -8140640118045101485L; + + public void execute() + { + card.tap(); + AllZone.InputControl.setInput(CardFactoryUtil.input_discard()); + AllZone.Stack.add(ability); + } + })); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Sparkspitter")) + { + final Ability_Tap ability = new Ability_Tap(card, "R") + { + private static final long serialVersionUID = -6381252527344512333L; + + public void resolve() + { + makeToken(); + + //computer discards here, todo: should discard when ability put on stack + if(card.getController().equals(Constant.Player.Computer)) + AllZone.GameAction.discardRandom(Constant.Player.Computer); + } + void makeToken() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + Card c = CardFactory.this.getCard("Spark Elemental", card.getController()); + c.setToken(true); + c.setImageName("R 3 1 Spark Elemental"); + play.add(c); + }//makeToken() + + public boolean canPlay() + { + Card c[] = AllZone.getZone(Constant.Zone.Hand, card.getController()).getCards(); + + return super.canPlay() && (0 < c.length); + } + + public boolean canPlayAI() + { + boolean canDiscard = 0 < AllZone.Computer_Hand.getCards().length; + return canPlay() && canDiscard; + } + };//SpellAbility + + card.addSpellAbility(ability); + ability.setDescription("R, tap, Discard a card: Put a 3/1 red Elemental creature token named Spark Elemental into play with trample, haste, and \"At end of turn, sacrifice Spark Elemental.\" "); + ability.setStackDescription("Sparkspitter - Put a 3/1 token into play"); + ability.setBeforePayMana(new Input_PayManaCost_Ability("R", new Command() + { + private static final long serialVersionUID = 4717424466422508064L; + + public void execute() + { + card.tap(); + AllZone.InputControl.setInput(CardFactoryUtil.input_discard()); + AllZone.Stack.add(ability); + } + })); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Sliversmith")) + { + final Ability_Tap ability = new Ability_Tap(card, "1") + { + private static final long serialVersionUID = -901356795848120643L; + + public void resolve() + { + makeToken(); + + //computer discards here, todo: should discard when ability put on stack + if(card.getController().equals(Constant.Player.Computer)) + AllZone.GameAction.discardRandom(Constant.Player.Computer); + } + void makeToken() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("1"); + c.setToken(true); + + c.addType("Artifact"); + c.addType("Creature"); + c.addType("Sliver"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + + //custom settings + c.setName("Metallic Sliver"); + c.setImageName("C 1 1 Metallic Sliver"); + + play.add(c); + }//makeToken() + + public boolean canPlay() + { + Card c[] = AllZone.getZone(Constant.Zone.Hand, card.getController()).getCards(); + + return super.canPlay() && (0 < c.length); + } + + public boolean canPlayAI() + { + boolean canDiscard = 0 < AllZone.Computer_Hand.getCards().length; + return canPlay() && canDiscard && AllZone.Phase.getPhase().equals(Constant.Phase.Main2); + } + };//SpellAbility + + card.addSpellAbility(ability); + ability.setDescription("1, tap, Discard a card: Put a 1/1 Sliver artifact creature token named Metallic Sliver into play."); + ability.setStackDescription(card +" - Put a 1/1 token into play"); + ability.setBeforePayMana(new Input_PayManaCost_Ability("1", new Command() + { + private static final long serialVersionUID = 7980998398222481323L; + + public void execute() + { + card.tap(); + AllZone.InputControl.setInput(CardFactoryUtil.input_discard()); + AllZone.Stack.add(ability); + } + })); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Cloudseeder")) + { + final Ability_Tap ability = new Ability_Tap(card, "U") + { + private static final long serialVersionUID = -4685908556244137496L; + + public void resolve() + { + makeToken(); + + //computer discards here, todo: should discard when ability put on stack + if(card.getController().equals(Constant.Player.Computer)) + AllZone.GameAction.discardRandom(Constant.Player.Computer); + } + void makeToken() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("U"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Faerie"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + + //custom settings + c.setName("Cloud Sprite"); + c.setImageName("U 1 1 Cloud Sprite"); + c.addIntrinsicKeyword("Flying"); + c.addIntrinsicKeyword("This creature can block only creatures with flying"); + + play.add(c); + }//makeToken() + + public boolean canPlay() + { + Card c[] = AllZone.getZone(Constant.Zone.Hand, card.getController()).getCards(); + + return super.canPlay() && (0 < c.length); + } + + public boolean canPlayAI() + { + boolean canDiscard = 0 < AllZone.Computer_Hand.getCards().length; + return canPlay() && canDiscard && AllZone.Phase.getPhase().equals(Constant.Phase.Main2); + } + };//SpellAbility + + card.addSpellAbility(ability); + ability.setDescription("U, tap, Discard a card: Put a 1/1 blue Sprite creature token named Cloud Sprite into play with flying and \"this creature can block only creatures with flying\"."); + ability.setStackDescription("Cloudseeker - Put a 1/1 token into play"); + ability.setBeforePayMana(new Input_PayManaCost_Ability("U", new Command() + { + private static final long serialVersionUID = 7707504858274558816L; + + public void execute() + { + card.tap(); + AllZone.InputControl.setInput(CardFactoryUtil.input_discard()); + AllZone.Stack.add(ability); + } + })); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Goldmeadow Lookout")) + { + final Ability_Tap ability = new Ability_Tap(card, "G") + { + private static final long serialVersionUID = -8413409735529340094L; + + public void resolve() + { + makeToken(); + + //computer discards here, todo: should discard when ability put on stack + if(card.getController().equals(Constant.Player.Computer)) + AllZone.GameAction.discardRandom(Constant.Player.Computer); + } + void makeToken() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("W"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Kithkin"); + c.addType("Soldier"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + + //custom settings + c.setName("Goldmeadow Harrier"); + c.setImageName("W 1 1 Goldmeadow Harrier"); + final SpellAbility ability = new Ability_Tap(c, "W") + { + private static final long serialVersionUID = -7327585136675896817L; + + public void resolve() + { + Card c = getTargetCard(); + c.tap(); + } + public boolean canPlayAI() {return false;} + };//SpellAbility + c.addSpellAbility(new Spell_Permanent(c)); + c.addSpellAbility(ability); + ability.setDescription("W, tap: Tap target creature."); + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + + + play.add(c); + }//makeToken() + + public boolean canPlay() + { + Card c[] = AllZone.getZone(Constant.Zone.Hand, card.getController()).getCards(); + + return super.canPlay() && (0 < c.length); + } + + public boolean canPlayAI() + { + boolean canDiscard = 0 < AllZone.Computer_Hand.getCards().length; + return canPlay() && canDiscard && AllZone.Phase.getPhase().equals(Constant.Phase.Main2); + } + };//SpellAbility + + card.addSpellAbility(ability); + ability.setDescription("W, tap, Discard a card: Put a 1/1 white Kithkin Soldier creature token named Goldmeadow Harrier into play with \"W, tap target creature.\""); + ability.setStackDescription("Goldmeadow Lookout - Put a 1/1 token into play"); + ability.setBeforePayMana(new Input_PayManaCost_Ability("W", new Command() + { + private static final long serialVersionUID = 8621733943286161557L; + + public void execute() + { + card.tap(); + AllZone.InputControl.setInput(CardFactoryUtil.input_discard()); + AllZone.Stack.add(ability); + } + })); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Goldmeadow Harrier") || cardName.equals("Loxodon Mystic") + || cardName.equals("Master Decoy")) + { + final SpellAbility ability = new Ability_Tap(card, "W") + { + + private static final long serialVersionUID = 4424848120984319655L; + public void resolve() + { + Card c = getTargetCard(); + c.tap(); + } + public boolean canPlayAI() {return false;} + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("W, tap: Tap target creature."); + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Silent Attendant")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + /** + * + */ + private static final long serialVersionUID = -2602340080268657851L; + public void resolve() + { + + AllZone.GameAction.getPlayerLife(card.getController()).addLife(1); + } + public boolean canPlayAI() + { + //computer should play ability if this creature doesn't attack + Combat c = ComputerUtil.getAttackers(); + CardList list = new CardList(c.getAttackers()); + + //could this creature attack?, if attacks, do not use ability + return (! list.contains(card)); + } + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: You gain 1 life."); + ability.setStackDescription(card.getName() + " - you gain 1 life."); + ability.setBeforePayMana(new Input_NoCost_TapAbility(ability)); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Ghost-Lit Redeemer")) + { + final SpellAbility ability = new Ability_Tap(card, "W") + { + private static final long serialVersionUID = -7119153679100849498L; + + public boolean canPlayAI() {return AllZone.Phase.getPhase().equals(Constant.Phase.Main2);} + + public void resolve() + { + Card c = card; + PlayerLife life = AllZone.GameAction.getPlayerLife(c.getController()); + life.addLife(2); + } + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("W, tap: You gain 2 life"); + ability.setStackDescription("Computer gains 2 life"); + + final Command paid = new Command() + { + private static final long serialVersionUID = 3649597692883194760L; + + public void execute() + { + Card c = card; + c.tap(); + AllZone.Human_Play.updateObservers();//so the card will tap at the correct time + + ability.setStackDescription(c.getController()+" gains 2 life"); + AllZone.Stack.add(ability); + AllZone.InputControl.resetInput(); + } + }; + ability.setBeforePayMana(new Input_PayManaCost_Ability(ability.getManaCost(), paid, Command.Blank)); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Tremor")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 3451888160398198322L; + + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.filter(new CardListFilter() + { + + public boolean addCard(Card c) { + return !c.getKeyword().contains("Flying") && CardFactoryUtil.canDamage(card, c) && + c.getNetDefense() == 1; + } + }); + computer = computer.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return !c.getKeyword().contains("Flying") && CardFactoryUtil.canDamage(card, c) && + c.getNetDefense() == 1; + } + }); + + // the computer will at least destroy 2 more human creatures + return computer.size() < human.size() - 1; + } + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + all = all.getType("Creature"); + + for(int i = 0; i < all.size(); i++) + if(! all.get(i).getKeyword().contains("Flying") && CardFactoryUtil.canDamage(card,all.get(i))) + all.get(i).addDamage(1); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Reviving Dose")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -3239301336328919121L; + + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.addLife(3); + + AllZone.GameAction.drawCard(card.getController()); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Swords to Plowshares")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 4752934806606319269L; + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + //add life + String player = getTargetCard().getController(); + PlayerLife life = AllZone.GameAction.getPlayerLife(player); + life.addLife(getTargetCard().getNetAttack()); + + //remove card from play + AllZone.GameAction.removeFromGame(getTargetCard()); + } + }//resolve() + public boolean canPlayAI() + { + CardList creature = new CardList(AllZone.Human_Play.getCards()); + creature = creature.getType("Creature"); + creature = creature.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return CardFactoryUtil.canTarget(card,c); + } + }); + return creature.size() != 0 && (AllZone.Phase.getTurn() > 4); + } + public void chooseTargetAI() + { + CardList play = new CardList(AllZone.Human_Play.getCards()); + Card target = CardFactoryUtil.AI_getBestCreature(play, card); + setTargetCard(target); + } + }; + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Unmake")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -9194035528349589512L; + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + //remove card from play + AllZone.GameAction.removeFromGame(getTargetCard()); + } + }//resolve() + public boolean canPlayAI() + { + CardList creature = new CardList(AllZone.Human_Play.getCards()); + creature = creature.getType("Creature"); + creature = creature.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return CardFactoryUtil.canTarget(card,c); + } + }); + return creature.size() != 0 && (AllZone.Phase.getTurn() > 4); + } + public void chooseTargetAI() + { + CardList play = new CardList(AllZone.Human_Play.getCards()); + Card target = CardFactoryUtil.AI_getBestCreature(play); + setTargetCard(target); + } + }; + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Crib Swap")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4567382566960071562L; + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + String player = getTargetCard().getController(); + makeToken(player); + + //remove card from play + AllZone.GameAction.removeFromGame(getTargetCard()); + } + }//resolve() + public boolean canPlayAI() + { + CardList creature = new CardList(AllZone.Human_Play.getCards()); + creature = creature.getType("Creature"); + return creature.size() != 0 && (AllZone.Phase.getTurn() > 4); + } + public void chooseTargetAI() + { + CardList play = new CardList(AllZone.Human_Play.getCards()); + Card target = CardFactoryUtil.AI_getBestCreature(play); + setTargetCard(target); + } + void makeToken(String player) + { + Card c = new Card(); + + c.setName("Shapeshifter"); + c.setName("C 1 1 Shapeshifter"); + + c.setOwner(player); + c.setController(player); + + c.setManaCost(""); + c.setToken(true); + + c.addType("Creature"); + c.addType("Shapeshifter"); + c.addIntrinsicKeyword("Changeling"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + play.add(c); + }//makeToken() + + }; + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Demonic Tutor") || cardName.equals("Diabolic Tutor") || cardName.equals("Grim Tutor")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 1481169060428051519L; + + public void resolve() + { + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void humanResolve() + { + Object check = AllZone.Display.getChoiceOptional("Select card", AllZone.Human_Library.getCards()); + if(check != null) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, (Card)check); + } + AllZone.GameAction.shuffle(Constant.Player.Human); + + //lose 3 life + if(cardName.equals("Grim Tutor")) + { + String player = Constant.Player.Human; + PlayerLife life = AllZone.GameAction.getPlayerLife(player); + life.subtractLife(3); + } + } + public void computerResolve() + { + Card[] library = AllZone.Computer_Library.getCards(); + CardList list = new CardList(library); + + //pick best creature + Card c = CardFactoryUtil.AI_getBestCreature(list); + if(c == null) + c = library[0]; + //System.out.println("comptuer picked - " +c); + AllZone.Computer_Library.remove(c); + AllZone.Computer_Hand.add(c); + + //lose 3 life + if(cardName.equals("Grim Tutor")) + { + String player = Constant.Player.Computer; + PlayerLife life = AllZone.GameAction.getPlayerLife(player); + life.subtractLife(3); + } + } + public boolean canPlay() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + + return library.getCards().length != 0 && AllZone.Phase.getActivePlayer().equals(card.getController()) + && !AllZone.Phase.getPhase().equals("End of Turn"); + } + public boolean canPlayAI() + { + CardList creature = new CardList(); + creature.addAll(AllZone.Computer_Library.getCards()); + creature = creature.getType("Creature"); + return creature.size() != 0; + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Entomb")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 4724906962713222211L; + public void resolve() + { + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void humanResolve() + { + Object check = AllZone.Display.getChoiceOptional("Select card", AllZone.Human_Library.getCards()); + if(check != null) + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + AllZone.GameAction.moveTo(grave, (Card)check); + } + AllZone.GameAction.shuffle(Constant.Player.Human); + } + public void computerResolve() + { + Card[] library = AllZone.Computer_Library.getCards(); + CardList list = new CardList(library); + + + //pick best creature + Card c = CardFactoryUtil.AI_getBestCreature(list); + if(c == null) + c = library[0]; + //System.out.println("comptuer picked - " +c); + AllZone.Computer_Library.remove(c); + AllZone.Computer_Graveyard.add(c); + } + public boolean canPlay() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + + return library.getCards().length != 0; + } + public boolean canPlayAI() + { + CardList creature = new CardList(); + creature.addAll(AllZone.Computer_Library.getCards()); + creature = creature.getType("Creature"); + return creature.size() != 0; + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Do or Die")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 8241241003478388362L; + + public boolean canPlayAI() + { + return 4 <= CardFactoryUtil.AI_getHumanCreature(card, true).size() && 4 < AllZone.Phase.getTurn(); + } + + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, getTargetPlayer()); + CardList list = new CardList(play.getCards()); + list = list.getType("Creature"); + + list.shuffle(); + + for(int i = 0; i < list.size() / 2; i++) + AllZone.GameAction.destroyNoRegeneration(list.get(i)); + } + };//SpellAbility + spell.setChooseTargetAI(CardFactoryUtil.AI_targetHuman()); + spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell)); + + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if (cardName.equals("Hymn to Tourach")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 42470566751344693L; + + public boolean canPlayAI() + { + return AllZone.Human_Hand.size() > 0; + } + + public void resolve() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + AllZone.GameAction.discardRandom(opponent); + AllZone.GameAction.discardRandom(opponent); + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Beacon of Destruction")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 6653675303299939465L; + + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + getTargetCard().addDamage(5); + done(); + } + else + AllZone.GameAction.moveToGraveyard(card); + } + else + { + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(5); + done(); + } + }//resolve() + void done() + { + //shuffle card back into the library + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + library.add(card); + AllZone.GameAction.shuffle(card.getController()); + } + }; + spell.setChooseTargetAI(CardFactoryUtil.AI_targetHumanCreatureOrPlayer()); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(spell, true)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Capsize")) + { + final SpellAbility spell_one = new Spell(card) + { + private static final long serialVersionUID = 7688777028599839669L; + + public boolean canPlayAI() {return false;} + + public void resolve() + { + final Card[] target = new Card[1]; + target[0] = getTargetCard(); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, target[0].getController()); + + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0]) ) + { + if (!target[0].isToken()) + AllZone.GameAction.moveTo(hand ,target[0]); + else + AllZone.GameAction.removeFromGame(target[0]); + + } + }//resolve() + };//SpellAbility + + final SpellAbility spell_two = new Spell(card) + { + + private static final long serialVersionUID = -2399079881132655853L; + public boolean canPlayAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + return 3 < AllZone.Phase.getTurn() && 0 < human.size(); + + } + public void chooseTargetAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + setTargetCard(CardFactoryUtil.AI_getBestCreature(human)); + } + + + public void resolve() + { + + final Card[] target = new Card[1]; + target[0] = getTargetCard(); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, target[0].getOwner()); + + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0]) ) + { + if (!target[0].isToken()) + AllZone.GameAction.moveTo(hand ,target[0]); + else + AllZone.GameAction.removeFromGame(target[0]); + } + done(); + }//resolve() + void done() + { + //return card to the hand + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, card); + } + };//SpellAbility + spell_two.setManaCost("4 U U"); + + spell_one.setDescription("Return target permanent to its owner's hand."); + spell_two.setDescription("Buyback 3 - Pay 4 U U, put this card into your hand as it resolves."); + spell_two.setIsBuyBackAbility(true); + + Input runtime1 = new Input() + { + + private static final long serialVersionUID = 6884105724632382299L; + + public void showMessage() + { + PlayerZone human = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + PlayerZone comp = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList perms = new CardList(); + perms.addAll(human.getCards()); + perms.addAll(comp.getCards()); + + stopSetNext(CardFactoryUtil.input_targetSpecific(spell_one, perms, "Select target permanent.", true)); + } + }; + + Input runtime2 = new Input() + { + private static final long serialVersionUID = 8564956495965504679L; + + public void showMessage() + { + PlayerZone human = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + PlayerZone comp = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList perms = new CardList(); + perms.addAll(human.getCards()); + perms.addAll(comp.getCards()); + + + stopSetNext(CardFactoryUtil.input_targetSpecific(spell_two, perms, "Select target permanent.", true)); + } + }; + + spell_one.setBeforePayMana(runtime1); + spell_two.setBeforePayMana(runtime2); + + card.clearSpellAbility(); + card.addSpellAbility(spell_one); + card.addSpellAbility(spell_two); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Whispers of the Muse")) + { + final SpellAbility spell_one = new Spell(card) + { + + private static final long serialVersionUID = 8341386638247535343L; + + public boolean canPlayAI() {return false;} + + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + }//resolve() + };//SpellAbility + + final SpellAbility spell_two = new Spell(card) + { + + private static final long serialVersionUID = -131686114078716307L; + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + done(); + }//resolve() + void done() + { + //return card to the hand + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, card); + } + };//SpellAbility + spell_two.setManaCost("5 U"); + + spell_one.setDescription("Draw a card."); + spell_one.setStackDescription(cardName + " - " +card.getController() + " draws a card."); + spell_two.setDescription("Buyback 5 - Pay 5 U , put this card into your hand as it resolves."); + spell_two.setStackDescription(cardName + " - (Buyback) " +card.getController() + " draws a card."); + spell_two.setIsBuyBackAbility(true); + + card.clearSpellAbility(); + card.addSpellAbility(spell_one); + card.addSpellAbility(spell_two); + + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Elvish Fury")) + { + final SpellAbility spell_one = new Spell(card) + { + private static final long serialVersionUID = 3356401944678089378L; + + public boolean canPlayAI() {return false;} + + public void resolve() + { + final Card[] target = new Card[1]; + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 7120352016188545025L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-2); + target[0].addTempDefenseBoost(-2); + } + } + }; + + target[0] = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0]) ) + { + target[0].addTempAttackBoost(2); + target[0].addTempDefenseBoost(2); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + };//SpellAbility + + final SpellAbility spell_two = new Spell(card) + { + private static final long serialVersionUID = 3898017438147188882L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public void chooseTargetAI() + { + setTargetCard(getAttacker()); + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + + CardList list = new CardList(c.getAttackers()); + CardListUtil.sortFlying(list); + + Card[] att = list.toArray(); + if(att.length != 0) + return att[0]; + else + return null; + }//getAttacker() + + + public void resolve() + { + final Card[] target = new Card[1]; + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 280295105716586978L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-2); + target[0].addTempDefenseBoost(-2); + } + } + }; + + target[0] = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0]) ) + { + target[0].addTempAttackBoost(2); + target[0].addTempDefenseBoost(2); + + AllZone.EndOfTurn.addUntil(untilEOT); + done(); + } + }//resolve() + void done() + { + //return card to the hand + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, card); + } + };//SpellAbility + spell_two.setManaCost("4 G"); + + spell_one.setDescription("Target creature gets +2/+2 until end of turn."); + spell_two.setDescription("Buyback 4 - Pay 4G, put this card into your hand as it resolves."); + + spell_one.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell_one)); + spell_two.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell_two)); + + spell_two.setIsBuyBackAbility(true); + + card.clearSpellAbility(); + card.addSpellAbility(spell_one); + card.addSpellAbility(spell_two); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Ramosian Revivalist")) + { + @SuppressWarnings("unused") // costMinusOne + String costMinusOne = ""; + int a = Integer.parseInt("6"); + a--; + costMinusOne = Integer.toString(a); + final int converted = a; + final String player = card.getController(); + + final SpellAbility ability = new Ability_Tap(card, "6") + { + private static final long serialVersionUID = 2675327938055139432L; + + public boolean canPlay() + { + SpellAbility sa; + for (int i=0; i0) + return true; + else + return false; + + } + + public void resolve() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, player); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + CardList rebels = new CardList(); + CardList list = new CardList(grave.getCards()); + list = list.getType("Rebel"); + + if (list.size()>0) + { + for (int i=0;i < list.size(); i++) + { + if (CardUtil.getConvertedManaCost(list.get(i).getManaCost()) <= converted) + { + rebels.add(list.get(i)); + } + + } + + if (rebels.size() > 0) + { + if (player.equals(Constant.Player.Computer)) + { + Card rebel = CardFactoryUtil.AI_getBestCreature(rebels); + grave.remove(rebel); + play.add(rebel); + } + else //human + { + Object o = AllZone.Display.getChoiceOptional("Select target Rebel", rebels.toArray()); + Card rebel = (Card)o; + grave.remove(rebel); + play.add(rebel); + } + }//rebels.size() >0 + }//list.size() > 0 + }//resolve + }; + ability.setDescription("6: Return target Rebel permanent card with converted mana cost 5 or less from your graveyard to play."); + ability.setStackDescription(card.getName() +" - return Rebel from graveyard to play."); + card.addSpellAbility(ability); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Marrow-Gnawer")) + { + final String player = card.getController(); + + final SpellAbility ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 447190529377334168L; + + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + CardList cards = new CardList(play.getCards()); + + Card c = getTargetCard(); + if (c != null) + { + AllZone.GameAction.sacrifice(c); + + CardList rats = new CardList(); + + for (int i=0;i < cards.size(); i++) + { + if (cards.get(i).getType().contains("Rat") || cards.get(i).getKeyword().contains("Changeling")){ + Card k = cards.get(i); + rats.add(k); + } + } + + if (!c.getName().equals("Marrow-Gnawer")) + { + for (int j=0; j < rats.size()-1; j++) + { + makeToken(); + } + } + else //some weird thing when targeting marrow himself, number of rats is different... so here's a hack: + { + for (int k=0; k < rats.size(); k++) + { + makeToken(); + } + } + } + }//resolve() + + public boolean canPlayAI() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.getType("Rat"); + + for (int i=0;i < list.size(); i++) + { + String name = list.get(i).getName(); + if (!name.equals("Marrow-Gnawer") && !name.equals("Relentless Rats")) + setTargetCard(list.get(i)); + if (name.equals("B 1 1 Rat")) + { + setTargetCard(list.get(i)); + break; + } + + } + + if (getTargetCard() == null) + System.out.println("getTargetCard null"); + if(getTargetCard() != null && list.size() > 3) + return true; + else + return false; + } + + + public void makeToken() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Rat"); + c.setImageName("B 1 1 Rat"); + c.setManaCost("B"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Rat"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + } + + + };//ability + + Input runtime = new Input() + { + private static final long serialVersionUID = 8552290582665041908L; + + public void showMessage() + { + CardList rats = new CardList(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards()); + rats = rats.getType("Rat"); + + stopSetNext(CardFactoryUtil.input_targetSpecific(ability, rats, "Select a Rat to sacrifice.", false)); + } + }; + + card.addSpellAbility(ability); + ability.setDescription("Tap, Sacrifice a rat: Put X 1/1 black Rat creature tokens into play, where X is the number of Rats you control."); + ability.setStackDescription(card.getName() + " - Put X 1/1 black Rat creature tokens into play, where X is the number of Rats you control."); + ability.setBeforePayMana(runtime); + + + }//*************** END ************ END ************************** + //*************** START *********** START ************************** + if(cardName.equals("Arcanis the Omnipotent")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 4743686230518855738L; + + public boolean canPlayAI() + { + return true; + } + + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + AllZone.GameAction.drawCard(card.getController()); + AllZone.GameAction.drawCard(card.getController()); + } + };//SpellAbility + + final SpellAbility ability2 = new Ability(card,"2 U U") + { + public void resolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getOwner()); + + card.untap(); + AllZone.getZone(card).remove(card); + if (!card.isToken()) + hand.add(card); + + } + public boolean canPlayAI() + { + return false; + } + }; //ability2 + + card.addSpellAbility(ability); + ability.setDescription("tap: Draw three cards."); + ability.setStackDescription("Arcanis - " + card.getController() + " draws three cards."); + ability.setBeforePayMana(new Input_NoCost_TapAbility(ability)); + + card.addSpellAbility(ability2); + ability2.setStackDescription(card.getController() + " returns Arcanis back to owner's hand."); + ability2.setDescription("2 U U: Return Arcanis the Omnipotent to its owner's hand."); + + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Lab Rats")) + { + final Command makeToken = new Command() + { + private static final long serialVersionUID = -6979735250385389139L; + + public void execute() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Rat"); + c.setImageName("B 1 1 Rat"); + c.setManaCost("B"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Rat"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//execute() + };//Command + + final SpellAbility spell_one = new Spell(card) + { + private static final long serialVersionUID = -8112024383172056976L; + + public boolean canPlayAI() {return false;} + + public void resolve() + { + makeToken.execute(); + }//resolve() + };//SpellAbility + + final SpellAbility spell_two = new Spell(card) + { + private static final long serialVersionUID = -7503701530510847636L; + + public void resolve() + { + makeToken.execute(); + + //return card to the hand + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, card); + } + + public boolean canPlayAI() + { + String phase = AllZone.Phase.getPhase(); + return phase.equals(Constant.Phase.Main2); + } + };//SpellAbility + + spell_one.setManaCost("B"); + spell_two.setManaCost("4 B"); + + spell_one.setDescription("Put a 1/1 black Rat token into play."); + spell_two.setDescription("Buyback 4 - Pay 4B, put this card into your hand as it resolves."); + + spell_one.setStackDescription("Lab Rats - Put a 1/1 black Rat token into play"); + spell_two.setStackDescription("Lab Rats - Buyback, Put a 1/1 black Rat token into play"); + + spell_two.setIsBuyBackAbility(true); + + card.clearSpellAbility(); + card.addSpellAbility(spell_one); + card.addSpellAbility(spell_two); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Sprout Swarm")) + { + final Command makeToken = new Command() + { + private static final long serialVersionUID = 648546709124047998L; + + public void execute() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Saproling"); + c.setImageName("G 1 1 Saproling"); + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Saproling"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//execute() + };//Command + + final SpellAbility spell_one = new Spell(card) + { + private static final long serialVersionUID = -609007714604161377L; + + public boolean canPlayAI() {return false;} + + public void resolve() + { + makeToken.execute(); + }//resolve() + };//SpellAbility + + final SpellAbility spell_two = new Spell(card) + { + private static final long serialVersionUID = -1387385820860395676L; + + public void resolve() + { + makeToken.execute(); + + //return card to the hand + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, card); + } + };//SpellAbility + + spell_one.setManaCost("1 G"); + spell_two.setManaCost("4 G"); + + spell_one.setDescription("Put a 1/1 green Saproling token into play. -- Sorry no convoke yet."); + spell_two.setDescription("Buyback 3 - Pay 4G, put this card into your hand as it resolves."); + + spell_one.setStackDescription("Sprout Swarm - Put a 1/1 green Saproling token into play"); + spell_two.setStackDescription("Sprout Swarm - Buyback, Put a 1/1 green Saproling token into play"); + + spell_two.setIsBuyBackAbility(true); + + card.clearSpellAbility(); + card.addSpellAbility(spell_one); + card.addSpellAbility(spell_two); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Threaten") || cardName.equals("Act of Treason")) + { + final PlayerZone[] orig = new PlayerZone[1]; + final PlayerZone[] temp = new PlayerZone[1]; + final String[] controllerEOT = new String[1]; + final Card[] target = new Card[1]; + + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 5310901886760561889L; + + public void execute() + { + //if card isn't in play, do nothing + if(! AllZone.GameAction.isCardInPlay(target[0])) + return; + + target[0].setController(controllerEOT[0]); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(false); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(false); + + //moveTo() makes a new card, so you don't have to remove "Haste" + //AllZone.GameAction.moveTo(playEOT[0], target[0]); + temp[0].remove(target[0]); + orig[0].add(target[0]); + target[0].untap(); + target[0].removeExtrinsicKeyword("Haste"); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(true); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(true); + }//execute() + };//Command + + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -3447822168516135816L; + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + orig[0] = AllZone.getZone(getTargetCard()); + controllerEOT[0] = getTargetCard().getController(); + target[0] = getTargetCard(); + + //set the controller + getTargetCard().setController(card.getController()); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(false); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(false); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(getTargetCard()); + temp[0] = play; + orig[0].remove(getTargetCard()); + + ((PlayerZone_ComesIntoPlay)AllZone.Human_Play).setTriggers(true); + ((PlayerZone_ComesIntoPlay)AllZone.Computer_Play).setTriggers(true); + + + getTargetCard().untap(); + getTargetCard().addExtrinsicKeyword("Haste"); + + AllZone.EndOfTurn.addUntil(untilEOT); + }//is card in play? + }//resolve() + public boolean canPlayAI() + { + //only use this card if creatures power is greater than 2 + CardList list = new CardList(AllZone.Human_Play.getCards()); + for(int i = 0; i < list.size(); i++) + if(2 < list.get(i).getNetAttack()) + return true; + + return false; + }//canPlayAI() + public void chooseTargetAI() + { + CardList list = new CardList(AllZone.Human_Play.getCards()); + setTargetCard(CardFactoryUtil.AI_getBestCreature(list)); + } + };//SpellAbility + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Beacon of Unrest")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -7614131436905786565L; + + public void resolve() + { + Card c = getTargetCard(); + PlayerZone grave = AllZone.getZone(c); + + if(AllZone.GameAction.isCardInZone(c, grave) && (c.isArtifact() || c.isCreature())) + { + //set the correct controller if needed + c.setController(card.getController()); + + //card changes zones + AllZone.getZone(c).remove(c); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + + //shuffle card back into the library + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + library.add(card); + AllZone.GameAction.shuffle(card.getController()); + } + }//resolve() + public boolean canPlay() + { + return getCreaturesAndArtifacts().length != 0; + } + + public Card[] getCreaturesAndArtifacts() + { + CardList graveyardCards = new CardList(); + graveyardCards.addAll(AllZone.Human_Graveyard.getCards()); + graveyardCards.addAll(AllZone.Computer_Graveyard.getCards()); + + CardList graveyardCreaturesAndArtifacts = graveyardCards.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isArtifact() || c.isCreature(); + } + }); + + return graveyardCreaturesAndArtifacts.toArray(); + } + public void chooseTargetAI() + { + Card c[] = getCreaturesAndArtifacts(); + Card biggest = c[0]; + for(int i = 0; i < c.length; i++) + if(biggest.getNetAttack() < c[i].getNetAttack()) + biggest = c[i]; + + setTargetCard(biggest); + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + Input target = new Input() + { + private static final long serialVersionUID = -83460850846474327L; + + public void showMessage() + { + Object check = AllZone.Display.getChoiceOptional("Select creature", getCreaturesAndArtifacts()); + if(check != null) + { + spell.setTargetCard((Card)check); + stopSetNext(new Input_PayManaCost(spell)); + } + else + stop(); + }//showMessage() + + //duplicated from SpellAbility above ^^^^^^^^ + public Card[] getCreaturesAndArtifacts() + { + CardList graveyardCards = new CardList(); + graveyardCards.addAll(AllZone.Human_Graveyard.getCards()); + graveyardCards.addAll(AllZone.Computer_Graveyard.getCards()); + + CardList graveyardCreaturesAndArtifacts = graveyardCards.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isArtifact() || c.isCreature(); + } + }); + + return graveyardCreaturesAndArtifacts.toArray(); + } + };//Input + spell.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Breath of Life") || cardName.equals("Resurrection") || cardName.equals("False Defeat") || cardName.equals("Zombify")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -5799646914112924814L; + + public void resolve() + { + Card c = getTargetCard(); + PlayerZone grave = AllZone.getZone(c); + + if(AllZone.GameAction.isCardInZone(c, grave)) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + AllZone.GameAction.moveTo(play, c); + } + }//resolve() + public boolean canPlay() + { + return getCreatures().length != 0; + } + public Card[] getCreatures() + { + CardList creature = new CardList(); + PlayerZone zone = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + creature.addAll(zone.getCards()); + creature = creature.getType("Creature"); + return creature.toArray(); + } + public void chooseTargetAI() + { + Card c[] = getCreatures(); + Card biggest = c[0]; + for(int i = 0; i < c.length; i++) + if(biggest.getNetAttack() < c[i].getNetAttack()) + biggest = c[i]; + + setTargetCard(biggest); + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + Input target = new Input() + { + private static final long serialVersionUID = -3717723884199321767L; + + public void showMessage() + { + Object check = AllZone.Display.getChoiceOptional("Select creature", getCreatures()); + if(check != null) + { + spell.setTargetCard((Card)check); + stopSetNext(new Input_PayManaCost(spell)); + } + else + stop(); + }//showMessage() + + public Card[] getCreatures() + { + CardList creature = new CardList(); + PlayerZone zone = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + creature.addAll(zone.getCards()); + creature = creature.getType("Creature"); + return creature.toArray(); + } + };//Input + spell.setBeforePayMana(target); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Horde of Notions")) + { + final Ability ability = new Ability(card, "W U B R G") + { + public void resolve() + { + Card c = null; + if (card.getController().equals("Human")) + { + Object o = AllZone.Display.getChoiceOptional("Select Elemental", getCreatures()); + c = (Card)o; + + } + else + { + c = getAIElemental(); + } + + PlayerZone grave = AllZone.getZone(c); + + if(AllZone.GameAction.isCardInZone(c, grave)) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + AllZone.GameAction.moveTo(play, c); + } + }//resolve() + public boolean canPlay() + { + return getCreatures().length != 0 && AllZone.GameAction.isCardInPlay(card); + } + public Card[] getCreatures() + { + CardList creature = new CardList(); + PlayerZone zone = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + creature.addAll(zone.getCards()); + creature = creature.getType("Elemental"); + return creature.toArray(); + } + public Card getAIElemental() + { + Card c[] = getCreatures(); + Card biggest = c[0]; + for(int i = 0; i < c.length; i++) + if(biggest.getNetAttack() < c[i].getNetAttack()) + biggest = c[i]; + + return biggest; + } + };//SpellAbility + card.addSpellAbility(ability); + + ability.setDescription("W U B R G: You may play target Elemental card from your graveyard without paying its mana cost."); + //ability.setBeforePayMana(new Input_); + ability.setStackDescription("Horde of Notions - play Elemental card from graveyard without paying its mana cost."); + ability.setBeforePayMana(new Input_PayManaCost(ability)); + + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Animate Dead")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 182812167945075560L; + + public void resolve() + { + Card c = getTargetCard(); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + PlayerZone grave = AllZone.getZone(c); + + if(AllZone.GameAction.isCardInZone(c, grave)) + { + c.addSemiPermanentAttackBoost(-1); + c.setController(card.getController()); + + play.add(c); + grave.remove(c); + } + }//resolve() + public boolean canPlay() + { + return getCreatures().length != 0; + } + public Card[] getCreatures() + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Graveyard.getCards()); + list.addAll(AllZone.Computer_Graveyard.getCards()); + list = list.getType("Creature"); + + return list.toArray(); + } + public boolean canPlayAI() + { + CardList all = new CardList(getCreatures()); + if(all.isEmpty()) + return false; + + Card c = CardFactoryUtil.AI_getBestCreature(all); + + if(2 < c.getNetAttack() && 2 < c.getNetDefense()) + return true; + + return false; + } + + public void chooseTargetAI() + { + Card c[] = getCreatures(); + Card biggest = c[0]; + for(int i = 0; i < c.length; i++) + if(biggest.getNetAttack() < c[i].getNetAttack()) + biggest = c[i]; + + setTargetCard(biggest); + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + Input target = new Input() + { + private static final long serialVersionUID = 9027742835781889044L; + + public void showMessage() + { + Object check = AllZone.Display.getChoiceOptional("Select creature", getCreatures()); + if(check != null) + { + spell.setTargetCard((Card)check); + stopSetNext(new Input_PayManaCost(spell)); + } + else + stop(); + }//showMessage() + + public Card[] getCreatures() + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Graveyard.getCards()); + list.addAll(AllZone.Computer_Graveyard.getCards()); + list = list.getType("Creature"); + + return list.toArray(); + } + };//Input + spell.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Blinding Light")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -631672055247954361L; + + public void resolve() + { + CardList nonwhite = new CardList(); + nonwhite.addAll(AllZone.Human_Play.getCards()); + nonwhite.addAll(AllZone.Computer_Play.getCards()); + nonwhite = nonwhite.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && (!CardUtil.getColors(c).contains(Constant.Color.White)); + } + }); + for(int i = 0; i < nonwhite.size(); i++) + nonwhite.get(i).tap(); + }//resolve() + public boolean canPlayAI() + { + //the computer seems to play this card at stupid times + return false; + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Raise the Alarm")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 3022771853846089829L; + + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + for (int i = 0; i < 2; i++) + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Soldier"); + c.setImageName("W 1 1 Soldier"); + c.setManaCost("W"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Soldier"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + play.add(c); + }//for + }//resolve() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Dragon Fodder")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -6704097906643840324L; + + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + for (int i = 0; i < 2; i++) + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Goblin"); + c.setImageName("R 1 1 Goblin"); + c.setManaCost("R"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Goblin"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + play.add(c); + }//for + }//resolve() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Empty the Warrens")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 1439643889038241969L; + + public void resolve() + { + int stormCount = 0; + + //get storm count + CardList list = new CardList(); + list.addAll(AllZone.Human_Graveyard.getCards()); + list.addAll(AllZone.Computer_Graveyard.getCards()); + + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + + for(int i = 0; i < list.size(); i++) + if(list.get(i).getTurnInZone() == AllZone.Phase.getTurn()) + stormCount++; + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + for (int i = 0; i < 2 * stormCount; i++) + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Goblin"); + c.setImageName("R 1 1 Goblin"); + c.setManaCost("R"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Goblin"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + play.add(c); + }//for + }//resolve() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Feudkiller's Verdict")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -5532477141899236266L; + + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.addLife(10); + + String opponent = AllZone.GameAction.getOpponent(card.getController()); + PlayerLife oppLife = AllZone.GameAction.getPlayerLife(opponent); + + if(oppLife.getLife() < life.getLife()) + makeToken(); + }//resolve() + + void makeToken() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Giant Warrior"); + c.setImageName("W 5 5 Giant Warrior"); + c.setManaCost("W"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Giant"); + c.addType("Warrior"); + c.setBaseAttack(5); + c.setBaseDefense(5); + + play.add(c); + }//makeToken() + + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Reach of Branches")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 2723115210677439611L; + + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + + //make token + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Treefolk Shaman"); + c.setImageName("G 2 5 Treefolk Shaman"); + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Treefolk"); + c.addType("Shaman"); + c.setBaseAttack(2); + c.setBaseDefense(5); + + play.add(c); + }//resolve() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Pyroclasm")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 8035123529251645470L; + + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + all = all.getType("Creature"); + + for(int i = 0; i < all.size(); i++) + { + if (CardFactoryUtil.canDamage(card,all.get(i))) + all.get(i).addDamage(2); + } + } + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Creature"); + computer = computer.getType("Creature"); + + human = CardListUtil.filterToughness(human, 2); + computer = CardListUtil.filterToughness(computer, 2); + + //the computer will at least destroy 2 more human creatures + return computer.size() < human.size()-1; + }//canPlayAI() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Volcanic Fallout")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 8274309635261086286L; + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + all = all.getType("Creature"); + + for(int i = 0; i < all.size(); i++) + { + if (CardFactoryUtil.canDamage(card,all.get(i))) + all.get(i).addDamage(2); + } + + PlayerLife compLife = AllZone.GameAction.getPlayerLife(Constant.Player.Computer); + compLife.subtractLife(2); + + PlayerLife humLife = AllZone.GameAction.getPlayerLife(Constant.Player.Human); + humLife.subtractLife(2); + + } + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Creature"); + computer = computer.getType("Creature"); + + human = CardListUtil.filterToughness(human, 2); + computer = CardListUtil.filterToughness(computer, 2); + + PlayerLife compLife = AllZone.GameAction.getPlayerLife(Constant.Player.Computer); + + //the computer will at least destroy 2 more human creatures + return computer.size() < human.size()-1 && compLife.getLife() > 3; + }//canPlayAI() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Flamebreak")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4224693616606508949L; + + public boolean canPlayAI() + { + return AllZone.Computer_Life.getLife()>3; + } + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + all = all.getType("Creature"); + + for(int i = 0; i < all.size(); i++) + if(! all.get(i).getKeyword().contains("Flying")) + { + if (CardFactoryUtil.canDamage(card, all.get(i))) + { + all.get(i).setShield(0); + all.get(i).addDamage(3); + } + } + + AllZone.Human_Life.subtractLife(3); + AllZone.Computer_Life.subtractLife(3); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Renewed Faith") || cardName.equals("Dosan's Oldest Chant") || cardName.equals("Nourish")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -1133816506198725425L; + + public boolean canPlay() + { + setStackDescription(card.getName() +" - " +card.getController() +" gains 6 life."); + return super.canPlay(); + } + + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.addLife(6); + } + }; + spell.setDescription("You gain 6 life."); + + card.clearSpellAbility(); + card.addSpellAbility(spell); + if (cardName.equals("Renewed Faith")) { + card.addSpellAbility(CardFactoryUtil.ability_cycle(card, "1 W")); + card.addCycleCommand(new Command(){ + private static final long serialVersionUID = 7699412574052780825L; + + public void execute() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.addLife(2); + } + }); + } + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("TestLife")) + { + SpellAbility ability1 = new Ability_Activated(card, "1") + { + private static final long serialVersionUID = -7597743923692184213L; + + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.addLife(1); + } + }; + ability1.setStackDescription(card.getController() +" gains 1 life"); + ability1.setDescription("1: gain 1 life"); + card.addSpellAbility(ability1); + + SpellAbility ability2 = new Ability_Activated(card, "1") + { + private static final long serialVersionUID = 1423759257249171223L; + + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.subtractLife(1); + } + }; + ability2.setStackDescription(card.getController() +" looses 1 life"); + ability2.setDescription("1: loose 1 life"); + card.addSpellAbility(ability2); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Life Burst")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 5653342880372240806L; + + public void resolve() + { + CardList count = new CardList(); + count.addAll(AllZone.Human_Graveyard.getCards()); + count.addAll(AllZone.Computer_Graveyard.getCards()); + count = count.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.getName().equals("Life Burst"); + } + }); + + PlayerLife life = AllZone.GameAction.getPlayerLife(getTargetPlayer()); + life.addLife(4 + (4 * count.size())); + } + }; + spell.setChooseTargetAI(CardFactoryUtil.AI_targetComputer()); + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell)); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Accumulated Knowledge")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -7650377883588723237L; + + public void resolve() + { + CardList count = new CardList(); + count.addAll(AllZone.Human_Graveyard.getCards()); + count.addAll(AllZone.Computer_Graveyard.getCards()); + count = count.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.getName().equals("Accumulated Knowledge"); + } + }); + + for (int i=0;i<=count.size();i++) + { + AllZone.GameAction.drawCard(card.getController()); + } + } + }; + spell.setDescription("Draw a card, then draw cards equal to the number of cards named Accumulated Knowledge in all graveyards."); + spell.setStackDescription(cardName + " - Draw a card, then draw cards equal to the number of cards named Accumulated Knowledge in all graveyards."); + card.clearSpellAbility(); + card.addSpellAbility(spell); + + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Wit's End")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 3829311830858468029L; + + public void resolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, getTargetPlayer()); + Card c[] = hand.getCards(); + for(int i = 0; i < c.length; i++) + AllZone.GameAction.discard(c[i]); + } + }; + spell.setChooseTargetAI(CardFactoryUtil.AI_targetHuman()); + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell)); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Cranial Extraction")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 8127696608769903507L; + + @SuppressWarnings("unchecked") // Comparator + public void resolve() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + Card choice = null; + + //check for no cards in library + PlayerZone library = AllZone.getZone(Constant.Zone.Library, opponent); + + if(library.size() == 0) //this is not right, but leaving it in here for now. + return; + + //human chooses + if(opponent.equals(Constant.Player.Computer)) + { + CardList all = AllZone.CardFactory.getAllCards(); + all.sort(new Comparator() + { + public int compare(Object a1, Object b1) + { + Card a = (Card)a1; + Card b = (Card)b1; + + return a.getName().compareTo(b.getName()); + } + }); + choice = (Card) AllZone.Display.getChoice("Choose", removeLand(all.toArray())); + + Card[] showLibrary = library.getCards(); + Comparator com = new TableSorter(new CardList(showLibrary), 2, true); + Arrays.sort(showLibrary, com); + + AllZone.Display.getChoiceOptional("Opponent's Library", showLibrary); + AllZone.GameAction.shuffle(opponent); + }//if + else//computer chooses + { + //the computer cheats by choosing a creature in the human players library or hand + CardList all = new CardList(); + all.addAll(AllZone.Human_Hand.getCards()); + all.addAll(AllZone.Human_Library.getCards()); + + CardList four = all.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if(c.isLand()) + return false; + + return 3 < CardUtil.getConvertedManaCost(c.getManaCost()); + } + }); + if(! four.isEmpty()) + choice = CardUtil.getRandom(four.toArray()); + else + choice = CardUtil.getRandom(all.toArray()); + + }//else + remove(choice, opponent); + AllZone.GameAction.shuffle(opponent); + }//resolve() + + void remove(Card c, String player) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player); + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + + CardList all = new CardList(); + all.addAll(hand.getCards()); + all.addAll(grave.getCards()); + all.addAll(library.getCards()); + + for(int i = 0; i < all.size(); i++) + if(all.get(i).getName().equals(c.getName())){ + if(player.equals(Constant.Player.Human)){ + AllZone.GameAction.moveTo(AllZone.Human_Removed, all.get(i)); + } + else{ + AllZone.GameAction.moveTo(AllZone.Computer_Removed, all.get(i)); + } + } + }//remove() + + public boolean canPlayAI() + { + Card[] c = removeLand(AllZone.Human_Library.getCards()); + return 0 < c.length; + } + Card[] removeLand(Card[] in) + { + CardList c = new CardList(in); + c = c.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return !c.isLand(); + } + }); + return c.toArray(); + }//removeLand() + };//SpellAbility spell + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(new Input_PayManaCost(spell)); + spell.setStackDescription(card.getName() +" - targeting opponent"); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Coercion")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 7200945225788294439L; + + public void resolve() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + Card choice = null; + + //check for no cards in hand on resolve + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, opponent); + Card[] handChoices = removeLand(hand.getCards()); + + if(handChoices.length == 0) + return; + + //human chooses + if(opponent.equals(Constant.Player.Computer)) + { + choice = (Card) AllZone.Display.getChoice("Choose", handChoices); + } + else//computer chooses + { + choice = CardUtil.getRandom(handChoices); + } + + AllZone.GameAction.discard(choice); + }//resolve() + + public boolean canPlayAI() + { + Card[] c = removeLand(AllZone.Human_Hand.getCards()); + return 0 < c.length; + } + + Card[] removeLand(Card[] in) + { + return in; + }//removeLand() + };//SpellAbility spell + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(new Input_PayManaCost(spell)); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Brainbite")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 6967309558624188256L; + + public void resolve() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + Card choice = null; + + //check for no cards in hand on resolve + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, opponent); + Card[] handChoices = removeLand(hand.getCards()); + + if(handChoices.length == 0){ + AllZone.GameAction.drawCard(card.getController()); + return; + } + + + //human chooses + if(opponent.equals(Constant.Player.Computer)) + { + choice = (Card) AllZone.Display.getChoice("Choose", handChoices); + } + else//computer chooses + { + choice = CardUtil.getRandom(handChoices); + } + + AllZone.GameAction.discard(choice); + AllZone.GameAction.drawCard(card.getController()); + }//resolve() + + public boolean canPlayAI() + { + Card[] c = removeLand(AllZone.Human_Hand.getCards()); + return 0 < c.length; + } + + Card[] removeLand(Card[] in) + { + return in; + }//removeLand() + };//SpellAbility spell + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(new Input_PayManaCost(spell)); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Thoughtseize") || cardName.equals("Distress")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 5338238621454661783L; + + public void resolve() + { + if(cardName.equals("Thoughtseize")) + AllZone.GameAction.getPlayerLife(card.getController()).subtractLife(2); + + Card choice = null; + + //check for no cards in hand on resolve + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, getTargetPlayer()); + Card[] handChoices = removeLand(hand.getCards()); + + if(handChoices.length == 0) + return; + + //human chooses + if(card.getController().equals(Constant.Player.Human)) + { + choice = (Card) AllZone.Display.getChoice("Choose", handChoices); + } + else//computer chooses + { + choice = CardUtil.getRandom(handChoices); + } + + AllZone.GameAction.discard(choice); + }//resolve() + + public boolean canPlayAI() + { + Card[] c = removeLand(AllZone.Human_Hand.getCards()); + return 0 < c.length; + } + + Card[] removeLand(Card[] in) + { + CardList c = new CardList(in); + c = c.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return !c.isLand(); + } + }); + return c.toArray(); + }//removeLand() + };//SpellAbility spell + spell.setChooseTargetAI(CardFactoryUtil.AI_targetHuman()); + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell)); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Douse in Gloom")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 7134826062024728943L; + + public boolean canPlayAI() + { + CardList c = getCreature(); + if(c.isEmpty()) + return false; + else + { + setTargetCard(c.get(0)); + return true; + } + }//canPlayAI() + CardList getCreature() + { + CardList out = new CardList(); + CardList list = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + list.shuffle(); + + for(int i = 0; i < list.size(); i++) + if((list.get(i).getNetAttack() >= 2) && (list.get(i).getNetDefense() <= 2)) + out.add(list.get(i)); + + //in case human player only has a few creatures in play, target anything + if(out.isEmpty() && + 0 < CardFactoryUtil.AI_getHumanCreature(2, card, true).size() && + 3 > CardFactoryUtil.AI_getHumanCreature(card, true).size()) + { + out.addAll(CardFactoryUtil.AI_getHumanCreature(2, card, true).toArray()); + CardListUtil.sortFlying(out); + } + return out; + }//getCreature() + + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + getTargetCard().addDamage(2); + AllZone.GameAction.getPlayerLife(card.getController()).addLife(2); + } + }//resolve() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Echoing Decay")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 3154935854257358023L; + + public boolean canPlayAI() + { + CardList c = getCreature(); + if(c.isEmpty()) + return false; + else + { + setTargetCard(c.get(0)); + return true; + } + }//canPlayAI() + CardList getCreature() + { + CardList out = new CardList(); + CardList list = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + list.shuffle(); + + for(int i = 0; i < list.size(); i++) + if((list.get(i).getNetAttack() >= 2) && (list.get(i).getNetDefense() <= 2)) + out.add(list.get(i)); + + //in case human player only has a few creatures in play, target anything + if(out.isEmpty() && + 0 < CardFactoryUtil.AI_getHumanCreature(2, card, true).size() && + 3 > CardFactoryUtil.AI_getHumanCreature(card, true).size()) + { + out.addAll(CardFactoryUtil.AI_getHumanCreature(2, card, true).toArray()); + CardListUtil.sortFlying(out); + } + return out; + }//getCreature() + + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + final Card c = getTargetCard(); + + c.addTempAttackBoost(-2); + c.addTempDefenseBoost(-2); + + AllZone.EndOfTurn.addUntil(new Command() + { + private static final long serialVersionUID = 1327455269456577020L; + + public void execute() + { + c.addTempAttackBoost(2); + c.addTempDefenseBoost(2); + } + }); + + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + + list = list.getName(getTargetCard().getName()); + list.remove(getTargetCard()); + + if (!getTargetCard().isFaceDown()) + for(int i = 0; i < list.size(); i++) + { + final Card crd = list.get(i); + + crd.addTempAttackBoost(-2); + crd.addTempDefenseBoost(-2); + + AllZone.EndOfTurn.addUntil(new Command() + { + private static final long serialVersionUID = 5151337777143949221L; + + public void execute() + { + crd.addTempAttackBoost(2); + crd.addTempDefenseBoost(2); + } + }); + //list.get(i).addDamage(2); + } + + }//in play? + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Maelstrom Pulse")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4050843868789582138L; + + public boolean canPlayAI() + { + CardList c = getCreature(); + if(c.isEmpty()) + return false; + else + { + setTargetCard(c.get(0)); + return true; + } + }//canPlayAI() + CardList getCreature() + { + CardList out = new CardList(); + CardList list = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + list.shuffle(); + + for(int i = 0; i < list.size(); i++) + if((list.get(i).getNetAttack() >= 2) && (list.get(i).getNetDefense() <= 2)) + out.add(list.get(i)); + + //in case human player only has a few creatures in play, target anything + if(out.isEmpty() && + 0 < CardFactoryUtil.AI_getHumanCreature(2, card, true).size() && + 3 > CardFactoryUtil.AI_getHumanCreature(card, true).size()) + { + out.addAll(CardFactoryUtil.AI_getHumanCreature(2, card, true).toArray()); + CardListUtil.sortFlying(out); + } + return out; + }//getCreature() + + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + + AllZone.GameAction.destroy(getTargetCard()); + + if(! getTargetCard().isToken() && !getTargetCard().isFaceDown()) + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + + list = list.getName(getTargetCard().getName()); + list.remove(getTargetCard()); + + if (!getTargetCard().isFaceDown()) + for(int i = 0; i < list.size(); i++) + AllZone.GameAction.destroy(list.get(i)); + }//is token? + }//in play? + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + Input target = new Input() + { + private static final long serialVersionUID = -4947592326270275532L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target non-land permanent for " +spell.getSourceCard()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(zone.is(Constant.Zone.Play) && !card.isLand()) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + } + };//Input + + spell.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Ravenous Rats") || cardName.equals("Corrupt Court Official")) + { + final Ability ability = new Ability(card,"0") + { + public boolean canPlayAI() + { + return true; + } + public void resolve() + { + if(Constant.Player.Computer.equals(getTargetPlayer())) + AllZone.GameAction.discardRandom(getTargetPlayer()); + else + AllZone.InputControl.setInput(CardFactoryUtil.input_discard()); + }//resolve() + };//SpellAbility + + Command intoPlay = new Command() + { + private static final long serialVersionUID = -2028008593708491452L; + + public void execute() + { + if(card.getController().equals(Constant.Player.Human)) + { + AllZone.InputControl.setInput(CardFactoryUtil.input_targetPlayer(ability)); + ButtonUtil.disableAll(); + } + else//computer + { + ability.setTargetPlayer(Constant.Player.Human); + AllZone.Stack.add(ability); + }//else + }//execute() + };//Command + card.addComesIntoPlayCommand(intoPlay); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Boris Devilboon")) + { + final Ability_Tap tokenAbility1 = new Ability_Tap(card, "2 B R") + { + private static final long serialVersionUID = -6343382804503119405L; + + public boolean canPlayAI() + { + String phase = AllZone.Phase.getPhase(); + return phase.equals(Constant.Phase.Main2); + } + public void chooseTargetAI() {card.tap();} + + public void resolve() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Minor Demon"); + c.setImageName("BR 1 1 Demon"); + c.setManaCost("B R"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Demon"); + + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//resolve() + };//SpellAbility + + card.addSpellAbility(tokenAbility1); + + tokenAbility1.setDescription("2 B R, tap: Put a 1/1 black and red Demon creature token named Minor Demon onto the battlefield."); + tokenAbility1.setStackDescription(card.getName() + " - Put a 1/1 black and red Demon creature token named Minor Demon onto the battlefield."); + tokenAbility1.setBeforePayMana(new Input_PayManaCost(tokenAbility1)); + } + + //*************** START *********** START ************************** + if(cardName.equals("Rhys the Redeemed")) + { + final Ability_Tap tokenAbility1 = new Ability_Tap(card, "2 GW") + { + private static final long serialVersionUID = 411298860775527337L; + + public boolean canPlayAI() + { + String phase = AllZone.Phase.getPhase(); + return phase.equals(Constant.Phase.Main2); + } + public void chooseTargetAI() {card.tap();} + + public void resolve() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Elf Warrior"); + c.setImageName("GW 1 1 Elf Warrior"); + c.setManaCost("GW"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Elf"); + c.addType("Warrior"); + + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//resolve() + };//SpellAbility + + card.addSpellAbility(tokenAbility1); + + tokenAbility1.setDescription("2 GW, tap: Put a 1/1 green and white Elf Warrior creature token into play."); + tokenAbility1.setStackDescription(card.getName() + " - Put a 1/1 green and white Elf Warrior creature token into play."); + tokenAbility1.setBeforePayMana(new Input_PayManaCost(tokenAbility1)); + + ///////////////////////////////////////////////////////////////////// + + final Ability_Tap copyTokens1 = new Ability_Tap(card, "4 GW GW") + { + private static final long serialVersionUID = 6297992502069547478L; + + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList allTokens = new CardList(); + allTokens.addAll(play.getCards()); + allTokens = allTokens.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && c.isToken(); + } + }); + + for (int i=0;i= 2; + } + }; + + card.addSpellAbility(copyTokens1); + + copyTokens1.setDescription("4 GW GW, tap: For each creature token you control, put a token into play that's a copy of that creature."); + copyTokens1.setStackDescription(card.getName() + " - For each creature token you control, put a token into play that's a copy of that creature."); + copyTokens1.setBeforePayMana(new Input_PayManaCost(copyTokens1)); + + + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Bringer of the Green Dawn") || cardName.equals("Bringer of the Blue Dawn") || + cardName.equals("Bringer of the White Dawn")) + { + final SpellAbility diffCost = new Spell(card) + { + private static final long serialVersionUID = -1598664186463358630L; + public void resolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand ,card.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play ,card.getController()); + + + hand.remove(card); + play.add(card); + card.comesIntoPlay(); //do i need this? + } + public boolean canPlay() + { + return AllZone.Phase.getActivePlayer().equals(card.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn") && !AllZone.GameAction.isCardInPlay(card); + } + + }; + diffCost.setManaCost("W U B R G"); + diffCost.setDescription("You may pay W U B R G rather than pay "+card.getName() +"'s mana cost. "); + diffCost.setStackDescription(card.getName() + " - Creature 5/5"); + card.addSpellAbility(diffCost); + + + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Thelonite Hermit")) + { + + Command turnsFaceUp = new Command() + { + private static final long serialVersionUID = -3882798504865405413L; + + public void execute() + { + makeToken(); + makeToken(); + makeToken(); + makeToken(); + + }//execute() + + public void makeToken() + { + Card c = new Card(); + + + c.setName("Saproling"); + c.setImageName("G 1 1 Saproling"); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Saproling"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + } + };//Command + + + card.addTurnFaceUpCommand(turnsFaceUp); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Imperial Hellkite")) + { + final String player = card.getController(); + Command turnsFaceUp = new Command() + { + private static final long serialVersionUID = -1407485989096862288L; + + public void execute() + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + + CardList list = new CardList(lib.getCards()); + list = list.getType("Dragon"); + + if (list.size()==0) + return; + + + if (player.equals(Constant.Player.Computer)) + { + Card dragon = CardFactoryUtil.AI_getBestCreature(list); + lib.remove(dragon); + hand.add(dragon); + } + else //human + { + Object o = AllZone.Display.getChoiceOptional("Select Dragon", list.toArray()); + Card dragon = (Card)o; + lib.remove(dragon); + hand.add(dragon); + } + AllZone.GameAction.shuffle(card.getController()); + }//execute() + };//Command + + card.addTurnFaceUpCommand(turnsFaceUp); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Corrupt")) + { + + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 335838994716307031L; + + Card check; + public boolean canPlayAI() + { + if(AllZone.Human_Life.getLife() <= countSwamps(card)) + return true; + + check = getFlying(); + return check != null; + } + + public int countSwamps(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + CardList swamps = new CardList(play.getCards()); + swamps = swamps.getType("Swamp"); + return swamps.size(); + } + + public void chooseTargetAI() + { + if(AllZone.Human_Life.getLife() <= 12) //12? mebbe 15? + { + setTargetPlayer(Constant.Player.Human); + return; + } + + Card c = getFlying(); + if((c == null) || (! check.equals(c))) + throw new RuntimeException(card +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + setTargetCard(c); + }//chooseTargetAI() + + //uses "damage" variable + Card getFlying() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + for(int i = 0; i < flying.size(); i++) + if(flying.get(i).getNetDefense() <= countSwamps(card)) + return flying.get(i); + + return null; + } + + public void resolve() + { + int damage = countSwamps(card); + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + Card c = getTargetCard(); + c.addDamage(damage); + AllZone.GameAction.getPlayerLife(card.getController()).addLife(damage); + } + } + else { + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage); + AllZone.GameAction.getPlayerLife(card.getController()).addLife(damage); + } + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(spell,true)); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Sunlance")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -8327380630150660908L; + + int damage = 3; + Card check; + public boolean canPlayAI() + { + check = getFlying(); + return check != null; + } + public void chooseTargetAI() + { + Card c = getFlying(); + if((c == null) || (! check.equals(c))) + throw new RuntimeException(card +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + setTargetCard(c); + }//chooseTargetAI() + + //uses "damage" variable + Card getFlying() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + for(int i = 0; i < flying.size(); i++) + if(flying.get(i).getNetDefense() <= damage && + (!CardUtil.getColors(flying.get(i)).contains(Constant.Color.White))) + { + return flying.get(i); + } + return null; + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + Card c = getTargetCard(); + c.addDamage(damage); + } + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + //target + Input target = new Input() + { + private static final long serialVersionUID = -579427555773493417L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target non-white creature for " +spell.getSourceCard()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if((!CardUtil.getColors(card).contains(Constant.Color.White)) && + card.isCreature() && + zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + } + };//SpellAbility - target + + spell.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Saltblast")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -8701870029034823295L; + + Card check; + public boolean canPlayAI() + { + check = getFlying(); + return check != null; + } + public void chooseTargetAI() + { + Card c = getFlying(); + if((c == null) || (! check.equals(c))) + throw new RuntimeException(card +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + setTargetCard(c); + }//chooseTargetAI() + + //uses "damage" variable + Card getFlying() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + for(int i = 0; i < flying.size(); i++) + if(!CardUtil.getColors(flying.get(i)).contains(Constant.Color.White)) + { + return flying.get(i); + } + return null; + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c)) + AllZone.GameAction.destroy(c); + } + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + //target + Input target = new Input() + { + private static final long serialVersionUID = 6040042391157137555L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target non-white permanent for " +spell.getSourceCard()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if((!CardUtil.getColors(card).contains(Constant.Color.White)) && + zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + } + };//SpellAbility - target + + spell.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Firebolt")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4100322462753117988L; + + int damage = 2; + Card check; + + public boolean canPlayAI() + { + if(AllZone.Human_Life.getLife() <= damage) + return true; + + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if (hand.size() >= 8) + return true; + + check = getFlying(); + return check != null; + } + public void chooseTargetAI() + { + if(AllZone.Human_Life.getLife() <= damage) + { + setTargetPlayer(Constant.Player.Human); + return; + } + + Card c = getFlying(); + if((c == null) || (! check.equals(c))) + throw new RuntimeException(card +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + setTargetCard(c); + }//chooseTargetAI() + + //uses "damage" variable + Card getFlying() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + for(int i = 0; i < flying.size(); i++) + if(flying.get(i).getNetDefense() <= damage) + return flying.get(i); + + return null; + } + + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + Card c = getTargetCard(); + c.addDamage(damage); + } + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage); + } + };//SpellAbility + + final SpellAbility flashback = new Spell(card) + { + + private static final long serialVersionUID = -4811352682106571233L; + int damage = 2; + Card check; + + public boolean canPlay() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard ,card.getController()); + String phase = AllZone.Phase.getPhase(); + String activePlayer = AllZone.Phase.getActivePlayer(); + + return AllZone.GameAction.isCardInZone(card, grave) && + ((phase.equals(Constant.Phase.Main1) || phase.equals(Constant.Phase.Main2)) && + card.getController().equals(activePlayer) && AllZone.Stack.size() == 0 ); + } + + public boolean canPlayAI() + { + if(AllZone.Human_Life.getLife() <= damage) + return true; + + check = getFlying(); + return check != null; + } + public void chooseTargetAI() + { + if(AllZone.Human_Life.getLife() <= damage) + { + setTargetPlayer(Constant.Player.Human); + return; + } + + Card c = getFlying(); + if((c == null) || (! check.equals(c))) + throw new RuntimeException(card +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + setTargetCard(c); + }//chooseTargetAI() + + //uses "damage" variable + Card getFlying() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + for(int i = 0; i < flying.size(); i++) + if(flying.get(i).getNetDefense() <= damage) + return flying.get(i); + + return null; + } + + public void resolve() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard , card.getController()); + PlayerZone removed = AllZone.getZone(Constant.Zone.Removed_From_Play, card.getController()); + + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + Card c = getTargetCard(); + c.addDamage(damage); + } + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage); + + grave.remove(card); + removed.add(card); + + } + };//flashback + flashback.setManaCost("4 R"); + flashback.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(flashback,true)); + flashback.setDescription("Flashback: 4R"); + + card.clearSpellAbility(); + card.addSpellAbility(spell); + card.addSpellAbility(flashback); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(spell,true)); + card.setFlashback(true); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Spark Spray")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 6619448976712515187L; + + public void chooseTargetAI() + { + setStackDescription("Spark Spray cycling - Computer draws a card"); + }//chooseTargetAI() + + public void resolve() + { + if(card.getController().equals(Constant.Player.Computer)) + { + AllZone.GameAction.drawCard(Constant.Player.Computer); + return; + } + + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + Card c = getTargetCard(); + c.addDamage(1); + } + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(1); + } + };//SpellAbility + spell.setDescription("Spark Spray deals 1 damage to target creature or player."); + card.clearSpellAbility(); + + card.addSpellAbility(spell); + card.addSpellAbility(CardFactoryUtil.ability_cycle(card, "R")); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(spell,true)); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Cackling Flames")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 2635417318395677454L; + + int damage = 3; + Card check; + public boolean canPlayAI() + { + if(AllZone.Human_Life.getLife() <= damage) + return true; + + check = getFlying(); + return check != null; + } + public void chooseTargetAI() + { + if(AllZone.Human_Life.getLife() <= damage) + { + setTargetPlayer(Constant.Player.Human); + return; + } + + Card c = getFlying(); + if((c == null) || (! check.equals(c))) + throw new RuntimeException(card +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + setTargetCard(c); + }//chooseTargetAI() + + //uses "damage" variable + Card getFlying() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + for(int i = 0; i < flying.size(); i++) + if(flying.get(i).getNetDefense() <= damage) + return flying.get(i); + + return null; + } + + + + public void resolve() + { + int damage = getDamage(); + + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + Card c = getTargetCard(); + c.addDamage(damage); + } + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage); + } + int getDamage() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + if(hand.size() == 0) + return 5; + + return 3; + } + };//SpellAbility + card.clearSpellAbility(); + + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(spell,true)); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Mob Justice")) + { + final SpellAbility spell = new Spell(card) + { + + private static final long serialVersionUID = -671093248575416927L; + + public boolean canPlayAI() + { + int damage = countControlledCreatures(Constant.Player.Computer); + + if(AllZone.Human_Life.getLife() <= damage || damage >= 4) + return true; + + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if (hand.size() >= 8) + return true; + + return false; + } + public void chooseTargetAI() + { + setTargetPlayer(Constant.Player.Human); + }//chooseTargetAI() + + public void resolve() + { + int damage = countControlledCreatures(card.getController()); + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage); + } + //count basic lands you control + int countControlledCreatures(String player) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + CardList creatures = new CardList(play.getCards()); + creatures = creatures.getType("Creature"); + + return creatures.size(); + }//countControlledCreatures(); + + };//SpellAbility + card.clearSpellAbility(); + + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell)); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Tribal Flames")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -9055422004395136061L; + + Card check; + public boolean canPlayAI() + { + int damage = countLandTypes(); + + if(AllZone.Human_Life.getLife() <= damage) + return true; + + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if (hand.size() >= 8) + return true; + + check = getFlying(); + return check != null; + } + public void chooseTargetAI() + { + int damage = countLandTypes(); + + if(AllZone.Human_Life.getLife() <= damage) + { + setTargetPlayer(Constant.Player.Human); + return; + } + + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if(getFlying() == null && hand.size() >= 7 ) //not 8, since it becomes 7 when getting cast + { + setTargetPlayer(Constant.Player.Human); + return; + } + + Card c = getFlying(); + if((c == null) || (! check.equals(c))) + throw new RuntimeException(card +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + setTargetCard(c); + }//chooseTargetAI() + + //uses "damage" variable + Card getFlying() + { + int damage = countLandTypes(); + + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + for(int i = 0; i < flying.size(); i++) + if(flying.get(i).getNetDefense() <= damage) + return flying.get(i); + + return null; + } + + + public void resolve() + { + int damage = countLandTypes(); + + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + Card c = getTargetCard(); + c.addDamage(damage); + } + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage); + } + //count basic lands you control + int countLandTypes() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList land = new CardList(play.getCards()); + + String basic[] = {"Forest", "Plains", "Mountain", "Island", "Swamp"}; + int count = 0; + + for(int i = 0; i < basic.length; i++) + { + CardList c = land.getType(basic[i]); + if(! c.isEmpty()) + count++; + } + + return count; + }//countLandTypes() + + };//SpellAbility + card.clearSpellAbility(); + + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(spell,true)); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Erratic Explosion")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -6003403347798646257L; + + int damage = 3; + Card check; + public boolean canPlayAI() + { + if(AllZone.Human_Life.getLife() <= damage) + return true; + + check = getFlying(); + return check != null; + } + public void chooseTargetAI() + { + if(AllZone.Human_Life.getLife() <= damage) + { + setTargetPlayer(Constant.Player.Human); + return; + } + + Card c = getFlying(); + if((c == null) || (! check.equals(c))) + throw new RuntimeException(card +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + setTargetCard(c); + }//chooseTargetAI() + + //uses "damage" variable + Card getFlying() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + for(int i = 0; i < flying.size(); i++) + if(flying.get(i).getNetDefense() <= damage) + return flying.get(i); + + return null; + } + + public void resolve() + { + int damage = getDamage(); + + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + javax.swing.JOptionPane.showMessageDialog(null, "Erratic Explosion causes " +damage +" to " +getTargetCard()); + + Card c = getTargetCard(); + c.addDamage(damage); + } + } + else + { + javax.swing.JOptionPane.showMessageDialog(null, "Erratic Explosion causes " +damage +" to " +getTargetPlayer()); + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage); + } + } + //randomly choose a nonland card + int getDamage() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + CardList notLand = new CardList(library.getCards()); + notLand = notLand.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return ! c.isLand(); + } + }); + notLand.shuffle(); + + if(notLand.isEmpty()) + return 0; + + Card card = notLand.get(0); + return CardUtil.getConvertedManaCost(card.getSpellAbility()[0]); + } + };//SpellAbility + card.clearSpellAbility(); + + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(spell, true)); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Char")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -1379875309204771345L; + + int damage = 4; + Card check; + public boolean canPlayAI() + { + if(AllZone.Computer_Life.getLife() < 2) + return false; + + if(AllZone.Human_Life.getLife() <= damage) + return true; + + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if (hand.size() >= 8) + return true; + + check = getFlying(); + return check != null; + } + public void chooseTargetAI() + { + if(AllZone.Human_Life.getLife() <= damage) + { + setTargetPlayer(Constant.Player.Human); + return; + } + + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if(getFlying() == null && hand.size() >= 7 ) //not 8, since it becomes 7 when getting cast + { + setTargetPlayer(Constant.Player.Human); + return; + } + + Card c = getFlying(); + if((c == null) || (! check.equals(c))) + throw new RuntimeException(card +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + setTargetCard(c); + }//chooseTargetAI() + + //uses "damage" variable + Card getFlying() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + for(int i = 0; i < flying.size(); i++) + if(flying.get(i).getNetDefense() <= damage) + return flying.get(i); + + return null; + } + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + Card c = getTargetCard(); + c.addDamage(damage); + AllZone.GameAction.getPlayerLife(card.getController()).subtractLife(2); + } + } + else + { + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage); + AllZone.GameAction.getPlayerLife(card.getController()).subtractLife(2); + } + + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + Input target = new Input() + { + private static final long serialVersionUID = -7645439029870010010L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target Creature, Player or Planeswalker"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if((card.isCreature() || card.isPlaneswalker())&& zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + }//selectCard() + public void selectPlayer(String player) + { + spell.setTargetPlayer(player); + stopSetNext(new Input_PayManaCost(spell)); + } + }; + spell.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Psionic Blast")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -5315747587330795963L; + + int damage = 4; + Card check; + public boolean canPlayAI() + { + if(AllZone.Computer_Life.getLife() <= 2) + return false; + + if(AllZone.Human_Life.getLife() <= damage) + return true; + + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if (hand.size() >= 8) + return true; + + check = getFlying(); + return check != null; + } + public void chooseTargetAI() + { + if(AllZone.Human_Life.getLife() <= damage) + { + setTargetPlayer(Constant.Player.Human); + return; + } + + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if(getFlying() == null && hand.size() >= 7 ) //not 8, since it becomes 7 when getting cast + { + setTargetPlayer(Constant.Player.Human); + return; + } + + Card c = getFlying(); + if((c == null) || (! check.equals(c))) + throw new RuntimeException(card +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + setTargetCard(c); + }//chooseTargetAI() + + //uses "damage" variable + Card getFlying() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + for(int i = 0; i < flying.size(); i++) + if(flying.get(i).getNetDefense() <= damage) + return flying.get(i); + + return null; + } + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + Card c = getTargetCard(); + c.addDamage(damage); + AllZone.GameAction.getPlayerLife(card.getController()).subtractLife(2); + } + } + else + { + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage); + AllZone.GameAction.getPlayerLife(card.getController()).subtractLife(2); + } + + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + Input target = new Input() + { + private static final long serialVersionUID = -3883369136409452222L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target Creature, Player or Planeswalker"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if((card.isCreature() || card.isPlaneswalker())&& zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + }//selectCard() + public void selectPlayer(String player) + { + spell.setTargetPlayer(player); + stopSetNext(new Input_PayManaCost(spell)); + } + }; + spell.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Hidetsugu's Second Rite")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 176857775451818523L; + + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(getTargetPlayer()); + if(life.getLife() == 10) + life.subtractLife(10); + } + public boolean canPlay() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + PlayerLife p = AllZone.GameAction.getPlayerLife(opponent); + return p.getLife() == 10; + } + }; + spell.setChooseTargetAI(CardFactoryUtil.AI_targetHuman()); + card.clearSpellAbility(); + card.addSpellAbility(spell); + + spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell)); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Soulscour") ) + { + SpellAbility spell = new Spell(card) + { + + private static final long serialVersionUID = -4554873222565897972L; + + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + for (int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + if (c.isPermanent() && !c.isArtifact()) + AllZone.GameAction.destroy(c); + } + }// resolve() + + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Creature"); + computer = computer.getType("Creature"); + + // the computer will at least destroy 2 more human creatures + return computer.size() < human.size() - 1 || + (AllZone.Computer_Life.getLife() < 7 && !human.isEmpty()); + } + };// SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }// *************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("March of Souls")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -1468254925312413359L; + + public void resolve() + { + change(AllZone.Human_Play, card.getController()); + change(AllZone.Computer_Play, card.getController()); + } + public void change(PlayerZone play, String owner) + { + Card[] c = play.getCards(); + for (int i = 0; i < c.length; i++) + { + if(c[i].isCreature()) + { + AllZone.GameAction.destroyNoRegeneration(c[i]); + play.add(getCreature(c[i].getController())); + } + } + }//change() + public Card getCreature(String owner) + { + //TODO: owner and controller is NOT the same player sometimes + //owner is the player who played March of Souls + //the controller is the player who's creature was destroyed + Card c = new Card(); + c.setToken(true); + c.setOwner(owner); + c.setController(owner); + + c.setName("Spirit"); + c.setImageName("W 1 1 Spirit"); + c.setBaseAttack(1); + c.setBaseDefense(1); + c.addIntrinsicKeyword("Flying"); + + c.setManaCost("W"); + c.addType("Creature"); + c.addType("Spirit"); + return c; + }//getCreature() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + +//*************** START *********** START ************************** + if (cardName.equals("Wrath of God") || cardName.equals("Damnation")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -18728406578984546L; + + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + for (int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + if (c.isCreature()) + AllZone.GameAction.destroyNoRegeneration(c); + } + }// resolve() + + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Creature"); + computer = computer.getType("Creature"); + + // the computer will at least destroy 2 more human creatures + return computer.size() < human.size() - 1 || + (AllZone.Computer_Life.getLife() < 7 && !human.isEmpty()); + } + };// SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }// *************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Day of Judgment")) + { + SpellAbility spell = new Spell(card) + { + + private static final long serialVersionUID = -2916641841124966207L; + + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + for (int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + if (c.isCreature()) + AllZone.GameAction.destroy(c); + } + }// resolve() + + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Creature"); + computer = computer.getType("Creature"); + + // the computer will at least destroy 2 more human creatures + return computer.size() < human.size() - 1 || + (AllZone.Computer_Life.getLife() < 7 && !human.isEmpty()); + } + };// SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }// *************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if (cardName.equals("Planar Cleansing") ) + { + SpellAbility spell = new Spell(card) + { + + private static final long serialVersionUID = -4233719265268955876L; + + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + for (int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + if (c.isPermanent() && !c.isLand()) + AllZone.GameAction.destroy(c); + } + }// resolve() + + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Creature"); + computer = computer.getType("Creature"); + + // the computer will at least destroy 2 more human creatures + return computer.size() < human.size() - 1 || + (AllZone.Computer_Life.getLife() < 7 && !human.isEmpty()); + } + };// SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }// *************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Tranquility") || cardName.equals("Tempest of Light") || cardName.equals("Cleanfall")) + { + SpellAbility spell = new Spell(card) + { + + private static final long serialVersionUID = 3087098751201624354L; + + public void resolve() + { + + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + for (int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + if (c.isEnchantment()) + AllZone.GameAction.destroy(c); + + } + + + }// resolve() + + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Enchantment"); + computer = computer.getType("Enchantment"); + + + if (human.size() == 0) + return false; + + // the computer will at least destroy 2 more human enchantments + return computer.size() < human.size() - 1 || + (AllZone.Computer_Life.getLife() < 7 && !human.isEmpty()); + } + };// SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }// *************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Hush")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -1572271570905127602L; + + public void resolve() + { + + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + for (int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + if (c.isEnchantment()) + AllZone.GameAction.destroy(c); + } + + }// resolve() + + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Enchantment"); + computer = computer.getType("Enchantment"); + + + if (human.size() == 0) + return false; + + // the computer will at least destroy 2 more human enchantments + return computer.size() < human.size() - 1 || + (AllZone.Computer_Life.getLife() < 7 && !human.isEmpty()); + } + };// SpellAbility + + spell.setDescription("Destroy all enchantments."); + card.clearSpellAbility(); + card.addSpellAbility(spell); + card.addSpellAbility(CardFactoryUtil.ability_cycle(card, "2")); + }// *************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Incendiary Command")) + { + //not sure what to call variables, so I just made up something + final String[] m_player = new String[1]; + final Card[] m_land = new Card[1]; + + final ArrayList userChoice = new ArrayList(); + + final String[] cardChoice = { + "Incendiary Command deals 4 damage to target player", + "Incendiary Command deals 2 damage to each creature", + "Destroy target nonbasic land", + "Each player discards all cards in his or her hand, then draws that many cards" + }; + + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 9178547049760990376L; + + public void resolve() + { +// System.out.println(userChoice); +// System.out.println(m_land[0]); +// System.out.println(m_player[0]); + + //"Incendiary Command deals 4 damage to target player", + if(userChoice.contains(cardChoice[0])) + AllZone.GameAction.getPlayerLife(m_player[0]).subtractLife(4); + + //"Incendiary Command deals 2 damage to each creature", + if(userChoice.contains(cardChoice[1])) + { + //get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Creature"); + + for(int i = 0; i < list.size(); i++) + list.get(i).addDamage(2); + } + + //"Destroy target nonbasic land", + if(userChoice.contains(cardChoice[2])) + AllZone.GameAction.destroy(m_land[0]); + + //"Each player discards all cards in his or her hand, then draws that many cards" + if(userChoice.contains(cardChoice[3])) + { + discardDraw(Constant.Player.Computer); + discardDraw(Constant.Player.Human); + } + }//resolve() + + void discardDraw(String player) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player); + int n = hand.size(); + + //technically should let the user discard one card at a time + //in case graveyard order matters + for(int i = 0; i < n; i++) + AllZone.GameAction.discardRandom(player); + + for(int i = 0; i < n; i++) + AllZone.GameAction.drawCard(player); + } + public boolean canPlayAI() + { + return false; + } + };//SpellAbility + + final Command setStackDescription = new Command() + { + + private static final long serialVersionUID = -4833850318955216009L; + + public void execute() + { + ArrayList a = new ArrayList(); + if(userChoice.contains(cardChoice[0])) + a.add("deals 4 damage to " +m_player[0]); + + if(userChoice.contains(cardChoice[1])) + a.add("deals 2 damage to each creature"); + + if(userChoice.contains(cardChoice[2])) + a.add("destroy " +m_land[0]); + + if(userChoice.contains(cardChoice[3])) + a.add("each player discards all cards in his or her hand, then draws that many cards"); + + String s = a.get(0) +", " +a.get(1); + spell.setStackDescription(card.getName() +" - " +s); + } + };//Command + + + final Input targetLand = new Input() + { + private static final long serialVersionUID = 1485276539154359495L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target nonbasic land"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + if(c.isLand() && + zone.is(Constant.Zone.Play) && + !c.getType().contains("Basic")) + { + m_land[0] = c; + setStackDescription.execute(); + + stopSetNext(new Input_PayManaCost(spell)); + }//if + }//selectCard() + };//Input targetLand + + final Input targetPlayer = new Input() + { + private static final long serialVersionUID = -2636869617248434242L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target player"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectPlayer(String player) + { + m_player[0] = player; + setStackDescription.execute(); + + //if user needs to target nonbasic land + if(userChoice.contains(cardChoice[2])) + stopSetNext(targetLand); + else + { + stopSetNext(new Input_PayManaCost(spell)); + } + }//selectPlayer() + };//Input targetPlayer + + + Input chooseTwoInput = new Input() + { + private static final long serialVersionUID = 5625588008756700226L; + + public void showMessage() + { + //reset variables + m_player[0] = null; + m_land[0] = null; + + userChoice.clear(); + + ArrayList display = new ArrayList(); + + //get all + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + + CardList land = list.getType("Land"); + CardList basicLand = list.getType("Basic"); + + display.add("Incendiary Command deals 4 damage to target player"); + display.add("Incendiary Command deals 2 damage to each creature"); + if(land.size() != basicLand.size()) + display.add("Destroy target nonbasic land"); + display.add("Each player discards all cards in his or her hand, then draws that many cards"); + + ArrayList a = chooseTwo(display); + //everything stops here if user cancelled + if(a == null) + { + stop(); + return; + } + + userChoice.addAll(a); + + if(userChoice.contains(cardChoice[0])) + stopSetNext(targetPlayer); + else if(userChoice.contains(cardChoice[2])) + stopSetNext(targetLand); + else + { + setStackDescription.execute(); + + stopSetNext(new Input_PayManaCost(spell)); + } + }//showMessage() + + ArrayList chooseTwo(ArrayList choices) + { + ArrayList out = new ArrayList(); + Object o = AllZone.Display.getChoiceOptional("Choose Two", choices.toArray()); + if(o == null) + return null; + + out.add((String) o); + + choices.remove(out.get(0)); + o = AllZone.Display.getChoiceOptional("Choose Two", choices.toArray()); + if(o == null) + return null; + + out.add((String) o); + + return out; + }//chooseTwo() + };//Input chooseTwoInput + + card.clearSpellAbility(); + card.addSpellAbility(spell); + spell.setBeforePayMana(chooseTwoInput); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Boil") || cardName.equals("Boiling Seas")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -5951776248246552958L; + + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + for(int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + if(c.getType().contains("Island")) + AllZone.GameAction.destroy(c); + } + }//resolve() + public boolean canPlayAI() + { + CardList list = new CardList(AllZone.Human_Play.getCards()); + list = list.getType("Island"); + + return 3 < list.size(); + } + };//SpellAbility + spell.setStackDescription(card.getName() + " - destroy all Islands."); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Plague Wind")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 6008660207658995400L; + + public void resolve() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, opponent); + + CardList all = new CardList(play.getCards()); + all = all.getType("Creature"); + + for(int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + if(c.isCreature()) + AllZone.GameAction.destroyNoRegeneration(c); + } + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Overwhelming Forces")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -7165356050118574287L; + + public void resolve() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, opponent); + + CardList all = new CardList(play.getCards()); + all = all.getType("Creature"); + + for(int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + if(c.isCreature()) + AllZone.GameAction.destroy(c); + AllZone.GameAction.drawCard(card.getController()); + } + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Path of Anger's Flame")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4070937328002003491L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + Card[] att = c.getAttackers(); + if(att.length != 0) + return att[0]; + else + return null; + }//getAttacker() + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList start = new CardList(play.getCards()); + final CardList list = start.getType("Creature"); + + for(int i = 0; i < list.size(); i++) + list.get(i).addTempAttackBoost(2); + + play.updateObservers(); + + Command untilEOT = new Command() + { + private static final long serialVersionUID = 6078548097470388679L; + + public void execute() + { + for(int i = 0; i < list.size(); i++) + if(AllZone.GameAction.isCardInPlay(list.get(i))) + list.get(i).addTempAttackBoost(-2); + } + }; + AllZone.EndOfTurn.addUntil(untilEOT); + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Kjeldoran War Cry")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -7384618531690849205L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + Card[] att = c.getAttackers(); + if(att.length != 0) + return att[0]; + else + return null; + }//getAttacker() + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList start = new CardList(play.getCards()); + final CardList list = start.getType("Creature"); + + final int boost = countCards(); + + for(int i = 0; i < list.size(); i++) + { + list.get(i).addTempAttackBoost(boost); + list.get(i).addTempDefenseBoost(boost); + } + + play.updateObservers(); + + Command untilEOT = new Command() + { + private static final long serialVersionUID = -2803160667440730370L; + + public void execute() + { + for(int i = 0; i < list.size(); i++) + if(AllZone.GameAction.isCardInPlay(list.get(i))) + { + list.get(i).addTempAttackBoost(- boost); + list.get(i).addTempDefenseBoost(- boost); + } + } + }; + AllZone.EndOfTurn.addUntil(untilEOT); + }//resolve() + int countCards() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Graveyard.getCards()); + all.addAll(AllZone.Computer_Graveyard.getCards()); + + all = all.getName("Kjeldoran War Cry"); + return all.size() + 1; + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Akroma's Vengeance") || + cardName.equals("Devastation") || + cardName.equals("Jokulhaups") || + cardName.equals("Purify") || + cardName.equals("Shatterstorm") || + cardName.equals("Obliterate")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -7384618531690849205L; + + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + for(int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + + if(cardName.equals("Akroma's Vengeance") && (c.isCreature() || c.isArtifact() || c.isEnchantment())) // Destroy Enchantment rather than Land + AllZone.GameAction.destroy(c); // Can regenerate + if(cardName.equals("Devastation") && (c.isCreature() || c.isLand())) + AllZone.GameAction.destroy(c); // Can regenerate + if((cardName.equals("Jokulhaups") || cardName.equals("Obliterate") ) && (c.isCreature() || c.isArtifact() || c.isLand())) + AllZone.GameAction.destroyNoRegeneration(c); // CAN'T regenerate + if(cardName.equals("Purify") && (c.isArtifact() || c.isEnchantment())) + AllZone.GameAction.destroy(c); // Can regenerate + if(cardName.equals("Shatterstorm") && (c.isArtifact())) + AllZone.GameAction.destroyNoRegeneration(c); // CAN'T regenerate + } + }//resolve() + };//SpellAbility + + if(cardName.equals("Akroma's Vengeance")) + { + spell.setStackDescription("Akroma's Vengeance - Destroy all artifacts, creatures, and enchantments."); // add stack description + spell.setDescription("Destroy all artifacts, creatures, and enchantments."); // add spell detail description + } + card.clearSpellAbility(); + card.addSpellAbility(spell); + if(cardName.equals("Akroma's Vengeance")) //add cycling + card.addSpellAbility(CardFactoryUtil.ability_cycle(card, "3")); + if(cardName.equals("Obliterate")) + card.setText("Obliterate can't be countered. \r\n" + card.getText()); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Wheel of Fortune")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -7707418370887790709L; + + public void resolve() + { + discardDraw7(Constant.Player.Human); + discardDraw7(Constant.Player.Computer); + }//resolve() + void discardDraw7(String player) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player); + Card[] c = hand.getCards(); + for(int i = 0; i < c.length; i++) + AllZone.GameAction.discard(c[i]); + + for(int i = 0; i < 7; i++) + AllZone.GameAction.drawCard(player); + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Armageddon") || cardName.equals("Ravages of War")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 432601263297207029L; + + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + for(int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + if(c.isLand()) + AllZone.GameAction.destroy(c); + } + }//resolve() + public boolean canPlayAI() + { + int human = countPower(AllZone.Human_Play); + int computer = countPower(AllZone.Computer_Play); + + return human < computer || MyRandom.percentTrue(10); + } + public int countPower(PlayerZone play) + { + CardList list = new CardList(play.getCards()); + list = list.getType("Creature"); + int power = 0; + for(int i = 0; i < list.size(); i++) + power += list.get(i).getNetAttack(); + + return power; + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Remove Soul") || cardName.equals("False Summoning") || cardName.equals("Essence Scatter") || cardName.equals("Preemptive Strike")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 4685055135070191326L; + + public void resolve() + { + SpellAbility sa = AllZone.Stack.pop(); + AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); + } + public boolean canPlay() + { + if(AllZone.Stack.size() == 0) + return false; + + //see if spell is on stack and that opponent played it + String opponent = AllZone.GameAction.getOpponent(card.getController()); + SpellAbility sa = AllZone.Stack.peek(); + + //is spell?, did opponent play it?, is this a creature spell? + return sa.isSpell() && + opponent.equals(sa.getSourceCard().getController()) && + sa.getSourceCard().getType().contains("Creature"); + }//canPlay() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Counterspell") || cardName.equals("Cancel") || cardName.equals("Last Word")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -2489268054171391552L; + + public void resolve() + { + SpellAbility sa = AllZone.Stack.pop(); + AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); + } + public boolean canPlay() + { + if(AllZone.Stack.size() == 0) + return false; + + //see if spell is on stack and that opponent played it + String opponent = AllZone.GameAction.getOpponent(card.getController()); + SpellAbility sa = AllZone.Stack.peek(); + + return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) + && CardFactoryUtil.isCounterable(sa.getSourceCard()); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Remand")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 7259402997927108504L; + + public void resolve() + { + //counter spell, return it to owner's hand + SpellAbility sa = AllZone.Stack.pop(); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, sa.getSourceCard().getOwner()); + AllZone.GameAction.moveTo(hand, sa.getSourceCard()); + + //draw card + AllZone.GameAction.drawCard(card.getController()); + } + public boolean canPlay() + { + if(AllZone.Stack.size() == 0) + return false; + + //see if spell is on stack and that opponent played it + String opponent = AllZone.GameAction.getOpponent(card.getController()); + SpellAbility sa = AllZone.Stack.peek(); + + return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) + && CardFactoryUtil.isCounterable(sa.getSourceCard()); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Regress")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 4207725827500789300L; + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + if(getTargetCard().isToken()) + AllZone.getZone(getTargetCard()).remove(getTargetCard()); + else + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, getTargetCard().getOwner()); + AllZone.GameAction.moveTo(hand, getTargetCard()); + } + } + }//resolve() + + public void chooseTargetAI() + { + PlayerZone hPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList hum = new CardList(hPlay.getCards()); + + Card best = CardFactoryUtil.AI_getMostExpensivePermanent(hum, card, true); + if (best!=null) + setTargetCard(best); + } + public boolean canPlayAI() + { + PlayerZone hPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList hum = new CardList(hPlay.getCards()); + + return hum.size()>0; + } + }; + //spell.setChooseTargetAI(CardFactoryUtil.AI_targetType("All", AllZone.Human_Play)); + + spell.setBeforePayMana(CardFactoryUtil.input_targetType(spell, "All")); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Echoing Truth")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 563933533543239220L; + + public boolean canPlayAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + return 4 < AllZone.Phase.getTurn() && 0 < human.size(); + } + public void chooseTargetAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + setTargetCard(CardFactoryUtil.AI_getBestCreature(human)); + } + + public void resolve() + { + //if target card is not in play, just quit + if(! AllZone.GameAction.isCardInPlay(getTargetCard()) || !CardFactoryUtil.canTarget(card, getTargetCard()) ) + return; + + //get all permanents + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + CardList sameName = all.getName(getTargetCard().getName()); + + if (!getTargetCard().isFaceDown()) + { + //bounce all permanents with the same name + for(int i = 0; i < sameName.size(); i++) + { + if(sameName.get(i).isToken()) + AllZone.GameAction.destroy(sameName.get(i)); + else + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, sameName.get(i).getOwner()); + AllZone.GameAction.moveTo(hand, sameName.get(i)); + } + }//for + }//if (!isFaceDown()) + else + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, getTargetCard().getOwner()); + AllZone.GameAction.moveTo(hand, getTargetCard()); + } + }//resolve() + };//SpellAbility + Input target = new Input() + { + private static final long serialVersionUID = -3978705328511825933L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target non-land permanent for " +spell.getSourceCard()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(! card.isLand() && zone.is(Constant.Zone.Play) && CardFactoryUtil.canTarget(spell, card)) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + } + };//Input + + spell.setBeforePayMana(target); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Repulse")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 7586791617021788730L; + + public boolean canPlayAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + return 3 < AllZone.Phase.getTurn() && 0 < human.size(); + } + public void chooseTargetAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + setTargetCard(CardFactoryUtil.AI_getBestCreature(human)); + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + if(getTargetCard().isToken()) + AllZone.getZone(getTargetCard()).remove(getTargetCard()); + else + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, getTargetCard().getOwner()); + @SuppressWarnings("unused") // play + PlayerZone play = AllZone.getZone(Constant.Zone.Play, getTargetCard().getOwner()); + AllZone.GameAction.moveTo(hand, getTargetCard()); + + //play.remove(getTargetCard()); + //hand.add(getTargetCard()); + } + AllZone.GameAction.drawCard(card.getController()); + }//if + }//resolve() + };//SpellAbility + Input target = new Input() + { + private static final long serialVersionUID = -4976281514575975012L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target creature for " +spell.getSourceCard()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(spell, card)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + + else if(card.isCreature() && zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + } + };//Input + + spell.setBeforePayMana(target); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Unsummon")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4920446621228732642L; + + public boolean canPlayAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + return 2 < AllZone.Phase.getTurn() && 0 < human.size(); + } + public void chooseTargetAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + setTargetCard(CardFactoryUtil.AI_getBestCreature(human)); + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + if(getTargetCard().isToken()) + AllZone.getZone(getTargetCard()).remove(getTargetCard()); + else + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, getTargetCard().getOwner()); + @SuppressWarnings("unused") // play + PlayerZone play = AllZone.getZone(Constant.Zone.Play, getTargetCard().getOwner()); + AllZone.GameAction.moveTo(hand, getTargetCard()); + + //play.remove(getTargetCard()); + //hand.add(getTargetCard()); + } + }//if + }//resolve() + };//SpellAbility + Input target = new Input() + { + private static final long serialVersionUID = -7657949950004365660L; + public void showMessage() + { + AllZone.Display.showMessage("Select target creature for " +spell.getSourceCard()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(spell, card)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + + else if(card.isCreature() && zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + } + };//Input + + spell.setBeforePayMana(target); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Impulse")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -6793636573741251978L; + + public boolean canPlayAI() {return false;} + + public void resolve() + { + CardList top = new CardList(); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + + Card c; + int j = 4; + if (library.size() < 4) + j = library.size(); + for(int i = 0; i < j; i++) + { + c = library.get(0); + library.remove(0); + top.add(c); + } + + if (top.size() >= 1) + { + //let user get choice + Card chosen = (Card) AllZone.Display.getChoice("Choose a card to put into your hand", top.toArray()); + top.remove(chosen); + + //put card in hand + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + hand.add(chosen); + + //add cards to bottom of library + for(int i = 0; i < top.size(); i++) + library.add(top.get(i)); + } + }//resolve() + };//SpellAbility + + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Bribery")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4267653042039058744L; + public void resolve() + { + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void humanResolve() + { + //choose creature from opponents library to put into play + //shuffle opponent's library + String opponent = AllZone.GameAction.getOpponent(card.getController()); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, opponent); + CardList choices = new CardList(library.getCards()); + + choices = choices.getType("Creature"); + Object o = AllZone.Display.getChoiceOptional("Choose a creature", choices.toArray()); + if(o != null) + resolve((Card)o); + } + public void computerResolve() + { + CardList all = new CardList(AllZone.Human_Library.getCards()); + all = all.getType("Creature"); + + CardList flying = all.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.getKeyword().contains("Flying"); + } + }); + //get biggest flying creature + Card biggest = null; + if(flying.size() != 0) + { + biggest = flying.get(0); + + for(int i = 0; i < flying.size(); i++) + if(biggest.getNetAttack() < flying.get(i).getNetAttack()) + biggest = flying.get(i); + } + + //if flying creature is small, get biggest non-flying creature + if(all.size() != 0 && + (biggest == null || biggest.getNetAttack() < 3)) + { + biggest = all.get(0); + + for(int i = 0; i < all.size(); i++) + if(biggest.getNetAttack() < all.get(i).getNetAttack()) + biggest = all.get(i); + } + if(biggest != null) + resolve(biggest); + }//computerResolve() + public void resolve(Card selectedCard) + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, opponent); + + Card c = selectedCard; + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + + //need to set controller before adding it to "play" + c.setController(card.getController()); + c.setSickness(true); + + library.remove(c); + play.add(c); + + + AllZone.GameAction.shuffle(opponent); + }//resolve() + }; + + spell.setBeforePayMana(new Input_PayManaCost(spell)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Words of Wisdom")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -7394898791285593737L; + + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + AllZone.GameAction.drawCard(card.getController()); + + String opponent = AllZone.GameAction.getOpponent(card.getController()); + AllZone.GameAction.drawCard(opponent); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Counsel of the Soratami") || cardName.equals("Inspiration") || cardName.equals("Touch of Brilliance")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -1889094576060845154L; + + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + AllZone.GameAction.drawCard(card.getController()); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Concentrate") || cardName.equals("Harmonize") ) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -3561111468549060269L; + + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + AllZone.GameAction.drawCard(card.getController()); + AllZone.GameAction.drawCard(card.getController()); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Amnesia")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -5456164079438881319L; + + public void resolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, getTargetPlayer()); + Card[] c = hand.getCards(); + + for(int i = 0; i < c.length; i++) + if(! c[i].isLand()) + AllZone.GameAction.discard(c[i]); + } + }; + spell.setChooseTargetAI(CardFactoryUtil.AI_targetHuman()); + + spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell)); + + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Evacuation")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -6305494177352031326L; + + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + all = all.getType("Creature"); + + for(int i = 0; i < all.size(); i++) + { + //if is token, remove token from play, else return creature to hand + if(all.get(i).isToken()) + getPlay(all.get(i)).remove(all.get(i)); + else + AllZone.GameAction.moveTo(getHand(all.get(i)), all.get(i)); + } + }//resolve() + PlayerZone getPlay(Card c) + { + return AllZone.getZone(Constant.Zone.Play, c.getController()); + } + + PlayerZone getHand(Card c) + { + return AllZone.getZone(Constant.Zone.Hand, c.getOwner()); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + if (cardName.equals("Lockjaw Snapper")) + { + + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone hPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + PlayerZone cPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + + CardList creatures = new CardList(); + creatures.addAll(hPlay.getCards()); + creatures.addAll(cPlay.getCards()); + creatures = creatures.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.getCounters(Counters.M1M1) > 0; + } + }); + + for (int i=0; i= 7) + { + makeToken(); + makeToken(); + } + } + public void makeToken() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Bear"); + c.setImageName("G 2 2 Bear"); + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Bear"); + c.setBaseAttack(2); + c.setBaseDefense(2); + + play.add(c); + + }//resolve() + }; + + spell.setDescription("Put two 2/2 green Bear creature tokens into play. Threshold - Put four 2/2 green Bear creature tokens into play instead if seven or more cards are in your graveyard. "); + spell.setStackDescription(card.getController() + " Puts 2/2 green Bear tokens into play."); + + card.setFlashback(true); + card.clearSpellAbility(); + card.addSpellAbility(spell); + card.addSpellAbility(CardFactoryUtil.ability_Flashback(card, "5 G G", "0")); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Sprout")) + { + SpellAbility spell = new Spell(card) + { + + private static final long serialVersionUID = 1299216756153970592L; + public void resolve() + { + makeToken(); + } + public void makeToken() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Saproling"); + c.setImageName("G 1 1 Saproling"); + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Saproling"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + play.add(c); + + }//resolve() + }; + + spell.setDescription("Put a 1/1 green Saproling creature token into play."); + spell.setStackDescription(card.getController() + " put a 1/1 green Saproling creature token into play."); + + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Delirium Skeins")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 7901561313373975648L; + + public void resolve() + { + for(int i = 0; i < 3; i++) + AllZone.GameAction.discardRandom(Constant.Player.Computer); + + AllZone.InputControl.setInput(CardFactoryUtil.input_discard(3)); + }//resolve() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Wrap in Vigor")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4235465815975050436L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + Card[] att = c.getAttackers(); + if(att.length != 0) + return att[0]; + else + return null; + }//getAttacker() + + public void resolve() + { + final Card[] c = AllZone.getZone(Constant.Zone.Play, card.getController()).getCards(); + + for(int i = 0; i < c.length; i++) + if(c[i].isCreature()) + c[i].addShield(); + + AllZone.EndOfTurn.addUntil(new Command() + { + private static final long serialVersionUID = -3946800525315027053L; + + public void execute() + { + for(int i = 0; i < c.length; i++) + c[i].resetShield(); + } + }); + + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Smother")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 6479035316340603704L; + + public boolean canPlayAI() + { + CardList c = CardFactoryUtil.AI_getHumanCreature(true, 3, card, true); + CardListUtil.sortAttack(c); + CardListUtil.sortFlying(c); + + if(c.isEmpty()) + return false; + else + { + setTargetCard(c.get(0)); + return true; + } + }//canPlayAI() + + public void resolve() + { + Card c = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(c) && CardUtil.getConvertedManaCost(card.getManaCost()) <= 3 && CardFactoryUtil.canTarget(card, getTargetCard()) ) + AllZone.GameAction.destroyNoRegeneration(c); + }//resolve() + };//SpellAbility + + Input target = new Input() + { + private static final long serialVersionUID = 1877945605889747187L; + public void showMessage() + { + AllZone.Display.showMessage("Select target creature for " +card.getName() +" - creature must have a converted manacost of 3 or less"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(spell, card)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + if(card.isCreature() && zone.is(Constant.Zone.Play) && CardUtil.getConvertedManaCost(card.getManaCost()) <= 3) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + } + };//Input + card.clearSpellAbility(); + card.addSpellAbility(spell); + spell.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Strangling Soot")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -3598479453933951865L; + + public boolean canPlayAI() + { + CardList c = CardFactoryUtil.AI_getHumanCreature(3, card, true); + CardListUtil.sortAttack(c); + CardListUtil.sortFlying(c); + + if(c.isEmpty()) + return false; + else + { + setTargetCard(c.get(0)); + return true; + } + }//canPlayAI() + + public void resolve() + { + + Card c = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(c) && c.getNetDefense() <= 3 && CardFactoryUtil.canTarget(card, getTargetCard()) ) + AllZone.GameAction.destroy(c); + + }//resolve() + };//SpellAbility + + final SpellAbility flashback = new Spell(card) + { + + private static final long serialVersionUID = -4009531242109129036L; + + public boolean canPlay() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard ,card.getController()); + + return AllZone.GameAction.isCardInZone(card, grave); + } + public boolean canPlayAI() + { + CardList c = CardFactoryUtil.AI_getHumanCreature(3, card, true); + CardListUtil.sortAttack(c); + CardListUtil.sortFlying(c); + + if(c.isEmpty()) + return false; + else + { + setTargetCard(c.get(0)); + return true; + } + }//canPlayAI() + + public void resolve() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard , card.getController()); + PlayerZone removed = AllZone.getZone(Constant.Zone.Removed_From_Play, card.getController()); + + Card c = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(c) && c.getNetDefense() <= 3 && CardFactoryUtil.canTarget(card, getTargetCard()) ) + AllZone.GameAction.destroy(c); + + grave.remove(card); + removed.add(card); + }//resolve() + };//flashback + + Input targetFB = new Input() + { + + private static final long serialVersionUID = -5469698194749752297L; + public void showMessage() + { + AllZone.Display.showMessage("Select target creature for " +card.getName() +" - creature must have a toughness of 3 or less"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(flashback, card)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + if(card.isCreature() && zone.is(Constant.Zone.Play) && card.getNetDefense() <= 3) + { + flashback.setTargetCard(card); + stopSetNext(new Input_PayManaCost(flashback)); + } + } + };//Input + + flashback.setManaCost("5 R"); + flashback.setBeforePayMana(targetFB); + flashback.setDescription("Flashback: 5 R"); + + Input target = new Input() + { + private static final long serialVersionUID = -198153850086215235L; + public void showMessage() + { + AllZone.Display.showMessage("Select target creature for " +card.getName() +" - creature must have a toughness of 3 or less"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(spell, card)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + if(card.isCreature() && zone.is(Constant.Zone.Play) && card.getNetDefense() <= 3) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + } + };//Input + card.clearSpellAbility(); + card.addSpellAbility(spell); + spell.setBeforePayMana(target); + + card.addSpellAbility(flashback); + + card.setFlashback(true); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Minions' Murmurs")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 7270026936498671973L; + + public boolean canPlayAI() + { + int n = countCreatures(); + return 0 < n && n < AllZone.Computer_Life.getLife(); + }//canPlayAI() + + public void resolve() + { + int n = countCreatures(); + for(int i = 0; i < n; i++) + AllZone.GameAction.drawCard(card.getController()); + + AllZone.GameAction.getPlayerLife(card.getController()).subtractLife(n); + }//resolve() + + int countCreatures() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList list = new CardList(play.getCards()); + list = list.getType("Creature"); + return list.size(); + } + };//SpellAbility + + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Tendrils of Corruption")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -618587752177627111L; + + public boolean canPlayAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + return 0 < human.size(); + }//canPlayAI() + + public void chooseTargetAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + CardListUtil.sortAttack(human); + setTargetCard(human.get(0)); + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + int n = countSwamps(); + getTargetCard().addDamage(n); + + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.addLife(n); + } + }//resolve() + + int countSwamps() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList list = new CardList(play.getCards()); + list = list.getType("Swamp"); + return list.size(); + } + };//SpellAbility + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Ichor Slick")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -273970706213674570L; + + public boolean canPlayAI() + { + CardList c = CardFactoryUtil.AI_getHumanCreature(3, card, true); + CardListUtil.sortAttack(c); + CardListUtil.sortFlying(c); + + if(c.isEmpty()) + return false; + else + { + setTargetCard(c.get(0)); + return true; + } + }//canPlayAI() + + public void resolve() + { + final Card[] target = new Card[1]; + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -1615047325868708734L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0]) ) + { + target[0].addTempAttackBoost(3); + target[0].addTempDefenseBoost(3); + } + } + }; + + target[0] = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0])) + { + target[0].addTempAttackBoost(-3); + target[0].addTempDefenseBoost(-3); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + };//SpellAbility + + Input target = new Input() + { + private static final long serialVersionUID = -7381927922574152604L; + public void showMessage() + { + AllZone.Display.showMessage("Select target creature for " +card.getName()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(spell, card)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + else if(card.isCreature() && zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + } + };//Input + spell.setDescription("Target creature gets -3/-3 until end of turn"); + + card.clearSpellAbility(); + card.addSpellAbility(spell); + card.addSpellAbility(CardFactoryUtil.ability_cycle(card, "2")); + + spell.setBeforePayMana(target); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Funeral Charm")) + { + //discard + final SpellAbility spell_one = new Spell(card) + { + private static final long serialVersionUID = 8273875515630095127L; + public boolean canPlayAI() + { + setTargetPlayer(Constant.Player.Human); + return MyRandom.random.nextBoolean(); + } + public void resolve() + { + if(Constant.Player.Computer.equals(getTargetPlayer())) + AllZone.GameAction.discardRandom(getTargetPlayer()); + else + AllZone.InputControl.setInput(CardFactoryUtil.input_discard()); + }//resolve() + };//SpellAbility + spell_one.setDescription("Target player discards a card."); + spell_one.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell_one)); + + + //creature gets +2/-1 + final SpellAbility spell_two = new Spell(card) + { + private static final long serialVersionUID = -4554812851052322555L; + + + public boolean canPlayAI() + { + CardList list = new CardList(ComputerUtil.getAttackers().getAttackers()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) {return 1 < c.getNetDefense();} + }); + + list.shuffle(); + if(list.size() > 0) + setTargetCard(list.get(0)); + + return (list.size() > 0) && MyRandom.random.nextBoolean(); + } + + + public void resolve() + { + final Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) ) + { + c.addTempAttackBoost(2); + c.addTempDefenseBoost(-1); + + Command until = new Command() + { + private static final long serialVersionUID = 4674846621452044251L; + + public void execute() + { + c.addTempAttackBoost(-2); + c.addTempDefenseBoost(1); + } + };//Command + AllZone.EndOfTurn.addUntil(until); + }//if card in play? + }//resolve() + };//SpellAbility + spell_two.setDescription("Target creature gets +2/-1 until end of turn."); + spell_two.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell_two)); + + card.clearSpellAbility(); + card.addSpellAbility(spell_one); + card.addSpellAbility(spell_two); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Regrowth")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -1771016287736735113L; + public void resolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand , card.getController()); + PlayerZone graveyard = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + + if(AllZone.GameAction.isCardInZone(getTargetCard(), graveyard)) + { + graveyard.remove(getTargetCard()); + hand.add(getTargetCard()); + } + }//resolve() + public boolean canPlay() + { + PlayerZone graveyard = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + return graveyard.getCards().length != 0 && super.canPlay(); + } + }; + Input runtime = new Input() + { + private static final long serialVersionUID = 3687454413838053102L; + + public void showMessage() + { + PlayerZone graveyard = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + Object o = AllZone.Display.getChoiceOptional("Select target card", graveyard.getCards()); + if(o == null) + stop(); + else + { + spell.setStackDescription("Return " +o +" to its owner's hand"); + spell.setTargetCard((Card)o); + + stopSetNext(new Input_PayManaCost(spell)); + } + }//showMessage() + }; + spell.setChooseTargetAI(CardFactoryUtil.AI_targetType("All", AllZone.Computer_Graveyard)); + spell.setBeforePayMana(runtime); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Commune with Nature")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -7652317332073733242L; + public boolean canPlayAI() {return false;} + + public void resolve() + { + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void computerResolve() + { + //get top 5 cards of library + CardList top = new CardList(); + int limit = AllZone.Computer_Library.getCards().length; + + for(int i = 0; i < 5 && i < limit; i++) + { + top.add(AllZone.Computer_Library.get(0)); + AllZone.Computer_Library.remove(0); + } + + //put creature card in hand, if there is one + CardList creature = top.getType("Creature"); + if(creature.size() != 0) + { + AllZone.Computer_Hand.add(creature.get(0)); + top.remove(creature.get(0)); + } + + //put cards on bottom of library + for(int i = 0; i < top.size(); i++) + AllZone.Computer_Library.add(top.get(i)); + }//computerResolve() + public void humanResolve() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand , card.getController()); + + CardList list = new CardList(); + for(int i = 0; i < 5 && i < library.getCards().length; i++) + list.add(library.get(i)); + + //optional, select a creature + Object o = AllZone.Display.getChoiceOptional("Select a creature", list.toArray()); + if(o != null && ((Card)o).isCreature()) + { + AllZone.GameAction.moveTo(hand, (Card)o); + list.remove((Card)o); + } + + //put remaining cards on the bottom of the library + for(int i = 0; i < list.size(); i++) + { + library.remove(list.get(i)); + library.add(list.get(i)); + } + }//resolve() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Kodama's Reach")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -3361422153566629825L; + + public void resolve() + { + String player = card.getController(); + + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void computerResolve() + { + CardList land = new CardList(AllZone.Computer_Library.getCards()); + land = land.getType("Basic"); + + //just to make the computer a little less predictable + land.shuffle(); + + //3 branches: 1-no land in deck, 2-one land in deck, 3-two or more land in deck + if(land.size() != 0) + { + //branch 2 - at least 1 land in library + Card tapped = land.remove(0); + tapped.tap(); + + AllZone.Computer_Play.add(tapped); + AllZone.Computer_Library.remove(tapped); + + //branch 3 + if(land.size() != 0) + { + Card toHand = land.remove(0); + AllZone.Computer_Hand.add(toHand); + AllZone.Computer_Library.remove(toHand); + } + } + }//computerResolve() + + public void humanResolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play , card.getController()); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand , card.getController()); + + CardList list = new CardList(library.getCards()); + list = list.getType("Basic"); + + //3 branches: 1-no land in deck, 2-one land in deck, 3-two or more land in deck + + //branch 1 + if(list.size() == 0) + return; + + //branch 2 + Object o = AllZone.Display.getChoiceOptional("Put into play tapped", list.toArray()); + if(o != null) + { + Card c = (Card)o; + c.tap(); + list.remove(c); + + library.remove(c); + play.add(c); + + if(list.size() == 0) + return; + + o = AllZone.Display.getChoiceOptional("Put into your hand", list.toArray()); + if(o != null) + { + //branch 3 + library.remove(o); + hand.add(o); + } + AllZone.GameAction.shuffle(card.getController()); + }//if + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Pestermite")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c)) + { + if(c.isTapped()) + c.untap(); + else + c.tap(); + } + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = 5202575895575352408L; + + public void execute() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + CardList hum = new CardList(); + hum.addAll(AllZone.Human_Play.getCards()); + + if (all.size() != 0) { + + if(card.getController().equals(Constant.Player.Human)) { + AllZone.InputControl.setInput(CardFactoryUtil.input_targetSpecific(ability, all, "Select target permanent to tap/untap.", true)); + ButtonUtil.enableAll(); + } + else if (card.getController().equals(Constant.Player.Computer)) { + Card human = CardFactoryUtil.AI_getBestCreature(hum); + ability.setTargetCard(human); + AllZone.Stack.add(ability); + } + } + + }//execute() + };//Command + card.addComesIntoPlayCommand(intoPlay); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = -3055232264358172133L; + + public boolean canPlayAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(card, true); + list = list.filter(new CardListFilter(){ + public boolean addCard(Card c) { + return c.isUntapped(); + } + }); + + return (list.size() > 0) && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Angel of Despair")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c)) + { + if(c.isToken()) + AllZone.getZone(c).remove(c); + + else + AllZone.GameAction.destroy(c); + } + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = -3583483691705438214L; + + public void execute() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + CardList hum = new CardList(); + hum.addAll(AllZone.Human_Play.getCards()); + + if (all.size() != 0) { + + if(card.getController().equals(Constant.Player.Human)) { + AllZone.InputControl.setInput(CardFactoryUtil.input_targetSpecific(ability, all, "Select target permanent.", true)); + ButtonUtil.disableAll(); + } + else if (card.getController().equals(Constant.Player.Computer)) { + Card human = CardFactoryUtil.AI_getBestCreature(hum); + ability.setTargetCard(human); + AllZone.Stack.add(ability); + } + } + + }//execute() + };//Command + card.addComesIntoPlayCommand(intoPlay); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = -173202865726476053L; + + public boolean canPlayAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(card, true); + + return (list.size() > 0) && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand); + } + }); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Yawgmoth's Bargain")){ + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + if(library.size() != 0) + { + Card c = library.get(0); + library.remove(0); + hand.add(c); + } + } + + public boolean canPlayAI() + { + return false; + } + };//SpellAbility + + ability.setDescription("Pay 1 life: Draw a card."); + ability.setStackDescription(card.getName() +" - Pay 1 life: Draw a card."); + + card.addSpellAbility(ability); + + //instead of paying mana, pay life and add to stack + //Input showMessage() is always the first method called + Input payLife = new Input() + { + + private static final long serialVersionUID = 8660593629867722192L; + + public void showMessage() + { + AllZone.GameAction.getPlayerLife(card.getController()).subtractLife(1); + + //this order is very important, do not change + stop(); + AllZone.Stack.push(ability); + } + };//Input + ability.setBeforePayMana(payLife); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Necropotence")) + { + final CardList necroCards = new CardList(); + + final Command necro = new Command() + { + private static final long serialVersionUID = 4511445425867383336L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + //put cards removed by Necropotence into player's hand + if(necroCards.size() > 0){ + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + + for(int i = 0;i 0; + } + + int calculateLife() + { + PlayerZone zone = AllZone.getZone(Constant.Zone.Play, card.getController()); + + CardList creatureList = new CardList(zone.getCards()); + creatureList = creatureList.getType("Creature"); + + return 2 * creatureList.size(); + } + + public void resolve() + { + AllZone.GameAction.getPlayerLife(card.getController()).addLife(calculateLife()); + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Mystic Snake")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + if(AllZone.Stack.size() > 0) { + SpellAbility sa = AllZone.Stack.peek(); + if (sa.isSpell() && CardFactoryUtil.isCounterable(sa.getSourceCard()) ) { + sa = AllZone.Stack.pop(); + AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); + } + } + }//resolve() + };//SpellAbility + Command intoPlay = new Command() + { + private static final long serialVersionUID = -6564365394043612388L; + + public void execute() + { + if(AllZone.Stack.size() > 0) { + ability.setStackDescription("Mystic Snake counters " +AllZone.Stack.peek().getSourceCard().getName()); + AllZone.Stack.add(ability); + } + } + }; + card.addComesIntoPlayCommand(intoPlay); + + card.clearSpellAbility(); + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = 6440845807532409545L; + + public boolean canPlayAI() + { + return false; + } + }); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Absorb")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -2007620906017942538L; + public void resolve() + { + SpellAbility sa = AllZone.Stack.pop(); + AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); + + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.addLife(3); + } + public boolean canPlay() + { + if(AllZone.Stack.size() == 0) + return false; + + //see if spell is on stack and that opponent played it + String opponent = AllZone.GameAction.getOpponent(card.getController()); + SpellAbility sa = AllZone.Stack.peek(); + + return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) + && CardFactoryUtil.isCounterable(sa.getSourceCard()); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Undermine")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4999966043862729936L; + public void resolve() + { + SpellAbility sa = AllZone.Stack.pop(); + AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); + + String opponent = AllZone.GameAction.getOpponent(card.getController()); + AllZone.GameAction.getPlayerLife(opponent).subtractLife(3); + + } + public boolean canPlay() + { + if(AllZone.Stack.size() == 0) + return false; + + //see if spell is on stack and that opponent played it + String opponent = AllZone.GameAction.getOpponent(card.getController()); + SpellAbility sa = AllZone.Stack.peek(); + + return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) + && CardFactoryUtil.isCounterable(sa.getSourceCard()); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Punish Ignorance")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 6845184687406705133L; + public void resolve() + { + SpellAbility sa = AllZone.Stack.pop(); + AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); + + String opponent = AllZone.GameAction.getOpponent(card.getController()); + AllZone.GameAction.getPlayerLife(opponent).subtractLife(3); + + String player = card.getController(); + AllZone.GameAction.getPlayerLife(player).addLife(3); + + } + public boolean canPlay() + { + if(AllZone.Stack.size() == 0) + return false; + + //see if spell is on stack and that opponent played it + String opponent = AllZone.GameAction.getOpponent(card.getController()); + SpellAbility sa = AllZone.Stack.peek(); + + return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) + && CardFactoryUtil.isCounterable(sa.getSourceCard()); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Exclude")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -5615796501064636046L; + public void resolve() + { + SpellAbility sa = AllZone.Stack.pop(); + AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); + AllZone.GameAction.drawCard(card.getController()); + } + public boolean canPlay() + { + if(AllZone.Stack.size() == 0) + return false; + + //see if spell is on stack and that opponent played it + String opponent = AllZone.GameAction.getOpponent(card.getController()); + SpellAbility sa = AllZone.Stack.peek(); + + //is spell?, did opponent play it?, is this a creature spell? + return sa.isSpell() && + opponent.equals(sa.getSourceCard().getController()) && + sa.getSourceCard().getType().contains("Creature") + && CardFactoryUtil.isCounterable(sa.getSourceCard()); + }//canPlay() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Eladamri's Call")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -6495398165357932918L; + public void resolve() + { + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void humanResolve() + { + CardList creatures = new CardList(AllZone.Human_Library.getCards()); + creatures = creatures.getType("Creature"); + + Object check = AllZone.Display.getChoiceOptional("Select creature", creatures.toArray()); + if(check != null) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, (Card)check); + } + AllZone.GameAction.shuffle(Constant.Player.Human); + } + public void computerResolve() + { + Card[] library = AllZone.Computer_Library.getCards(); + CardList list = new CardList(library); + list = list.getType("Creature"); + + + //pick best creature + Card c = CardFactoryUtil.AI_getBestCreature(list); + if(c == null) + c = library[0]; + AllZone.Computer_Library.remove(c); + AllZone.Computer_Hand.add(c); + } + public boolean canPlay() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + return library.getCards().length != 0; + } + public boolean canPlayAI() + { + CardList creature = new CardList(); + creature.addAll(AllZone.Computer_Library.getCards()); + creature = creature.getType("Creature"); + return creature.size() != 0; + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Dismiss")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -7959473218345045760L; + public void resolve() + { + SpellAbility sa = AllZone.Stack.pop(); + AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); + + AllZone.GameAction.drawCard(card.getController()); + + } + public boolean canPlay() + { + if(AllZone.Stack.size() == 0) + return false; + + //see if spell is on stack and that opponent played it + String opponent = AllZone.GameAction.getOpponent(card.getController()); + SpellAbility sa = AllZone.Stack.peek(); + + return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) + && CardFactoryUtil.isCounterable(sa.getSourceCard()); + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Global Ruin")) + { + final CardList target = new CardList(); + //need to use arrays so we can declare them final and still set the values in the input and runtime classes. This is a hack. + final int[] index = new int[1]; + final int[] countBase = new int[1]; + final Vector humanBasic = new Vector(); + + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 5739127258598357186L; + + public boolean canPlayAI() + { + return false; + //should check if computer has land in hand, or if computer has more basic land types than human. + } + @SuppressWarnings("unchecked") // computerBasic + public void resolve() + { + //add computer's lands to target + @SuppressWarnings("unused") // computerCountBasic + int computerCountBase = 0; + @SuppressWarnings("unused") // computerBasic + Vector computerBasic = new Vector(); + + //figure out which basic land types the computer has + CardList land = new CardList(AllZone.Computer_Play.getCards()); + String basic[] = {"Forest", "Plains", "Mountain", "Island", "Swamp"}; + + for (int i = 0; i < basic.length; i++) + { + CardList cl = land.getType(basic[i]); + if (!cl.isEmpty()) + { + //remove one land of this basic type from this list + //the computer AI should really jump in here and select the land which is the best. + //to determine the best look at which lands have enchantments, which lands are tapped + cl.remove(cl.get(0)); + //add the rest of the lands of this basic type to the target list, this is the list which will be sacrificed. + target.addAll(cl.toArray()); + } + } + + //when this spell resolves all basic lands which were not selected are sacrificed. + for(int i = 0; i < target.size(); i++) + if(AllZone.GameAction.isCardInPlay(target.get(i))) + AllZone.GameAction.sacrifice(target.get(i)); + }//resolve() + };//SpellAbility + + + final Input input = new Input() + { + private static final long serialVersionUID = 1739423591445361917L; + private int count; + public void showMessage() + { //count is the current index we are on. + //countBase[0] is the total number of basic land types the human has + //index[0] is the number to offset the index by + count = countBase[0] - index[0] - 1; //subtract by one since humanBasic is 0 indexed. + if(count<0){ + //need to reset the variables in case they cancel this spell and it stays in hand. + humanBasic.clear(); + countBase[0] = 0; + index[0] = 0; + stop(); + } + else{ + AllZone.Display.showMessage("Select target " + humanBasic.get(count) +" land to not sacrifice"); + ButtonUtil.enableOnlyCancel(); + } + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + if(c.isLand() && zone.is(Constant.Zone.Play) && c.getController().equals(Constant.Player.Human) && c.getName().equals(humanBasic.get(count))) + { + //get all other basic[count] lands human player controls and add them to target + PlayerZone humanPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList land = new CardList(humanPlay.getCards()); + CardList cl = land.getType((String)humanBasic.get(count)); + cl.remove(c); + target.addAll(cl.toArray()); + + index[0]++; + showMessage(); + + if(index[0] >= humanBasic.size()) + stopSetNext(new Input_PayManaCost(spell)); + } + }//selectCard() + };//Input + + Input runtime = new Input() + { + private static final long serialVersionUID = -122635387376995855L; + + public void showMessage() + { + countBase[0] = 0; + //figure out which basic land types the human has + //put those in an set to use later + CardList land = new CardList(AllZone.Human_Play.getCards()); + String basic[] = {"Forest", "Plains", "Mountain", "Island", "Swamp"}; + + for (int i = 0; i < basic.length; i++) + { + CardList c = land.getType(basic[i]); + if (!c.isEmpty()) + { + humanBasic.add(basic[i]); + countBase[0]++; + } + } + if(countBase[0] == 0){ + //human has no basic land, so don't prompt to select one. + stop(); + } + else{ + index[0] = 0; + target.clear(); + stopSetNext(input); + } + } + };//Input + + card.clearSpellAbility(); + card.addSpellAbility(spell); + spell.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Gerrard's Verdict")) + { + SpellAbility spell = new Spell(card) + { + + private static final long serialVersionUID = 4734024742326763385L; + public boolean canPlayAI() + { + PlayerZone humanHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Human); + if (humanHand.size() >= 2) + return true; + else + return false; + } + + public void resolve() + { + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void humanResolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList list = new CardList(hand.getCards()); + list.shuffle(); + + if (list.size()== 0) + return; + + Card c1 = list.get(0); + list.remove(c1); + AllZone.Computer_Graveyard.add(c1); + AllZone.Computer_Hand.remove(c1); + + if (list.size()== 0) + return; + + Card c2 = list.get(0); + list.remove(c2); + AllZone.Computer_Graveyard.add(c2); + AllZone.Computer_Hand.remove(c2); + + if (c1.getType().contains("Land")) { + PlayerLife life = AllZone.GameAction.getPlayerLife(Constant.Player.Human); + life.addLife(3); + } + + if (c2.getType().contains("Land")) { + PlayerLife life = AllZone.GameAction.getPlayerLife(Constant.Player.Human); + life.addLife(3); + } + + + }//resolve() + public void computerResolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Human); + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, Constant.Player.Human); + CardList list = new CardList(hand.getCards()); + + if (list.size() > 0){ + + Object o = AllZone.Display.getChoiceOptional("First card to discard", list.toArray()); + + Card c = (Card)o; + list.remove(c); + + hand.remove(c); + grave.add(c); + + if(c.getType().contains("Land")) { + PlayerLife life = AllZone.GameAction.getPlayerLife(Constant.Player.Computer); + life.addLife(3); + } + + if (list.size() > 0) + { + Object o2 = AllZone.Display.getChoiceOptional("Second card to discard", list.toArray()); + + Card c2 = (Card)o2; + list.remove(c2); + + hand.remove(c2); + grave.add(c2); + + if(c2.getType().contains("Land")) { + PlayerLife life = AllZone.GameAction.getPlayerLife(Constant.Player.Computer); + life.addLife(3); + } + } + } + } + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Temporal Spring")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 2649912511833536966L; + + public boolean canPlayAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + return 3 < AllZone.Phase.getTurn() && 0 < human.size(); + } + public void chooseTargetAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + setTargetCard(CardFactoryUtil.AI_getBestCreature(human)); + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + if(getTargetCard().isToken()) + AllZone.getZone(getTargetCard()).remove(getTargetCard()); + else + { + AllZone.GameAction.moveToTopOfLibrary(getTargetCard()); + } + }//if + }//resolve() + };//SpellAbility + Input target = new Input() + { + + private static final long serialVersionUID = 3852696858086356864L; + public void showMessage() + { + AllZone.Display.showMessage("Select target permanent for " +spell.getSourceCard()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(spell, c)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + else if(zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(c); + stopSetNext(new Input_PayManaCost(spell)); + } + } + };//Input + + spell.setBeforePayMana(target); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + else if(cardName.equals("Boomerang") || cardName.equals("Eye of Nowhere")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 5383879224433456795L; + + public boolean canPlayAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + return 3 < AllZone.Phase.getTurn() && 0 < human.size(); + } + public void chooseTargetAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + setTargetCard(CardFactoryUtil.AI_getBestCreature(human)); + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + if(getTargetCard().isToken()) + AllZone.getZone(getTargetCard()).remove(getTargetCard()); + else + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, getTargetCard().getOwner()); + AllZone.GameAction.moveTo(hand, getTargetCard()); + } + @SuppressWarnings("unused") // targetManaCost + String targetManaCost = getTargetCard().getManaCost(); + //System.out.println("target card has a converted manacost of: " +CardUtil.getConvertedManaCost(targetManaCost)); + }//if + }//resolve() + };//SpellAbility + Input target = new Input() + { + private static final long serialVersionUID = 7717499561403038165L; + public void showMessage() + { + AllZone.Display.showMessage("Select target permanent for " +spell.getSourceCard()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(spell, c)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + else if(zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(c); + stopSetNext(new Input_PayManaCost(spell)); + } + } + };//Input + + spell.setBeforePayMana(target); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Culling Sun")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 2169815434022673011L; + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + for(int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + int convertedManaCost = CardUtil.getConvertedManaCost(c.getManaCost()); + if(c.isCreature() && (convertedManaCost <= 3)) + AllZone.GameAction.destroy(c); + } + }//resolve() + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Creature"); + computer = computer.getType("Creature"); + + //the computer will at least destroy 2 more human creatures + return computer.size() < human.size()-1 || (AllZone.Computer_Life.getLife() < 7 && !human.isEmpty()); + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Retribution of the Meek")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 4989080454206680708L; + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + for(int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + int power = c.getNetAttack(); + if(c.isCreature() && (power >= 4)) + AllZone.GameAction.destroyNoRegeneration(c); + } + }//resolve() + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Creature"); + computer = computer.getType("Creature"); + + human = human.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.getNetAttack() >= 4; + } + }); + + human = human.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.getNetAttack() >= 4; + } + }); + + //the computer will at least destroy 2 more human creatures + return computer.size() < human.size()-1 || (AllZone.Computer_Life.getLife() < 7 && !human.isEmpty()); + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Mass Calcify")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -3985301372801316515L; + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + for(int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + //int convertedManaCost = CardUtil.getConvertedManaCost(c.getManaCost()); + if(c.isCreature() && !CardUtil.getColors(c).contains(Constant.Color.White)) + AllZone.GameAction.destroy(c); + } + }//resolve() + public boolean canPlayAI() + { + CardList human = new CardList(AllZone.Human_Play.getCards()); + CardList computer = new CardList(AllZone.Computer_Play.getCards()); + + human = human.getType("Creature"); + computer = computer.getType("Creature"); + + //the computer will at least destroy 2 more human creatures + return computer.size() < human.size()-1 || (AllZone.Computer_Life.getLife() < 7 && !human.isEmpty()); + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Cleanse")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 6329910910925881386L; + public void resolve() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + for(int i = 0; i < all.size(); i++) + { + Card c = all.get(i); + + if(c.isCreature() && CardUtil.getColors(c).contains(Constant.Color.Black)) + AllZone.GameAction.destroy(c); + } + }//resolve() + public boolean canPlayAI() + { + CardList hum = new CardList(AllZone.Human_Play.getCards()); + CardList comp = new CardList(AllZone.Computer_Play.getCards()); + + hum = hum.getType("Creature"); + comp = comp.getType("Creature"); + + CardList human = new CardList(); + CardList computer = new CardList(); + + for (int i=0; i= 8) + return true; + + check = getFlying(); + return check != null; + } + public void chooseTargetAI() + { + if(AllZone.Human_Life.getLife() <= damage) + { + setTargetPlayer(Constant.Player.Human); + return; + } + + Card c = getFlying(); + if((c == null) || (! check.equals(c))) + throw new RuntimeException(card +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + if (c == null) { + setTargetPlayer(Constant.Player.Human); + return; + } + setTargetCard(c); + }//chooseTargetAI() + + //uses "damage" variable + Card getFlying() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + for(int i = 0; i < flying.size(); i++) + if(flying.get(i).getNetDefense() <= damage) + return flying.get(i); + + return null; + } + + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + Card c = getTargetCard(); + c.addDamage(damage); + } + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage); + AllZone.GameAction.getPlayerLife(card.getController()).addLife(3); + + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + + Input target = new Input() + { + private static final long serialVersionUID = -924544537419004913L; + public void showMessage() + { + AllZone.Display.showMessage("Select target Creature, Player or Planeswalker"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(spell, card)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + else if((card.isCreature() || card.isPlaneswalker()) && zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + }//selectCard() + public void selectPlayer(String player) + { + spell.setTargetPlayer(player); + stopSetNext(new Input_PayManaCost(spell)); + } + }; + spell.setBeforePayMana(target); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Archon of Justice")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + if(getTargetCard() != null){ + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + AllZone.GameAction.removeFromGame(getTargetCard()); + } + } + } + }; + ability.setStackDescription("Archon of Justice - Remove target permament from the game."); + + Command leavesPlay = new Command() + { + private static final long serialVersionUID = 7552566264976488465L; + + public void execute() + { + if(card.getController().equals(Constant.Player.Human)) + AllZone.InputControl.setInput(CardFactoryUtil.input_targetPermanent(ability)); + else + { + //if computer controlled Archon of Justice have it select the best creature, or enchantment, or artifact, whatever the human controllers, and as a last option a card it controls + + CardList human_list = new CardList(AllZone.Human_Play.getCards()); + ability.setTargetCard(CardFactoryUtil.AI_getBestCreature(human_list)); + if(ability.getTargetCard() == null){ + ability.setTargetCard(CardFactoryUtil.AI_getBestEnchantment(human_list, card, true)); + } + if(ability.getTargetCard() == null){ + ability.setTargetCard(CardFactoryUtil.AI_getBestArtifact(human_list)); + } + if(ability.getTargetCard() == null){ + if(human_list.size() == 0){ + CardList computer_list = new CardList(AllZone.Computer_Play.getCards()); + if(computer_list.size() == 0){ + return; //we have nothing in play to destroy. + } + else{ + ability.setTargetCard(computer_list.get(0)); //should determine the worst card to destroy, but this case wont be hit much. + } + } + ability.setTargetCard(human_list.get(0)); + } + AllZone.Stack.add(ability); + } + }//execute() + };//Command + card.addDestroyCommand(leavesPlay); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Knight of the Reliquary")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 7554368501399705784L; + public void resolve() + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + + Card c = getTargetCard(); + if (AllZone.GameAction.isCardInPlay(c)) + { + AllZone.GameAction.sacrifice(c); + + CardList landInLib = new CardList(lib.getCards()); + landInLib = landInLib.getType("Land"); + + if (landInLib.size() > 0) + { + if (card.getController().equals(Constant.Player.Computer)) + { + lib.remove(landInLib.get(0)); + play.add(landInLib.get(0)); + } + else + { + Object o = AllZone.Display.getChoiceOptional("Select land card to put into play: ", landInLib.toArray()); + if (o != null) + { + Card crd = (Card)o; + lib.remove(crd); + play.add(crd); + } + } + AllZone.GameAction.shuffle(card.getController()); + } + }//if(isCardInPlay) + } + + public boolean canPlayAI() + { + CardList landInLib = new CardList(AllZone.getZone(Constant.Zone.Library, Constant.Player.Computer).getCards()); + CardList landInPlay = new CardList(AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer).getCards()); + + landInLib = landInLib.getType("Land"); + landInPlay = landInPlay.getType("Land"); + + if (landInLib.size() > 0 && landInPlay.size() > 0) + return true; + else + return false; + + } + public void chooseTargetAI() + { + CardList land = new CardList(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards()); + land = land.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if(c.getType().contains("Plains") || c.getType().contains("Forest")) + return true; + else + return false; + } + }); + if(land.size()>0) + setTargetCard(land.get(0)); + } + }; + + Input runtime = new Input() + { + private static final long serialVersionUID = -4320917612145305541L; + + public void showMessage() + { + CardList land = new CardList(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards()); + land = land.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if(c.getType().contains("Plains") || c.getType().contains("Forest")) + return true; + else + return false; + } + }); + + stopSetNext(CardFactoryUtil.input_targetSpecific(ability, land, "Select a Plains or Forest to sacrifice.", false)); + } + }; + ability.setBeforePayMana(runtime); + ability.setDescription("T, Sacrifice a Forest or Plains: Search your library for a land card, put it into play, then shuffle your library."); + ability.setStackDescription(card.getName() + " - Search your library for a card and put it into play, then shuffle your library"); + card.addSpellAbility(ability); + + } + + //*************** START *********** START ************************** + if(cardName.equals("Knight of the White Orchid")) + { + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card.getController()); + + + CardList basic = new CardList(lib.getCards()); + basic = basic.getType("Plains"); + + + + if (card.getController().equals(Constant.Player.Computer)) + { + if (basic.size() > 0) + { + Card c = basic.get(0); + lib.remove(c); + play.add(c); + + } + } + else // human + { + if (basic.size() > 0) + { + Object o = AllZone.Display.getChoiceOptional("Select Plains card to put into play: ", basic.toArray()); + if (o != null) + { + Card c = (Card)o; + lib.remove(c); + play.add(c); + } + } + } + AllZone.GameAction.shuffle(card.getController()); + }//resolve() + + };//Ability + + Command fetchBasicLand = new Command() + { + + private static final long serialVersionUID = -1086551054597721988L; + + public void execute() + { + String player = card.getController(); + PlayerZone oppPlay = AllZone.getZone(Constant.Zone.Play, AllZone.GameAction.getOpponent(player)); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + CardList self = new CardList(play.getCards()); + CardList opp = new CardList(oppPlay.getCards()); + + self = self.getType("Land"); + opp = opp.getType("Land"); + + if (self.size() < opp.size()) + { + ability.setStackDescription(card.getName()+ " - search library for a plains and put it into play"); + AllZone.Stack.add(ability); + } + } + }; + + card.addComesIntoPlayCommand(fetchBasicLand); + + + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Niv-Mizzet, the Firemind")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 8670005059055071206L; + public boolean canPlayAI() {return false;} + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + } + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("tap: Draw a card."); + ability.setStackDescription(card.getName() + " - draw a card."); + ability.setBeforePayMana(new Input_NoCost_TapAbility(ability)); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Hoofprints of the Stag")) + { + Command intoPlay = new Command() + { + private static final long serialVersionUID = -7275454992618058248L; + public boolean firstTime = true; + public void execute() + { + + if(firstTime){ + card.setCounter(Counters.HOOFPRINT, 0); + } + firstTime = false; + } + }; + + card.addComesIntoPlayCommand(intoPlay); + + final SpellAbility a2 = new Ability(card, "2 W") + { + public void resolve() + { + card.subtractCounter(Counters.HOOFPRINT, 4); + + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Elemental"); + c.setImageName("W 4 4 Elemental"); + c.setManaCost("W"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Elemental"); + c.addIntrinsicKeyword("Flying"); + c.setBaseAttack(4); + c.setBaseDefense(4); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + + } + + public boolean canPlay() + { + SpellAbility sa; + for (int i=0; i= 4 && AllZone.getZone(card).is(Constant.Zone.Play) && + AllZone.Phase.getActivePlayer().equals(card.getController()) && + !AllZone.Phase.getPhase().equals("End of Turn"); + }//canPlay() + public boolean canPlayAI() + { + return true; + } + };//spellAbility + + a2.setDescription("2 W, Remove four hoofprint counters from Hoofprints of the Stag: Put a 4/4 white Elemental creature token with flying into play. Play this ability only during your turn."); + a2.setStackDescription(card.getName() + " - put a 4/4 white Elemental creature token with flying into play."); + + card.addSpellAbility(a2); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Elvish Farmer") || cardName.equals("Mycologist")) + { + Command intoPlay = new Command() + { + private static final long serialVersionUID = 882942955555047018L; + public boolean firstTime = true; + public void execute() + { + + if(firstTime){ + card.setCounter(Counters.SPORE, 0); + } + firstTime = false; + } + }; + + card.addComesIntoPlayCommand(intoPlay); + + final SpellAbility a2 = new Ability(card, "0") + { + public void chooseTargetAI() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList saps = new CardList(play.getCards()); + saps = saps.filter(new CardListFilter() + { + + public boolean addCard(Card c) { + if((c.getType().contains("Saproling") || c.getKeyword().contains("Changeling")) && + AllZone.GameAction.isCardInPlay(c) ) + return true; + return false; + } + + }); + + if (saps.size() != 0) + setTargetCard(saps.getCard(0)); + } + public void resolve() + { + //get all saprolings: + Card c = getTargetCard(); + if(c == null ) + return; + + if (!AllZone.GameAction.isCardInPlay(c)) + return; + + if(AllZone.GameAction.isCardInPlay(c)) + { + //AllZone.getZone(c).remove(c); + AllZone.GameAction.sacrifice(c); + + PlayerLife life = AllZone.GameAction.getPlayerLife(c.getController()); + life.addLife(2); + } + }//resolve + public boolean canPlayAI() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList saps = new CardList(play.getCards()); + saps = saps.filter(new CardListFilter() + { + + public boolean addCard(Card c) { + if(c.getType().contains("Saproling") || c.getKeyword().contains("Changeling") && + AllZone.GameAction.isCardInPlay(c)) + return true; + return false; + } + + }); + if(AllZone.Computer_Life.getLife() < 6 && saps.size() > 0) + return true; + else + return false; + } + };//SpellAbility + + Input runtime = new Input() + { + private static final long serialVersionUID = -4803541385354247499L; + + public void showMessage() + { + CardList saps = new CardList(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards()); + saps = saps.getType("Saproling"); + + stopSetNext(CardFactoryUtil.input_targetSpecific(a2, saps, "Select a Saproling to sacrifice.", false)); + } + }; + + card.addSpellAbility(a2); + a2.setDescription("Sacrifice a Saproling: You gain 2 life."); + a2.setStackDescription(card.getController() + " gains 2 life."); + a2.setBeforePayMana(runtime); + + + }//*************** END ************ END ************************** + + else if (cardName.equals("Pallid Mycoderm")) + { + + Command intoPlay = new Command() + { + private static final long serialVersionUID = 3400057700040211691L; + public boolean firstTime = true; + public void execute() + { + + if(firstTime){ + card.setCounter(Counters.SPORE, 0); + } + firstTime = false; + } + }; + + card.addComesIntoPlayCommand(intoPlay); + + final SpellAbility a2 = new Ability(card, "0") + { + final Command eot1 = new Command() + { + private static final long serialVersionUID = -4485431571276851181L; + + public void execute() + { + String player = card.getController(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + CardList creats = new CardList(play.getCards()); + creats = creats.getType("Creature"); + + for (int i=0; i < creats.size(); i++) + { + Card creat = creats.get(i); + + if (creat.getType().contains("Fungus") || creat.getType().contains("Saproling") || creat.getKeyword().contains("Changeling")) + { + creat.addTempAttackBoost(-1); + creat.addTempDefenseBoost(-1); + } + } + + } + }; + public void resolve() + { + //get all player controls saprolings: + String player = card.getController(); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + CardList creats = new CardList(play.getCards()); + creats = creats.getType("Creature"); + + @SuppressWarnings("unused") // saps + CardList saps = new CardList(); + + Card c = getTargetCard(); + @SuppressWarnings("unused") // hand + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, c.getOwner()); + + if(AllZone.GameAction.isCardInPlay(c)) + { + //AllZone.getZone(c).remove(c); + AllZone.GameAction.sacrifice(c); + + + for (int i=0; i < creats.size(); i++) + { + Card creat = creats.get(i); + + if (creat.getType().contains("Fungus") || creat.getType().contains("Saproling")) + { + creat.addTempAttackBoost(1); + creat.addTempDefenseBoost(1); + } + } + + } + AllZone.EndOfTurn.addUntil(eot1); + } + public boolean canPlayAI() + { + return false; + } + };//SpellAbility + + Input runtime = new Input() + { + private static final long serialVersionUID = 6754180514935882692L; + + public void showMessage() + { + CardList saps = new CardList(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards()); + saps = saps.getType("Saproling"); + + stopSetNext(CardFactoryUtil.input_targetSpecific(a2, saps, "Select a Saproling to sacrifice.", false)); + } + }; + + card.addSpellAbility(a2); + a2.setDescription("Sacrifice a Saproling: Each Fungus and each Saproling you control gets +1/+1 until end of turn"); + a2.setStackDescription("Saprolings and Fungi you control get +1/+1 until end of turn."); + + a2.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + //*************** START *********** START ************************** + else if(cardName.equals("Psychotrope Thallid")) + { + Command intoPlay = new Command() + { + private static final long serialVersionUID = 8020106056714209199L; + public boolean firstTime = true; + public void execute() + { + + if(firstTime){ + card.setCounter(Counters.SPORE, 0); + } + firstTime = false; + } + }; + + card.addComesIntoPlayCommand(intoPlay); + + final SpellAbility a2 = new Ability(card, "1") + { + public void resolve() + { + + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c)) + { + //AllZone.getZone(c).remove(c); + AllZone.GameAction.sacrifice(c); + + AllZone.GameAction.drawCard(c.getController()); + } + }//resolve + public boolean canPlayAI() + { + //TODO: make AI able to use this + return false; + } + };//SpellAbility + + Input runtime = new Input() + { + private static final long serialVersionUID = -6388866343458002392L; + + public void showMessage() + { + CardList saps = new CardList(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards()); + saps = saps.getType("Saproling"); + + stopSetNext(CardFactoryUtil.input_targetSpecific(a2, saps, "Select a Saproling to sacrifice.", false)); + } + }; + + card.addSpellAbility(a2); + a2.setDescription("1, Sacrifice a Saproling: You draw a card."); + a2.setStackDescription(card.getController() + " draws a card."); + a2.setBeforePayMana(runtime); + + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Wall of Mulch")) + { + + final SpellAbility a2 = new Ability(card, "G") + { + public void resolve() + { + + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c)) + { + //AllZone.getZone(c).remove(c); + AllZone.GameAction.sacrifice(c); + AllZone.GameAction.drawCard(c.getController()); + } + }//resolve + public boolean canPlayAI() + { + //TODO: make AI able to use this + return false; + } + };//SpellAbility + + Input runtime = new Input() + { + private static final long serialVersionUID = -4390488827563977718L; + + public void showMessage() + { + CardList walls = new CardList(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards()); + walls = walls.getType("Wall"); + + stopSetNext(CardFactoryUtil.input_targetSpecific(a2, walls, "Select a Wall to sacrifice.", false)); + } + }; + + card.addSpellAbility(a2); + a2.setDescription("G, Sacrifice a Wall: You draw a card."); + a2.setStackDescription(card.getController() + " draws a card."); + a2.setBeforePayMana(runtime); + + + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + else if (cardName.equals("Rootwater Thief")) + { + //final String player = card.getController(); + //final String opponent = AllZone.GameAction.getOpponent(player); + + final Ability ability2 = new Ability(card, "2") + { + public void resolve() + { + String opponent = AllZone.GameAction.getOpponent(card.getController()); + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, opponent); + CardList cards = new CardList(lib.getCards()); + + if (cards.size() > 0 ) + { + if (card.getController().equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Select card to remove: ", cards.toArray()); + Card c = (Card)o; + AllZone.GameAction.removeFromGame(c); + AllZone.GameAction.shuffle(opponent); + } + else + { + Card c = lib.get(0); + AllZone.GameAction.removeFromGame(c); + AllZone.GameAction.shuffle(opponent); + } + } + + } + public boolean canPlay() + { + //this is set to false, since it should only TRIGGER + return false; + } + };// ability2 + //card.clearSpellAbility(); + card.addSpellAbility(ability2); + ability2.setStackDescription(card.getName() + " - search opponent's library and remove a card from game."); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if (cardName.equals("Goblin Trenches")) + { + final String player = card.getController(); + + final SpellAbility ability = new Ability(card, "2") + { + public boolean canPlay() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + CardList lands = new CardList(); + lands.addAll(play.getCards()); + lands = lands.getType("Land"); + + if (lands.size() >= 1 && AllZone.GameAction.isCardInPlay(card)) + return true; + else + return false; + } + + public void chooseTargetAI() + { + Card c = getTappedLand(); //first, try to get a tapped land to sac + if (c!=null) + { + setTargetCard(c); + + } + else + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + CardList lands = new CardList(); + lands.addAll(play.getCards()); + lands = lands.getType("Land"); + + setTargetCard(c); + + } + } + public Card getTappedLand() + { + //target creature that is going to attack + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + CardList lands = new CardList(); + lands.addAll(play.getCards()); + lands = lands.getType("Land"); + + for(int i=0;i 0 && AllZone.GameAction.isCardInPlay(card)) + return true; + else + return false; + } + public boolean canPlayAI() { + String phase = AllZone.Phase.getPhase(); + return phase.equals(Constant.Phase.Main2); + } + + public void resolve() + { + card.subtractCounter(Counters.ICE, 1); + + if (card.getCounters(Counters.ICE) == 0) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + + //make token + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Marit Lage"); + c.setManaCost("B"); + c.setToken(true); + + c.addType("Legendary"); + c.addType("Creature"); + c.addType("Avatar"); + c.addIntrinsicKeyword("Flying"); + c.addExtrinsicKeyword("Indestructible"); + c.setBaseAttack(20); + c.setBaseDefense(20); + + play.add(c); + AllZone.GameAction.sacrifice(card); + }// if counters == 0 + } + }; + ability.setDescription("3: Remove an ice counter from Dark Depths."); + ability.setStackDescription(card.getName() +" - remove an ice counter."); + + card.addSpellAbility(ability); + + }//*************** END ************ END ************************** + /* + //*************** START *********** START ************************** + else if (cardName.equals("Acridian")) + { + final String player = card.getController(); + + final Ability echo = new Ability(card, "1 G") + { + public void resolve() + { + card.setEchoPaid(true); + System.out.println("set echo to true"); + } + public boolean canPlay() + { + //this is set to false, since it should only TRIGGER + return false; + } + };// ability2 + //card.clearSpellAbility(); + card.addSpellAbility(echo); + echo.setStackDescription(card.getName() + " - " + player + " paid echo."); + + Command paid = new Command() {public void execute() {AllZone.Stack.add(echo);}}; + + //echo.setBeforePayMana(new Input_PayManaCost_Ability(echo.getManaCost(), paid)); + echo.setAfterPayMana(new Input_PayManaCost_Ability(echo.getManaCost(), paid)); + + + }//*************** END ************ END ************************** + + */ + + //*************** START *********** START ************************** + else if (cardName.equals("Oros, the Avenger")) + { + final String player = card.getController(); + + final Ability ability2 = new Ability(card, "2 W") + { + public void resolve() + { + if (player.equals("Human")) + { + CardList cards = new CardList(); + PlayerZone hum = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + PlayerZone comp = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + cards.addAll(hum.getCards()); + cards.addAll(comp.getCards()); + cards = cards.getType("Creature"); + + for (int i=0;i 0; + } + + public void resolve() + { + Card c = getTargetCard(); + + if (c!=null) + { + if ( CardFactoryUtil.canTarget(card, c) && c.isCreature() && c.getType().contains("Legendary") ) + AllZone.GameAction.moveTo(AllZone.getZone(Constant.Zone.Hand, card.getOwner()), c); + } + } + }; + + Input runtime = new Input() + { + + private static final long serialVersionUID = -7649200192384343204L; + + public void showMessage() + { + CardList choice = new CardList(); + choice.addAll(AllZone.Human_Play.getCards()); + choice.addAll(AllZone.Computer_Play.getCards()); + + choice = choice.getType("Creature"); + choice = choice.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (c.isCreature() && c.getType().contains("Legendary")); + } + }); + + //System.out.println("size of choice: " + choice.size()); + stopSetNext(CardFactoryUtil.input_targetSpecific(ability, choice, "Select target Legendary creature:", true)); + } + }; + + ability.setDescription("tap: Return target legendary creature to its owner's hand."); + //ability.setStackDescription(card.getName() + " - gives target creature +1/+2 until end of turn."); + + card.addSpellAbility(ability); + ability.setBeforePayMana(runtime); + + //not sure what's going on here, maybe because it's a land it doesn't add the ability to the text? + //anyway, this does the trick: + //card.removeIntrinsicKeyword("tap: add G"); + card.setText(card.getSpellText() + "\r\ntap: Return target legendary creature to its owner's hand."); + //card.addIntrinsicKeyword("tap: add G"); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Pendelhaven")) + { + final Ability_Tap ability = new Ability_Tap(card, "0") + { + private static final long serialVersionUID = 8154776336533992188L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + + public void chooseTargetAI() + { + setTargetCard(getAttacker()); + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + CardList att = new CardList(); + att.addAll(c.getAttackers()); + + for (int i=0; i 0 && AllZone.GameAction.isCardInPlay(card) && card.isUntapped()) + return true; + else + return false; + } + + }; + + ability.setDescription("1 U, tap: Put target artifact card in your graveyard on top of your library."); + ability.setStackDescription(card.getName() + " - put artifact card in your graveyard on top of your library."); + + card.addSpellAbility(ability); + + //not sure what's going on here, maybe because it's a land it doesn't add the ability to the text? + //anyway, this does the trick: + //card.removeIntrinsicKeyword("tap: add 1"); + card.setText(card.getSpellText() + "\r\n1 U, tap: Put target artifact card in your graveyard on top of your library."); + //card.addExtrinsicKeyword("tap: add 1"); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Volrath's Stronghold")) + { + final Ability_Tap ability = new Ability_Tap(card, "1 B") + { + private static final long serialVersionUID = 2821525387844776907L; + + public void resolve() + { + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + + public void humanResolve() + { + CardList cards = new CardList(AllZone.Human_Graveyard.getCards()); + + CardList list = new CardList(); + + for (int i=0;i < cards.size(); i++) + { + //System.out.println("type: " +cards.get(i).getType()); + if (cards.get(i).getType().contains("Creature")){ + //System.out.println(cards.get(i).getName()); + Card c = cards.get(i); + list.add(c); + + } + } + + if (list.size() != 0) { + Object check = AllZone.Display.getChoiceOptional("Select Creature", list.toArray()); + if(check != null) + { + //PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + //library.add((Card)check, 0); + AllZone.GameAction.moveToTopOfLibrary((Card)check); + } + } + } + public void computerResolve() + { + Card[] grave = AllZone.Computer_Graveyard.getCards(); + CardList list = new CardList(grave); + CardList creats = new CardList(); + + for (int i=0;i < list.size(); i++) + { + if (list.get(i).getType().contains("Creature")){ + Card k = list.get(i); + creats.add(k); + } + + } + + //pick best artifact + if (creats.size() != 0){ + Card c = CardFactoryUtil.AI_getBestCreature(list); + if(c == null) + c = grave[0]; + //System.out.println("computer picked - " +c); + AllZone.Computer_Graveyard.remove(c); + //AllZone.Computer_Library.add(c, 0); + AllZone.GameAction.moveToTopOfLibrary(c); + } + }//computerResolve + + public boolean canPlay(){ + String controller = card.getController(); + + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, controller); + CardList list = new CardList(grave.getCards()); + CardList cards = new CardList(); + + for (int i=0;i 0 && AllZone.GameAction.isCardInPlay(card) && card.isUntapped()) + return true; + else + return false; + } + + }; + + ability.setDescription("1 B, tap: Put target creature card in your graveyard on top of your library."); + ability.setStackDescription(card.getName() + " - put creature card in your graveyard on top of your library."); + + card.addSpellAbility(ability); + + //not sure what's going on here, maybe because it's a land it doesn't add the ability to the text? + //anyway, this does the trick: + //card.removeIntrinsicKeyword("tap: add 1"); + card.setText(card.getSpellText() + "\r\n1 U, tap: Put target creature card in your graveyard on top of your library."); + //card.addExtrinsicKeyword("tap: add 1"); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Oboro, Palace in the Clouds")) + { + final Ability ability = new Ability(card, "1") + { + + public boolean canPlayAI() + { + return false; + } + + public void resolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, card); + } + }; + + ability.setDescription("1: Return Oboro, Palace in the Clouds to your hand."); + ability.setStackDescription("Return " + card.getName() + " to your hand."); + + card.addSpellAbility(ability); + + //not sure what's going on here, maybe because it's a land it doesn't add the ability to the text? + //anyway, this does the trick: + //card.removeIntrinsicKeyword("tap: add 1"); + card.setText(card.getSpellText() + "\r\n1: Return Oboro, Palace in the Clouds to your hand."); + //card.addExtrinsicKeyword("tap: add 1"); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Mikokoro, Center of the Sea")) + { + final Ability_Tap ability = new Ability_Tap(card, "2") + { + private static final long serialVersionUID = -199960897120235012L; + + public void resolve() + { + AllZone.GameAction.drawCard(Constant.Player.Computer); + AllZone.GameAction.drawCard(Constant.Player.Human); + } + }; + + ability.setDescription("2, tap: Each player draws a card."); + ability.setStackDescription(card.getName() + " - Each player draws a card."); + + card.addSpellAbility(ability); + + //not sure what's going on here, maybe because it's a land it doesn't add the ability to the text? + //anyway, this does the trick: + //card.removeIntrinsicKeyword("tap: add 1"); + card.setText(card.getSpellText() + "\r\n2, tap: Each player draws a card."); + //card.addExtrinsicKeyword("tap: add 1"); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Gargoyle Castle")) + { + final Ability_Tap ability = new Ability_Tap(card, "5") + { + + private static final long serialVersionUID = 8524185208900629992L; + + public boolean canPlay() + { + if (AllZone.GameAction.isCardInPlay(card) && card.isUntapped()) + return true; + else + return false; + } + + public void resolve() + { + String player = card.getController(); + AllZone.GameAction.sacrifice(card); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + //make token + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Gargoyle"); + c.setImageName("C 3 4 Gargoyle"); + c.setManaCost("1"); + c.setToken(true); + + c.addType("Artifact"); + c.addType("Creature"); + c.addType("Gargoyle"); + c.setBaseAttack(3); + c.setBaseDefense(4); + c.addIntrinsicKeyword("Flying"); + + play.add(c); + } + }; + + ability.setDescription("5, tap, sacrifice Gargoyle Castle: Put a 3/4 colorless Gargoyle artifact creature token with flying onto the battlefield."); + ability.setStackDescription(card.getName() + " - Put a 3/4 colorless Gargoyle artifact creature token with flying onto the battlefield."); + + card.addSpellAbility(ability); + + //not sure what's going on here, maybe because it's a land it doesn't add the ability to the text? + //anyway, this does the trick: + //card.removeIntrinsicKeyword("tap: add 1"); + card.setText(card.getSpellText() + "\r\n5, tap, sacrifice Gargoyle Castle: Put a 3/4 colorless Gargoyle artifact creature token with flying onto the battlefield."); + //card.addIntrinsicKeyword("tap: add 1"); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Kher Keep")) + { + final Ability_Tap ability = new Ability_Tap(card, "1 R") + { + private static final long serialVersionUID = 4037838521451709399L; + + public boolean canPlay() + { + if (AllZone.GameAction.isCardInPlay(card) && card.isUntapped()) + return true; + else + return false; + } + + public void resolve() + { + String player = card.getController(); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + //make token + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Kobolds of Kher Keep"); + c.setManaCost("R"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Kobold"); + c.setBaseAttack(0); + c.setBaseDefense(1); + + play.add(c); + } + }; + + ability.setDescription("1 R, tap: Put a 0/1 red Kobold creature token named Kobolds of Kher Keep into play."); + ability.setStackDescription(card.getName() + " - Put a 0/1 red Kobold creature token named Kobolds of Kher Keep into play."); + + card.addSpellAbility(ability); + + //not sure what's going on here, maybe because it's a land it doesn't add the ability to the text? + //anyway, this does the trick: + //card.removeIntrinsicKeyword("tap: add 1"); + card.setText(card.getSpellText() + "\r\n1 R, tap: Put a 0/1 red Kobold creature token named Kobolds of Kher Keep into play."); + //card.addIntrinsicKeyword("tap: add 1"); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Vitu-Ghazi, the City-Tree")) + { + final Ability_Tap ability = new Ability_Tap(card, "2 G W") + { + private static final long serialVersionUID = 1781653158406511188L; + + public boolean canPlay() + { + if (AllZone.GameAction.isCardInPlay(card)) + return true; + else + return false; + } + + public void resolve() + { + String player = card.getController(); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + //make token + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Saproling"); + c.setImageName("G 1 1 Saproling"); + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Saproling"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + play.add(c); + } + }; + + ability.setDescription("2 G W, tap: Put a 1/1 green Saproling creature token into play."); + ability.setStackDescription(card.getName() + " - Put a 1/1 green Saproling creature token named into play."); + + card.addSpellAbility(ability); + + //not sure what's going on here, maybe because it's a land it doesn't add the ability to the text? + //anyway, this does the trick: + //card.removeIntrinsicKeyword("tap: add 1"); + card.setText(card.getSpellText() + "\r\n 2 G W, tap: Put a 1/1 green Saproling creature token into play."); + //card.addIntrinsicKeyword("tap: add 1"); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Hatching Plans")) + { + + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + AllZone.GameAction.drawCard(card.getController()); + AllZone.GameAction.drawCard(card.getController()); + } + }; + + Command draw3Cards = new Command() + { + private static final long serialVersionUID = -4919203791300685078L; + + public void execute() + { + ability.setStackDescription(card.getName()+ " - draw three cards."); + AllZone.Stack.add(ability); + } + }; + + card.addDestroyCommand(draw3Cards); + + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Anodet Lurker")) + { + + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.addLife(3); + } + }; + + Command gain3Life = new Command() + { + private static final long serialVersionUID = 9156307402354672176L; + + public void execute() + { + ability.setStackDescription(card.getName()+ " - Gain 3 life."); + AllZone.Stack.add(ability); + } + }; + + card.addDestroyCommand(gain3Life); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + else if(cardName.equals("Tarpan")) + { + + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.addLife(1); + } + }; + + Command gain1Life = new Command() + { + private static final long serialVersionUID = 206350020224577500L; + + public void execute() + { + ability.setStackDescription(card.getName()+ " - Gain 1 life."); + AllZone.Stack.add(ability); + } + }; + + card.addDestroyCommand(gain1Life); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Onulet")) + { + + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.addLife(2); + } + }; + + Command gain2Life = new Command() + { + private static final long serialVersionUID = 7840609060047275126L; + + public void execute() + { + ability.setStackDescription(card.getName()+ " - Gain 2 life."); + AllZone.Stack.add(ability); + } + }; + + card.addDestroyCommand(gain2Life); + + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Sprouting Thrinax")) + { + + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + makeToken(); + makeToken(); + makeToken(); + }//resolve() + + void makeToken() + { + Card c = new Card(); + + c.setName("Saproling"); + c.setImageName("G 1 1 Saproling"); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Saproling"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//makeToken() + };//Ability + + Command make3Tokens = new Command() + { + private static final long serialVersionUID = 5246587197020320581L; + + public void execute() + { + ability.setStackDescription(card.getName()+ " - put three 1/1 Saproling creature tokens into play."); + AllZone.Stack.add(ability); + } + }; + + card.addDestroyCommand(make3Tokens); + + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + else if(cardName.equals("Solemn Simulacrum")) + { + + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card.getController()); + + CardList basic = new CardList(lib.getCards()); + basic = basic.getType("Basic"); + + if (card.getController().equals(Constant.Player.Computer)) + { + if (basic.size() > 0) + { + Card c = basic.get(0); + lib.remove(c); + play.add(c); + c.tap(); + + } + } + else // human + { + if (basic.size() > 0) + { + Object o = AllZone.Display.getChoiceOptional("Select Basic Land card to put into play tapped: ", basic.toArray()); + if (o != null) + { + Card c = (Card)o; + lib.remove(c); + play.add(c); + c.tap(); + } + } + } + AllZone.GameAction.shuffle(card.getController()); + }//resolve() + };//Ability + + Command fetchBasicLand = new Command() + { + private static final long serialVersionUID = -7912757481694029348L; + + public void execute() + { + ability.setStackDescription(card.getName()+ " - search library for a basic land card and put it into play tapped."); + AllZone.Stack.add(ability); + } + }; + + final Ability ability2 = new Ability(card, "0") + { + public void resolve() + { + + AllZone.GameAction.drawCard(card.getController()); + }//resolve() + };//Ability + + Command draw = new Command() + { + private static final long serialVersionUID = -549395102229088642L; + + public void execute() + { + ability2.setStackDescription(card.getName()+ " - Draw a card."); + AllZone.Stack.add(ability2); + } + }; + + card.addDestroyCommand(draw); + card.addComesIntoPlayCommand(fetchBasicLand); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Gods' Eye, Gate to the Reikai")) + { + + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("1"); + c.setToken(true); + + c.setName("Spirit"); + c.setImageName("C 1 1 Spirit"); + + c.addType("Creature"); + c.addType("Spirit"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + play.add(c); + + }//resolve() + };//Ability + + Command makeToken = new Command() + { + private static final long serialVersionUID = 2339209292936869322L; + + public void execute() + { + ability.setStackDescription(card.getName()+ " - put a 1/1 Spirit creature token into play"); + AllZone.Stack.add(ability); + } + }; + + card.addDestroyCommand(makeToken); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Flagstones of Trokair")) + { + + final Ability ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card.getController()); + + CardList plains = new CardList(lib.getCards()); + plains = plains.getType("Plains"); + + if (card.getController().equals(Constant.Player.Computer)) + { + if (plains.size() > 0) + { + Card c = plains.get(0); + lib.remove(c); + play.add(c); + c.tap(); + + } + } + else // human + { + if (plains.size() > 0) + { + Object o = AllZone.Display.getChoiceOptional("Select plains card to put into play tapped: ", plains.toArray()); + if (o != null) + { + Card c = (Card)o; + lib.remove(c); + play.add(c); + c.tap(); + } + } + } + AllZone.GameAction.shuffle(card.getController()); + }//resolve() + };//Ability + + Command fetchPlains = new Command() + { + + private static final long serialVersionUID = 5991465998493672076L; + + public void execute() + { + ability.setStackDescription(card.getName()+ " - search library for a plains card and put it into play tapped."); + AllZone.Stack.add(ability); + } + }; + + card.addDestroyCommand(fetchPlains); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Master Transmuter")) + { + final Ability_Tap ability = new Ability_Tap(card, "U") + { + + private static final long serialVersionUID = -9076784333448226913L; + + public void resolve() { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList artifacts = new CardList(hand.getCards()); + artifacts = artifacts.getType("Artifact"); + if (card.getController().equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Select artifact to put onto the battlefield: ", artifacts.toArray()); + if(o!=null) + { + Card c = (Card)o; + hand.remove(c); + play.add(c); + } + } + else + { + //CardList arts = new CardList(play.getCards()); + //arts = arts.getType("Artifact"); + + Card c = getTargetCard(); + AllZone.GameAction.moveTo(hand, c); + + Card crd = CardFactoryUtil.AI_getMostExpensivePermanent(artifacts, card, false); + hand.remove(crd); + play.add(crd); + + } + } + + public boolean canPlayAI() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + + CardList handArts = new CardList(hand.getCards()); + handArts = handArts.getType("Artifact"); + + CardList playArts = new CardList(play.getCards()); + playArts = playArts.getType("Artifact"); + + if (handArts.size() > 0 && playArts.size() > 0){ + + if (CardUtil.getConvertedManaCost(CardFactoryUtil.AI_getCheapestPermanent(playArts, card, false).getManaCost()) < + CardUtil.getConvertedManaCost(CardFactoryUtil.AI_getMostExpensivePermanent(handArts, card, false).getManaCost())) + { + setTargetCard(CardFactoryUtil.AI_getCheapestPermanent(playArts, card, false)); + return true; + } + + } + return false; + } + }; + + Input target = new Input() + { + + private static final long serialVersionUID = 4246650335595231655L; + public void showMessage() + { + AllZone.Display.showMessage("Select artifact to return to hand"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play,card.getController()); + if(c.isArtifact() && AllZone.GameAction.isCardInZone(c, play)) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand,card.getController()); + + AllZone.GameAction.moveTo(hand, c); + AllZone.Stack.add(ability); + stopSetNext(new ComputerAI_StackNotEmpty()); + } + }//selectCard() + };//Input + + card.addSpellAbility(ability); + ability.setDescription("U, tap, Return an artifact you control to its owner's hand: You may put an artifact card from your hand onto the battlefield."); + ability.setStackDescription(card + "You may put an artifact card from your hand onto the battlefield"); + ability.setAfterPayMana(target); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Hanna, Ship's Navigator")) + { + final Ability_Tap ability = new Ability_Tap(card, "1 U W") + { + private static final long serialVersionUID = 7959233413572648987L; + + public void resolve() + { + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + }//resolve() + public void humanResolve() + { + CardList cards = new CardList(AllZone.Human_Graveyard.getCards()); + //legends = legends.getType().contains("Legendary"); + CardList list = new CardList(); + + for (int i=0;i < cards.size(); i++) + { + //System.out.println("type: " +cards.get(i).getType()); + if (cards.get(i).getType().contains("Artifact") || cards.get(i).getType().contains("Enchantment")){ + //System.out.println(cards.get(i).getName()); + Card c = cards.get(i); + list.add(c); + + } + } + + if (list.size() != 0) { + Object check = AllZone.Display.getChoiceOptional("Select Artifact or Enchantment", list.toArray()); + if(check != null) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, (Card)check); + } + } + } + public void computerResolve() + { + Card[] grave = AllZone.Computer_Graveyard.getCards(); + CardList list = new CardList(grave); + CardList artenchants = new CardList(); + //list = list.getType("Creature"); + + for (int i=0;i < list.size(); i++) + { + if (list.get(i).getType().contains("Artifact") || list.get(i).getType().contains("Enchantment")){ + Card k = list.get(i); + artenchants.add(k); + } + + } + + //pick best artifact / enchantment + if (artenchants.size() != 0){ + Card c = CardFactoryUtil.AI_getBestArtifact(list); + if(c == null) + c = CardFactoryUtil.AI_getBestEnchantment(list,card, true); + if(c == null) + c = grave[0]; + System.out.println("computer picked - " +c); + AllZone.Computer_Graveyard.remove(c); + AllZone.Computer_Hand.add(c); + } + }//computerResolve + + public boolean canPlay(){ + String controller = card.getController(); + + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, controller); + CardList list = new CardList(grave.getCards()); + CardList cards = new CardList(); + + for (int i=0;i 0 && AllZone.GameAction.isCardInPlay(card) && !card.hasSickness() && card.isUntapped()) + return true; + else + return false; + } + + + };//SpellAbility + //card.addSpellAbility(ability); + ability.setDescription("1 U W, tap: Return target artifact or enchantment card from your graveyard to your hand."); + ability.setBeforePayMana(new Input_PayManaCost(ability)); + ability.setStackDescription("Hanna, Ship's Navigator - Returns an artifact or enchantment card from graveyard to hand."); + card.addSpellAbility(ability); + + + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + else if(cardName.equals("Sleight of Hand")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 5608200094037045828L; + public boolean canPlay() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + if (library.size() >= 1 && super.canPlay()) + return true; + else + return false; + + } + public void resolve() + { + + PlayerZone library = AllZone.getZone(Constant.Zone.Library,card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + CardList lib = new CardList(library.getCards()); + + CardList topTwo = new CardList(); + + if (lib.size() == 1) { + AllZone.GameAction.drawCard(card.getController()); + } + else + { + if (card.getController().equals(Constant.Player.Human)) + { + topTwo.add(lib.get(0)); + topTwo.add(lib.get(1)); + + Object o = AllZone.Display.getChoiceOptional("Select card to put in hand: ", topTwo.toArray()); + + Card c1 = (Card)o; + topTwo.remove(c1); + library.remove(c1); + hand.add(c1); + + Card c2 = topTwo.get(0); + library.remove(c2); + library.add(c2); + } + else //computer + { + Card c1 = lib.get(0); + library.remove(c1); + lib.remove(c1); + hand.add(c1); + + Card c2 = lib.get(0); + library.remove(c2); + lib.remove(c2); + library.add(c2); //put on bottom + + } + + } + + } + }; + + card.clearSpellAbility(); + card.addSpellAbility(spell); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Brainstorm")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -5722651962081633839L; + + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + AllZone.GameAction.drawCard(card.getController()); + AllZone.GameAction.drawCard(card.getController()); + + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + + public void humanResolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Human); + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, Constant.Player.Human); + + CardList putOnTop = new CardList(hand.getCards()); + + Object o = AllZone.Display.getChoiceOptional("First card to put on top: ", putOnTop.toArray()); + if(o != null) + { + Card c1 = (Card)o; + putOnTop.remove(c1); + hand.remove(c1); + lib.add(c1,0); + } + o = AllZone.Display.getChoiceOptional("Second card to put on top: ", putOnTop.toArray()); + if(o != null) + { + Card c2 = (Card)o; + putOnTop.remove(c2); + hand.remove(c2); + lib.add(c2,0); + } + + } + + public void computerResolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, Constant.Player.Computer); + + CardList putOnTop = new CardList(hand.getCards()); + + Card c1 = putOnTop.get(0); + putOnTop.remove(c1); + hand.remove(c1); + lib.add(c1, 0); + + Card c2 = putOnTop.get(0); + putOnTop.remove(c2); + hand.remove(c2); + lib.add(c2, 0); + //TODO: somehow find the least desirable cards at the moment, and put those on top + } + + public boolean canPlay() + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card.getController()); + + if (lib.size() >= 2) + return true; + else + return false; + } + + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Banishing Knack")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 6518824567946786581L; + public boolean canPlayAI(){return false;} + public void resolve() + { + final Card creature = getTargetCard(); + final Ability_Tap tBanish = new Ability_Tap(creature) + { + private static final long serialVersionUID = -1008113001678623984L; + + public boolean canPlayAI() {return false;} + + public void resolve() + { + setStackDescription(creature+" - Return"+getTargetCard()+"to its owner's hand"); + final Card[] target = new Card[1]; + target[0] = getTargetCard(); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, target[0].getOwner()); + + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(creature, target[0]) ) + { + AllZone.GameAction.moveTo(hand ,target[0]); + } + }//resolve() + };//tBanish; + tBanish.setDescription("T: Return target nonland permanent to its owner's hand."); + creature.addSpellAbility(tBanish); + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + all = all.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return (!c.isLand() && CardFactoryUtil.canTarget(creature, c)); + } + }); + tBanish.setBeforePayMana(CardFactoryUtil.input_targetSpecific(tBanish, all, "Return target nonland permanent to its owner's hand.", true)); + AllZone.EndOfTurn.addUntil(new Command(){ + private static final long serialVersionUID = -7819140065166374666L; + + public void execute(){ + creature.removeSpellAbility(tBanish); + } + }); + } + };//SpellAbility + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + spell.setDescription("Until end of turn, target creature gains \"T: Return target nonland permanent to its owner's hand.\""); + spell.setStackDescription("Target creature gains \"T: Return target nonland permanent to its owner's hand.\""); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Cromat")){ + + //LibBounce Ability + final Ability a1 = new Ability(card, "G U") + { + public boolean canPlayAI() {return false;} + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card) ) + { + card.setBaseAttack(5); + card.setBaseDefense(5); + + card.setAssignedDamage(0); + card.setDamage(0); + card.untap(); + AllZone.getZone(card).remove(card); + + //put card on top of library + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getOwner()); + library.add(card, 0); + } + }//resolve() + };//SpellAbility + + Input runtime1 = new Input() + { + private static final long serialVersionUID = 1469011418219527227L; + + public void showMessage() + { + a1.setStackDescription("Put " +card +" on top of its owner's library"); + + stopSetNext(new Input_PayManaCost(a1)); + } + }; + a1.setDescription("G U: Put Cromat on top of its owner's library."); + a1.setStackDescription("Put Cromat on top of its owner's library."); + card.addSpellAbility(a1); + a1.setBeforePayMana(runtime1); + //Kill ability + + final Ability a2 = new Ability(card, "W B"){ + public boolean canPlay() + { + return (AllZone.GameAction.isCardInPlay(card) && (AllZone.Combat.isBlocked(card) || AllZone.Combat.getAllBlockers().contains(card))); + } + public boolean canPlayAI() + { + return false; + //TODO + } + public void resolve() + { + AllZone.GameAction.destroy(getTargetCard()); + }//resolve() + }; + Input runtime2 = new Input() + { + private static final long serialVersionUID = 1L; + + public void showMessage() + { + CardList targets = new CardList(); + if(AllZone.Combat.isBlocked(card) || AllZone.Combat.getAllBlockers().contains(card)){ + if (AllZone.Combat.isBlocked(card)){ targets = AllZone.Combat.getBlockers(card); } + else { + targets = new CardList(); + for (Card c : AllZone.Combat.getAttackers()){ + if (AllZone.Combat.isBlocked(c)) + if (AllZone.Combat.getBlockers(c).contains(card)) targets.add(c); + } + } + } + stopSetNext(CardFactoryUtil.input_targetSpecific(a2, targets, "Select target blocking or blocked by Cromat.", true)); + } + }; + card.addSpellAbility(a2); + a2.setBeforePayMana(runtime2); + a2.setDescription("W B: Destroy target creature blocking or blocked by Cromat."); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Mutavault")) + { + final Command eot1 = new Command() + { + private static final long serialVersionUID = 5106629534549783845L; + + public void execute() + { + Card c = card; + + c.setBaseAttack(0); + c.setBaseDefense(0); + c.removeIntrinsicKeyword("Changeling"); + c.removeType("Creature"); + } + }; + + final SpellAbility a1 = new Ability(card, "1") + { + public boolean canPlayAI() + { + return false; + } + public void resolve() + { + Card c = card; + + c.setBaseAttack(2); + c.setBaseDefense(2); + + //to prevent like duplication like "Changeling Changeling Creature Creature" + if(! c.getIntrinsicKeyword().contains("Changeling")) + { + c.addIntrinsicKeyword("Changeling"); + c.addType("Creature"); + } + AllZone.EndOfTurn.addUntil(eot1); + } + };//SpellAbility + + card.clearSpellAbility(); + card.addSpellAbility(a1); + a1.setDescription("1: Mutavault becomes a 2/2 creature with all creature types until end of turn. It's still a land."); + a1.setStackDescription(card +" becomes a 2/2 creature with changeling until EOT"); + + Command paid1 = new Command() { + private static final long serialVersionUID = -601119544294387668L; + public void execute() {AllZone.Stack.add(a1);} + }; + + a1.setBeforePayMana(new Input_PayManaCost_Ability(a1.getManaCost(), paid1)); + + //not sure what's going on here, maybe because it's a land it doesn't add the ability to the text? + //anyway, this does the trick: + card.removeIntrinsicKeyword("tap: add 1"); + card.setText(card.getText() + "\r\n1: Mutavault becomes a 2/2 creature with all creature types until end of turn. It's still a land."); + card.addIntrinsicKeyword("tap: add 1"); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Dragon Blood")) + { + Ability_Tap ability = new Ability_Tap(card, "3") + { + private static final long serialVersionUID = -8095802059752537764L; + public void resolve() + { + if(getTargetCard() != null && getTargetCard().isCreature() + && CardFactoryUtil.canTarget(card, getTargetCard()) ) + getTargetCard().addCounter(Counters.P1P1,1); + } + public boolean canPlayAI() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + setTargetCard(CardFactoryUtil.AI_getBestCreature(list)); + return (getTargetCard() != null); + } + }; + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + ability.setDescription("3, T: Put a +1/+1 counter on target creature."); + ability.setStackDescription(card+": put a +1/+1 counter on target Creature."); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Reminisce")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 505983020365091226L; + + public void resolve() + { + String player = getTargetPlayer(); + // Move graveyard into library + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + Card[] g = grave.getCards(); + for (int i = 0; i < g.length; i++) + { + grave.remove(g[i]); + library.add(g[i],0); + } + // Shuffle library + AllZone.GameAction.shuffle(player);; + } + + public boolean canPlayAI()//97% of the time shuffling your grave into your library is a good thing + { + setTargetPlayer(Constant.Player.Computer); + return true; + } + + };//SpellAbility + spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Energizer")) + { + Ability_Tap ability = new Ability_Tap(card, "2") + { + private static final long serialVersionUID = 6444406158364728638L; + public void resolve() + { + card.addCounter(Counters.P1P1,1); + } + public boolean canPlayAI() + { + return(true); + } + }; + ability.setDescription("2, T: Put a +1/+1 counter on Energizer."); + ability.setStackDescription("Put a +1/+1 counter on target Energizer."); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("AEther Vial")) + { + //final int[] converted = null; + final Ability_Tap ability = new Ability_Tap(card, "0") + { + private static final long serialVersionUID = 1854859213307704018L; + + public boolean canPlay() + { + return card.getCounters(Counters.CHARGE) > 0; + } + + public void resolve() { + String player = card.getController(); + + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + //converted[0] = card.getCounters(Counters.CHARGE); + //System.out.println("converted: " + converted[0]); + + CardList list = new CardList(hand.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return CardUtil.getConvertedManaCost(c.getManaCost()) == card.getCounters(Counters.CHARGE) && c.isCreature(); + } + }); + + + if (list.size()>0) + { + if (player.equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Pick creature to put into play", list.toArray()); + if (o!=null) + { + Card c = (Card)o; + hand.remove(c); + play.add(c); + } + } + else + { + Card c = list.get(0); + if(AllZone.GameAction.isCardInZone(c, hand)) { + hand.remove(c); + play.add(c); + } + } + } + } + }; + + ability.setDescription("Tap: You may put a creature card with converted mana cost equal to the number of charge counters on AEther Vial from your hand into play."); + ability.setStackDescription(card.getName() + " - put creature card with converted mana cost equal to the number of charge counters into play."); + + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("AEther Spellbomb")) + { + + final Ability ability = new Ability(card, "U") + { + public boolean canPlay() + { + return AllZone.GameAction.isCardInPlay(card)&&!AllZone.Stack.getSourceCards().contains(card); + } + public boolean canPlayAI() + { + CardList humanPlay = new CardList(AllZone.Human_Play.getCards()); + if (humanPlay.size() > 0) + setTargetCard(CardFactoryUtil.AI_getBestCreature(humanPlay)); + return ((AllZone.Computer_Hand.size() > 2)&&(getTargetCard() != null)) ; + } + public void resolve() + { + final Card[] target = new Card[1]; + target[0] = getTargetCard(); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, target[0].getOwner()); + + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0]) ) + { + if (!target[0].isToken()) + AllZone.GameAction.moveTo(hand ,target[0]); + else + AllZone.getZone(target[0]).remove(target[0]); + } + AllZone.GameAction.sacrifice(getSourceCard()); + }//resolve() + };//SpellAbility + ability.setDescription("U, Sacrifice AEther Spellbomb: Return target creature to its owner's hand."); + card.addSpellAbility(ability); + ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability)); + } + //*************** START *********** START ************************** + if(cardName.equals("Lifespark Spellbomb")) + { + final SpellAbility ability = new Ability_Activated(card, "G") + { + private static final long serialVersionUID = -5744842090293912606L; + public boolean canPlay() + { + return AllZone.GameAction.isCardInPlay(card)&&!AllZone.Stack.getSourceCards().contains(card); + } + public boolean canPlayAI() + { + CardList land = new CardList(AllZone.Computer_Play.getCards()); + land = land.getType("Land"); + CardList basic = land.getType("Basic"); + if (basic.size() < 3) return false; + Card[] basic_1 = basic.toArray(); + for(Card var : basic_1) + if (var.isTapped()) basic.remove(var); + basic.shuffle(); + if (basic.size() == 0) + return false; + if (basic.get(0) != null) { + setTargetCard(basic.get(0)); + return true; + } + return false; + }//canPlayAI() + + public void resolve() + { + //in case ability is played twice + final int[] oldAttack = new int[1]; + final int[] oldDefense = new int[1]; + + final Card card[] = new Card[1]; + card[0] = getTargetCard(); + + oldAttack[0] = card[0].getBaseAttack(); + oldDefense[0] = card[0].getBaseDefense(); + + card[0].setBaseAttack(3); + card[0].setBaseDefense(3); + card[0].addType("Creature"); + + //EOT + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 7236360479349324099L; + + public void execute() + { + card[0].setBaseAttack(oldAttack[0]); + card[0].setBaseDefense(oldDefense[0]); + + card[0].removeType("Creature"); + } + }; + + AllZone.EndOfTurn.addUntil(untilEOT); + AllZone.GameAction.sacrifice(getSourceCard()); + }//resolve() + };//SpellAbility + card.addSpellAbility(ability); + ability.setDescription("G, Sacrifice Lifespark Spellbomb: Target land becomes a 3/3 Creature until end of turn. It is still a land."); + ability.setBeforePayMana(CardFactoryUtil.input_targetType(ability, "Land")); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Pyrite Spellbomb")) + { + + final SpellAbility ability = new Ability_Activated(card, "R") + { + private static final long serialVersionUID = 1L; + + public boolean canPlay() + { + return AllZone.GameAction.isCardInPlay(card)&&!AllZone.Stack.getSourceCards().contains(card); + } + public boolean canPlayAI() + { + Random r = new Random(); + if (r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed())) + return true; + else + return false; + } + + public void chooseTargetAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(2, card, true); + list.shuffle(); + + if(list.isEmpty() || AllZone.Human_Life.getLife() < 5 + 2) + setTargetPlayer(Constant.Player.Human); + else + setTargetCard(list.get(0)); + }//chooseTargetAI + public void resolve() + { + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + getTargetCard().addDamage(2); + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(2); + AllZone.GameAction.sacrifice(getSourceCard()); + }//resolve() + };//Ability_Activated + + ability.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(ability, true)); + ability.setDescription("R, Sacrifice Pyrite Spellbomb: Pyrite Spellbomb deals 2 damage to target creature or player."); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Sunbeam Spellbomb")) + { + final Ability ability = new Ability(card, "W") + { + public boolean canPlay() + { + return AllZone.GameAction.isCardInPlay(card)&&!AllZone.Stack.getSourceCards().contains(card); + } + public boolean canPlayAI() + { + return (AllZone.GameAction.getPlayerLife(Constant.Player.Computer).getLife() < 7); + } + public void resolve() + { + AllZone.GameAction.getPlayerLife(card.getController()).addLife(5); + AllZone.GameAction.sacrifice(getSourceCard()); + }//resolve() + };//SpellAbility + ability.setStackDescription("You gain 5 life"); + ability.setDescription("W, Sacrifice Sunbeam Spellbomb: You gain 5 life."); + card.addSpellAbility(ability); + } //*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Necrogen Spellbomb")) + { + final Ability ability = new Ability(card, "B") + { + public boolean canPlay() + { + return AllZone.GameAction.isCardInPlay(card)&&!AllZone.Stack.getSourceCards().contains(card); + } + public boolean canPlayAI() + { + setTargetPlayer(Constant.Player.Human); + return (MyRandom.random.nextBoolean()&&AllZone.Human_Hand.size()>0); + } + public void resolve() + { + String s = getTargetPlayer(); + setStackDescription("Necrogen Spellbomb - " +s +" discards a card"); + if(Constant.Player.Computer.equals(getTargetPlayer())) + AllZone.GameAction.discardRandom(getTargetPlayer()); + else + AllZone.InputControl.setInput(CardFactoryUtil.input_discard()); + AllZone.GameAction.sacrifice(getSourceCard()); + }//resolve() + };//SpellAbility + ability.setDescription("B, Sacrifice Necrogen Spellbomb: Target player discards a card"); + ability.setBeforePayMana(CardFactoryUtil.input_targetPlayer(ability)); + card.addSpellAbility(ability); + } //*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Sensei's Divining Top")) + { + //ability2: Draw card, and put divining top on top of library + final SpellAbility ability2 = new Ability_Tap(card, "0") + { + private static final long serialVersionUID = -2523015092351744208L; + + public void resolve() + { + String player = card.getController(); + String owner = card.getOwner(); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, owner); + + AllZone.GameAction.drawCard(player); + play.remove(card); + lib.add(card,0); //move divining top to top of library + card.untap(); + + } + + public boolean canPlayAI() + { + return false; + } + + public boolean canPlay() + { + if (AllZone.getZone(card).is(Constant.Zone.Play)) + return true; + else + return false; + }//canPlay() + };//SpellAbility ability2 + + ability2.setBeforePayMana(new Input() + { + private static final long serialVersionUID = -4773496833654414458L; + @SuppressWarnings("unused") // check + int check = -1; + public void showMessage() + { + AllZone.Stack.push(ability2); + stop(); + }//showMessage() + }); + + + + //ability (rearrange top 3 cards) : + final SpellAbility ability1 = new Ability(card, "1") + { + public void resolve() + { + String player = card.getController(); + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player); + + if (lib.size() < 3) + return; + + CardList topThree = new CardList(); + + //show top 3 cards: + topThree.add(lib.get(0)); + topThree.add(lib.get(1)); + topThree.add(lib.get(2)); + + for (int i=1;i<=3;i++){ + String Title = "Put on top: "; + if (i==2) + Title = "Put second from top: "; + if (i==3) + Title = "Put third from top: "; + Object o = AllZone.Display.getChoiceOptional(Title, topThree.toArray()); + if(o == null) + break; + Card c_1 = (Card)o; + topThree.remove(c_1); + lib.remove(c_1); + lib.add(c_1,i-1); + } + + } + public boolean canPlayAI() + { + return false; + + } + public boolean canPlay() + { + if (AllZone.getZone(card).is(Constant.Zone.Play)) + return true; + else + return false; + }//canPlay() + };//SpellAbility ability1 + + + ability1.setDescription("1: Look at the top three cards of your library, then put them back in any order."); + ability1.setStackDescription("Sensei's Divining Top - rearrange top 3 cards"); + card.addSpellAbility(ability1); + ability1.setBeforePayMana(new Input_PayManaCost(ability1)); + + ability2.setDescription("tap: Draw a card, then put Sensei's Divining Top on top of its owner's library."); + ability2.setStackDescription("Sensei's Divining Top - draw a card, then put back on owner's library"); + ability2.setBeforePayMana(new Input_NoCost_TapAbility((Ability_Tap) ability2)); + card.addSpellAbility(ability2); + + } + //*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Sphinx of Jwar Isle")) + { + final SpellAbility ability1 = new Ability(card, "0") + { + public void resolve() + { + String player = card.getController(); + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player); + + if (lib.size() < 1) + return; + + CardList cl = new CardList(); + cl.add(lib.get(0)); + + AllZone.Display.getChoiceOptional("Top card", cl.toArray()); + } + public boolean canPlayAI() + { + return false; + } + }; + + ability1.setStackDescription(card.getName() + " - look at top card of library."); + ability1.setDescription("You may look at the top card of your library."); + card.addSpellAbility(ability1); + } + //*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Imperial Recruiter")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + + if(AllZone.GameAction.isCardInZone(getTargetCard(), lib)) + { + Card c = getTargetCard(); + AllZone.GameAction.shuffle(card.getController()); + lib.remove(c); + hand.add(c, 0); + + } + }//resolve() + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = -8887306085997352723L; + + public void execute() + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card.getController()); + CardList cards = new CardList(lib.getCards()); + CardList powerTwoCreatures = new CardList(); + + for (int i=0;i 0) + { + if (card.getController().equals("Human")) + { + Object o = AllZone.Display.getChoiceOptional("Select a card in opponent's graveyard to remove", gravecards.toArray()); + if (o!=null) + { + Card removedCard = (Card)o; + AllZone.GameAction.removeFromGame(removedCard); + } + } + else + { + AllZone.GameAction.removeFromGame(gravecards.get(0)); + } + } + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + + CardList creatures = new CardList(play.getCards()); + creatures = creatures.getType("Creature"); + + //Object o = AllZone.Display.getChoiceOptional("Select a creature card to bounce", blackBlue.toArray()); + + + AllZone.InputControl.setInput(CardFactoryUtil.input_targetSpecific(ability, creatures, "Select a creature you control.", false)); + ButtonUtil.disableAll(); + + }//execute() + };//Command + card.addComesIntoPlayCommand(intoPlay); + + card.clearSpellAbility(); + + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = 3089921616375272120L; + + public boolean canPlayAI() + { + return false; + } + }); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Cavern Harpy")) + { + final SpellAbility a1 = new Ability(card,"0") + { + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.subtractLife(1); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getOwner()); + + if (card.isToken()) + AllZone.getZone(card).remove(card); + else + AllZone.GameAction.moveTo(hand, card); + + + } + public boolean canPlayAI() + { + return false; + } + }; + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + Card c = getTargetCard(); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, c.getOwner()); + + if(AllZone.GameAction.isCardInPlay(c)) + { + AllZone.getZone(c).remove(c); + + if(! c.isToken()) + { + Card newCard = AllZone.CardFactory.getCard(c.getName(), c.getOwner()); + hand.add(newCard); + } + } + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = -7855081477395863590L; + + public void execute() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + + CardList creatures = new CardList(play.getCards()); + creatures = creatures.getType("Creature"); + + CardList blackBlue = new CardList(); + + + for(int i=0;i 0 && life >= 4) + return true; + else + return false; + } + + public void resolve() + { + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void computerResolve() + { + //TODO: somehow select a good non-creature card for AI + CardList creature = new CardList(AllZone.Computer_Library.getCards()); + creature = creature.getType("Creature"); + if(creature.size() != 0) + { + Card c = CardFactoryUtil.AI_getBestCreature(creature); + + if(c == null) + { + creature.shuffle(); + c = creature.get(0); + } + + AllZone.GameAction.shuffle(card.getController()); + + //move to top of library + AllZone.Computer_Library.remove(c); + AllZone.Computer_Library.add(c, 0); + + //lose 2 life + String player = Constant.Player.Computer; + PlayerLife life = AllZone.GameAction.getPlayerLife(player); + life.subtractLife(2); + } + }//computerResolve() + public void humanResolve() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + + CardList list = new CardList(library.getCards()); + + if(list.size() != 0) + { + Object o = AllZone.Display.getChoiceOptional("Select a card", list.toArray()); + + AllZone.GameAction.shuffle(card.getController()); + if(o != null) + { + //put card on top of library + library.remove(o); + library.add((Card)o, 0); + } + //lose 2 life + String player = Constant.Player.Human; + PlayerLife life = AllZone.GameAction.getPlayerLife(player); + life.subtractLife(2); + }//if + + + }//resolve() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Nemata, Grove Guardian")) + { + final SpellAbility a1 = new Ability(card, "2 G") + { + public boolean canPlayAI() + { + return MyRandom.random.nextBoolean(); + } + public boolean canPlay() + { + SpellAbility sa; + //this is a hack, check the stack to see if this card has an ability on the stack + //if so, we can't use the ability + for (int i=0; i 0) + return true; + else + return false; + } + }); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Aven Cloudchaser") || cardName.equals("Cloudchaser Eagle") || cardName.equals("Monk Realist")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + { + if(c.isToken()) + AllZone.getZone(c).remove(c); + + else + AllZone.GameAction.destroy(c); + } + } + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = 8586704292133752803L; + + public void execute() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + all = all.getType("Enchantment"); + + + if (all.size() != 0) { + + if(card.getController().equals(Constant.Player.Human)) { + AllZone.InputControl.setInput(CardFactoryUtil.input_targetSpecific(ability, all, "Select target enchantment.", true)); + ButtonUtil.disableAll(); + } + else if (card.getController().equals(Constant.Player.Computer)) { + Card human = CardFactoryUtil.AI_getBestEnchantment(all, card, true); + ability.setTargetCard(human); + AllZone.Stack.add(ability); + } + } + + }//execute() + };//Command + card.addComesIntoPlayCommand(intoPlay); + + card.clearSpellAbility(); + + card.addSpellAbility(new Spell_Permanent(card) + { + private static final long serialVersionUID = -8467111038318551304L; + + public boolean canPlayAI() + { + CardList ench = new CardList(); + ench.addAll(AllZone.Human_Play.getCards()); + ench = ench.getType("Enchantment"); + + if (ench.size() > 0) + return true; + else + return false; + } + }); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Intuition")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 8282597086298330698L; + + public void resolve() + { + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void humanResolve() + { + CardList libraryList = new CardList(AllZone.Human_Library.getCards()); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + CardList selectedCards = new CardList(); + + Object o = AllZone.Display.getChoiceOptional("Select first card", libraryList.toArray()); + if(o != null) + { + Card c1 = (Card)o; + libraryList.remove(c1); + selectedCards.add(c1); + } + else { + return; + } + o = AllZone.Display.getChoiceOptional("Select second card", libraryList.toArray()); + if(o != null) + { + Card c2 = (Card)o; + libraryList.remove(c2); + selectedCards.add(c2); + } + else { + return; + } + o = AllZone.Display.getChoiceOptional("Select third card", libraryList.toArray()); + if(o != null) + { + Card c3 = (Card)o; + libraryList.remove(c3); + selectedCards.add(c3); + } + else { + return; + } + + Card choice = selectedCards.get(MyRandom.random.nextInt(2)); //comp randomly selects one of the three cards + + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController()); + library.remove(choice); + hand.add(choice); + + selectedCards.remove(choice); + Card toGrave1 = selectedCards.get(0); + Card toGrave2 = selectedCards.get(1); + library.remove(toGrave1); + library.remove(toGrave2); + selectedCards.remove(toGrave2); + selectedCards.remove(toGrave2); + + grave.add(toGrave1); + grave.add(toGrave2); + + AllZone.GameAction.shuffle(Constant.Player.Human); + } + public void computerResolve() + { + Card[] library = AllZone.Computer_Library.getCards(); + CardList list = new CardList(library); + CardList selectedCards = new CardList(); + + //pick best creature + Card c = CardFactoryUtil.AI_getBestCreature(list); + if(c == null) { + c = library[0]; + } + list.remove(c); + selectedCards.add(c); + + c = CardFactoryUtil.AI_getBestCreature(list); + if(c == null) { + c = library[0]; + } + list.remove(c); + selectedCards.add(c); + + c = CardFactoryUtil.AI_getBestCreature(list); + if(c == null) { + c = library[0]; + } + list.remove(c); + selectedCards.add(c); + + Object o = AllZone.Display.getChoiceOptional("Select card to give to computer", selectedCards.toArray()); + + Card choice = (Card)o; + + selectedCards.remove(choice); + AllZone.Computer_Library.remove(choice); + AllZone.Computer_Hand.add(choice); + + AllZone.Computer_Library.remove(selectedCards.get(0)); + AllZone.Computer_Library.remove(selectedCards.get(1)); + + AllZone.Computer_Graveyard.add(selectedCards.get(0)); + AllZone.Computer_Graveyard.add(selectedCards.get(1)); + + } + public boolean canPlay() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + return library.getCards().length >= 3; + } + public boolean canPlayAI() + { + CardList creature = new CardList(); + creature.addAll(AllZone.Computer_Library.getCards()); + creature = creature.getType("Creature"); + return creature.size() != 0; + } + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Rakka Mar")) + { + final SpellAbility a1 = new Ability_Tap(card, "R") + { + private static final long serialVersionUID = -3868544882464692305L; + + public boolean canPlayAI() + { + return true; + + } + public void resolve() + { + makeToken(); + } + void makeToken() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Elemental"); + c.setImageName("R 3 1 Elemental"); + c.setManaCost("R"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Elemental"); + c.setBaseAttack(3); + c.setBaseDefense(1); + c.addIntrinsicKeyword("Haste"); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//makeToken() + };//SpellAbility + card.addSpellAbility(a1); + a1.setDescription("R, T: Put a 3/1 red Elemental creature token with haste into play."); + a1.setStackDescription("Put a 3/1 red Elemental creature token with haste into play."); + + a1.setBeforePayMana(new Input_PayManaCost(a1)); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Tolsimir Wolfblood")) + { + final SpellAbility a1 = new Ability_Tap(card) + { + private static final long serialVersionUID = -1900858280382389010L; + + public boolean canPlayAI() + { + String controller = card.getController(); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, controller); + CardList voja = new CardList(play.getCards()); + voja = voja.getName("Voja"); + + if (voja.size() == 0) + return true; + else + return false; + + } + public void resolve() + { + makeToken(); + } + void makeToken() + { + Card c = new Card(); + + c.setName("Voja"); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("W G"); + c.setToken(true); + + c.addType("Legendary"); + c.addType("Creature"); + c.addType("Wolf"); + c.setBaseAttack(2); + c.setBaseDefense(2); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//makeToken() + };//SpellAbility + card.addSpellAbility(a1); + a1.setDescription("T: Put a legendary 2/2 green and white Wolf creature token named Voja into play."); + a1.setStackDescription("Put a 2/2 white green Legendary Wolf creature token named Voja into play."); + + a1.setBeforePayMana(new Input_PayManaCost(a1)); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Invincible Hymn")) + { + final String player = card.getController(); + + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -827136493013927725L; + + public void resolve() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + CardList libCards = new CardList(library.getCards()); + int lifeGain = libCards.size(); + + System.out.println("lifeGain: " + lifeGain); + + PlayerLife life = AllZone.GameAction.getPlayerLife(player); + life.setLife(lifeGain); + + System.out.println("life.getLife(): " + life.getLife()); + } + public boolean canPlayAI() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + CardList libCards = new CardList(library.getCards()); + int lifeGain = libCards.size(); + + PlayerLife compLife = AllZone.GameAction.getPlayerLife(Constant.Player.Computer); + if (lifeGain > compLife.getLife()) + return true; + else + return false; + } + };//spell + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if (cardName.equals("Ranger of Eos")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + + + CardList cards = new CardList(lib.getCards()); + CardList oneCostCreatures = new CardList(); + + for (int i=0;i= 1) + { + Card c1 = oneCostCreatures.getCard(0); + lib.remove(c1); + hand.add(c1); + oneCostCreatures.remove(c1); + + if (oneCostCreatures.size() >= 1) + { + Card c2 = oneCostCreatures.getCard(0); + lib.remove(c2); + hand.add(c2); + oneCostCreatures.remove(c2); + + } + + + } + //ability.setTargetCard(powerTwoCreatures.get(0)); + //AllZone.Stack.add(ability); + AllZone.GameAction.shuffle(controller); + } + + + //... + + }//resolve() + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = -5697680711324878027L; + + public void execute() + { + ability.setStackDescription("Ranger of Eos - Grab 2 creatures"); + AllZone.Stack.add(ability); + }//execute() + };//Command + //ability.setStackDescription("Ranger of Eos - Grab 2 creatures"); + //AllZone.Stack.add(ability); + card.addComesIntoPlayCommand(intoPlay); + + + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Scarblade Elite")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 3505019464802566898L; + + public boolean canPlay() + { + String controller = card.getController(); + PlayerZone graveyard = AllZone.getZone(Constant.Zone.Graveyard ,controller); + + CardList sins = new CardList(graveyard.getCards()); + sins = sins.getType("Assassin"); + + if (sins.size() > 0 && AllZone.GameAction.isCardInPlay(card) && CardFactoryUtil.canTarget(card, getTargetCard()) ) + return true; + else + return false; + + } + public boolean canPlayAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + human = human.filter(new CardListFilter() + { + public boolean addCard(Card c) {return AllZone.GameAction.isCardInPlay(c);} + }); + + CardListUtil.sortAttack(human); + CardListUtil.sortFlying(human); + + //if(0 < human.size()) + // setTargetCard(human.get(0)); + + PlayerZone graveyard = AllZone.getZone(Constant.Zone.Graveyard, Constant.Player.Computer); + + CardList grave = new CardList(graveyard.getCards()); + grave = grave.getType("Assassin"); + + if (human.size() > 0 && grave.size() > 0) + setTargetCard(human.get(0)); + + return 0 < human.size() && 0 < grave.size(); + } + + public void resolve() + { + String controller = card.getController(); + PlayerZone graveyard = AllZone.getZone(Constant.Zone.Graveyard ,controller); + + CardList sins = new CardList(graveyard.getCards()); + sins = sins.getType("Assassin"); + + if (card.getController().equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Pick an Assassin to remove", sins.toArray()); + + if(o != null) + { + Card crd = (Card)o; + graveyard.remove(crd); + + + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) ) + { + AllZone.GameAction.destroy(c); + } + } //if o!= null + }//player.equals("human") + else + { + Card crd = sins.get(0); + graveyard.remove(crd); + + Card c = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) ) + { + AllZone.GameAction.destroy(c); + } + } + }//resolve() + };//SpellAbility + + Input target = new Input() + { + private static final long serialVersionUID = -4853162388286494888L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target creature to destroy"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + if(!CardFactoryUtil.canTarget(ability, card)){ + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + if(c.isCreature() && zone.is(Constant.Zone.Play)) + { + //tap ability + card.tap(); + + ability.setTargetCard(c); + AllZone.Stack.add(ability); + stop(); + } + }//selectCard() + };//Input + + card.addSpellAbility(ability); + ability.setDescription("tap: Remove an Assassin card in your graveyard from the game: Destroy target creature."); + ability.setBeforePayMana(target); + + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Broodmate Dragon")) + { + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Dragon"); + c.setImageName("R 4 4 Dragon"); + c.setManaCost("R"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Dragon"); + + c.addIntrinsicKeyword("Flying"); + + c.setBaseAttack(4); + c.setBaseDefense(4); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + + }//resolve() + }; + Command intoPlay = new Command() + { + private static final long serialVersionUID = 2848700532090223394L; + + public void execute() + { + ability.setStackDescription("Broodmate Dragon - put a 4/4 red Dragon creature token into play."); + AllZone.Stack.add(ability); + } + }; + card.addComesIntoPlayCommand(intoPlay); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Gift of Estates")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4997834790204261916L; + + public boolean canPlay() + { + String oppPlayer = AllZone.GameAction.getOpponent(card.getController()); + + PlayerZone selfZone = AllZone.getZone(Constant.Zone.Play, card.getController()); + PlayerZone oppZone = AllZone.getZone(Constant.Zone.Play, oppPlayer); + + CardList self = new CardList(selfZone.getCards()); + CardList opp = new CardList(oppZone.getCards()); + + self = self.getType("Land"); + opp = opp.getType("Land"); + + return (self.size() < opp.size()) && super.canPlay(); + }//canPlay() + + public void resolve() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + + CardList plains = new CardList(library.getCards()); + plains = plains.getType("Plains"); + + for(int i = 0; i < 3 && i < plains.size(); i++) + AllZone.GameAction.moveTo(hand, plains.get(i)); + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + else if(cardName.equals("Tithe")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 1504792204526793942L; + + public boolean oppMoreLand() + { + String oppPlayer = AllZone.GameAction.getOpponent(card.getController()); + + PlayerZone selfZone = AllZone.getZone(Constant.Zone.Play, card.getController()); + PlayerZone oppZone = AllZone.getZone(Constant.Zone.Play, oppPlayer); + + CardList self = new CardList(selfZone.getCards()); + CardList opp = new CardList(oppZone.getCards()); + + self = self.getType("Land"); + opp = opp.getType("Land"); + + return (self.size() < opp.size()) && super.canPlay(); + }//oppoMoreLand() + + public void resolve() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController()); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + + CardList plains = new CardList(library.getCards()); + plains = plains.getType("Plains"); + + if(0 < plains.size()) + AllZone.GameAction.moveTo(hand, plains.get(0)); + + if(oppMoreLand() && 1 < plains.size()) + AllZone.GameAction.moveTo(hand, plains.get(1)); + + }//resolve() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Survival of the Fittest")) + { + SpellAbility ability = new Ability(card, "G") + { + public void resolve() + { + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + }//resolve() + public void humanResolve() + { + CardList handCreatures = new CardList(AllZone.Human_Hand.getCards()); + handCreatures = handCreatures.getType("Creature"); + + if (handCreatures.size() == 0) + return; + + Object discard = AllZone.Display.getChoiceOptional("Select Creature to discard", handCreatures.toArray()); + if (discard != null){ + + CardList creatures = new CardList(AllZone.Human_Library.getCards()); + creatures = creatures.getType("Creature"); + + if (creatures.size() != 0) { + Object check = AllZone.Display.getChoiceOptional("Select Creature", creatures.toArray()); + if(check != null) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + AllZone.GameAction.moveTo(hand, (Card)check); + } + AllZone.GameAction.shuffle(Constant.Player.Human); + } + AllZone.GameAction.discard((Card)discard); + } + } + public void computerResolve() + { + //TODO + } + + + };//SpellAbility + + //card.clearSpellAbility(); + ability.setDescription("G: Discard a creature card: Search your library for a creature card, reveal that card, and put it into your hand. Then shuffle your library."); + //ability.setBeforePayMana(new Input_NoCost_TapAbility((Ability) ability)); + //ability.setBeforePayMana(new Input_PayManaCost(ability)); + ability.setStackDescription("Survival of the Fittest - search for a creature card and put into hand"); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Gerrard's Command")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 3128602006949603902L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public void chooseTargetAI() + { + setTargetCard(getAttacker()); + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + Card[] att = c.getAttackers(); + if(att.length != 0) + return att[0]; + else + return null; + }//getAttacker() + public void resolve() + { + final Card[] target = new Card[1]; + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -650846106294962607L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-3); + target[0].addTempDefenseBoost(-3); + } + } + }; + + target[0] = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0])) + { + target[0].addTempAttackBoost(3); + target[0].addTempDefenseBoost(3); + target[0].untap(); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + }; + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + +//*************** START *********** START ************************** + if(cardName.equals("Brute Force")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 4733538427752827505L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public void chooseTargetAI() + { + setTargetCard(getAttacker()); + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + //Card[] att = c.getAttackers(); + + CardList list = new CardList(); + list.addAll(c.getAttackers()); + list = list.filter(new CardListFilter() + { + + public boolean addCard(Card c) { + return CardFactoryUtil.canTarget(card, c); + } + + }); + + if(list.size() != 0) + return list.get(0); + else + return null; + }//getAttacker() + public void resolve() + { + final Card[] target = new Card[1]; + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 8299648917436556370L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-3); + target[0].addTempDefenseBoost(-3); + } + } + }; + + target[0] = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0]) ) + { + target[0].addTempAttackBoost(3); + target[0].addTempDefenseBoost(3); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + }; + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Nameless Inversion")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 5479536291205544905L; + + public boolean canPlayAI() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(3, card, true); + CardListUtil.sortFlying(list); + + for(int i = 0; i < list.size(); i++) + if(2 <= list.get(i).getNetAttack()) + { + setTargetCard(list.get(i)); + return true; + } + return false; + }//canPlayAI() + + public void resolve() + { + final Card[] target = new Card[1]; + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -1954104042512587145L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-3); + target[0].addTempDefenseBoost(3); + } + } + }; + + target[0] = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0])) + { + target[0].addTempAttackBoost(3); + target[0].addTempDefenseBoost(-3); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + }; + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Tromp the Domains")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 1523193367625798058L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + Card[] att = c.getAttackers(); + if(att.length != 0) + return att[0]; + else + return null; + }//getAttacker() + + int countLandTypes() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList land = new CardList(play.getCards()); + + String basic[] = {"Forest", "Plains", "Mountain", "Island", "Swamp"}; + int count = 0; + + for(int i = 0; i < basic.length; i++) + { + CardList c = land.getType(basic[i]); + if(! c.isEmpty()) + count++; + } + + return count; + }//countLandTypes() + public void resolve() + { + + final int boost = countLandTypes(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList list = new CardList(play.getCards()); + @SuppressWarnings("unused") // c + Card c; + + for(int i = 0; i < list.size(); i++) + { + final Card[] target = new Card[1]; + target[0] = list.get(i); + + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -4207130279969069542L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-boost); + target[0].addTempDefenseBoost(-boost); + + target[0].removeExtrinsicKeyword("Trample"); + } + } + };//Command + + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(boost); + target[0].addTempDefenseBoost(boost); + + target[0].addExtrinsicKeyword("Trample"); + + AllZone.EndOfTurn.addUntil(untilEOT); + }//if + }//for + }//resolve() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Titanic Ultimatum")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 4920407567000133514L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + Card[] att = c.getAttackers(); + if(att.length != 0) + return att[0]; + else + return null; + }//getAttacker() + + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList list = new CardList(play.getCards()); + @SuppressWarnings("unused") // c + Card c; + + for(int i = 0; i < list.size(); i++) + { + final Card[] target = new Card[1]; + target[0] = list.get(i); + + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -3807842003906681893L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-5); + target[0].addTempDefenseBoost(-5); + + target[0].removeExtrinsicKeyword("Trample"); + target[0].removeExtrinsicKeyword("First Strike"); + target[0].removeExtrinsicKeyword("Lifelink"); + } + } + };//Command + + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(5); + target[0].addTempDefenseBoost(5); + + target[0].addExtrinsicKeyword("Trample"); + target[0].addExtrinsicKeyword("First Strike"); + target[0].addExtrinsicKeyword("Lifelink"); + + AllZone.EndOfTurn.addUntil(untilEOT); + }//if + }//for + }//resolve() + }; + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Primal Boost")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 2449600319884238808L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public void chooseTargetAI() + { + setTargetCard(getAttacker()); + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + + CardList list = new CardList(c.getAttackers()); + CardListUtil.sortFlying(list); + + Card[] att = list.toArray(); + if(att.length != 0) + return att[0]; + else + return null; + }//getAttacker() + public void resolve() + { + final Card[] target = new Card[1]; + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 3753684523153747308L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-4); + target[0].addTempDefenseBoost(-4); + } + } + }; + + target[0] = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0])) + { + target[0].addTempAttackBoost(4); + target[0].addTempDefenseBoost(4); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + }; + spell.setDescription("Target creature gets +4/+4 until end of turn."); + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + card.addSpellAbility(CardFactoryUtil.ability_cycle(card, "2 G")); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Wildsize")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4558777579924787035L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public void chooseTargetAI() + { + setTargetCard(getAttacker()); + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + + CardList list = new CardList(c.getAttackers()); + CardListUtil.sortFlying(list); + + Card[] att = list.toArray(); + if(att.length != 0) + return att[0]; + else + return null; + }//getAttacker() + + public void resolve() + { + final Card[] target = new Card[1]; + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -8390763209393328399L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-2); + target[0].addTempDefenseBoost(-2); + + target[0].removeExtrinsicKeyword("Trample"); + } + } + }; + + target[0] = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0])) + { + target[0].addTempAttackBoost(2); + target[0].addTempDefenseBoost(2); + target[0].addExtrinsicKeyword("Trample"); + + AllZone.EndOfTurn.addUntil(untilEOT); + AllZone.GameAction.drawCard(card.getController()); + } + }//resolve() + }; + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Feral Lightning")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -1841642966580694848L; + + public boolean canPlayAI() + { + return AllZone.Phase.getPhase().equals(Constant.Phase.Main1); + } + + + public void resolve() + { + final Card[] token = new Card[3]; + final Command atEOT = new Command() + { + private static final long serialVersionUID = -1928884889370422828L; + + public void execute() + { + //destroy tokens at end of turn + for(int i = 0; i < token.length; i++) + if(AllZone.GameAction.isCardInPlay(token[i])) + AllZone.GameAction.destroy(token[i]); + } + }; + AllZone.EndOfTurn.addAt(atEOT); + + for(int i = 0; i < token.length; i++) + token[i] = makeToken(); + }//resolve() + Card makeToken() + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Elemental"); + c.setImageName("R 3 1 Elemental"); + c.setManaCost("R"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Elemental"); + c.setBaseAttack(3); + c.setBaseDefense(1); + c.addIntrinsicKeyword("Haste"); + c.setSacrificeAtEOT(true); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + + return c; + }//makeToken() + };//SpellAbility + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Inspirit")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -601100008975177639L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public void chooseTargetAI() + { + setTargetCard(getAttacker()); + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + Card[] att = c.getAttackers(); + if(att.length != 0) + return att[0]; + else + return null; + }//getAttacker() + public void resolve() + { + final Card[] target = new Card[1]; + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -3197321199337917886L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-2); + target[0].addTempDefenseBoost(-4); + } + } + }; + + target[0] = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0])) + { + target[0].addTempAttackBoost(2); + target[0].addTempDefenseBoost(4); + + target[0].untap(); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + }; + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + //*************** START *********** START ************************** + if(cardName.equals("Might of Oaks")) + { + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -33985340162641452L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public void chooseTargetAI() + { + setTargetCard(getAttacker()); + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + Card[] att = c.getAttackers(); + if(att.length != 0) + return att[0]; + else + return null; + }//getAttacker() + public void resolve() + { + final Card[] target = new Card[1]; + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -5138969487216215323L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-7); + target[0].addTempDefenseBoost(-7); + } + } + }; + + target[0] = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + target[0].addTempAttackBoost(7); + target[0].addTempDefenseBoost(7); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + }; + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Guided Strike")) + { + final Card[] target = new Card[1]; + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 6381010042083054770L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0])) + { + target[0].addTempAttackBoost(-1); + target[0].removeExtrinsicKeyword("First Strike"); + } + } + }; + + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 6373328936243472966L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public void chooseTargetAI() + { + setTargetCard(getAttacker()); + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + Card[] att = c.getAttackers(); + if(att.length != 0) + return att[0]; + else + return null; + }//getAttacker() + public void resolve() + { + target[0] = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(1); + target[0].addExtrinsicKeyword("First Strike"); + + AllZone.EndOfTurn.addUntil(untilEOT); + AllZone.GameAction.drawCard(card.getController()); + } + }//resolve() + }; + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Aggressive Urge")) + { + final Card[] target = new Card[1]; + final Command untilEOT = new Command() + { + private static final long serialVersionUID = 5519847437187468154L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].addTempAttackBoost(-1); + target[0].addTempDefenseBoost(-1); + } + } + }; + + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -1043326570050661433L; + + public boolean canPlayAI() + { + return getAttacker() != null; + } + public void chooseTargetAI() + { + setTargetCard(getAttacker()); + } + public Card getAttacker() + { + //target creature that is going to attack + Combat c = ComputerUtil.getAttackers(); + Card[] att = c.getAttackers(); + if(att.length != 0) + return att[0]; + else + return null; + }//getAttacker() + public void resolve() + { + target[0] = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0])) + { + target[0].addTempAttackBoost(1); + target[0].addTempDefenseBoost(1); + + AllZone.EndOfTurn.addUntil(untilEOT); + AllZone.GameAction.drawCard(card.getController()); + } + }//resolve() + }; + spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell)); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Vindicate")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -2302610807061478203L; + + public boolean canPlayAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + return 4 < AllZone.Phase.getTurn() && 0 < human.size(); + } + public void chooseTargetAI() + { + CardList human = CardFactoryUtil.AI_getHumanCreature(card, true); + setTargetCard(CardFactoryUtil.AI_getBestCreature(human)); + } + + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + if(getTargetCard().isToken()) + AllZone.getZone(getTargetCard()).remove(getTargetCard()); + else + { + AllZone.GameAction.destroy(getTargetCard()); + } + }//if + }//resolve() + };//SpellAbility + Input target = new Input() + { + private static final long serialVersionUID = -7826307781920832218L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target permanent for " +spell.getSourceCard()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + } + };//Input + + spell.setBeforePayMana(target); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Shatter")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -8518902112426882210L; + + public boolean canPlayAI() + { + return (getArtifact().size() != 0) && (AllZone.Phase.getTurn() > 4); + } + public void chooseTargetAI() + { + if(getArtifact().size() != 0){ + Card bestArtifact = CardFactoryUtil.AI_getBestArtifact(getArtifact()); + setTargetCard(bestArtifact); + } + }//getEnchantment() + CardList getArtifact() + { + CardList list = CardFactoryUtil.AI_getHumanArtifact(card, true); + return list; + }//getArtifact() + public void resolve() + { + AllZone.GameAction.destroy(getTargetCard()); + }//resolve() + }; + + Input runtime = new Input() + { + private static final long serialVersionUID = 7950082427462078698L; + + public void showMessage() + { + //Display all artifacts in play + //Allow human player to select which one to destroy + CardList allCards = new CardList(); + allCards.addAll(AllZone.Human_Play.getCards()); + allCards.addAll(AllZone.Computer_Play.getCards()); + + //get artifacts + CardList allArtifacts = allCards.getType("Artifact"); + stopSetNext(CardFactoryUtil.input_targetSpecific(spell, allArtifacts, "Select target Artifact to destroy.",true)); + + } + }; + + card.clearSpellAbility(); + spell.setBeforePayMana(runtime); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + else if(cardName.equals("Disenchant") || cardName.equals("Naturalize")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 6231507037766815249L; + + public boolean canPlayAI() + { + return (getEnchantment().size() != 0 || getArtifact().size() != 0) && (AllZone.Phase.getTurn() > 4); + } + public void chooseTargetAI() + { + if(getEnchantment().size() != 0) + { + Card bestEnchantment = CardFactoryUtil.AI_getBestEnchantment(getEnchantment(), card, true); + if(getArtifact().size() != 0){ + Card bestArtifact = CardFactoryUtil.AI_getBestArtifact(getArtifact()); + if(CardUtil.getConvertedManaCost(bestArtifact.getManaCost()) > CardUtil.getConvertedManaCost(bestEnchantment.getManaCost())){ + setTargetCard(bestArtifact); + } + else{ + setTargetCard(bestEnchantment); + } + } + else{ + setTargetCard(bestEnchantment); + } + } + else if(getArtifact().size() != 0){ + Card bestArtifact = CardFactoryUtil.AI_getBestArtifact(getArtifact()); + setTargetCard(bestArtifact); + } + + } + CardList getEnchantment() + { + CardList list = CardFactoryUtil.AI_getHumanEnchantment(card, true); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return !c.getKeyword().contains("Indestructible"); + } + }); + return list; + }//getEnchantment() + CardList getArtifact() + { + CardList list = CardFactoryUtil.AI_getHumanArtifact(card, true); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return !c.getKeyword().contains("Indestructible"); + } + }); + return list; + }//getArtifact() + public void resolve() + { + //AllZone.GameAction.destroyNoRegeneration(getTargetCard()); + AllZone.GameAction.destroy(getTargetCard()); + + }//resolve() + }; + + Input runtime = new Input() + { + private static final long serialVersionUID = -1212213052029735882L; + + public void showMessage() + { + //Display all artifacts and enchantments in play + //Allow human player to select which one to destroy + CardList allCards = new CardList(); + allCards.addAll(AllZone.Human_Play.getCards()); + allCards.addAll(AllZone.Computer_Play.getCards()); + + //get enchantments and get artifacts + CardList allEnchantments = allCards.getType("Enchantment"); + CardList allArtifacts = allCards.getType("Artifact"); + + //put enchantments and artifacts in same cardList to display + CardList allEnchantmentsAndArtifacts = allEnchantments; + allEnchantmentsAndArtifacts.addAll(allArtifacts.toArray()); + + + stopSetNext(CardFactoryUtil.input_targetSpecific(spell, allEnchantmentsAndArtifacts, "Select target Enchantment or Artifact to destroy.", true)); + } + }; + + card.clearSpellAbility(); + spell.setBeforePayMana(runtime); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Demystify")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = -4045818747862804365L; + + public boolean canPlayAI() + { + return (getEnchantment().size() != 0) && (AllZone.Phase.getTurn() > 4); + } + public void chooseTargetAI() + { + Card best = CardFactoryUtil.AI_getBestEnchantment(getEnchantment(), card, true); + setTargetCard(best); + } + CardList getEnchantment() + { + CardList list = CardFactoryUtil.AI_getHumanEnchantment(card, true); + return list; + }//getCreature() + public void resolve() + { + AllZone.GameAction.destroyNoRegeneration(getTargetCard()); + }//resolve() + }; + + Input runtime = new Input() + { + private static final long serialVersionUID = 746063168471322007L; + + public void showMessage() + { + CardList choice = new CardList(); + choice.addAll(AllZone.Human_Play.getCards()); + choice.addAll(AllZone.Computer_Play.getCards()); + + choice = choice.getType("Enchantment"); + + stopSetNext(CardFactoryUtil.input_targetSpecific(spell, choice, "Select target Enchantment to destroy.",true)); + } + }; + + card.clearSpellAbility(); + spell.setBeforePayMana(runtime); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + + + + + //*************** START *********** START ************************** + if(cardName.equals("Animate Land")) + { + final Card[] target = new Card[1]; + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -3359299797188942353L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(target[0])) + { + target[0].removeType("Creature"); + } + } + }; + + SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 4890851927124377327L; + + public void resolve() + { + target[0] = getTargetCard(); + if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0])) + { + target[0].addType("Creature"); + target[0].setBaseAttack(3); + target[0].setBaseDefense(3); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve() + public boolean canPlayAI() + { + return false; +/* all this doesnt work, computer will not attack with the animated land + +//does the computer have any land in play? +CardList land = new CardList(AllZone.Computer_Play.getCards()); +land = land.getType("Land"); +land = land.filter(new CardListFilter() +{ + public boolean addCard(Card c) + { + //checks for summoning sickness, and is not tapped + return CombatUtil.canAttack(c); + } +}); +return land.size() > 1 && CardFactoryUtil.AI_isMainPhase(); +*/ + } + };//SpellAbility +// spell.setChooseTargetAI(CardFactoryUtil.AI_targetType("Land", AllZone.Computer_Play)); + + spell.setBeforePayMana(CardFactoryUtil.input_targetType(spell, "Land")); + card.clearSpellAbility(); + card.addSpellAbility(spell); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Aven Riftwatcher")) + { + Command gain2Life = new Command() + { + private static final long serialVersionUID = 5588978023269625349L; + + public boolean firstTime = true; + public void execute() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.addLife(2); + + //testAndSet - only needed when comes into play. + if(firstTime){ + card.setCounter(Counters.AGE, 3); //vanishing + } + firstTime = false; + } + }; + + card.addLeavesPlayCommand(gain2Life); + card.addComesIntoPlayCommand(gain2Life); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Calciderm")) + { + Command ageCounters = new Command() + { + private static final long serialVersionUID = 431920157968451817L; + public boolean firstTime = true; + public void execute() + { + + //testAndSet - only needed when comes into play. + if(firstTime){ + card.setCounter(Counters.AGE, 4); + } + firstTime = false; + } + }; + card.addComesIntoPlayCommand(ageCounters); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if(cardName.equals("Blastoderm")) + { + Command fadeCounters = new Command() + { + private static final long serialVersionUID = -580691660706977218L; + public boolean firstTime = true; + public void execute() + { + + //testAndSet - only needed when comes into play. + if(firstTime){ + card.setCounter(Counters.FADE, 3); + } + firstTime = false; + } + }; + + card.addComesIntoPlayCommand(fadeCounters); + + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Godsire")) + { + final SpellAbility a1 = new Ability_Tap(card) + { + private static final long serialVersionUID = -1160527561099142816L; + + public void resolve() + { + makeToken(); + } + void makeToken() + { + Card c = new Card(); + + c.setName("Beast"); + c.setImageName("RGW 8 8 Beast"); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setManaCost("R G W"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Beast"); + c.setBaseAttack(8); + c.setBaseDefense(8); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//makeToken() + + public boolean canPlayAI() + { + return AllZone.Phase.getPhase().equals("Main2"); + } + + };//SpellAbility + card.addSpellAbility(a1); + a1.setDescription("T: Put an 8/8 Beast creature token into play that's red, green, and white."); + a1.setStackDescription("Put an 8/8 Beast creature token into play that's red, green, and white."); + + //a1.setBeforePayMana(new Input_PayManaCost(a1)); + }//*************** END ************ END ************************** + + if (cardName.equals("Ior Ruin Expedition")) + { + final SpellAbility ability = new Ability(card, "0") + { + public boolean canPlay() + { + return card.getCounters(Counters.QUEST) >= 3 && AllZone.GameAction.isCardInPlay(card)&&!AllZone.Stack.getSourceCards().contains(card);//in play and not already activated(Sac cost problems) + } + public boolean canPlayAI() {return (AllZone.Computer_Hand.size() < 6)&&(AllZone.Computer_Library.size()>0);} + + public void resolve() + { + AllZone.GameAction.drawCard(card.getController()); + AllZone.GameAction.drawCard(card.getController()); + AllZone.GameAction.sacrifice(getSourceCard()); + } + }; + ability.setDescription("Remove three quest counters from Ior Ruin Expedition and sacrifice it: Draw two cards."); + ability.setStackDescription(card.getName() +" - Draw two cards."); + + card.addSpellAbility(ability); + } + + //*************** START *********** START ************************** + if(cardName.equals("Wydwen, the Biting Gale")) + { + final SpellAbility a1 = new Ability(card,"U B") + { + public boolean canPlayAI() + { + return false; + } + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); + life.subtractLife(1); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getOwner()); + /* + AllZone.getZone(card).remove(card); + hand.add(card); + */ + if (card.isToken()) + AllZone.getZone(card).remove(card); + else + AllZone.GameAction.moveTo(hand, card); + + + } + };//a1 + + //card.clearSpellAbility(); + card.addSpellAbility(a1); + a1.setStackDescription(card.getController() + " pays 1 life and returns Wydwen back to owner's hand."); + a1.setDescription("U B, Pay 1 life: Return Wydwen, the Biting Gale to its owner's hand."); + + + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Earthcraft")) + { + final SpellAbility a1 = new Ability(card,"0") + { + private static final long serialVersionUID = 6787319311700905218L; + + public boolean canPlayAI() + { + return false; + } + + public boolean canPlay() + { + String controller = card.getController(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, controller); + + CardList creats = new CardList(); + + creats.addAll(play.getCards()); + creats = creats.getType("Creature"); + creats = creats.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.isUntapped(); + } + }); + + if (creats.size() > 0 && AllZone.GameAction.isCardInPlay(card)) + return true; + else + return false; + } + public void resolve() + { + + if (getTargetCard()== null) + return; + + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + //else + // computerResolve(); + } + public void humanResolve() + { + String controller = card.getController(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, controller); + CardList creats = new CardList(); + + creats.addAll(play.getCards()); + creats = creats.getType("Creature"); + creats = creats.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.isUntapped() && !c.equals(card); + } + }); + + if (creats.size() == 1) { + creats.get(0).tap(); + if (AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + getTargetCard().untap(); + + } + else if (creats.size() > 1) { + Object o = AllZone.Display.getChoice("Select creature to tap", creats.toArray()); + + if (o!= null) + { + Card c1 = (Card)o; + c1.tap(); + if (AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + getTargetCard().untap(); + } + } + + + + }//humanResolve + + };//a1 + + //card.clearSpellAbility(); + card.addSpellAbility(a1); + a1.setDescription("Tap an untapped creature you control: untap target basic land."); + + Input runtime = new Input() + { + private static final long serialVersionUID = -2287693175821059029L; + + public void showMessage() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + all = all.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return (c.isBasicLand()) && CardFactoryUtil.canTarget(card, c) && c.isTapped(); + } + }); + + stopSetNext(CardFactoryUtil.input_targetSpecific(a1, all, "Select target basic land", true)); + } + }; + a1.setBeforePayMana(runtime); + + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Tradewind Rider")) + { + final SpellAbility a1 = new Ability_Tap(card,"0") + { + private static final long serialVersionUID = 3438865371487994984L; + + public void chooseTargetAI() + { + if(getCreature().size() != 0) + { + Card bestCreature = CardFactoryUtil.AI_getBestCreature(getCreature()); + if(getEnchantment().size() != 0){ + Card bestEnchantment = CardFactoryUtil.AI_getBestEnchantment(getEnchantment(), card, true); + if(CardUtil.getConvertedManaCost(bestCreature.getManaCost()) > CardUtil.getConvertedManaCost(bestEnchantment.getManaCost())){ + setTargetCard(bestCreature); + } + else{ + setTargetCard(bestEnchantment); + } + } + else{ + setTargetCard(bestCreature); + } + } + else if(getArtifact().size() != 0){ + Card bestArtifact = CardFactoryUtil.AI_getBestArtifact(getArtifact()); + setTargetCard(bestArtifact); + } + + }//ChooseTargetAI() + CardList getCreature() + { + CardList list = CardFactoryUtil.AI_getHumanCreature(card, true); + return list; + }//getEnchantment() + CardList getArtifact() + { + CardList list = CardFactoryUtil.AI_getHumanArtifact(card, true); + return list; + }//getArtifact() + CardList getEnchantment() + { + CardList list = CardFactoryUtil.AI_getHumanEnchantment(card, true); + return list; + } + + + + public boolean canPlayAI() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList cards = new CardList(); + + cards.addAll(play.getCards()); + cards = cards.filter(new CardListFilter(){ + + public boolean addCard(Card c) { + return (c.isArtifact() || c.isEnchantment() || c.isCreature() ) && CardFactoryUtil.canTarget(card, c); + } + + }); + + return cards.size() > 0; + + } + public boolean canPlay() + { + String controller = card.getController(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, controller); + + CardList creats = new CardList(); + + creats.addAll(play.getCards()); + creats = creats.getType("Creature"); + creats = creats.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.isUntapped() && !c.equals(card); + } + }); + + if (creats.size() > 1 && AllZone.GameAction.isCardInPlay(card) && card.isUntapped() && !card.hasSickness()) + return true; + else + return false; + } + public void resolve() + { + + if (getTargetCard()== null) + return; + + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void humanResolve() + { + String controller = card.getController(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, controller); + CardList creats = new CardList(); + + creats.addAll(play.getCards()); + creats = creats.getType("Creature"); + creats = creats.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.isUntapped() && !c.equals(card); + } + }); + + CardList tappedCreats = new CardList(); + + Object o = AllZone.Display.getChoice("Pick first creature to tap", creats.toArray()); + + if (o!= null) + { + Card c1 = (Card)o; + creats.remove(c1); + tappedCreats.add(c1); + } + else + return; + + o = AllZone.Display.getChoice("Pick second creature to tap", creats.toArray()); + if (o!= null) + { + Card c2 = (Card)o; + creats.remove(c2); + tappedCreats.add(c2); + } + else + return; + + for(int i = 0; i CardUtil.getConvertedManaCost(bestEnchantment.getManaCost())){ + setTargetCard(bestArtifact); + } + else{ + setTargetCard(bestEnchantment); + } + } + else{ + setTargetCard(bestEnchantment); + } + } + else if(getArtifact().size() != 0){ + Card bestArtifact = CardFactoryUtil.AI_getBestArtifact(getArtifact()); + setTargetCard(bestArtifact); + } + + } + CardList getEnchantment() + { + CardList list = CardFactoryUtil.AI_getHumanEnchantment(card, true); + return list; + }//getEnchantment() + CardList getArtifact() + { + CardList list = CardFactoryUtil.AI_getHumanArtifact(card, true); + return list; + }//getArtifact() + + + public boolean canPlayAI() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList cards = new CardList(); + + cards.addAll(play.getCards()); + cards = cards.filter(new CardListFilter(){ + + public boolean addCard(Card c) { + return (c.isArtifact() || c.isEnchantment() ) && CardFactoryUtil.canTarget(card, c); + } + + }); + + return cards.size() > 0; + + } + public boolean canPlay() + { + String controller = card.getController(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, controller); + + CardList creats = new CardList(); + + creats.addAll(play.getCards()); + creats = creats.getType("Creature"); + creats = creats.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.isUntapped(); + } + }); + + if (creats.size() > 3 && AllZone.GameAction.isCardInPlay(card)) + return true; + else + return false; + } + public void resolve() + { + + if (getTargetCard()== null) + return; + + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void humanResolve() + { + String controller = card.getController(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, controller); + CardList creats = new CardList(); + + creats.addAll(play.getCards()); + creats = creats.getType("Creature"); + creats = creats.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.isUntapped(); + } + }); + + CardList tappedCreats = new CardList(); + + Object o = AllZone.Display.getChoice("Pick first creature to tap", creats.toArray()); + + if (o!= null) + { + Card c1 = (Card)o; + creats.remove(c1); + tappedCreats.add(c1); + } + else + return; + + o = AllZone.Display.getChoice("Pick second creature to tap", creats.toArray()); + if (o!= null) + { + Card c2 = (Card)o; + creats.remove(c2); + tappedCreats.add(c2); + } + else + return; + + o = AllZone.Display.getChoice("Pick third creature to tap", creats.toArray()); + if (o!= null) + { + Card c3 = (Card) o; + creats.remove(c3); + tappedCreats.add(c3); + } + else + return; + + o = AllZone.Display.getChoice("Pick fourth creature to tap", creats.toArray()); + if (o!= null) + { + Card c4 = (Card) o; + creats.remove(c4); + tappedCreats.add(c4); + } + else + return; + + + for(int i = 0; i 6 && druidsUntapped > 6 && AllZone.GameAction.isCardInPlay(card)) + return true; + else + return false; + } + public void resolve() + { + + String player = card.getController(); + if(player.equals(Constant.Player.Human)) + humanResolve(); + else + computerResolve(); + } + public void humanResolve() + { + String controller = card.getController(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, controller); + CardList druids = new CardList(); + + druids.addAll(play.getCards()); + druids = druids.getType("Druid"); + + CardList tappedDruids = new CardList(); + + Object o = AllZone.Display.getChoice("Pick first druid to tap", druids.toArray()); + + if (o!= null) + { + Card c1 = (Card)o; + druids.remove(c1); + tappedDruids.add(c1); + } + else + return; + + o = AllZone.Display.getChoice("Pick second druid to tap", druids.toArray()); + if (o!= null) + { + Card c2 = (Card)o; + druids.remove(c2); + tappedDruids.add(c2); + } + else + return; + + o = AllZone.Display.getChoice("Pick third druid to tap", druids.toArray()); + if (o!= null) + { + Card c3 = (Card) o; + druids.remove(c3); + tappedDruids.add(c3); + } + else + return; + + o = AllZone.Display.getChoice("Pick fourth druid to tap", druids.toArray()); + if (o!= null) + { + Card c4 = (Card) o; + druids.remove(c4); + tappedDruids.add(c4); + } + else + return; + o = AllZone.Display.getChoice("Pick fifth druid to tap", druids.toArray()); + if (o!= null) + { + Card c5 = (Card) o; + druids.remove(c5); + tappedDruids.add(c5); + } + else + return; + + o = AllZone.Display.getChoice("Pick sixth druid to tap", druids.toArray()); + if (o!= null) + { + Card c6 = (Card) o; + druids.remove(c6); + tappedDruids.add(c6); + } + else + return; + + o = AllZone.Display.getChoice("Pick seventh druid to tap", druids.toArray()); + if (o!=null) + { + Card c7 = (Card) o; + druids.remove(c7); + tappedDruids.add(c7); + } + else + return; + + for(int i = 0; i humCreats.size()) + return true; + else + return false; + } + }); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Chameleon Colossus")) + { + final int attack[] = new int[1]; + final int defense[] = new int[1]; + + + final Command untilEOT = new Command() + { + + private static final long serialVersionUID = 861635058350850025L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + card.setTempAttackBoost(0); + card.setTempDefenseBoost(0); + } + } + }; + + SpellAbility ability = new Ability_Activated(card, "2 G G") + { + + private static final long serialVersionUID = -4910313985049099384L; + public boolean canPlayAI() + { + return CardFactoryUtil.AI_doesCreatureAttack(card); + } + public boolean canPlay() + { + if (CardFactoryUtil.canUseAbility(card) && AllZone.GameAction.isCardInPlay(card) && + !card.isFaceDown()) + return true; + else + return false; + } + public void resolve() + { + if(AllZone.GameAction.isCardInPlay(card)) + { + attack[0] = card.getNetAttack(); + defense[0] = attack[0]; + + card.addTempAttackBoost(attack[0]); + card.addTempDefenseBoost(defense[0]); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + } + }; + + + ability.setDescription("2 G G : Chameleon Colossus gets +X/+X until end of turn, where X is its power." ); + ability.setStackDescription("Chameleon Colossus gets +X/+X until end of turn, where X is its power."); + + card.addSpellAbility(ability); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Figure of Destiny")) + { + Ability ability1 = new Ability(card, "RW") + { + public void resolve() + { + boolean artifact = false; + card.setBaseAttack(2); + card.setBaseDefense(2); + + card.removeIntrinsicKeyword("Flying"); + card.removeIntrinsicKeyword("First Strike"); + + if (card.isArtifact()) + artifact = true; + + card.setType(new ArrayList()); + if (artifact) + card.addType("Artifact"); + card.addType("Creature"); + card.addType("Kithkin"); + card.addType("Spirit"); + } + + public boolean canPlayAI() + { + return !card.getType().contains("Spirit"); + } + + };// ability1 + + ability1.setDescription("RW: Figure of Destiny becomes a 2/2 Kithkin Spirit."); + ability1.setStackDescription("Figure of Destiny becomes a 2/2 Kithkin Spirit."); + card.addSpellAbility(ability1); + + + Ability ability2 = new Ability(card, "RW RW RW") + { + public void resolve() + { + boolean artifact = false; + card.setBaseAttack(4); + card.setBaseDefense(4); + + card.removeIntrinsicKeyword("Flying"); + card.removeIntrinsicKeyword("First Strike"); + + if (card.isArtifact()) + artifact = true; + + card.setType(new ArrayList()); + if (artifact) + card.addType("Artifact"); + card.addType("Creature"); + card.addType("Kithkin"); + card.addType("Spirit"); + card.addType("Warrior"); + } + + public boolean canPlay() + { + return card.getType().contains("Spirit"); + } + + public boolean canPlayAI() + { + return !card.getType().contains("Warrior"); + } + + };// ability2 + + ability2.setDescription("RW RW RW: If Figure of Destiny is a Spirit, it becomes a 4/4 Kithkin Spirit Warrior."); + ability2.setStackDescription("Figure of Destiny becomes a 4/4 Kithkin Spirit Warrior."); + card.addSpellAbility(ability2); + + + Ability ability3 = new Ability(card, "RW RW RW RW RW RW") + { + public void resolve() + { + boolean artifact = false; + card.setBaseAttack(8); + card.setBaseDefense(8); + + card.addIntrinsicKeyword("Flying"); + card.addIntrinsicKeyword("First Strike"); + + if (card.isArtifact()) + artifact = true; + + card.setType(new ArrayList()); + if (artifact) + card.addType("Artifact"); + card.addType("Creature"); + card.addType("Kithkin"); + card.addType("Spirit"); + card.addType("Warrior"); + card.addType("Avatar"); + } + public boolean canPlay() + { + return card.getType().contains("Warrior"); + } + public boolean canPlayAI() + { + return !card.getType().contains("Avatar"); + } + };// ability3 + + ability3.setDescription("RW RW RW RW RW RW: If Figure of Destiny is a Warrior, it becomes an 8/8 Kithkin Spirit Warrior Avatar with flying and first strike. "); + ability3.setStackDescription("Figure of Destiny becomes an 8/8 Kithkin Spirit Warrior Avatar with flying and first strike."); + card.addSpellAbility(ability3); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Jenara, Asura of War")) + { + + Ability ability2 = new Ability(card, "1 W") + { + public void resolve() + { + card.addCounter(Counters.P1P1, 1); + } + };// ability2 + + ability2.setStackDescription(card.getName() + " - gets a +1/+1 counter."); + card.addSpellAbility(ability2); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Legacy Weapon")) + { + final Ability ability = new Ability(card, "W U B R G") + { + public void resolve() + { + Card c = getTargetCard(); + + if (AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c)) + { + AllZone.GameAction.removeFromGame(c); + } + } + + public void chooseTargetAI() + { + PlayerZone hplay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList human = new CardList(hplay.getCards()); + human = human.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return CardFactoryUtil.canTarget(card, c); + } + }); + + if (human.size() != 0) + { + setTargetCard(CardFactoryUtil.AI_getMostExpensivePermanent(human, card, true)); + } + } + + public boolean canPlayAI() + { + PlayerZone hplay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList human = new CardList(hplay.getCards()); + human = human.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return CardFactoryUtil.canTarget(card, c); + } + }); + return human.size() > 0; + } + + };//ability + + Input target = new Input() + { + private static final long serialVersionUID = -7279903055386088569L; + public void showMessage() + { + AllZone.Display.showMessage("Select target permanent for " +ability.getSourceCard()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card crd, PlayerZone zone) + { + if(zone.is(Constant.Zone.Play) && CardFactoryUtil.canTarget(card, crd)) + { + ability.setTargetCard(crd); + stopSetNext(new Input_PayManaCost(ability)); + } + } + };//Input + + ability.setBeforePayMana(target); + card.addSpellAbility(ability); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Voltaic Key")) + { + final Ability_Tap ability = new Ability_Tap(card, "1") + { + private static final long serialVersionUID = 6097818373831898299L; + public void resolve() + { + Card c = getTargetCard(); + if (AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) && c.isTapped()) + c.untap(); + } + public boolean canPlayAI() + { + return false; + } + };//ability + + Input target = new Input() + { + private static final long serialVersionUID = -7279903055386088569L; + public void showMessage() + { + AllZone.Display.showMessage("Select target tapped artifact for " +ability.getSourceCard()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card crd, PlayerZone zone) + { + if(zone.is(Constant.Zone.Play) && CardFactoryUtil.canTarget(card, crd) && crd.isArtifact() && crd.isTapped()) + { + ability.setTargetCard(crd); + stopSetNext(new Input_PayManaCost(ability)); + } + } + };//Input + + ability.setBeforePayMana(target); + card.addSpellAbility(ability); + + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Seething Song")) + { + final SpellAbility spell = new Spell(card) + { + private static final long serialVersionUID = 113811381138L; + + public void resolve() + { + CardList list = new CardList(AllZone.getZone(Constant.Zone.Play, Constant.Player.Human).getCards()); + list = list.getName("Mana Pool"); + Card mp = list.getCard(0); + mp.addExtrinsicKeyword("ManaPool:R"); + mp.addExtrinsicKeyword("ManaPool:R"); + mp.addExtrinsicKeyword("ManaPool:R"); + mp.addExtrinsicKeyword("ManaPool:R"); + mp.addExtrinsicKeyword("ManaPool:R"); + } + public boolean canPlayAI() + { + return false; + } + }; + + spell.setStackDescription("Adds R R R R R to your mana pool"); + card.clearSpellAbility(); + card.addSpellAbility(spell); + + return card; + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Dark Ritual")) + { + final SpellAbility spell = new Spell(card) + { + + private static final long serialVersionUID = -8579887529151755266L; + public void resolve() + { + CardList list = new CardList(AllZone.getZone(Constant.Zone.Play, Constant.Player.Human).getCards()); + list = list.getName("Mana Pool"); + Card mp = list.getCard(0); + mp.addExtrinsicKeyword("ManaPool:B"); + mp.addExtrinsicKeyword("ManaPool:B"); + mp.addExtrinsicKeyword("ManaPool:B"); + } + public boolean canPlayAI() + { + return false; + } + }; + + spell.setStackDescription(cardName + " adds B B B to your mana pool"); + card.clearSpellAbility(); + card.addSpellAbility(spell); + + return card; + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Black Lotus")) + { + final SpellAbility ability = new Ability_Tap(card) + { + private static final long serialVersionUID = 8394047173115959008L; + + public boolean canPlayAI(){return false;} + + public void resolve() + { + if (card.getController().equals(Constant.Player.Human)) + { + CardList list = new CardList(AllZone.getZone(Constant.Zone.Play, Constant.Player.Human).getCards()); + list = list.getName("Mana Pool"); + Card mp = list.getCard(0); + + String color = new String(); + + Object o = AllZone.Display.getChoice("Choose mana color",Constant.Color.Colors); + color = (String)o; + + if (color.equals("white")) + color = "W"; + else if (color.equals("blue")) + color = "U"; + else if (color.equals("black")) + color = "B"; + else if (color.equals("red")) + color = "R"; + else if (color.equals("green")) + color = "G"; + else + color = "1"; + + + //System.out.println("ManaPool:"+color+":"); + for (int i = 0; i < 3; i++) + mp.addExtrinsicKeyword("ManaPool:"+ color); + + AllZone.GameAction.sacrifice(card); + } + } + }; + ability.setDescription("tap, Sacrifice Black Lotus: Add three mana of any one color to your mana pool."); + ability.setStackDescription("Adds 3 mana of any one color to your mana pool"); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + //*************** START *********** START ************************** + if (cardName.equals("Composite Golem")) + { + final Ability ability = new Ability(card, "0") + { + + public boolean canPlay() + { + SpellAbility sa; + for (int i=0; i 0) + return true; + else + return false; + } + };//SpellAbility + + Input runtime = new Input() + { + + private static final long serialVersionUID = 1408675899387720506L; + + public void showMessage() + { + CardList cars = new CardList(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards()); + cars = cars.getType("Caribou"); + + stopSetNext(CardFactoryUtil.input_targetSpecific(a2, cars, "Select a Caribou to sacrifice.", false)); + } + }; + + card.addSpellAbility(a2); + a2.setDescription("Sacrifice a Caribou: You gain 1 life."); + a2.setStackDescription(card.getController() + " gains 1 life."); + a2.setBeforePayMana(runtime); + + + card.addEnchantCommand(onEnchant); + card.addUnEnchantCommand(onUnEnchant); + card.addLeavesPlayCommand(onLeavesPlay); + + Input runtime2 = new Input() + { + + private static final long serialVersionUID = -6674543815905055287L; + + public void showMessage() + { + PlayerZone hum = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList land = new CardList(); + land.addAll(hum.getCards()); + land = land.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isLand(); + } + }); + + stopSetNext(CardFactoryUtil.input_targetSpecific(spell, land, "Select target land you control", true)); + } + }; + spell.setBeforePayMana(runtime2); + }//*************** END ************ END ************************** + + + + //*************** START *********** START ************************** + if(cardName.equals("Leafdrake Roost")) + { + + final SpellAbility spell = new Spell(card) + { + + private static final long serialVersionUID = -4695012002471107694L; + public boolean canPlayAI() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.getType("Land"); + + if(list.isEmpty()) + return false; + + setTargetCard(list.get(0)); + return true; + }//canPlayAI() + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(card); + + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) ) + card.enchantCard(c); + + }//resolve() + };//SpellAbility + spell.setType("Extrinsic"); + card.clearSpellAbility(); + card.addSpellAbility(spell); + + final SpellAbility produceDrakes = new Ability_Tap(spell.getTargetCard(), "G U") + { + + private static final long serialVersionUID = -3849765771560556442L; + public void resolve() + { + makeToken(); + } + void makeToken() + { + Card c = new Card(); + Card crd = spell.getTargetCard(); + + c.setName("Drake"); + c.setImageName("G U 2 2 Drake"); + + c.setOwner(crd.getController()); + c.setController(crd.getController()); + + c.setManaCost("G U"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Drake"); + c.setBaseAttack(2); + c.setBaseDefense(2); + c.addIntrinsicKeyword("Flying"); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//makeToken() + };//SpellAbility + + produceDrakes.setDescription("G U, Tap: Put a 2/2 green and blue Drake creature token with flying onto the battlefield."); + produceDrakes.setStackDescription("Put a 2/2 green and blue Drake creature token with flying onto the battlefield."); + + Command onEnchant = new Command() + { + + private static final long serialVersionUID = -5501311059855861341L; + + public void execute() + { + if (card.isEnchanting()) + { + Card crd = card.getEnchanting().get(0); + //crd.clearSpellAbility(); + crd.addSpellAbility(produceDrakes); + + } + }//execute() + };//Command + + + Command onUnEnchant = new Command() + { + + private static final long serialVersionUID = 3589766088284055294L; + + public void execute() + { + if (card.isEnchanting()) + { + + Card crd = card.getEnchanting().get(0); + crd.removeSpellAbility(produceDrakes); + + } + + }//execute() + };//Command + + Command onLeavesPlay = new Command() + { + + private static final long serialVersionUID = -3747590484749776557L; + + public void execute() + { + if (card.isEnchanting()) + { + Card crd = card.getEnchanting().get(0); + card.unEnchantCard(crd); + } + } + }; + + card.addEnchantCommand(onEnchant); + card.addUnEnchantCommand(onUnEnchant); + card.addLeavesPlayCommand(onLeavesPlay); + + Input runtime = new Input() + { + + private static final long serialVersionUID = 967525396666242309L; + + public void showMessage() + { + PlayerZone comp = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + PlayerZone hum = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList land = new CardList(); + land.addAll(comp.getCards()); + land.addAll(hum.getCards()); + land = land.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isLand(); + } + }); + + stopSetNext(CardFactoryUtil.input_targetSpecific(spell, land, "Select target land", true)); + } + }; + spell.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + + + //*************** START *********** START ************************** + if(cardName.equals("Squirrel Nest")) + { + + final SpellAbility spell = new Spell(card) + { + + private static final long serialVersionUID = 6115713202262504968L; + public boolean canPlayAI() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.getType("Land"); + + if(list.isEmpty()) + return false; + + setTargetCard(list.get(0)); + return true; + }//canPlayAI() + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(card); + + Card c = getTargetCard(); + + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) ) + card.enchantCard(c); + + }//resolve() + };//SpellAbility + spell.setType("Extrinsic"); + + card.clearSpellAbility(); + card.addSpellAbility(spell); + + final SpellAbility produceSquirrels = new Ability_Tap(spell.getTargetCard()) + { + private static final long serialVersionUID = -4800170026789001271L; + public void resolve() + { + makeToken(); + } + void makeToken() + { + Card c = new Card(); + Card crd = spell.getTargetCard(); + + c.setName("Squirrel"); + c.setImageName("G 1 1 Squirrel"); + + c.setOwner(crd.getController()); + c.setController(crd.getController()); + + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Squirrel"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + play.add(c); + }//makeToken() + };//SpellAbility + + produceSquirrels.setDescription("Tap: Put a 1/1 green Squirrel creature token into play."); + produceSquirrels.setStackDescription("Put a 1/1 green Squirrel creature token into play."); + + Command onEnchant = new Command() + { + + + private static final long serialVersionUID = 3528675502863241126L; + + public void execute() + { + if (card.isEnchanting()) + { + Card crd = card.getEnchanting().get(0); + //crd.clearSpellAbility(); + crd.addSpellAbility(produceSquirrels); + + } + }//execute() + };//Command + + + Command onUnEnchant = new Command() + { + private static final long serialVersionUID = -2021446345291180334L; + + public void execute() + { + if (card.isEnchanting()) + { + + Card crd = card.getEnchanting().get(0); + crd.removeSpellAbility(produceSquirrels); + + } + + }//execute() + };//Command + + Command onLeavesPlay = new Command() + { + + private static final long serialVersionUID = -4543302260602460839L; + + public void execute() + { + if (card.isEnchanting()) + { + Card crd = card.getEnchanting().get(0); + card.unEnchantCard(crd); + } + } + }; + + card.addEnchantCommand(onEnchant); + card.addUnEnchantCommand(onUnEnchant); + card.addLeavesPlayCommand(onLeavesPlay); + + Input runtime = new Input() + { + + private static final long serialVersionUID = 967525396666242309L; + + public void showMessage() + { + PlayerZone comp = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + PlayerZone hum = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList land = new CardList(); + land.addAll(comp.getCards()); + land.addAll(hum.getCards()); + land = land.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isLand(); + } + }); + + stopSetNext(CardFactoryUtil.input_targetSpecific(spell, land, "Select target land", true)); + } + }; + spell.setBeforePayMana(runtime); + }//*************** END ************ END ************************** + //*************** START ************ START ************************** + if (cardName.equals("Ashnod's Transmogrant")) + { + final Ability_Tap ability = new Ability_Tap(card) + { + private static final long serialVersionUID = -401631574059431293L; + public void resolve() + { + if (card.getController().equals(Constant.Player.Computer)) + AllZone.GameAction.sacrifice(card); + if(getTargetCard() == null || !getTargetCard().isCreature()) + return; + Card crd = getTargetCard(); + crd.addCounter(Counters.P1P1, 1); + if(!crd.getType().contains("Artifact")) + crd.addType("Artifact"); + } + public boolean canPlayAI() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()).filter( + new CardListFilter(){public boolean addCard(Card c){ return !c.isArtifact() && c.isCreature(); }}); + Card crd = CardFactoryUtil.AI_getBestCreature(list); + if (crd != null) + setTargetCard(crd); + return (getTargetCard() != null); + } + }; + Input runtime = new Input() + { + private static final long serialVersionUID = 141164423096887945L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target creature for " +card); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card c, PlayerZone zone) + { + if (!CardFactoryUtil.canTarget(ability, c)) + { + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + else if(c.isCreature() && !c.isArtifact() && zone.is(Constant.Zone.Play)) + { + ability.setTargetCard(c); + AllZone.GameAction.sacrifice(card); + stopSetNext(new Input_NoCost_TapAbility(ability)); + } + } + }; + ability.setBeforePayMana(runtime); + ability.setDescription("T, Sacrifice Ashnod's Transmogrant: put a +1/+1 counter on target nonartifact creature. That creature becomes an artifact in addition to its other types."); + card.addSpellAbility(ability); + }//*************** END ************ END ************************** + + //*************** START ************ START ************************** + if (cardName.equals("Gemstone Array")) + { + final Ability store = new Ability(card, "2"){ + public void resolve(){card.addCounter(Counters.CHARGE, 1);} + public boolean canPlayAI(){ return AllZone.Phase.is(Constant.Phase.Main2, Constant.Player.Computer);} + }; + store.setDescription("2: Put a charge counter on Gemstone Array."); + store.setStackDescription("Put a charge counter on Gemstone Array"); + card.addSpellAbility(store); + + final Ability_Mana retrieve = new Ability_Mana(card, "Remove a charge counter from Gemstone Array: Add one mana of any color to your mana pool.") + { + private static final long serialVersionUID = -2938965362221626028L; + + @SuppressWarnings("unused") + boolean undoable = true; + public void undo() {card.addCounter(Counters.CHARGE, 1);} + public String Mana() {return this.choices_made[0].toString();} + public boolean canPlay() {return super.canPlay() && card.getCounters(Counters.CHARGE) > 0;} + public void resolve(){card.subtractCounter(Counters.CHARGE, 1); super.resolve();} + }; + retrieve.choices_made = new String[1]; + retrieve.setBeforePayMana(new Input(){ + /** + * + */ + private static final long serialVersionUID = 376497609786542558L; + + public void showMessage() + { + retrieve.choices_made[0] = Input_PayManaCostUtil.getColor2((String)AllZone.Display.getChoiceOptional("Select a Color", Constant.Color.onlyColors)); + if(retrieve.choices_made[0] == null) + retrieve.choices_made[0] = "1"; + AllZone.Stack.add(retrieve); + stop(); + } + }); + card.addSpellAbility(retrieve); + }//*************** END ************ END ************************** + + //*************** START ************ START ************************** + if (cardName.equals("Rats of Rath")) + { + final Ability ability = new Ability(card,"B") + { + public boolean canPlayAI(){return false;}; + public void resolve(){AllZone.GameAction.destroy(getTargetCard());}; + }; + ability.setBeforePayMana(new Input(){ + private static final long serialVersionUID = 7691864588170864421L; + + public void showMessage() + { + CardList choices = new CardList(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards()); + choices.filter(new CardListFilter(){public boolean addCard(Card c){ + return c.isArtifact() || c.isCreature() || c.isLand();}}); + stopSetNext(CardFactoryUtil.input_targetSpecific(ability, choices, "Select an artifact, creature, or land you control", true));} + }); + ability.setDescription("B: Destroy target artifact, creature, or land you control."); + card.addSpellAbility(ability); + } + //*************** END ************ END ************************** + + //*************** START ************ START ************************** + if (cardName.equals("Goblin Grenade")) + { + final SpellAbility DamageCP = new Spell(card) + { + private static final long serialVersionUID = -4289150611689144985L; + Card check; + + public boolean canPlay() + { + CardList gobs = new CardList(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards()); + gobs = gobs.getType("Goblin"); + + return gobs.size()>0; + } + + public boolean canPlayAI() + { + if(AllZone.Human_Life.getLife() <= 5) + return true; + + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if (hand.size() >= 8) + return true; + + check = getFlying(); + return check != null; + } + + public void chooseTargetAI() + { + if(AllZone.Human_Life.getLife() <= 5) + { + setTargetPlayer(Constant.Player.Human); + return; + } + + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if(getFlying() == null && hand.size() >= 7 ) //not 8, since it becomes 7 when getting cast + { + setTargetPlayer(Constant.Player.Human); + return; + } + + Card c = getFlying(); + + if (check == null && c != null) + System.out.println("Check equals null"); + else if((c == null) || (! check.equals(c))) + throw new RuntimeException(card +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + if (c != null) + setTargetCard(c); + else + setTargetPlayer(Constant.Player.Human); + }//chooseTargetAI() + + //uses "damage" variable + Card getFlying() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", card, true); + for(int i = 0; i < flying.size(); i++) + if(flying.get(i).getNetDefense() <= 5){ + System.out.println("getFlying() returns " + flying.get(i).getName()); + return flying.get(i); + } + + System.out.println("getFlying() returned null"); + return null; + } + public void resolve() + { + if (card.getController().equals(Constant.Player.Computer)) + { + CardList gobs = new CardList(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards()); + gobs = gobs.getType("Goblin"); + + if (gobs.size()>0) + { + CardListUtil.sortAttackLowFirst(gobs); + AllZone.GameAction.sacrifice(gobs.get(0)); + } + //TODO, if AI can't sack, break out of this + } + + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard())) + { + Card c = getTargetCard(); + //c.addDamage(damage); + AllZone.GameAction.addDamage(c, 5); + } + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(5); + //resolve() + } + }; //spellAbility + DamageCP.setDescription(card.getName() + " deals 5 damage to target creature or player."); + //DamageCP.setStackDescription(card.getName() +" deals 5 damage."); + + Input target = new Input() + { + private static final long serialVersionUID = 1843037500197925110L; + public void showMessage() + { + AllZone.Display.showMessage("Select target Creature, Player, or Planeswalker"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card crd, PlayerZone zone) + { + if((crd.isCreature() || crd.isPlaneswalker() ) && zone.is(Constant.Zone.Play) && CardFactoryUtil.canTarget(DamageCP, crd) ) + { + DamageCP.setTargetCard(crd); + done(); + } + }//selectCard() + public void selectPlayer(String player) + { + DamageCP.setTargetPlayer(player); + done(); + } + void done() + { + AllZone.Stack.add(DamageCP); + stop(); + } + }; + + Input targetSac = new Input() + { + + private static final long serialVersionUID = -6102143961778874295L; + public void showMessage() + { + AllZone.Display.showMessage("Select a Goblin to sacrifice."); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card crd, PlayerZone zone) + { + CardList choices = new CardList(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards()); + choices = choices.getType("Goblin"); + + if(choices.contains(crd)) + { + AllZone.GameAction.sacrifice(crd); + //DamageCP.setTargetCard(crd); + if(DamageCP instanceof Ability_Tap && DamageCP.getManaCost().equals("0")) + stopSetNext(new Input_NoCost_TapAbility((Ability_Tap)DamageCP)); + else if(DamageCP.getManaCost().equals("0")) + { + //AllZone.Stack.add(DamageCP); + stop(); + } + else + stopSetNext(new Input_PayManaCost(DamageCP)); + } + }//selectCard() + }; + + DamageCP.setBeforePayMana(targetSac); + DamageCP.setAfterPayMana(target); + card.clearSpellAbility(); + card.addSpellAbility(DamageCP); + }//*************** END ************ END ************************** + + + // Cards with Cycling abilities + // -1 means keyword "Cycling" not found + if (shouldCycle(card) != -1) + { + int n = shouldCycle(card); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + final String manacost = k[1]; + + card.addSpellAbility(CardFactoryUtil.ability_cycle(card, manacost)); + } + }//Cycling + + + return card; + }//getCard2 + + + + // copies stats like attack, defense, etc.. + private Card copyStats(Object o) { + Card sim = (Card) o; + Card c = new Card(); + + c.setBaseAttack(sim.getBaseAttack()); + c.setBaseDefense(sim.getBaseDefense()); + c.setIntrinsicKeyword(sim.getKeyword()); + c.setName(sim.getName()); + c.setType(sim.getType()); + c.setText(sim.getSpellText()); + c.setManaCost(sim.getManaCost()); + + return c; + }// copyStats() + + public static void main(String[] args) { + CardFactory f = new CardFactory("cards.txt"); + Card c = f.getCard("Arc-Slogger", "d"); + System.out.println(c.getOwner()); + } +} \ No newline at end of file diff --git a/src/CardFactoryUtil.java b/src/CardFactoryUtil.java new file mode 100644 index 00000000000..70f639fe202 --- /dev/null +++ b/src/CardFactoryUtil.java @@ -0,0 +1,2381 @@ +import java.util.*; + +public class CardFactoryUtil +{ + private static Random random = new Random(); + + public final static String getPumpString(int n) + { + if(0 <= n) + return "+" +n; + else + return "" +n; + } + + public static Card AI_getMostExpensivePermanent(CardList list, final Card spell, boolean targeted) + { + CardList all = list; + if (targeted) + { + all = all.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return CardFactoryUtil.canTarget(spell, c); + } + }); + } + if (all.size() == 0) + return null; + + //get biggest Permanent + Card biggest = null; + biggest = all.get(0); + + for(int i = 0; i < all.size(); i++){ + if(CardUtil.getConvertedManaCost(biggest.getManaCost()) >= CardUtil.getConvertedManaCost(biggest.getManaCost())){ + biggest = all.get(i); + } + } + + return biggest; + + } + + public static Card AI_getCheapestPermanent(CardList list, final Card spell, boolean targeted) + { + CardList all = list; + if (targeted) { + all = all.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return CardFactoryUtil.canTarget(spell, c); + } + }); + } + if (all.size() == 0) + return null; + + //get cheapest card: + Card cheapest = null; + cheapest = all.get(0); + + for(int i = 0; i < all.size(); i++){ + if(CardUtil.getConvertedManaCost(cheapest.getManaCost()) <= CardUtil.getConvertedManaCost(cheapest.getManaCost())){ + cheapest = all.get(i); + } + } + + return cheapest; + + } + + public static Card AI_getBestLand(CardList list) + { + CardList land = list.getType("Land"); + if (! (land.size() > 0)) + return null; + + CardList nbLand = land.filter(new CardListFilter () // prefer to target non basic lands + { + public boolean addCard(Card c) + { + return (!c.getType().contains("Basic")); + } + } + ); + + if (nbLand.size() > 0) + { + //TODO: Rank non basics? + + Random r = new Random(); + return nbLand.get(r.nextInt(nbLand.size())); + } + + // if no non-basic lands, target the least represented basic land type + String names[] = {"Plains", "Island", "Swamp", "Mountain", "Forest"}; + String sminBL = new String(); + int iminBL = 20000; // hopefully no one will ever have more than 20000 lands of one type.... + int n = 0; + for (int i = 0; i < 5; i++) + { + n = land.getType(names[i]).size(); + if (n < iminBL && n > 0) // if two or more are tied, only the first one checked will be used + { + iminBL = n; + sminBL = names[i]; + } + } + if (iminBL == 20000) + return null; // no basic land was a minimum + + CardList BLand = land.getType(sminBL); + for (int i=0; i= CardUtil.getConvertedManaCost(biggest.getManaCost())){ + biggest = all.get(i); + } + } + + return biggest; + } + + +//The AI doesn't really pick the best artifact, just the most expensive. + public static Card AI_getBestArtifact(CardList list) + { + CardList all = list; + all = all.getType("Artifact"); + if(all.size() == 0){ + return null; + } + + //get biggest Artifact + Card biggest = null; + biggest = all.get(0); + + for(int i = 0; i < all.size(); i++){ + if(CardUtil.getConvertedManaCost(biggest.getManaCost()) >= CardUtil.getConvertedManaCost(biggest.getManaCost())){ + biggest = all.get(i); + } + } + + return biggest; + } + + public static CardList AI_getHumanArtifact(final Card spell, boolean targeted) + { + CardList artifact = new CardList(AllZone.Human_Play.getCards()); + artifact = artifact.getType("Artifact"); + if(targeted) + { + artifact = artifact.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return canTarget(spell,c); + } + }); + } + return artifact; + } + + public static CardList AI_getHumanEnchantment(final Card spell, boolean targeted) + { + CardList enchantment = new CardList(AllZone.Human_Play.getCards()); + enchantment = enchantment.getType("Enchantment"); + if (targeted) + { + enchantment = enchantment.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return canTarget(spell,c); + } + }); + } + return enchantment; + } + + +//yes this is more hacky code + //Object[0] is the cardname + //Object[1] is the max number of times it can be used per turn + //Object[1] has to be an Object like Integer and not just an int + private static Object[][] AbilityLimits = + { + {"Azimaet Drake" , new Integer(1)}, + {"Drake Hatchling" , new Integer(1)}, + {"Fire Drake" , new Integer(1)}, + {"Plated Rootwalla" , new Integer(1)}, + {"Rootwalla" , new Integer(1)}, + {"Spitting Drake" , new Integer(1)}, + {"Ghor-Clan Bloodscale", new Integer(1)}, + {"Wild Aesthir", new Integer(1)}, + {"Viashino Slaughtermaster", new Integer(1)}, + {"Twinblade Slasher", new Integer(1)}, + + {"Phyrexian Battleflies" , new Integer(2)}, + {"Pit Imp" , new Integer(2)}, + {"Roterothopter" , new Integer(2)}, + {"Vampire Bats" , new Integer(2)}, + {"Fire-Belly Changeling" , new Integer(2)}, + {"Azusa, Lost but Seeking" , new Integer(2)} + }; + + public static boolean canUseAbility(Card card) + { + int found = -1; + + //try to find card name in AbilityLimits[][] + for(int i = 0; i < AbilityLimits.length; i++) + if(AbilityLimits[i][0].equals(card.getName())) + found = i; + + if(found == -1) + return true; + + //card was found + if(card.getAbilityTurnUsed() != AllZone.Phase.getTurn()) + { + card.setAbilityTurnUsed(AllZone.Phase.getTurn()); + card.setAbilityUsed(0); + } + SpellAbility sa; + //this is a hack, check the stack to see if this card has an ability on the stack + //if so, we can't use the ability: this is to prevent using a limited ability too many times + for (int i=0; i (loss+2)); + } + public boolean canPlay() + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard ,sourceCard.getController()); + String phase = AllZone.Phase.getPhase(); + String activePlayer = AllZone.Phase.getActivePlayer(); + + return AllZone.GameAction.isCardInZone(sourceCard, grave) && (sourceCard.isInstant() || + (phase.equals(Constant.Phase.Main1) || phase.equals(Constant.Phase.Main2)) && + sourceCard.getController().equals(activePlayer) && AllZone.Stack.size() == 0 ); + + } + + }; + + String lifecost = ""; + if (loss != 0) + lifecost = ", pay " + lifeloss + " life"; + + + flashback.setManaCost(manaCost); + flashback.setDescription("Flashback: " + manaCost + lifecost); + flashback.setStackDescription("Flashback: " + sourceCard.getName()); + + return flashback; + + }//ability_Flashback() + + public static SpellAbility ability_Spore_Saproling(final Card sourceCard) + { + final SpellAbility ability = new Ability(sourceCard, "0") + { + public boolean canPlay() + { + SpellAbility sa; + for (int i=0; i= 3 && AllZone.GameAction.isCardInPlay(sourceCard)) + return true; + else + return false; + } + public boolean canPlayAI() {return true;} + + public void resolve() + { + sourceCard.subtractCounter(Counters.SPORE, 3); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, sourceCard.getController()); + + //make token + Card c = new Card(); + + c.setOwner(sourceCard.getController()); + c.setController(sourceCard.getController()); + + c.setName("Saproling"); + c.setImageName("G 1 1 Saproling"); + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Saproling"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + play.add(c); + } + }; + ability.setDescription("Remove three spore counters from " +sourceCard.getName() +": Put a 1/1 green Saproling creature token into play."); + ability.setStackDescription(sourceCard.getName() +" - put a 1/1 green Saproling creature token into play."); + return ability; + }//ability_Spore_Saproling() + + public static SpellAbility ability_Morph_Down(final Card sourceCard) + { + final String player = sourceCard.getController(); + final SpellAbility morph_down = new Spell(sourceCard) + { + private static final long serialVersionUID = -1438810964807867610L; + + public void resolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand ,player); + PlayerZone play = AllZone.getZone(Constant.Zone.Play ,player); + + //card.setName("Morph"); + sourceCard.setIsFaceDown(true); + sourceCard.setManaCost(""); + sourceCard.setBaseAttack(2); + sourceCard.setBaseDefense(2); + sourceCard.comesIntoPlay(); + sourceCard.setIntrinsicKeyword(new ArrayList()); //remove all keywords + sourceCard.setType(new ArrayList()); //remove all types + sourceCard.addType("Creature"); + + hand.remove(sourceCard); + play.add(sourceCard); + } + public boolean canPlay() + { + return AllZone.Phase.getActivePlayer().equals(sourceCard.getController()) && + ( AllZone.Phase.getPhase().equals(Constant.Phase.Main1) || AllZone.Phase.getPhase().equals(Constant.Phase.Main2) ) && + !AllZone.Phase.getPhase().equals("End of Turn") && !AllZone.GameAction.isCardInPlay(sourceCard); + } + + }; + + morph_down.setManaCost("3"); + morph_down.setDescription("You may play this face down as a 2/2 creature for 3. Turn it face up any time for its morph cost."); + morph_down.setStackDescription("Morph - Creature 2/2"); + + return morph_down; + } + + public static SpellAbility ability_Spellbomb(final Card sourceCard){ + final SpellAbility ability = new Ability(sourceCard, "1") + { + public boolean canPlay() + { + return AllZone.GameAction.isCardInPlay(sourceCard)&&!AllZone.Stack.getSourceCards().contains(sourceCard);//in play and not already activated(Sac cost problems) + } + public boolean canPlayAI() {return (AllZone.Computer_Hand.size() < 4)&&(AllZone.Computer_Library.size()>0)&&MyRandom.random.nextBoolean();} + + public void resolve() + { + AllZone.GameAction.drawCard(sourceCard.getController()); + AllZone.GameAction.sacrifice(getSourceCard()); + } + }; + ability.setDescription("1, Sacrifice "+sourceCard.getName()+": Draw a card."); + ability.setStackDescription(sourceCard.getName() +" - Draw a card."); + return ability; + } + + public static Ability ability_Morph_Up(final Card sourceCard, String cost, String orgManaCost, int a, int d) + { + //final String player = sourceCard.getController(); + //final String manaCost = cost; + final int attack = a; + final int defense = d; + final String origManaCost = orgManaCost; + final Ability morph_up = new Ability(sourceCard, cost) + { + private static final long serialVersionUID = -7892773658629724785L; + + public void resolve() + { + //PlayerZone hand = AllZone.getZone(Constant.Zone.Hand ,player); + //PlayerZone play = AllZone.getZone(Constant.Zone.Play ,player); + + //card.setName("Morph"); + sourceCard.setIsFaceDown(false); + sourceCard.setManaCost(origManaCost); + sourceCard.setBaseAttack(attack); + sourceCard.setBaseDefense(defense); + sourceCard.setIntrinsicKeyword(sourceCard.getPrevIntrinsicKeyword()); + sourceCard.setType(sourceCard.getPrevType()); + sourceCard.turnFaceUp(); + } + public boolean canPlay() + { + return sourceCard.isFaceDown() && AllZone.GameAction.isCardInPlay(sourceCard); + } + + };//morph_up + + morph_up.setManaCost(cost); + morph_up.setDescription(cost + " - turn this card face up."); + morph_up.setStackDescription(sourceCard.getName() +" - turn this card face up."); + + return morph_up; + + } + public static SpellAbility spellability_spDamageP(final Card sourceCard, final String dmg) + { + final int damage = Integer.parseInt(dmg); + + final SpellAbility spDamageP = new Spell(sourceCard) + { + private static final long serialVersionUID = -1263171535312610675L; + + @SuppressWarnings("unused") // check + Card check; + + public boolean canPlayAI() + { + return false; + } + + public void chooseTargetAI() + { + CardFactoryUtil.AI_targetHuman(); + return; + } + + public void resolve() + { + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage); + } + }; + spDamageP.setDescription(sourceCard.getName() + " deals " + damage + " damage to target player."); + spDamageP.setStackDescription(sourceCard.getName() +" deals " + damage + " damage."); + spDamageP.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spDamageP)); + return spDamageP; + }//Spellability_spDamageP + + public static SpellAbility spellability_spDamageCP(final Card sourceCard, final String dmg) + { + final int damage = Integer.parseInt(dmg); // converting string dmg -> int + + final SpellAbility DamageCP = new Spell(sourceCard) + { + private static final long serialVersionUID = 7239608350643325111L; + + Card check; + //Shock's code here atm + public boolean canPlayAI() + { + if(AllZone.Human_Life.getLife() <= damage) + return true; + + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if (hand.size() >= 8) + return true; + + check = getFlying(); + return check != null; + } + + public void chooseTargetAI() + { + if(AllZone.Human_Life.getLife() <= damage) + { + setTargetPlayer(Constant.Player.Human); + return; + } + + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if(getFlying() == null && hand.size() >= 7 ) //not 8, since it becomes 7 when getting cast + { + setTargetPlayer(Constant.Player.Human); + return; + } + + Card c = getFlying(); + + if (check == null && c != null) + System.out.println("Check equals null"); + else if((c == null) || (! check.equals(c))) + throw new RuntimeException(sourceCard +" error in chooseTargetAI() - Card c is " +c +", Card check is " +check); + + if (c != null) + setTargetCard(c); + else + setTargetPlayer(Constant.Player.Human); + }//chooseTargetAI() + + //uses "damage" variable + Card getFlying() + { + CardList flying = CardFactoryUtil.AI_getHumanCreature("Flying", sourceCard, true); + for(int i = 0; i < flying.size(); i++) + if(flying.get(i).getNetDefense() <= damage){ + System.out.println("getFlying() returns " + flying.get(i).getName()); + return flying.get(i); + } + + System.out.println("getFlying() returned null"); + return null; + } + public void resolve() + { + + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard()) && canTarget(sourceCard, getTargetCard())) + { + Card c = getTargetCard(); + //c.addDamage(damage); + AllZone.GameAction.addDamage(c, damage); + } + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage); + //resolve() + } + }; //spellAbility + DamageCP.setDescription(sourceCard.getName() + " deals " + damage + " damage to target creature or player."); + DamageCP.setStackDescription(sourceCard.getName() +" deals " + damage + " damage."); + DamageCP.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(DamageCP, true)); + return DamageCP; + }//spellability_DamageCP + + public static SpellAbility ability_Merc_Search(final Card sourceCard, String cost) + { + final int intCost = Integer.parseInt(cost); + //final String player = sourceCard.getController(); + + final SpellAbility ability = new Ability_Tap(sourceCard, cost) + { + private static final long serialVersionUID = 4988299801575232348L; + + public boolean canPlay() + { + SpellAbility sa; + for (int i=0; i 0) + return true; + else + return false; + } + + public void resolve() + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, sourceCard.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, sourceCard.getController()); + + CardList mercs = new CardList(); + CardList list = new CardList(lib.getCards()); + list = list.getType("Mercenary"); + + if (list.size()==0) + return; + + for (int i=0;i < list.size(); i++) + { + if (CardUtil.getConvertedManaCost(list.get(i).getManaCost()) <= intCost) + { + mercs.add(list.get(i)); + } + } + if (mercs.size() == 0) + return; + + if (sourceCard.getController().equals(Constant.Player.Computer)) + { + Card merc = AI_getBestCreature(mercs); + lib.remove(merc); + play.add(merc); + } + else //human + { + Object o = AllZone.Display.getChoiceOptional("Select target Mercenary", mercs.toArray()); + if (o!=null){ + Card merc = (Card)o; + lib.remove(merc); + play.add(merc); + } + } + AllZone.GameAction.shuffle(sourceCard.getController()); + } + }; + ability.setDescription(cost+ ", tap: Search your library for a Mercenary permanent card with converted mana cost " +cost +" or less and put it into play. Then shuffle your library."); + ability.setStackDescription(sourceCard.getName() +" - search for a Mercenary and put it into play."); + return ability; + } + + public static SpellAbility ability_Rebel_Search(final Card sourceCard, String cost) + { + String costMinusOne = ""; + int a = Integer.parseInt(cost); + a--; + costMinusOne = Integer.toString(a); + final int converted = a; + //final String player = sourceCard.getController(); + + final SpellAbility ability = new Ability_Tap(sourceCard, cost) + { + private static final long serialVersionUID = 7219065355049285681L; + + public boolean canPlay() + { + SpellAbility sa; + for (int i=0; i 0) + return true; + else + return false; + + } + + + public void resolve() + { + + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, sourceCard.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, sourceCard.getController()); + + CardList rebels = new CardList(); + CardList list = new CardList(lib.getCards()); + list = list.getType("Rebel"); + + if (list.size()==0) + return; + + for (int i=0;i < list.size(); i++) + { + if (CardUtil.getConvertedManaCost(list.get(i).getManaCost()) <= converted) + { + rebels.add(list.get(i)); + } + } + if (rebels.size() == 0) + return; + + if (sourceCard.getController().equals(Constant.Player.Computer)) + { + Card rebel = AI_getBestCreature(rebels); + lib.remove(rebel); + play.add(rebel); + } + else //human + { + Object o = AllZone.Display.getChoiceOptional("Select target Rebel", rebels.toArray()); + if (o!=null){ + Card rebel = (Card)o; + lib.remove(rebel); + play.add(rebel); + } + } + AllZone.GameAction.shuffle(sourceCard.getController()); + } + }; + ability.setDescription(cost+ ", tap: Search your library for a Rebel permanent card with converted mana cost " +costMinusOne +" or less and put it into play. Then shuffle your library."); + ability.setStackDescription(sourceCard.getName() +" - search for a Rebel and put it into play."); + return ability; + } + + public static SpellAbility ability_cycle(final Card sourceCard, final String cycleCost) + { + final SpellAbility cycle = new Ability_Hand(sourceCard, cycleCost) + { + private static final long serialVersionUID = -4960704261761785512L; + + public boolean canPlayAI() {return false;} + + public void resolve() + { + AllZone.GameAction.discard(sourceCard); + AllZone.GameAction.drawCard(sourceCard.getController()); + sourceCard.cycle(); + } + }; + cycle.setDescription("Cycling " +cycleCost +" (" +cycleCost +", Discard this card: Draw a card.)"); + cycle.setStackDescription(sourceCard +" Cycling: Draw a card"); + return cycle; + }//ability_cycle() + + + //CardList choices are the only cards the user can successful select + public static Input input_targetSpecific(final SpellAbility spell, final CardList choices, final String message, final boolean targeted) + { + return input_targetSpecific(spell, choices, message, Command.Blank, targeted); + } + + //CardList choices are the only cards the user can successful select + public static Input input_targetSpecific(final SpellAbility spell, final CardList choices, final String message, final Command paid, final boolean targeted) + { + Input target = new Input() + { + private static final long serialVersionUID = -1779224307654698954L; + + public void showMessage() + { + AllZone.Display.showMessage(message); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if (targeted && !canTarget(spell, card)) + { + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + else if(choices.contains(card)) + { + spell.setTargetCard(card); + if(spell instanceof Ability_Tap && spell.getManaCost().equals("0")) + stopSetNext(new Input_NoCost_TapAbility((Ability_Tap)spell)); + else if(spell.getManaCost().equals("0")) + { + AllZone.Stack.add(spell); + stop(); + } + else + stopSetNext(new Input_PayManaCost(spell)); + + paid.execute(); + } + }//selectCard() + }; + return target; + }//input_targetSpecific() + + public static Input input_discard(final SpellAbility spell, final int nCards) + { + Input target = new Input() + { + private static final long serialVersionUID = 5101772642421944050L; + + int n = 0; + public void showMessage() + { + AllZone.Display.showMessage("Select a card to discard"); + ButtonUtil.disableAll(); + + if(n == nCards || AllZone.Human_Hand.getCards().length == 0) + stop(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(zone.is(Constant.Zone.Hand)) + { + AllZone.GameAction.discard(card); + n++; + if(spell.getManaCost().equals("0")) + { + AllZone.Stack.add(spell); + stop(); + } + else + stopSetNext(new Input_PayManaCost(spell)); + + //showMessage(); + } // if + + + }//selectCard + + }; + return target; + + } + + public static Input input_discard() + { + return input_discard(1); + } + + public static Input input_discard(final int nCards) + { + Input target = new Input() + { + private static final long serialVersionUID = -329993322080934435L; + + int n = 0; + + public void showMessage() + { + AllZone.Display.showMessage("Select a card to discard"); + ButtonUtil.disableAll(); + + //in case no more cards in hand + if(n == nCards || AllZone.Human_Hand.getCards().length == 0) + stop(); + } + public void selectCard(Card card, PlayerZone zone) + { + if(zone.is(Constant.Zone.Hand)) + { + AllZone.GameAction.discard(card); + n++; + showMessage(); + } + } + }; + return target; + }//input_discard() + + + + //cardType is like "Creature", "Land", "Artifact", "Goblin", "Legendary" + //cardType can also be "All", which will allow any permanent to be selected + public static Input input_targetType(final SpellAbility spell, final String cardType) + { + Input target = new Input() + { + private static final long serialVersionUID = 4944828318048780429L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target " +cardType); + + if(cardType.equals("All")) + AllZone.Display.showMessage("Select target permanent"); + + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(((card.getType().contains(cardType) || card.getKeyword().contains("Changeling")) || cardType.equals("All")) && + zone.is(Constant.Zone.Play) && canTarget(spell, card)) + { + spell.setTargetCard(card); + stopSetNext(new Input_PayManaCost(spell)); + } + } + }; + return target; + }//input_targetType() + + + public static Input input_targetCreature(final SpellAbility spell) + { + return input_targetCreature(spell, Command.Blank); + } + + public static Input input_targetCreature(final SpellAbility spell, final Command paid) + { + Input target = new Input() + { + private static final long serialVersionUID = 141164423096887945L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target creature for " +spell.getSourceCard()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if (!canTarget(spell, card)) + { + AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?)."); + } + else if(card.isCreature() && zone.is(Constant.Zone.Play)) + { + spell.setTargetCard(card); + done(); + } + } + void done() + { + if(spell instanceof Ability_Tap && spell.getManaCost().equals("0")) + stopSetNext(new Input_NoCost_TapAbility((Ability_Tap)spell)); + else if(spell.getManaCost().equals("0"))//for "sacrifice this card" abilities + { + AllZone.Stack.add(spell); + stop(); + } + else + stopSetNext(new Input_PayManaCost(spell)); + + paid.execute(); + } + }; + return target; + }//input_targetCreature() + + public static Input input_targetCreature_NoCost_TapAbility(final Ability_Tap spell) + { + Input target = new Input() + { + private static final long serialVersionUID = 6027194502614341779L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target creature"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(card.isCreature() && zone.is(Constant.Zone.Play) && canTarget(spell, card)) + { + spell.setTargetCard(card); + spell.getSourceCard().tap(); + AllZone.Stack.push(spell); + stop(); + } + } + }; + return target; + }//input_targetCreature() + + public static Input input_targetCreature_NoCost_TapAbility_NoTargetSelf(final Ability_Tap spell) + { + Input target = new Input() + { + private static final long serialVersionUID = -6310420275914649718L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target creature other than "+spell.getSourceCard().getName()); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectCard(Card card, PlayerZone zone) + { + if(card == spell.getSourceCard()){ + AllZone.Display.showMessage("You must select a target creature other than "+spell.getSourceCard().getName()); + } + else if(card.isCreature() && zone.is(Constant.Zone.Play) && !card.getKeyword().contains("Shroud")) + { + spell.setTargetCard(card); + spell.getSourceCard().tap(); + AllZone.Stack.push(spell); + stop(); + } + } + }; + return target; + }//input_targetCreature_NoCost_TapAbility_NoTargetSelf + + + + public static Input input_targetPlayer(final SpellAbility spell) + { + Input target = new Input() + { + private static final long serialVersionUID = 8736682807625129068L; + + public void showMessage() + { + AllZone.Display.showMessage("Select target player"); + ButtonUtil.enableOnlyCancel(); + } + public void selectButtonCancel() {stop();} + public void selectPlayer(String player) + { + spell.setTargetPlayer(player); + if(spell.getManaCost().equals("0")) + { + AllZone.Stack.add(spell); + stop(); + } + else + stopSetNext(new Input_PayManaCost(spell)); + } + }; + return target; + }//input_targetPlayer() + + public static CardList AI_getHumanCreature(final Card spell, boolean targeted) + { + CardList creature = new CardList(AllZone.Human_Play.getCards()); + creature = creature.getType("Creature"); + if (targeted) + { + creature = creature.filter(new CardListFilter(){ + public boolean addCard(Card c) { + return canTarget(spell, c); + } + }); + } + return creature; + } + public static CardList AI_getHumanCreature(final String keyword, final Card spell, final boolean targeted) + { + CardList creature = new CardList(AllZone.Human_Play.getCards()); + creature = creature.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if(targeted) + return c.isCreature() && c.getKeyword().contains(keyword) && canTarget(spell, c); + else + return c.isCreature() && c.getKeyword().contains(keyword); + } + }); + return creature; + }//AI_getHumanCreature() + public static CardList AI_getHumanCreature(final int toughness, final Card spell, final boolean targeted) + { + CardList creature = new CardList(AllZone.Human_Play.getCards()); + creature = creature.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if(targeted) + return c.isCreature() && (c.getNetDefense() <= toughness) && canTarget(spell, c); + else + return c.isCreature() && (c.getNetDefense() <= toughness); + } + }); + return creature; + }//AI_getHumanCreature() + + public static CardList AI_getHumanCreature(final boolean lower, final int manaCost,final Card spell, final boolean targeted) + { + CardList creature = new CardList(AllZone.Human_Play.getCards()); + creature = creature.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if(targeted && lower) + return c.isCreature() && (CardUtil.getConvertedManaCost(c.getManaCost()) <= 3) && canTarget(spell, c); + else if (lower) + return c.isCreature() && (CardUtil.getConvertedManaCost(c.getManaCost()) <= 3); + + else if (targeted && !lower) + return c.isCreature() && (CardUtil.getConvertedManaCost(c.getManaCost()) >= 3) && canTarget(spell, c); + else //if !targeted && !lower + return c.isCreature() && (CardUtil.getConvertedManaCost(c.getManaCost()) >= 3); + } + }); + return creature; + }//AI_getHumanCreature() + + public static CommandArgs AI_targetHumanCreatureOrPlayer() + { + return new CommandArgs() + { + private static final long serialVersionUID = 1530080942899792553L; + + public void execute(Object o) + { + SpellAbility sa = (SpellAbility)o; + + CardList creature = new CardList(AllZone.Human_Play.getCards()); + creature = creature.getType("Creature"); + Card c = getRandomCard(creature); + + if((c == null) || random.nextBoolean()) + { + sa.setTargetPlayer(Constant.Player.Human); + } + else + { + sa.setTargetCard(c); + } + } + };//CommandArgs + }//human_creatureOrPlayer() + public static CommandArgs AI_targetHuman() + { + return new CommandArgs() + { + private static final long serialVersionUID = 8406907523134006697L; + + public void execute(Object o) + { + SpellAbility sa = (SpellAbility)o; + sa.setTargetPlayer(Constant.Player.Human); + } + }; + }//targetHuman() + + //is it the computer's main phase before attacking? + public static boolean AI_isMainPhase() + { + return AllZone.Phase.getPhase().equals(Constant.Phase.Main1) && + AllZone.Phase.getActivePlayer().equals(Constant.Player.Computer); + } + public static CommandArgs AI_targetComputer() + { + return new CommandArgs() + { + private static final long serialVersionUID = -445231553588926627L; + + public void execute(Object o) + { + SpellAbility sa = (SpellAbility)o; + sa.setTargetPlayer(Constant.Player.Computer); + } + }; + }//targetComputer() + + //type can also be "All" + public static CommandArgs AI_targetType(final String type, final PlayerZone zone) + { + return new CommandArgs() + { + private static final long serialVersionUID = 6475810798098105603L; + + public void execute(Object o) + { + CardList filter = new CardList(zone.getCards()); + + if(! type.equals("All")) + filter = filter.getType(type); + + Card c = getRandomCard(filter); + if(c != null) + { + SpellAbility sa = (SpellAbility)o; + sa.setTargetCard(c); + + //doesn't work for some reason +// if(shouldAttack && CombatUtil.canAttack(c)) +// AllZone.Combat.addAttacker(c); + } + }//execute() + }; + }//targetInPlay() + + public static int getNumberOfPermanentsByColor(String color) + { + CardList cards = new CardList(); + cards.addAll(AllZone.Human_Play.getCards()); + cards.addAll(AllZone.Computer_Play.getCards()); + + CardList coloredPerms = new CardList(); + + for (int i=0; i= 2; + } + + }); + + return list.size() >= 1; + + } + + public static int getNumberOfManaSymbolsControlledByColor(String colorAbb, String player) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play,player); + + CardList cards = new CardList(); + cards.addAll(play.getCards()); + + int count = 0; + for(int i=0;i list = target.getKeyword(); + + String kw = ""; + for (int i=0;i list = target.getKeyword(); + + String kw = ""; + for (int i=0;i list = receiver.getKeyword(); + + String kw = ""; + for (int i=0;i 1) + m[0] = l[1]; + final String [] sq; + sq = l[0].split("\\."); + + CardList someCards = new CardList(); + + //Complex counting methods + + // Count$Domain + if (sq[0].contains("Domain")) + { + someCards.addAll(myField.getCards()); + String basic[] = {"Forest", "Plains", "Mountain", "Island", "Swamp"}; + + for(int i = 0; i < basic.length; i++) + if (! someCards.getType(basic[i]).isEmpty()) + n++; + + return doXMath(n, m); + } + + // Count$YourLifeTotal + if (sq[0].contains("YourLifeTotal")) + { + if (cardController.equals(Constant.Player.Computer)) + return doXMath(AllZone.Computer_Life.getLife(), m); + else if (cardController.equals(Constant.Player.Human)) + return doXMath(AllZone.Human_Life.getLife(), m); + + return 0; + } + + // Count$OppLifeTotal + if (sq[0].contains("OppLifeTotal")) + { + if (oppController.equals(Constant.Player.Computer)) + return doXMath(AllZone.Computer_Life.getLife(), m); + else if (oppController.equals(Constant.Player.Human)) + return doXMath(AllZone.Human_Life.getLife(), m); + + return 0; + } + + // Count$Chroma. + if (sq[0].contains("Chroma")) + return doXMath(getNumberOfManaSymbolsControlledByColor(sq[1], cardController), m); + + // Count$Hellbent.. + if (sq[0].contains("Hellbent")) + if (myHand.size() <= 1) + return doXMath(Integer.parseInt(sq[1]), m); // Hellbent + else + return doXMath(Integer.parseInt(sq[2]), m); // not Hellbent + + + //Generic Zone-based counting + // Count$QualityAndZones.Subquality + + // build a list of cards in each possible specified zone + + // if a card was ever written to count two different zones, + // make sure they don't get added twice. + boolean MF = false, MY = false, MH = false; + boolean OF = false, OY = false, OH = false; + + if (sq[0].contains("YouCtrl")) + if (MF == false) + { + someCards.addAll(myField.getCards()); + MF = true; + } + + if (sq[0].contains("InYourYard")) + if (MY == false) + { + someCards.addAll(myYard.getCards()); + MY = true; + } + + if (sq[0].contains("InYourHand")) + if (MH == false) + { + someCards.addAll(myHand.getCards()); + MH = true; + } + + if (sq[0].contains("OppCtrl")) + if (OF == false) + { + someCards.addAll(opField.getCards()); + OF = true; + } + + if (sq[0].contains("InOppYard")) + if (OY == false) + { + someCards.addAll(opYard.getCards()); + OY = true; + } + + if (sq[0].contains("InOppHand")) + if (OH == false) + { + someCards.addAll(opHand.getCards()); + OH = true; + } + + if (sq[0].contains("OnBattlefield")) + { + if (MF == false) + someCards.addAll(myField.getCards()); + if (OF == false) + someCards.addAll(opField.getCards()); + } + + if (sq[0].contains("InAllYards")) + { + if (MY == false) + someCards.addAll(myYard.getCards()); + if (OY = false) + someCards.addAll(opYard.getCards()); + } + + if (sq[0].contains("InAllHands")) + { + if (MH == false) + someCards.addAll(myHand.getCards()); + if (OH == false) + someCards.addAll(opHand.getCards()); + } + + // filter lists based on the specified quality + + // "Clerics you control" - Count$TypeYouCtrl.Cleric + if (sq[0].contains("Type")) + { + someCards = someCards.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if (c.getType().contains(sq[1]) || c.getKeyword().contains("Changeling")) + return true; + + return false; + } + }); + } + + // "Named in all graveyards" - Count$NamedAllYards. + + if (sq[0].contains("Named")) + { + someCards = someCards.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if (c.getName().equals(sq[1])) + return true; + + return false; + } + }); + } + + // Refined qualities + + // "Untapped Lands" - Count$UntappedTypeYouCtrl.Land + if (sq[0].contains("Untapped")) + { + someCards = someCards.filter(new CardListFilter() + { + public boolean addCard(Card c){ + return !c.isTapped();} + }); + } + + if (sq[0].contains("Tapped")) + { + someCards = someCards.filter(new CardListFilter() + { + public boolean addCard(Card c){ + return c.isTapped();} + }); + } + + // "White Creatures" - Count$WhiteTypeYouCtrl.Creature + if (sq[0].contains("White")) + { + someCards = someCards.filter(new CardListFilter() + { + public boolean addCard(Card c){ + return CardUtil.getColor(c) == Constant.Color.White;} + }); + } + + if (sq[0].contains("Blue")) + { + someCards = someCards.filter(new CardListFilter() + { + public boolean addCard(Card c){ + return CardUtil.getColor(c) == Constant.Color.Blue;} + }); + } + + if (sq[0].contains("Black")) + { + someCards = someCards.filter(new CardListFilter() + { + public boolean addCard(Card c){ + return CardUtil.getColor(c) == Constant.Color.Black;} + }); + } + + if (sq[0].contains("Red")) + { + someCards = someCards.filter(new CardListFilter() + { + public boolean addCard(Card c){ + return CardUtil.getColor(c) == Constant.Color.Red;} + }); + } + + if (sq[0].contains("Green")) + { + someCards = someCards.filter(new CardListFilter() + { + public boolean addCard(Card c){ + return CardUtil.getColor(c) == Constant.Color.Green;} + }); + } + + if (sq[0].contains("Multicolor")) + someCards = someCards.filter(new CardListFilter () + { + public boolean addCard(Card c){ + return (CardUtil.getColors(c).size() > 1); + } + }); + + if (sq[0].contains("Monocolor")) + someCards = someCards.filter(new CardListFilter () + { + public boolean addCard(Card c){ + return (CardUtil.getColors(c).size() == 1); + } + }); + + n = someCards.size(); + + return doXMath(n, m); + } + + private static int doXMath(int num, String[] m) + { + if (m[0].equals("none")) + return num; + + String[] s = m[0].split("\\."); + + if (s[0].contains("Plus")) + return num + Integer.parseInt(s[1]); + else if (s[0].contains("NMinus")) + return Integer.parseInt(s[1]) - num; + else if (s[0].contains("Minus")) + return num - Integer.parseInt(s[1]); + else if (s[0].contains("Twice")) + return num * 2; + else if (s[0].contains("HalfUp")) + return (int) (Math.ceil(num / 2)); + else if (s[0].contains("HalfDown")) + return (int) (Math.floor(num / 2)); + + return num; + } + + + public static void doDrawBack(String DB, int nDB, String cardController, String Opp, String TgtP, Card Src, Card TgtC) + { + // Drawbacks may be any simple additional effect a spell or ability may have + // not just the negative ones + + String d[] = DB.split("/"); + int X; + if (d[1].equals("X")) + X = nDB; + else + X = Integer.parseInt(d[1]); + + String dbPlayer = new String(); + if (d[0].contains("You")) + dbPlayer = cardController; + else if (d[0].contains("Opp")) + dbPlayer = Opp; + else if (d[0].contains("Tgt")) + dbPlayer = TgtP; + + if (d[0].contains("Damage")) + AllZone.GameAction.addDamage(dbPlayer, X); + + if (d[0].contains("GainLife")) + AllZone.GameAction.addLife(dbPlayer, X); + + if (d[0].contains("LoseLife")) + AllZone.GameAction.subLife(TgtP, X); + + if (d[0].contains("Discard")) + { + if (d.length > 2) + { + if (d[2].contains("UnlessDiscardType")) + { + String dd[] = d[2].split("\\."); + AllZone.GameAction.discardUnless(dbPlayer, X, dd[1]); + } + if (d[2].contains("AtRandom")) + AllZone.GameAction.discardRandom(dbPlayer, X); + } else + AllZone.GameAction.discard(dbPlayer, X); + } + + if (d[0].contains("HandToLibrary")) + AllZone.GameAction.handToLibrary(dbPlayer, X, d[2]); + + if (d[0].contains("Draw")) + for (int i=0; i < X; i++) + AllZone.GameAction.drawCard(dbPlayer); + + if (d[0].contains("GenToken")) // placeholder for effect + X = X + 0; + + if (d[0].contains("ReturnFromYard")) // placeholder for effect + X = X + 0; + + if (d[0].contains("Sacrifice")) // placeholder for effect + X = X + 0; + } + public static int getNumberOfMostProminentCreatureType(CardList list, String type) + { + list = list.getType(type); + return list.size(); + } + + public static String getMostProminentCreatureType(CardList list) + { + + Map map = new HashMap(); + String s = ""; + + for (int i=0;i typeList = c.getType(); + + for (String var : typeList) + { + if (var.equals("Creature") || var.equals("Artifact") || var.equals("Land") || var.equals("Tribal") || var.equals("Enchantment") || + var.equals("Legendary") ) + ; + else if (!map.containsKey(var)) + map.put(var, 1); + else + { + map.put(var, map.get(var)+1); + } + } + }//for + + int max = 0; + String maxType = ""; + + for (int i=0;i iter = map.keySet().iterator(); + while(iter.hasNext()) { + String type = iter.next(); + System.out.println(type + " - " + map.get(type)); + + if (max < map.get(type)) + { + max = map.get(type); + maxType = type; + } + } + } + s = maxType; + return s; + } + + + public static String chooseCreatureTypeAI(Card c) + { + String s = ""; + //TODO, take into account what human has + + PlayerZone humanPlayZone = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + PlayerZone humanLibZone = AllZone.getZone(Constant.Zone.Library, Constant.Player.Human); + + CardList humanPlay = new CardList(humanPlayZone.getCards()); + CardList humanLib = new CardList(humanLibZone.getCards()); + + PlayerZone compPlayZone = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + PlayerZone compLibZone = AllZone.getZone(Constant.Zone.Library, Constant.Player.Computer); + PlayerZone compHandZone = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + + CardList compPlay = new CardList(compPlayZone.getCards()); + CardList compLib = new CardList(compLibZone.getCards()); + CardList compHand = new CardList(compHandZone.getCards()); + + humanPlay = humanPlay.getType("Creature"); + humanLib = humanLib.getType("Creature"); + + compPlay = compPlay.getType("Creature"); + compLib = compLib.getType("Creature"); + + //Buffs + if (c.getName().equals("Conspiracy") || c.getName().equals("Cover of Darkness") || c.getName().equals("Belbe's Portal") || + c.getName().equals("Steely Resolve") || c.getName().equals("Shared Triumph")) + { + + String type = ""; + int number = 0; + if ((c.getName().equals("Shared Triumph") || c.getName().equals("Cover of Darkness") || c.getName().equals("Steely Resolve") )&& compPlay.size() > 7) + { + type = getMostProminentCreatureType(compPlay); + number = getNumberOfMostProminentCreatureType(compPlay, type); + + } + + if (number >= 3) + s = type; + else { + type = getMostProminentCreatureType(compLib); + number = getNumberOfMostProminentCreatureType(compLib, type); + if (number >= 5) + s = type; + + } + + CardList turnTimber = new CardList(); + turnTimber.addAll(compPlay.toArray()); + turnTimber.addAll(compLib.toArray()); + turnTimber.addAll(compHand.toArray()); + + turnTimber = turnTimber.getName("Turntimber Ranger"); + + if (c.getName().equals("Conspiracy") && turnTimber.size() > 0 ) + s = "Ally"; + + } + //Debuffs + else if(c.getName().equals("Engineered Plague")) + { + String type = ""; + int number = 0; + if (c.getName().equals("Engineered Plague") && humanPlay.size() > 6) + { + type = getMostProminentCreatureType(humanPlay); + number = getNumberOfMostProminentCreatureType(humanPlay, type); + if (number >= 3) + s = type; + else if (humanLib.size()>0) + { + type = getMostProminentCreatureType(humanLib); + number = getNumberOfMostProminentCreatureType(humanLib, type); + if (number >=5) + s = type; + } + } + } + return s; + } + + + //may return null + static public Card getRandomCard(CardList list) + { + if(list.size() == 0) + return null; + + int index = random.nextInt(list.size()); + return list.get(index); + } + //may return null + static public Card getRandomCard(PlayerZone zone) + { + return getRandomCard(new CardList(zone.getCards())); + } + + public static void main(String[] args) + { + + CardList in = AllZone.CardFactory.getAllCards(); + + CardList list = new CardList(); + list.addAll(CardListUtil.getColor(in, "black").toArray()); + list = list.getType("Creature"); + + System.out.println("Most prominent creature type: " + getMostProminentCreatureType(list)); + } + +} \ No newline at end of file diff --git a/src/CardList.java b/src/CardList.java new file mode 100644 index 00000000000..56518e055f3 --- /dev/null +++ b/src/CardList.java @@ -0,0 +1,216 @@ +import java.util.*; + +public class CardList implements Iterable +{ + + public Iterator iterator() { + return list.iterator(); + } + + private ArrayList list = new ArrayList(); + //private LinkedList list = new LinkedList(); + + public CardList() {} + public CardList(Card c[]) { addAll(c);} + public CardList(Object c[]) {addAll(c);} + +// cardColor is like "R" or "G", returns a new CardList that is a subset of current CardList + public CardList getColor(String cardColor) + { + CardList c = new CardList(); + Card card; + for(int i = 0; i < size(); i++) + { + card = getCard(i); + + if(0 < card.getManaCost().indexOf(cardColor))//hopefully this line works + c.add(getCard(i)); + } + return c; + }//getColor() + + public void reverse() + { + Collections.reverse(list); + } + + public boolean equals(CardList a) + { + if(list.size() != a.size()) + return false; + + for(int i = 0; i < list.size(); i++) + if(! list.get(i).equals(a.get(i))) + return false; + + return true; + } + + //removes one copy of that card + public void remove(final String cardName) + { + CardList find = this.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.getName().equals(cardName); + } + }); + + if(0 < find.size()) + this.remove(find.get(0)); + else + throw new RuntimeException("CardList : remove(String cardname), error - card name not found: " +cardName +" - contents of Arraylist:" +list); + + }//remove(String cardName) + + public int size() {return list.size();} + public void add(Card c) {list.add(c);} + public void add(int n, Card c) {list.add(n, c);} + public boolean contains(Card c) {return list.contains(c);} + + //probably remove getCard() in the future + public Card getCard(int index){return (Card)list.get(index);} + public Card get(int i) {return getCard(i);} + + public void addAll(Object c[]) + { + for(int i = 0; i < c.length; i++) + list.add((Card)c[i]); + } + public boolean containsName(Card c) + { + return containsName(c.getName()); + } + public boolean containsName(String name) + { + for(int i = 0; i < size(); i++) + if(getCard(i).getName().equals(name)) + return true; + + return false; + } + //returns new subset of all the cards with the same name + public CardList getName(String name) + { + CardList c = new CardList(); + + for(int i = 0; i < size(); i++) + if(getCard(i).getName().equals(name)) + c.add(getCard(i)); + + return c; + } + //cardType is like "Land" or "Goblin", returns a new CardList that is a subset of current CardList + public CardList getType(String cardType) + { + CardList c = new CardList(); + Card card; + for(int i = 0; i < size(); i++) + { + card = getCard(i); + if(card.getType().contains(cardType) || + ( (card.isCreature() || (card.isTribal() && !cardType.equals("Creature")) ) && !cardType.equals("Legendary") && !cardType.equals("Planeswalker") && !cardType.equals("Basic") && + !cardType.equals("Enchantment") && !cardType.equals("Land") && !cardType.equals("Sorcery") && !cardType.equals("Instant") && + !cardType.equals("Artifact") && !cardType.equals("Plains") && !cardType.equals("Mountain") && !cardType.equals("Island") && + !cardType.equals("Forest") && !cardType.equals("Swamp") && card.getKeyword().contains("Changeling") ) )//changelings, see Lorwyn FAQ + c.add(getCard(i)); + } + return c; + }//getType() + public CardList filter(CardListFilter f) + { + CardList c = new CardList(); + for(int i = 0; i < size(); i++) + if(f.addCard(getCard(i))) + c.add(getCard(i)); + + return c; + } + public final Card[] toArray() + { + Card[] c = new Card[list.size()]; + list.toArray(c); + return c; + } + public String toString() {return list.toString();} + public boolean isEmpty() {return list.isEmpty();} + public Card remove(int i) {return (Card)list.remove(i);} + public void remove(Card c) {list.remove(c);} + public void clear() {list.clear();} + + public void shuffle() + { + Collections.shuffle(list, MyRandom.random); + Collections.shuffle(list, MyRandom.random); + Collections.shuffle(list, MyRandom.random); + } + + public void sort(Comparator c) {Collections.sort(list, c);} + + public CardList getValidCards(String Restrictions[]) + { + CardList tmpList = new CardList(toArray()); + CardList retList = new CardList(); + + for (int i=0;i 1) + { + final String excR = incR[1]; + tmpList = tmpList.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + boolean r = true; + String exR[] = excR.split("\\+"); // Exclusive Restrictions are ... + for (int j=0;j 1); + else if (exR[j].contains("with")) // ... Card keywords + if (exR[j].startsWith("without")) + r = r && (! c.getKeyword().contains(exR[j].substring(7))); + else + r = r && (c.getKeyword().contains(exR[j].substring(4))); + //TODO: converted mana cost + //TODO: tapped + //TODO: enchanted + //TODO: enchanting + //TODO: token + //TODO: counters + else + if (exR[j].startsWith("non")) // ... Other Card types + r = r && (! c.getType().contains(exR[j].substring(3))); + else + r = r && (c.getType().contains(exR[j])); + } + return r; + } + }); + } + retList.addAll(tmpList.toArray()); + } + return retList; + }//getValidCards + + +} \ No newline at end of file diff --git a/src/CardListFilter.java b/src/CardListFilter.java new file mode 100644 index 00000000000..0ba3aa2f3e5 --- /dev/null +++ b/src/CardListFilter.java @@ -0,0 +1,4 @@ +public interface CardListFilter +{ + public boolean addCard(Card c); +} diff --git a/src/CardListUtil.java b/src/CardListUtil.java new file mode 100644 index 00000000000..fadaf89f1d9 --- /dev/null +++ b/src/CardListUtil.java @@ -0,0 +1,183 @@ +import java.util.*; + +public class CardListUtil +{ + public static CardList filterToughness(CardList in, int atLeastToughness) + { + CardList out = new CardList(); + for(int i = 0; i < in.size(); i++) + if(in.get(i).getNetDefense() <= atLeastToughness) + out.add(in.get(i)); + + return out; + } + + //the higher the defense the better + @SuppressWarnings("unchecked") // Comparator needs +public static void sortDefense(CardList list) + { + Comparator com = new Comparator() + { + public int compare(Object a1, Object b1) + { + Card a = (Card)a1; + Card b = (Card)b1; + + return b.getNetDefense() - a.getNetDefense(); + } + }; + list.sort(com); + }//sortDefense() + + //the higher the attack the better + @SuppressWarnings("unchecked") // Comparator needs type +public static void sortAttack(CardList list) + { + Comparator com = new Comparator() + { + public int compare(Object a1, Object b1) + { + Card a = (Card)a1; + Card b = (Card)b1; + + if (CombatUtil.isDoranInPlay()) + return b.getNetDefense() - a.getNetDefense(); + else + return b.getNetAttack() - a.getNetAttack(); + } + }; + list.sort(com); + }//sortAttack() + + + //the lower the attack the better + @SuppressWarnings("unchecked") // Comparator needs +public static void sortAttackLowFirst(CardList list) + { + Comparator com = new Comparator() + { + public int compare(Object a1, Object b1) + { + Card a = (Card)a1; + Card b = (Card)b1; + + if (CombatUtil.isDoranInPlay()) + return a.getNetDefense() - b.getNetDefense(); + else + return a.getNetAttack() - b.getNetAttack(); + } + }; + list.sort(com); + }//sortAttackLowFirst() + + public static void sortNonFlyingFirst(CardList list) + { + sortFlying(list); + list.reverse(); + }//sortNonFlyingFirst + + //the creature with flying are better + @SuppressWarnings("unchecked") // Comparator needs +public static void sortFlying(CardList list) + { + Comparator com = new Comparator() + { + public int compare(Object a1, Object b1) + { + Card a = (Card)a1; + Card b = (Card)b1; + + if(a.getKeyword().contains("Flying") && b.getKeyword().contains("Flying")) + return 0; + else if(a.getKeyword().contains("Flying")) + return -1; + else if(b.getKeyword().contains("Flying")) + return 1; + + return 0; + } + }; + list.sort(com); + }//sortFlying() + + @SuppressWarnings("unchecked") // Comparator needs + public static void sortCMC(CardList list) + { + Comparator com = new Comparator() + { + public int compare(Object a1, Object b1) + { + Card a = (Card)a1; + Card b = (Card)b1; + + int cmcA = CardUtil.getConvertedManaCost(a.getManaCost()); + int cmcB = CardUtil.getConvertedManaCost(b.getManaCost()); + + if (cmcA == cmcB) + return 0; + if (cmcA > cmcB) + return -1; + if (cmcB > cmcA) + return 1; + + return 0; + } + }; + list.sort(com); + }//sortCMC + + + public static CardList getColor(CardList list, final String color) + { + return list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return CardUtil.getColor(c).equals(color); + } + }); + }//getColor() + + public static CardList getGoldCards(CardList list) + { + return list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return CardUtil.getColors(c).size() >= 2; + } + }); + } + + public static int sumAttack(CardList c) + { + int attack = 0; + + for(int i = 0; i < c.size(); i++){ + if(c.get(i).isCreature() && (!c.get(i).hasFirstStrike() || (c.get(i).hasDoubleStrike() && c.get(i).hasFirstStrike())) ) { + if (!CombatUtil.isDoranInPlay()) + attack += c.get(i).getNetAttack(); + else if(CombatUtil.isDoranInPlay()) + attack += c.get(i).getNetDefense(); + } + } + //System.out.println("Total attack: " +attack); + return attack; + }//sumAttack() + + public static int sumFirstStrikeAttack(CardList c) + { + int attack = 0; + + for(int i = 0; i < c.size(); i++){ + if(c.get(i).isCreature() && (c.get(i).hasFirstStrike() || c.get(i).hasDoubleStrike())) { + if (!CombatUtil.isDoranInPlay()) + attack += c.get(i).getNetAttack(); + else if(CombatUtil.isDoranInPlay()) + attack += c.get(i).getNetDefense(); + } + } + System.out.println("Total First Strike attack: " +attack); + return attack; + }//sumFirstStrikeAttack() +} \ No newline at end of file diff --git a/src/CardPanel.java b/src/CardPanel.java new file mode 100644 index 00000000000..949422e2951 --- /dev/null +++ b/src/CardPanel.java @@ -0,0 +1,20 @@ +import javax.swing.*; + +public class CardPanel extends JPanel +{ + private static final long serialVersionUID = 509877513760665415L; +private Card card; + + public CardPanel(Card card) + { + this.card = card; + } + public Card getCard() + { + return card; + } + + //~ + public CardPanel connectedCard; + //~ +} diff --git a/src/CardUtil.java b/src/CardUtil.java new file mode 100644 index 00000000000..e0b88b0ba4e --- /dev/null +++ b/src/CardUtil.java @@ -0,0 +1,184 @@ +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.StringTokenizer; + +public class CardUtil +{ + public final static Random r = new Random(); + + + public static int getRandomIndex(Object[] o) + { + if(o == null || o.length == 0) + throw new RuntimeException("CardUtil : getRandomIndex() argument is null or length is 0"); + + return r.nextInt(o.length); + } + public static Card getRandom(Card[] o) + { + return o[getRandomIndex(o)]; + } + public static int getRandomIndex(SpellAbilityList list) + { + if(list == null || list.size() == 0) + throw new RuntimeException("CardUtil : getRandomIndex(SpellAbilityList) argument is null or length is 0"); + + return r.nextInt(list.size()); + } + public static int getRandomIndex(CardList c) + {return r.nextInt(c.size());} + + //returns Card Name (unique number) attack/defense + //example: Big Elf (12) 2/3 + public static String toText(Card c) + { + return c.getName() +" (" +c.getUniqueNumber() +") " +c.getNetAttack() +"/" +c.getNetDefense(); + } + public static Card[] toCard(Collection col) + { + Object o[] = col.toArray(); + Card c[] = new Card[o.length]; + + for(int i = 0; i < c.length; i++) + { + Object swap = o[i]; + if(swap instanceof Card) + c[i] = (Card)o[i]; + else + throw new RuntimeException("CardUtil : toCard() invalid class, should be Card - " +o[i].getClass() +" - toString() - " +o[i].toString()); + } + + return c; + } + public static Card[] toCard(ArrayList list) + { + Card[] c = new Card[list.size()]; + list.toArray(c); + return c; + } + public static ArrayList toList(Card c[]) + { + ArrayList a = new ArrayList(); + for(int i = 0; i < c.length; i++) + a.add(c[i]); + return a; + } + //returns "G", longColor is Constant.Color.Green and the like + public static String getShortColor(String longColor) + { + Map map = new HashMap(); + map.put(Constant.Color.Black, "B"); + map.put(Constant.Color.Blue , "U"); + map.put(Constant.Color.Green, "G"); + map.put(Constant.Color.Red , "R"); + map.put(Constant.Color.White, "W"); + + Object o = map.get(longColor); + if(o == null) + throw new RuntimeException("CardUtil : getShortColor() invalid argument - " +longColor); + + return (String)o; + } + + + //returns something like Constant.Color.Green or something + public static String getColor(Card c) + { + String manaCost = c.getManaCost(); + + if(-1 != manaCost.indexOf("G")) + return Constant.Color.Green; + else if(-1 != manaCost.indexOf("W")) + return Constant.Color.White; + else if(-1 != manaCost.indexOf("B")) + return Constant.Color.Black; + else if(-1 != manaCost.indexOf("U")) + return Constant.Color.Blue; + else if(-1 != manaCost.indexOf("R")) + return Constant.Color.Red; + else + return Constant.Color.Colorless; + } + public static ArrayList getColors(Card c) + { + String m = c.getManaCost(); + Set colors = new HashSet(); + + for(int i = 0; i < m.length(); i++) + { + switch(m.charAt(i)) + { + case ' ': break; + case 'G': colors.add(Constant.Color.Green); break; + case 'W': colors.add(Constant.Color.White); break; + case 'B': colors.add(Constant.Color.Black); break; + case 'U': colors.add(Constant.Color.Blue); break; + case 'R': colors.add(Constant.Color.Red); break; + } + } + if(colors.isEmpty()) + colors.add(Constant.Color.Colorless); + + return new ArrayList(colors); + } + public static boolean hasCardName(String cardName, ArrayList list) + { + Card c; + boolean b = false; + + for(int i = 0; i < list.size(); i++) + { + c = (Card)list.get(i); + if(c.getName().equals(cardName)) + { + b = true; + break; + } + } + return b; + }//hasCardName() + + //probably should put this somewhere else, but not sure where + static public int getConvertedManaCost(SpellAbility sa) + { + return getConvertedManaCost(sa.getManaCost()); + } + + static public int getConvertedManaCost(String manaCost) + { + //see if the mana cost is all colorless, like "2", "0", or "12" + + if(manaCost.equals("")) + return 0; + + if (!manaCost.matches(".*[A-Z]+.*")) + { + try{ + return Integer.parseInt(manaCost); + } + catch(NumberFormatException ex) { ErrorViewer.showError(ex); } + } + + //see if mana cost is colored and colorless like "2 B" or "1 U U" + StringTokenizer tok = new StringTokenizer(manaCost); + int cost = 0; + try{ + //get the int from the mana cost like "1 U", get the 1 + cost = Integer.parseInt(tok.nextToken()); + //count colored mana cost + cost += tok.countTokens(); + return cost; + } + //catches in case the cost has no colorless mana requirements like "U U" + catch(NumberFormatException ex) {} + + //the mana cost is all colored mana like "U" or "B B B" + tok = new StringTokenizer(manaCost); + return tok.countTokens(); + } +} \ No newline at end of file diff --git a/src/Combat.java b/src/Combat.java new file mode 100644 index 00000000000..4aa94b623f8 --- /dev/null +++ b/src/Combat.java @@ -0,0 +1,409 @@ +import java.util.*; + +public class Combat +{ + //key is attacker Card + //value is CardList of blockers + private Map map = new HashMap(); + private Set blocked = new HashSet(); + + private HashMap unblockedMap = new HashMap(); + + private int attackingDamage; + private int defendingDamage; + private int defendingFirstStrikeDamage; + //private int trampleDamage; + //private int trampleFirstStrikeDamage; + + private String attackingPlayer; + private String defendingPlayer; + + private int declaredAttackers; + + private Card planeswalker; + + public Combat() {reset();} + + public void reset() + { + planeswalker = null; + + map.clear(); + blocked.clear(); + + unblockedMap.clear(); + + attackingDamage = 0; + defendingDamage = 0; + defendingFirstStrikeDamage = 0; + + declaredAttackers = 0; + attackingPlayer = ""; + defendingPlayer = ""; + } + public void setPlaneswalker(Card c){planeswalker = c;} + public Card getPlaneswalker() {return planeswalker;} + + public int getDeclaredAttackers() { return declaredAttackers;} + + public void setAttackingPlayer(String player) {attackingPlayer = player;} + public void setDefendingPlayer(String player) {defendingPlayer = player;} + + public String getAttackingPlayer() {return attackingPlayer;} + public String getDefendingPlayer() {return defendingPlayer;} + + //relates to defending player damage + public int getDefendingDamage() {return defendingDamage;} + public int getDefendingFirstStrikeDamage() {return defendingFirstStrikeDamage;} + public void setDefendingDamage() + { + defendingDamage = 0; + CardList att = new CardList(getAttackers()); + //sum unblocked attackers' power + for(int i = 0; i < att.size(); i++) { + if(! isBlocked(att.get(i))) { + int damageDealt = att.get(i).getNetAttack(); + if (CombatUtil.isDoranInPlay()) + damageDealt = att.get(i).getNetDefense(); + + //if the creature has first strike do not do damage in the normal combat phase + if(!att.get(i).hasFirstStrike() || (att.get(i).hasFirstStrike() && att.get(i).hasDoubleStrike()) ) + defendingDamage += damageDealt; + } + } + } + public void setDefendingFirstStrikeDamage() + { + defendingFirstStrikeDamage = 0; + CardList att = new CardList(getAttackers()); + //sum unblocked attackers' power + for(int i = 0; i < att.size(); i++) { + if(! isBlocked(att.get(i))) { + int damageDealt = att.get(i).getNetAttack(); + if (CombatUtil.isDoranInPlay()) + damageDealt = att.get(i).getNetDefense(); + + //if the creature has first strike or double strike do damage in the first strike combat phase + + if(att.get(i).hasFirstStrike() || att.get(i).hasDoubleStrike()){ + defendingFirstStrikeDamage += damageDealt; + } + } + } + } + public void addDefendingDamage(int n) {defendingDamage += n;} + public void addDefendingFirstStrikeDamage(int n) {defendingFirstStrikeDamage += n;} + + public void addAttackingDamage(int n) {attackingDamage += n;} + public int getAttackingDamage() {return attackingDamage;} + + public void addAttacker(Card c) {map.put(c, new CardList()); declaredAttackers++;} + public void resetAttackers() {map.clear();} + public Card[] getAttackers() + { + CardList out = new CardList(); + Iterator it = map.keySet().iterator(); + //int i = 0; //unused + + while(it.hasNext()) { + out.add((Card)it.next()); + } + + return out.toArray(); + }//getAttackers() + + public boolean isBlocked(Card attacker) {return blocked.contains(attacker);} + public void addBlocker(Card attacker, Card blocker) + { + blocked.add(attacker); + getList(attacker).add(blocker); + CombatUtil.checkBlockedAttackers(attacker, blocker); + } + public void resetBlockers() + { + reset(); + + CardList att = new CardList(getAttackers()); + for(int i = 0; i < att.size(); i++) + addAttacker(att.get(i)); + } + public CardList getAllBlockers() + { + CardList att = new CardList(getAttackers()); + CardList block = new CardList(); + + for(int i = 0; i < att.size(); i++) + block.addAll(getBlockers(att.get(i)).toArray()); + + return block; + }//getAllBlockers() + + public CardList getBlockers(Card attacker) {return new CardList(getList(attacker).toArray()); + } + private CardList getList(Card attacker) {return (CardList)map.get(attacker);} + + public void removeFromCombat(Card c) + { + //is card an attacker? + CardList att = new CardList(getAttackers()); + if(att.contains(c)) + map.remove(c); + else//card is a blocker + { + for(int i = 0; i < att.size(); i++) + if(getBlockers(att.get(i)).contains(c)) + getList(att.get(i)).remove(c); + } + }//removeFromCombat() + public void verifyCreaturesInPlay() + { + CardList all = new CardList(); + all.addAll(getAttackers()); + all.addAll(getAllBlockers().toArray()); + + for(int i = 0; i < all.size(); i++) + if(! AllZone.GameAction.isCardInPlay(all.get(i))) + removeFromCombat(all.get(i)); + }//verifyCreaturesInPlay() + + //set Card.setAssignedDamage() for all creatures in combat + //also assigns player damage by setPlayerDamage() + public void setAssignedFirstStrikeDamage() + { + setDefendingFirstStrikeDamage(); + + CardList block; + CardList attacking = new CardList(getAttackers()); + for(int i = 0; i < attacking.size(); i++) + { + + block = getBlockers(attacking.get(i)); + + //attacker always gets all blockers' attack + AllZone.GameAction.setAssignedDamage(attacking.get(i), block, CardListUtil.sumFirstStrikeAttack(block)); + //attacking.get(i).setAssignedDamage(CardListUtil.sumFirstStrikeAttack(block)); + if(block.size() == 0)//this damage is assigned to a player by setPlayerDamage() + { + //GameActionUtil.executePlayerCombatDamageEffects(attacking.get(i)); + addUnblockedAttacker(attacking.get(i)); + } + else if(block.size() == 1) + { + if(attacking.get(i).hasFirstStrike() || attacking.get(i).hasDoubleStrike()){ + int damageDealt = attacking.get(i).getNetAttack(); + if (CombatUtil.isDoranInPlay()) + damageDealt = attacking.get(i).getNetDefense(); + + //block.get(0).setAssignedDamage(damageDealt); + CardList cl = new CardList(); + cl.add(attacking.get(i)); + AllZone.GameAction.setAssignedDamage(block.get(0), cl , damageDealt); + + //trample + int trample = damageDealt - block.get(0).getNetDefense(); + if(attacking.get(i).getKeyword().contains("Trample") && 0 < trample) + { + this.addDefendingFirstStrikeDamage(trample); + //System.out.println("First Strike trample damage: " + trample); + } + } + }//1 blocker + else if(getAttackingPlayer().equals(Constant.Player.Computer)) + { + if(attacking.get(i).hasFirstStrike() || attacking.get(i).hasDoubleStrike()){ + int damageDealt = attacking.get(i).getNetAttack(); + if (CombatUtil.isDoranInPlay()) + damageDealt = attacking.get(i).getNetDefense(); + setAssignedFirstStrikeDamage(attacking.get(i), block, damageDealt); + } + } + else//human + { + if(attacking.get(i).hasFirstStrike() || attacking.get(i).hasDoubleStrike()){ + //GuiDisplay2 gui = (GuiDisplay2) AllZone.Display; + int damageDealt = attacking.get(i).getNetAttack(); + if (CombatUtil.isDoranInPlay()) + damageDealt = attacking.get(i).getNetDefense(); + AllZone.Display.assignDamage(attacking.get(i),block, damageDealt); + //System.out.println("setAssignedFirstStrikeDmg called for:" + damageDealt + " damage."); + } + } + }//for + + //should first strike affect the following? + if(getPlaneswalker() != null) + { + //System.out.println("defendingDmg (setAssignedFirstStrikeDamage) :" +defendingFirstStrikeDamage); + planeswalker.setAssignedDamage(defendingFirstStrikeDamage); + defendingFirstStrikeDamage = 0; + } + }//setAssignedFirstStrikeDamage() + private void setAssignedFirstStrikeDamage(Card attacker, CardList list, int damage) + { + CardListUtil.sortAttack(list); + Card c; + for(int i = 0; i < list.size(); i++) + { + c = list.get(i); + if(c.getKillDamage() <= damage) + { + damage -= c.getKillDamage(); + CardList cl = new CardList(); + cl.add(attacker); + + AllZone.GameAction.setAssignedDamage(c, cl, c.getKillDamage()); + //c.setAssignedDamage(c.getKillDamage()); + } + }//for + }//setAssignedFirstStrikeDamage() + + //set Card.setAssignedDamage() for all creatures in combat + //also assigns player damage by setPlayerDamage() + public void setAssignedDamage() + { + setDefendingDamage(); + + CardList block; + CardList attacking = new CardList(getAttackers()); + for(int i = 0; i < attacking.size(); i++) + { + if(!attacking.get(i).hasFirstStrike() || (attacking.get(i).hasFirstStrike() && attacking.get(i).hasDoubleStrike() )){ + block = getBlockers(attacking.get(i)); + + //attacker always gets all blockers' attack + //attacking.get(i).setAssignedDamage(CardListUtil.sumAttack(block)); + AllZone.GameAction.setAssignedDamage(attacking.get(i), block, CardListUtil.sumAttack(block)); + if(block.size() == 0)//this damage is assigned to a player by setPlayerDamage() + { + //GameActionUtil.executePlayerCombatDamageEffects(attacking.get(i)); + addUnblockedAttacker(attacking.get(i)); + } + else if(block.size() == 1) + { + int damageDealt = attacking.get(i).getNetAttack(); + if (CombatUtil.isDoranInPlay()) + damageDealt = attacking.get(i).getNetDefense(); + + //block.get(0).setAssignedDamage(damageDealt); + CardList cl = new CardList(); + cl.add(attacking.get(i)); + AllZone.GameAction.setAssignedDamage(block.get(0), cl , damageDealt); + + + //trample + int trample = damageDealt - block.get(0).getNetDefense(); + if(attacking.get(i).getKeyword().contains("Trample") && 0 < trample) { + this.addDefendingDamage(trample); + //System.out.println("Reg trample damage: " + trample); + } + }//1 blocker + else if(getAttackingPlayer().equals(Constant.Player.Computer)) + { + int damageDealt = attacking.get(i).getNetAttack(); + if (CombatUtil.isDoranInPlay()) + damageDealt = attacking.get(i).getNetDefense(); + setAssignedDamage(attacking.get(i),block, damageDealt); + + } + else//human + { + //GuiDisplay2 gui = (GuiDisplay2) AllZone.Display; + int damageDealt = attacking.get(i).getNetAttack(); + if (CombatUtil.isDoranInPlay()) + damageDealt = attacking.get(i).getNetDefense(); + AllZone.Display.assignDamage(attacking.get(i), block, damageDealt); + //System.out.println("setAssignedDmg called for:" + damageDealt + " damage."); + } + }//if !hasFirstStrike ... + //hacky code, to ensure surviving non-first-strike blockers will hit first strike attackers: + else { + block = getBlockers(attacking.get(i)); + //System.out.println("block size: " + block.size()); + if( (attacking.get(i).hasFirstStrike() || attacking.get(i).hasDoubleStrike()) ) + { + int blockerDamage = 0; + for(int j=0; j < block.size(); j++) + { + blockerDamage += block.get(j).getNetAttack(); + } + //attacking.get(i).setAssignedDamage(blockerDamage); + AllZone.GameAction.setAssignedDamage(attacking.get(i), block , blockerDamage); + } + } + }//for + + //should first strike affect the following? + if(getPlaneswalker() != null) + { + //System.out.println("defendingDmg (setAssignedDamage): " + defendingDamage); + planeswalker.setAssignedDamage(defendingDamage); + defendingDamage = 0; + } + }//assignDamage() + private void setAssignedDamage(Card attacker, CardList list, int damage) + { + CardListUtil.sortAttack(list); + Card c; + for(int i = 0; i < list.size(); i++) + { + c = list.get(i); + //if(!c.hasFirstStrike() || (c.hasFirstStrike() && c.hasDoubleStrike()) ){ + if(c.getKillDamage() <= damage) + { + damage -= c.getKillDamage(); + CardList cl = new CardList(); + cl.add(attacker); + AllZone.GameAction.setAssignedDamage(c, cl, c.getKillDamage()); + //c.setAssignedDamage(c.getKillDamage()); + } + //} + }//for + }//assignDamage() + + + public Card[] getUnblockedAttackers() + { + CardList out = new CardList(); + Iterator it = unblockedMap.keySet().iterator(); + while(it.hasNext()){ //only add creatures without firstStrike to this list. + Card c = (Card)it.next(); + if(!c.hasFirstStrike()){ + out.add(c); + } + } + + return out.toArray(); + }//getUnblockedAttackers() + + public Card[] getUnblockedFirstStrikeAttackers() + { + CardList out = new CardList(); + Iterator it = unblockedMap.keySet().iterator(); + while(it.hasNext()){ //only add creatures without firstStrike to this list. + Card c = (Card)it.next(); + if(c.hasFirstStrike() || c.hasDoubleStrike()){ + out.add(c); + } + } + + return out.toArray(); + }//getUnblockedAttackers() + + public void addUnblockedAttacker(Card c) + { + unblockedMap.put(c, new CardList()); + } + + }//Class Combat + + +/* +if(cr only has 1 blocker) + assign damage to attacker and blocker +else attacking play is computer + attacker.assignDamage(sum blockers' attack) + Combat.assignDamage(blockers, attack.getAttack()) +else //human + attacker.assignDamage(sum blockers' attack) + guiDisplay.assignDamage(blockers, attack.getAtack()) +*/ diff --git a/src/CombatPlaneswalker.java b/src/CombatPlaneswalker.java new file mode 100644 index 00000000000..4c09c139b8f --- /dev/null +++ b/src/CombatPlaneswalker.java @@ -0,0 +1,183 @@ +import java.util.*; + +public class CombatPlaneswalker +{ + //key is attacker Card + //value is CardList of blockers + private Map map = new HashMap(); + private Set blocked = new HashSet(); + + private int attackingDamage; + private int defendingDamage; + + private String attackingPlayer; + private String defendingPlayer; + + private Card planeswalker; + + public CombatPlaneswalker() {reset();} + + public void reset() + { + planeswalker = null; + + map.clear(); + blocked.clear(); + + attackingDamage = 0; + defendingDamage = 0; + + attackingPlayer = ""; + defendingPlayer = ""; + } + public void setPlaneswalker(Card c){planeswalker = c;} + public Card getPlaneswalker() {return planeswalker;} + + public void setAttackingPlayer(String player) {attackingPlayer = player;} + public void setDefendingPlayer(String player) {defendingPlayer = player;} + + public String getAttackingPlayer() {return attackingPlayer;} + public String getDefendingPlayer() {return defendingPlayer;} + + //relates to defending player damage + public int getDefendingDamage() {return defendingDamage;} + public void setDefendingDamage() + { + defendingDamage = 0; + CardList att = new CardList(getAttackers()); + //sum unblocked attackers' power + for(int i = 0; i < att.size(); i++) + if(! isBlocked(att.get(i))) + defendingDamage += att.get(i).getNetAttack(); + } + public void addDefendingDamage(int n) {defendingDamage += n;} + + public void addAttackingDamage(int n) {attackingDamage += n;} + public int getAttackingDamage() {return attackingDamage;} + + public void addAttacker(Card c) {map.put(c, new CardList());} + public void resetAttackers() {map.clear();} + public Card[] getAttackers() + { + CardList out = new CardList(); + Iterator it = map.keySet().iterator(); + while(it.hasNext()) + out.add((Card)it.next()); + + return out.toArray(); + }//getAttackers() + + public boolean isBlocked(Card attacker) {return blocked.contains(attacker);} + public void addBlocker(Card attacker, Card blocker) + { + blocked.add(attacker); + getList(attacker).add(blocker); + } + public void resetBlockers() + { + reset(); + + CardList att = new CardList(getAttackers()); + for(int i = 0; i < att.size(); i++) + addAttacker(att.get(i)); + } + public CardList getAllBlockers() + { + CardList att = new CardList(getAttackers()); + CardList block = new CardList(); + + for(int i = 0; i < att.size(); i++) + block.addAll(getBlockers(att.get(i)).toArray()); + + return block; + }//getAllBlockers() + + public CardList getBlockers(Card attacker) {return new CardList(getList(attacker).toArray());} + private CardList getList(Card attacker) {return (CardList)map.get(attacker);} + + public void removeFromCombat(Card c) + { + //is card an attacker? + CardList att = new CardList(getAttackers()); + if(att.contains(c)) + map.remove(c); + else//card is a blocker + { + for(int i = 0; i < att.size(); i++) + if(getBlockers(att.get(i)).contains(c)) + getList(att.get(i)).remove(c); + } + }//removeFromCombat() + public void verifyCreaturesInPlay() + { + CardList all = new CardList(); + all.addAll(getAttackers()); + all.addAll(getAllBlockers().toArray()); + + for(int i = 0; i < all.size(); i++) + if(! AllZone.GameAction.isCardInPlay(all.get(i))) + removeFromCombat(all.get(i)); + }//verifyCreaturesInPlay() + + //set Card.setAssignedDamage() for all creatures in combat + //also assigns player damage by setPlayerDamage() + public void setAssignedDamage() + { + setDefendingDamage(); + + CardList block; + CardList attacking = new CardList(getAttackers()); + for(int i = 0; i < attacking.size(); i++) + { + block = getBlockers(attacking.get(i)); + + //attacker always gets all blockers' attack + AllZone.GameAction.setAssignedDamage(attacking.get(i), block, CardListUtil.sumAttack(block)); + //attacking.get(i).setAssignedDamage(CardListUtil.sumAttack(block)); + if(block.size() == 0)//this damage is assigned to a player by setPlayerDamage() + ; + else if(block.size() == 1) + { + block.get(0).setAssignedDamage(attacking.get(i).getNetAttack()); + + //trample + int trample = attacking.get(i).getNetAttack() - block.get(0).getNetDefense(); + if(attacking.get(i).getKeyword().contains("Trample") && 0 < trample) + this.addDefendingDamage(trample); + + trample = block.get(0).getNetAttack() - attacking.get(i).getNetDefense(); + if(block.get(0).getKeyword().contains("Trample") && 0 < trample) + this.addAttackingDamage(trample); + + }//1 blocker + else if(getAttackingPlayer().equals(Constant.Player.Computer)) + { + setAssignedDamage(block, attacking.get(i).getNetAttack()); + } + else//human + { + GuiDisplay2 gui = (GuiDisplay2) AllZone.Display; + gui.assignDamage(attacking.get(i), block, attacking.get(i).getNetAttack()); + } + }//for + + planeswalker.setAssignedDamage(defendingDamage); + defendingDamage = 0; + + }//assignDamage() + private void setAssignedDamage(CardList list, int damage) + { + CardListUtil.sortAttack(list); + Card c; + for(int i = 0; i < list.size(); i++) + { + c = list.get(i); + if(c.getKillDamage() <= damage) + { + damage -= c.getKillDamage(); + c.setAssignedDamage(c.getKillDamage()); + } + }//for + }//assignDamage() +} + diff --git a/src/CombatUtil.java b/src/CombatUtil.java new file mode 100644 index 00000000000..e87a1779d06 --- /dev/null +++ b/src/CombatUtil.java @@ -0,0 +1,1288 @@ +import java.util.ArrayList; + +public class CombatUtil +{ + public static boolean canBlock(Card attacker, Card blocker) + { + + if(attacker == null || blocker == null) + return false; + + if (!canBlockProtection(attacker, blocker)) + return false; + + //rare case: + if (blocker.getKeyword().contains("Shadow") + && blocker.getKeyword().contains("This creature can block creatures with shadow as though they didn't have shadow.")) + return false; + + /* + if(attacker.getKeyword().contains("Shadow")) + return blocker.getKeyword().contains("Shadow") || + blocker.getKeyword().contains("This creature can block creatures with shadow as though they didn't have shadow."); + */ + if (attacker.getKeyword().contains("Shadow") && !blocker.getKeyword().contains("Shadow") + && !blocker.getKeyword().contains("This creature can block creatures with shadow as though they didn't have shadow.") ) + return false; + + if(! attacker.getKeyword().contains("Shadow") && + blocker.getKeyword().contains("Shadow")) + return false; + + if (attacker.getNetAttack() <= 2 && blocker.getName().equals("Sunweb")) + return false; + + + PlayerZone blkPZ = AllZone.getZone(Constant.Zone.Play, blocker.getController()); + CardList blkCL = new CardList(blkPZ.getCards()); + CardList temp = new CardList(); + + if(attacker.getKeyword().contains("Plainswalk")) + { + temp = blkCL.getType("Plains"); + if(!temp.isEmpty()) + return false; + } + + if(attacker.getKeyword().contains("Islandwalk")) + { + temp = blkCL.getType("Island"); + if(!temp.isEmpty()) + return false; + } + + if(attacker.getKeyword().contains("Swampwalk")) + { + temp = blkCL.getType("Swamp"); + if(!temp.isEmpty()) + return false; + } + + if(attacker.getKeyword().contains("Mountainwalk")) + { + temp = blkCL.getType("Mountain"); + if(!temp.isEmpty()) + return false; + } + + if(attacker.getKeyword().contains("Forestwalk")) + { + temp = blkCL.getType("Forest"); + if(!temp.isEmpty()) + return false; + } + + if (attacker.getKeyword().contains("Legendary landwalk")) + { + temp = blkCL.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.isLand() && c.getType().contains("Legendary"); + } + }); + if (!temp.isEmpty()) + return false; + } + + if (attacker.getKeyword().contains("Nonbasic landwalk")) + { + temp = blkCL.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.isLand() && !c.isBasicLand(); + } + }); + if (!temp.isEmpty()) + return false; + } + + + if(blocker.getKeyword().contains("This creature can block only creatures with flying.") && !attacker.getKeyword().contains("Flying")) + return false; + + if(attacker.getKeyword().contains("Unblockable")) + return false; + + if(blocker.getKeyword().contains("This creature cannot block") || blocker.getKeyword().contains("This creature can't attack or block")) + return false; + + if (attacker.getKeyword().contains("Flying")) + { + if (!blocker.getKeyword().contains("Flying") && + !blocker.getKeyword().contains("This creature can block as though it had flying.") && + !blocker.getKeyword().contains("Reach")) + return false; + } + + if (attacker.getKeyword().contains("Horsemanship")) + { + if (!blocker.getKeyword().contains("Horsemanship")) + return false; + } + + if (attacker.getName().equals("Taoist Warrior") || attacker.getName().equals("Zuo Ci, the Mocking Sage")) + { + if (blocker.getKeyword().contains("Horsemanship")) + return false; + } + + if (attacker.getKeyword().contains("Fear")) + { + if (!blocker.getType().contains("Artifact") && + !CardUtil.getColors(blocker).contains(Constant.Color.Black) /*&& + !CardUtil.getColors(blocker).contains(Constant.Color.Colorless) */) //should not include colorless, right? + return false; + } + + if (attacker.getName().equals("Barrenton Cragtreads")) + { + if (CardUtil.getColors(blocker).contains(Constant.Color.Red)) + return false; + } + + if (attacker.getName().equals("Amrou Seekers")) + { + if (!blocker.getType().contains("Artifact") && + !CardUtil.getColors(blocker).contains(Constant.Color.White)) + return false; + } + + if (attacker.getName().equals("Skirk Shaman")) + { + if (!blocker.getType().contains("Artifact") && + !CardUtil.getColors(blocker).contains(Constant.Color.Red)) + return false; + } + /* + if(attacker.getKeyword().contains("Flying")) + return blocker.getKeyword().contains("Flying") || + blocker.getKeyword().contains("This creature can block as though it had flying.") || + blocker.getKeyword().contains("Reach"); + + if(attacker.getKeyword().contains("Fear")) + return blocker.getType().contains("Artifact") || + CardUtil.getColors(blocker).contains(Constant.Color.Black) || + CardUtil.getColors(blocker).contains(Constant.Color.Colorless); + + if (attacker.getName().equals("Amrou Seekers")) + return blocker.getType().contains("Artifact") || + CardUtil.getColors(blocker).contains(Constant.Color.White); + + if(attacker.getName().equals("Skirk Shaman")) + return blocker.getType().contains("Artifact") || + CardUtil.getColors(blocker).contains(Constant.Color.Red); + */ + if(attacker.getName().equals("Goldmeadow Dodger")) + return blocker.getNetAttack() < 4; + + if(attacker.getName().equals("Juggernaut") && blocker.getType().contains("Wall")) + return false; + + return true; + }//canBlock() + public static boolean canAttack(Card c) + { + + boolean moatPrevented = false; + if (isMoatInPlay() || isMagusMoatInPlay()) + { + if (!c.getKeyword().contains("Flying")) + { + moatPrevented = true; + } + } + if(c.isTapped() || c.hasSickness() || c.getKeyword().contains("Defender") || moatPrevented || oppControlsBlazingArchon(c) + || c.getKeyword().contains("This creature can't attack") || c.getKeyword().contains("This creature can't attack or block") ) + return false; + + //if Card has Haste, Card.hasSickness() will return false + return true; + }//canAttack() + + public static boolean canDestroyAttacker(Card attacker, Card defender) + { + + if (attacker.getName().equals("Sylvan Basilisk")) + return false; + + int flankingMagnitude = 0; + if (attacker.getKeyword().contains("Flanking") && !defender.getKeyword().contains("Flanking")) + { + + String kw = ""; + ArrayList list = attacker.getKeyword(); + + for (int i=0;i= defender.getNetDefense() - defender.getDamage()) + return false; + + }//flanking + + if (attacker.getName().equals("Cho-Manno, Revolutionary")) + return false; + + //this usually doesn't happen, unless the attacker got pro {color} after being blocked, or the defender became {color} + if (attacker.getKeyword().contains("Protection from white") && CardUtil.getColors(defender).contains(Constant.Color.White)) + return false; + if (attacker.getKeyword().contains("Protection from blue") && CardUtil.getColors(defender).contains(Constant.Color.Blue)) + return false; + if (attacker.getKeyword().contains("Protection from black") && CardUtil.getColors(defender).contains(Constant.Color.Black)) + return false; + if (attacker.getKeyword().contains("Protection from red") && CardUtil.getColors(defender).contains(Constant.Color.Red)) + return false; + if (attacker.getKeyword().contains("Protection from green") && CardUtil.getColors(defender).contains(Constant.Color.Green)) + return false; + + if (attacker.getKeyword().contains("Protection from artifacts") && defender.isArtifact()) + return false; + + if (attacker.getKeyword().contains("Protection from creatures")) + return false; + + if (attacker.getKeyword().contains("Protection from Dragons") && (defender.getType().contains("Dragon") || defender.getKeyword().contains("Changeling") )) + return false; + if (attacker.getKeyword().contains("Protection from Demons") && (defender.getType().contains("Demon") || defender.getKeyword().contains("Changeling") )) + return false; + if (attacker.getKeyword().contains("Protection from Goblins") && (defender.getType().contains("Goblin") || defender.getKeyword().contains("Changeling") )) + return false; + + + int defenderDamage = defender.getNetAttack() - flankingMagnitude; + int attackerDamage = attacker.getNetAttack(); + + if (isDoranInPlay()) { + defenderDamage = defender.getNetDefense() - flankingMagnitude; + attackerDamage = attacker.getNetDefense(); + } + int defenderLife = defender.getNetDefense() - flankingMagnitude; + int attackerLife = attacker.getNetDefense(); + + if (defender.getKeyword().contains("Double Strike")) + { + if (defender.getKeyword().contains("Deathtouch")) + return true; + + if (attacker.getKeyword().contains("Double Strike")) + { + if (defenderDamage >= attackerLife - attacker.getDamage()) + return true; + if ( ((defenderLife - defender.getDamage()) > attackerDamage) && + (attackerLife - attacker.getDamage() <= 2*defenderDamage) && !attacker.getKeyword().contains("Deathtouch")) + return true; + } + else if (attacker.getKeyword().contains("First Strike")) //hmm, same as previous if ? + { + if (defenderDamage >= attackerLife - attacker.getDamage()) + return true; + if ( ((defenderLife - defender.getDamage()) > attackerDamage) && + ((attackerLife - attacker.getDamage()) <= 2*defenderDamage) && !attacker.getKeyword().contains("Deathtouch")) + return true; + } + else //no double nor first strike for attacker + { + if (defenderDamage >= attackerLife - attacker.getDamage()) + return true; + if ((attackerLife - attacker.getDamage()) <= 2*defenderDamage) + return true; + } + + }//defender double strike + + else if(defender.getKeyword().contains("First Strike")) + { + if (defender.getKeyword().contains("Deathtouch")) + return true; + + if (defenderDamage >= attackerLife - attacker.getDamage()) + return true; + }//defender first strike + + else //no double nor first strike for defender + { + if (attacker.getKeyword().contains("Double Strike")) + { + if (defenderDamage >= attackerLife - attacker.getDamage() && + attackerDamage*2 < defenderLife - defender.getDamage()) + return true; + + if (defender.getKeyword().contains("Deathtouch") && !attacker.getKeyword().contains("Deathtouch") && + attackerDamage*2 < defenderLife - defender.getDamage()) + return true; + } + else if (attacker.getKeyword().contains("First Strike")) //same as previous if? + { + if (defenderDamage >= attackerLife - attacker.getDamage() && !attacker.getKeyword().contains("Deathtouch") && + attackerDamage < defenderLife - defender.getDamage()) + return true; + + if (defender.getKeyword().contains("Deathtouch") && !attacker.getKeyword().contains("Deathtouch") && + attackerDamage < defenderLife - defender.getDamage()) + return true; + } + else //no double nor first strike for attacker + { + if (defender.getKeyword().contains("Deathtouch")) + return true; + + return defenderDamage >= attackerLife - attacker.getDamage(); + } + + }//defender no double/first strike + return false; //should never arrive here + } //canDestroyAttacker + + public static boolean canDestroyBlocker(Card defender, Card attacker) + { + if (attacker.getName().equals("Sylvan Basilisk")) + return true; + + int flankingMagnitude = 0; + if (attacker.getKeyword().contains("Flanking") && !defender.getKeyword().contains("Flanking")) + { + + String kw = ""; + ArrayList list = attacker.getKeyword(); + + for (int i=0;i= defender.getNetDefense() - defender.getDamage()) + return true; + + }//flanking + if (defender.getName().equals("Cho-Manno, Revolutionary")) + return false; + + + if (defender.getKeyword().contains("Protection from white") && CardUtil.getColors(attacker).contains(Constant.Color.White)) + return false; + if (defender.getKeyword().contains("Protection from blue") && CardUtil.getColors(attacker).contains(Constant.Color.Blue)) + return false; + if (defender.getKeyword().contains("Protection from black") && CardUtil.getColors(attacker).contains(Constant.Color.Black)) + return false; + if (defender.getKeyword().contains("Protection from red") && CardUtil.getColors(attacker).contains(Constant.Color.Red)) + return false; + if (defender.getKeyword().contains("Protection from green") && CardUtil.getColors(attacker).contains(Constant.Color.Green)) + return false; + + if (defender.getKeyword().contains("Protection from artifacts") && attacker.isArtifact()) + return false; + + if (defender.getKeyword().contains("Protection from creatures")) + return false; + + if (defender.getKeyword().contains("Protection from Dragons") && (attacker.getType().contains("Dragon") || attacker.getKeyword().contains("Changeling") )) + return false; + if (defender.getKeyword().contains("Protection from Demons") && (attacker.getType().contains("Demon") || attacker.getKeyword().contains("Changeling") )) + return false; + if (defender.getKeyword().contains("Protection from Goblins") && (attacker.getType().contains("Goblin") || attacker.getKeyword().contains("Changeling") )) + return false; + + int defenderDamage = defender.getNetAttack() - flankingMagnitude; + int attackerDamage = attacker.getNetAttack(); + + if (isDoranInPlay()) { + defenderDamage = defender.getNetDefense() - flankingMagnitude; + attackerDamage = attacker.getNetDefense(); + } + int defenderLife = defender.getNetDefense() - flankingMagnitude; + int attackerLife = attacker.getNetDefense(); + + if (attacker.getKeyword().contains("Double Strike")) + { + if (attacker.getKeyword().contains("Deathtouch")) + return true; + + if (defender.getKeyword().contains("Double Strike")) + { + if (defenderDamage >= attackerLife - attacker.getDamage()) + return true; + if ( ((attackerLife - attacker.getDamage()) > defenderDamage) && + (defenderLife - defender.getDamage() <= 2*attackerDamage) && !defender.getKeyword().contains("Deathtouch")) + return true; + } + else if (defender.getKeyword().contains("First Strike")) //hmm, same as previous if ? + { + if (attackerDamage >= defenderLife - defender.getDamage()) + return true; + if ( ((attackerLife - attacker.getDamage()) > defenderDamage) && + ((defenderLife - defender.getDamage()) <= 2*attackerDamage) && !defender.getKeyword().contains("Deathtouch")) + return true; + } + else //no double nor first strike for defender + { + if (attackerDamage >= defenderLife - defender.getDamage()) + return true; + if ((defenderLife - defender.getDamage()) <= 2*attackerDamage) + return true; + } + + }//attacker double strike + + else if(attacker.getKeyword().contains("First Strike")) + { + if (attacker.getKeyword().contains("Deathtouch")) + return true; + if (attackerDamage >= defenderLife - defender.getDamage()) + return true; + }//attacker first strike + + else //no double nor first strike for attacker + { + if (defender.getKeyword().contains("Double Strike")) + { + if (attackerDamage >= defenderLife - defender.getDamage() && + defenderDamage < attackerLife - attacker.getDamage()) + return true; + } + else if (defender.getKeyword().contains("First Strike")) //same as previous if? + { + if (attackerDamage >= defenderLife - defender.getDamage() && + defenderDamage < attackerLife - attacker.getDamage()) + return true; + } + else //no double nor first strike for defender + { + if (attacker.getKeyword().contains("Deathtouch")) + return true; + + return attackerDamage >= defenderLife - defender.getDamage(); + } + + }//attacker no double/first strike + return false; //should never arrive here + }//canDestroyBlocker + + public static void removeAllDamage() + { + Card[] c = AllZone.Human_Play.getCards(); + for(int i = 0; i < c.length; i++) + c[i].setDamage(0); + + c = AllZone.Computer_Play.getCards(); + for(int i = 0; i < c.length; i++) + c[i].setDamage(0); + } + public static void showCombat() + { + //clear + AllZone.Display.showCombat(""); + + Card attack[] = AllZone.Combat.getAttackers(); + Card defend[] = null; + String display = ""; + String attackerName = ""; + String blockerName = ""; + + //loop through attackers + for(int i = 0; i < attack.length; i++) + { + GameActionUtil.executeExaltedEffects2(attack[i], AllZone.Combat); + checkDeclareAttackers(attack[i]); + attackerName = attack[i].getName(); + if (attack[i].isFaceDown()) + attackerName = "Morph"; + display += attackerName +" (" +attack[i].getUniqueNumber() +") " +attack[i].getNetAttack() +"/" +attack[i].getNetDefense() +" is attacking \n"; + + defend = AllZone.Combat.getBlockers(attack[i]).toArray(); + + //loop through blockers + for(int inner = 0; inner < defend.length; inner++) + { + checkDeclareBlockers(defend[inner]); + blockerName = defend[inner].getName(); + if(defend[inner].isFaceDown()) + blockerName = "Morph"; + display += " " +blockerName +" (" +defend[inner].getUniqueNumber() +") " +defend[inner].getNetAttack() +"/" +defend[inner].getNetDefense() +" is blocking \n"; + } + }//while - loop through attackers + String s = display + getPlaneswalkerBlockers(); + AllZone.Display.showCombat(s.trim()); + + }//showBlockers() + + private static String getPlaneswalkerBlockers() + { + Card attack[] = AllZone.pwCombat.getAttackers(); + Card defend[] = null; + String display = ""; + + if(attack.length != 0) + display = "Planeswalker Combat\r\n"; + + String attackerName = ""; + String blockerName = ""; + //loop through attackers + for(int i = 0; i < attack.length; i++) + { + GameActionUtil.executeExaltedEffects2(attack[i], AllZone.pwCombat); + checkDeclareAttackers(attack[i]); + attackerName = attack[i].getName(); + if (attack[i].isFaceDown()) + attackerName = "Morph"; + + display += attackerName +" (" +attack[i].getUniqueNumber() +") " +attack[i].getNetAttack() +"/" +attack[i].getNetDefense() +" is attacking \n"; + + defend = AllZone.pwCombat.getBlockers(attack[i]).toArray(); + + //loop through blockers + for(int inner = 0; inner < defend.length; inner++) + { + checkDeclareBlockers(defend[inner]); + blockerName = defend[inner].getName(); + if(defend[inner].isFaceDown()) + blockerName = "Morph"; + display += " " +blockerName +" (" +defend[inner].getUniqueNumber() +") " +defend[inner].getNetAttack() +"/" +defend[inner].getNetDefense() +" is blocking \n"; + } + }//while - loop through attackers + + return display; + }//getPlaneswalkerBlockers() + + private static boolean canBlockProtection(Card attacker, Card blocker) + { + ArrayList list = attacker.getKeyword(); + + String kw = ""; + for (int i=0;i 0) + return true; + else + return false; + } + public static boolean oppControlsBlazingArchon(Card c) + { + String opp = AllZone.GameAction.getOpponent(c.getController()); + + CardList list = new CardList(); + list.addAll(AllZone.getZone(Constant.Zone.Play, opp).getCards()); + + list = list.getName("Blazing Archon"); + if (list.size() > 0) + return true; + else + return false; + } + + public static boolean isMoatInPlay() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + all = all.getName("Moat"); + if (all.size() > 0) + return true; + else + return false; + } + + public static boolean isMagusMoatInPlay() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + all = all.getName("Magus of the Moat"); + if (all.size() > 0) + return true; + else + return false; + } + + private static void checkDeclareAttackers(Card c) //this method checks triggered effects of attacking creatures, right before defending player declares blockers + { + if (AllZone.Phase.getPhase().equals("Declare Attackers")) + { + + //Beastmaster Ascension + if (!c.getCreatureAttackedThisTurn()) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + CardList list = new CardList(play.getCards()); + list = list.getName("Beastmaster Ascension"); + + for(Card var:list) { + var.addCounter(Counters.QUEST, 1); + } + } //BMA + + //Fervent Charge + if (!c.getCreatureAttackedThisTurn()) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + CardList list = new CardList(play.getCards()); + list = list.getName("Fervent Charge"); + + for(Card var:list) { + final Card crd = c; + Ability ability2 = new Ability(var,"0") + { + public void resolve() + { + + final Command untilEOT = new Command() + { + + private static final long serialVersionUID = 4495506596523335907L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(crd)) + { + crd.addTempAttackBoost(-2); + crd.addTempDefenseBoost(-2); + } + } + };//Command + + + if(AllZone.GameAction.isCardInPlay(crd)) + { + crd.addTempAttackBoost(2); + crd.addTempDefenseBoost(2); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve + + };//ability + + ability2.setStackDescription(var.getName() + " - " + c.getName() + " gets +2/+2 until EOT."); + AllZone.Stack.add(ability2); + + } + }//Fervent Charge + + if (c.getName().equals("Zhang He, Wei General") && !c.getCreatureAttackedThisTurn()) + { + final PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + + //final Card crd = c; + Ability ability2 = new Ability(c,"0") + { + public void resolve() + { + CardList cl = new CardList(play.getCards()); + cl = cl.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && !c.getName().equals("Zhang He, Wei General"); + } + }); + + final CardList creatures = cl; + + final Command untilEOT = new Command() + { + + private static final long serialVersionUID = 8799962485775380711L; + + + + public void execute() + { + for (Card creat:creatures){ + if(AllZone.GameAction.isCardInPlay(creat)) + { + creat.addTempAttackBoost(-1); + } + } + } + };//Command + + for (Card creat:creatures){ + if(AllZone.GameAction.isCardInPlay(creat) ) + { + creat.addTempAttackBoost(1); + } + } + AllZone.EndOfTurn.addUntil(untilEOT); + } + }; + + ability2.setStackDescription(c.getName() + " - all other creatures you control get +1/+0 until end of turn."); + AllZone.Stack.add(ability2); + }//Zhang He + + if (c.getName().equals("Soltari Champion") && !c.getCreatureAttackedThisTurn()) + { + final PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + + final Card crd = c; + Ability ability2 = new Ability(c,"0") + { + public void resolve() + { + CardList cl = new CardList(play.getCards()); + cl = cl.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && !c.equals(crd); + } + }); + + final CardList creatures = cl; + + final Command untilEOT = new Command() + { + + private static final long serialVersionUID = -8434529949884582940L; + + public void execute() + { + for (Card creat:creatures){ + if(AllZone.GameAction.isCardInPlay(creat)) + { + creat.addTempAttackBoost(-1); + creat.addTempDefenseBoost(-1); + } + } + } + };//Command + + for (Card creat:creatures){ + if(AllZone.GameAction.isCardInPlay(creat) ) + { + creat.addTempAttackBoost(1); + creat.addTempDefenseBoost(1); + } + } + AllZone.EndOfTurn.addUntil(untilEOT); + } + }; + + ability2.setStackDescription(c.getName() + " - all other creatures you control get +1/+1 until end of turn."); + AllZone.Stack.add(ability2); + }//Soltari Champion + + if (c.getName().equals("Goblin General") && !c.getCreatureAttackedThisTurn()) + { + final PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + + //final Card crd = c; + Ability ability2 = new Ability(c,"0") + { + public void resolve() + { + CardList cl = new CardList(play.getCards()); + cl = cl.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && (c.getType().contains("Goblin") || c.getKeyword().contains("Changeling") ); + } + }); + + final CardList creatures = cl; + + final Command untilEOT = new Command() + { + + private static final long serialVersionUID = -8434529949884582940L; + + public void execute() + { + for (Card creat:creatures){ + if(AllZone.GameAction.isCardInPlay(creat)) + { + creat.addTempAttackBoost(-1); + creat.addTempDefenseBoost(-1); + } + } + } + };//Command + + for (Card creat:creatures){ + if(AllZone.GameAction.isCardInPlay(creat) ) + { + creat.addTempAttackBoost(1); + creat.addTempDefenseBoost(1); + } + } + AllZone.EndOfTurn.addUntil(untilEOT); + } + }; + + ability2.setStackDescription(c.getName() + " - Goblin creatures you control get +1/+1 until end of turn."); + AllZone.Stack.add(ability2); + }//Goblin General + + if(c.getName().equals("Zur the Enchanter") && !c.getCreatureAttackedThisTurn()) + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, c.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + PlayerZone oppPlay = AllZone.getZone(Constant.Zone.Play, AllZone.GameAction.getOpponent(c.getController())); + + CardList enchantments = new CardList(library.getCards()); + enchantments = enchantments.filter(new CardListFilter(){ + + public boolean addCard(Card c) { + if (c.isEnchantment() && CardUtil.getConvertedManaCost(c.getManaCost()) <= 3) + return true; + else + return false; + } + }); + + if (enchantments.size() > 0) { + if (c.getController().equals("Human")) + { + Object o = AllZone.Display.getChoiceOptional("Pick an enchantment to put into play", enchantments.toArray()); + if(o != null) + { + Card crd = (Card)o; + library.remove(crd); + play.add(crd); + + if (crd.isAura()) + { + Object obj = null; + if (crd.getKeyword().contains("Enchant creature")) + { + CardList creats = new CardList(play.getCards()); + creats.addAll(oppPlay.getCards()); + creats = creats.getType("Creature"); + obj = AllZone.Display.getChoiceOptional("Pick a creature to attach "+crd.getName() + " to",creats.toArray() ); + } + else if (crd.getKeyword().contains("Enchant land") || crd.getKeyword().contains("Enchant land you control")) + { + CardList lands = new CardList(play.getCards()); + //lands.addAll(oppPlay.getCards()); + lands = lands.getType("Land"); + if (lands.size() > 0) + obj = AllZone.Display.getChoiceOptional("Pick a land to attach "+crd.getName() + " to",lands.toArray() ); + } + if (obj != null) + { + Card target = (Card)obj; + if(AllZone.GameAction.isCardInPlay(target)) { + crd.enchantCard(target); + } + } + + } + AllZone.GameAction.shuffle(c.getController()); + //we have to have cards like glorious anthem take effect immediately: + for (String effect : AllZone.StateBasedEffects.getStateBasedMap().keySet() ) { + Command com = GameActionUtil.commands.get(effect); + com.execute(); + } + GameActionUtil.executeCardStateEffects(); + + } + } + else if (c.getController().equals("Computer")) + { + enchantments = enchantments.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return !c.isAura(); + } + }); + if (enchantments.size() > 0) + { + Card card = enchantments.get(0); + library.remove(card); + play.add(card); + AllZone.GameAction.shuffle(c.getController()); + //we have to have cards like glorious anthem take effect immediately: + GameActionUtil.executeCardStateEffects(); + } + } + } //enchantments.size > 0 + }//Zur the enchanter + + else if(c.getName().equals("Yore-Tiller Nephilim") && !c.getCreatureAttackedThisTurn()) + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, c.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + + CardList creatures = new CardList(grave.getCards()); + creatures = creatures.getType("Creature"); + + if (creatures.size() > 0) { + if (c.getController().equals("Human")) + { + Object o = AllZone.Display.getChoiceOptional("Pick a creature to put into play", creatures.toArray()); + if(o != null) + { + Card card = (Card)o; + grave.remove(card); + play.add(card); + + card.tap(); + AllZone.Combat.addAttacker(card); + //the card that gets put into play tapped and attacking might trigger another ability: + //however, this turns out to be incorrect rules-wise + //checkDeclareAttackers(card); + } + } + else if (c.getController().equals("Computer")) + { + Card card = creatures.get(0); + grave.remove(card); + play.add(card); + + card.tap(); + AllZone.Combat.addAttacker(card); + //checkDeclareAttackers(card); + } + + } //if (creatures.size() > 0) + }//Yore-Tiller Nephilim + else if(c.getName().equals("Flowstone Charger") && !c.getCreatureAttackedThisTurn()) + { + final Card charger = c; + Ability ability2 = new Ability(c,"0") + { + public void resolve() + { + + final Command untilEOT = new Command() + { + private static final long serialVersionUID = -1703473800920781454L; + + public void execute() + { + if(AllZone.GameAction.isCardInPlay(charger)) + { + charger.addTempAttackBoost(-3); + charger.addTempDefenseBoost(3); + } + } + };//Command + + + if(AllZone.GameAction.isCardInPlay(charger)) + { + charger.addTempAttackBoost(3); + charger.addTempDefenseBoost(-3); + + AllZone.EndOfTurn.addUntil(untilEOT); + } + }//resolve + + };//ability + + ability2.setStackDescription(c.getName() + " - gets +3/-3 until EOT."); + AllZone.Stack.add(ability2); + + + }//Flowstone Charger + else if(c.getName().equals("Jedit Ojanen of Efrava") && !c.getCreatureAttackedThisTurn()) + { + final Card jedit = c; + Ability ability2 = new Ability(c,"0") + { + public void resolve() + { + Card card = new Card(); + + card.setOwner(jedit.getController()); + card.setController(jedit.getController()); + + card.setName("Cat Warrior"); + card.setImageName("G 2 2 Cat Warrior"); + card.setManaCost("G"); + card.setToken(true); + card.addIntrinsicKeyword("Forestwalk"); + + card.addType("Creature"); + card.addType("Cat"); + card.addType("Warrior"); + card.setBaseAttack(2); + card.setBaseDefense(2); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, jedit.getController()); + play.add(card); + + //(anger) : + GameActionUtil.executeCardStateEffects(); + + } + }; //Ability + + + ability2.setStackDescription(c.getName() + " - put a 2/2 green Cat Warrior creature token with forestwalk into play."); + AllZone.Stack.add(ability2); + + }//Jedit + + else if(c.getName().equals("Preeminent Captain") && !c.getCreatureAttackedThisTurn()) + { + System.out.println("Preeminent Captain Attacks"); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, c.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + + CardList soldiers = new CardList(hand.getCards()); + soldiers = soldiers.getType("Soldier"); + + if (soldiers.size() > 0) { + if (c.getController().equals("Human")) + { + Object o = AllZone.Display.getChoiceOptional("Pick a soldier to put into play", soldiers.toArray()); + if(o != null) + { + Card card = (Card)o; + hand.remove(card); + play.add(card); + + card.tap(); + AllZone.Combat.addAttacker(card); + //the card that gets put into play tapped and attacking might trigger another ability: + //however, this turns out to be incorrect rules-wise + //checkDeclareAttackers(card); + card.setCreatureAttackedThisTurn(true); + } + } + else if (c.getController().equals("Computer")) + { + Card card = soldiers.get(0); + hand.remove(card); + play.add(card); + + card.tap(); + AllZone.Combat.addAttacker(card); + //checkDeclareAttackers(card); + card.setCreatureAttackedThisTurn(true); + } + + } //if (creatures.size() > 0) + }//Preeminent Captain + + c.setCreatureAttackedThisTurn(true); + + }//if Phase = declare attackers + }//checkDeclareAttackers + private static void checkDeclareBlockers(Card c) + { + if (AllZone.Phase.getPhase().equals("Declare Blockers")) + { + if(c.getName().equals("Jedit Ojanen of Efrava") && !c.getCreatureBlockedThisTurn()) + { + Card card = new Card(); + + card.setOwner(c.getController()); + card.setController(c.getController()); + + card.setName("Cat Warrior"); + card.setImageName("G 2 2 Cat Warrior"); + card.setManaCost("G"); + card.setToken(true); + card.addIntrinsicKeyword("Forestwalk"); + + card.addType("Creature"); + card.addType("Cat"); + card.addType("Warrior"); + card.setBaseAttack(2); + card.setBaseDefense(2); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + play.add(card); + + //(anger) : + GameActionUtil.executeCardStateEffects(); + + c.setCreatureBlockedThisTurn(true); + + + }//Jedit + else if(c.getName().equals("Shield Sphere") && !c.getCreatureBlockedThisTurn()) + { + //int toughness = c.getNetDefense(); + //c.setDefense(toughness-1); + c.addCounter(Counters.P0M1, 1); + + c.setCreatureBlockedThisTurn(true); + + //ability2.setStackDescription(c.getName() + " blocks and gets a 0/-1 counter."); + //AllZone.Stack.add(ability2); + + }//Shield Sphere + + else if(c.getName().equals("Meglonoth") && !c.getCreatureBlockedThisTurn()) + { + PlayerLife oppLife = AllZone.GameAction.getPlayerLife(AllZone.GameAction.getOpponent(c.getController())); + oppLife.subtractLife(c.getNetAttack()); + + + c.setCreatureBlockedThisTurn(true); + + //ability2.setStackDescription(c.getName() + " blocks and deals damage equal to its power to attacking player."); + //AllZone.Stack.add(ability2); + + }//Shield Sphere + + }//if Phase == declare blockers + }//checkDeclareBlockers + + public static void checkBlockedAttackers(Card a, Card b) + { + System.out.println(a.getName() + " got blocked by " + b.getName()); + + if(a.getKeyword().contains("Flanking") && !b.getKeyword().contains("Flanking")) + { + int flankingMagnitude = 0; + String kw = ""; + ArrayList list = a.getKeyword(); + + for (int i=0;i a = new ArrayList(); + + //bug fix, when token is pumped up like with Giant Growth + //and Sorceress Queen targets token, the effects need to be done + //in this order, weird I know, DO NOT CHANGE THIS + public void add(Command c) {a.add(0,c);} + + + public Command get(int i) {return (Command) a.get(i);} + public Command remove(int i) {return (Command)a.remove(i);} + public int size() {return a.size();} + public void clear() {a.clear();} + + public void execute() + { + for(int i = 0; i < size(); i++) + get(i).execute(); + } + +} diff --git a/src/CommandReturn.java b/src/CommandReturn.java new file mode 100644 index 00000000000..16548fff7f0 --- /dev/null +++ b/src/CommandReturn.java @@ -0,0 +1,4 @@ +public interface CommandReturn +{ + public Object execute(); +} \ No newline at end of file diff --git a/src/Computer.java b/src/Computer.java new file mode 100644 index 00000000000..15bb224841d --- /dev/null +++ b/src/Computer.java @@ -0,0 +1,15 @@ +public interface Computer +{ + //must shuffle this + public Card[] getLibrary(); + + public void main1(); + public void declare_attackers_before(); //can play Instants and Abilities + public void declare_attackers(); + public void declare_blockers();//this is called after when the Human or Computer blocks + public void declare_blockers_after();//can play Instants and Abilities + public void main2(); + public void end_of_turn();//end of Human's turn + + public void stack_not_empty(); +} diff --git a/src/ComputerAI_Burn.java b/src/ComputerAI_Burn.java new file mode 100644 index 00000000000..6b7066f1ab2 --- /dev/null +++ b/src/ComputerAI_Burn.java @@ -0,0 +1,132 @@ +//import java.util.*; +import javax.swing.SwingUtilities; + + +public class ComputerAI_Burn implements Computer { + private volatile boolean playLand = true; + + public void main1() { + if(playLand) { + playLand = false; + ComputerUtil.playLand(); + } + Runnable run = new Runnable() { + public void run() { + synchronized(ComputerAI_Burn.this) { + if(AllZone.Stack.size() == 0) { + SpellAbility[] all = ComputerUtil.getSpellAbility(); + + for(int i = 0; i < all.length; i++) { + if(ComputerUtil.canPayCost(all[i]) && all[i].canPlay()) { + if(all[i].isSpell()) AllZone.Computer_Hand.remove(all[i].getSourceCard()); + + if(all[i] instanceof Ability_Tap) { + all[i].getSourceCard().tap(); + } + + ComputerUtil.payManaCost(all[i]); + String name = all[i].getSourceCard().getName(); + if(name.equals("Shock") || name.equals("Lightning Bolt") || name.equals("Char")) all[i].setTargetPlayer(Constant.Player.Human); + else all[i].chooseTargetAI(); + AllZone.Stack.add(all[i]); + return; + } + }//for + if(AllZone.Phase.is(Constant.Phase.Main1, Constant.Player.Computer)) { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Burn.runnable) = true; Note: this is untested, did it work?"); + AllZone.Phase.setNeedToNextPhase(true); + } + }//if + }//synchronized + }//run() + };//Runnable + try { + SwingUtilities.invokeLater(run); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("ComputerAI_Burn : main1() error, " + ex); + } + }//main1() + + public void main2() { + playLand = true; + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Burn.main2) = true; Note, this is untested, did it work?"); + AllZone.Phase.setNeedToNextPhase(true); + } + public void declare_attackers_before() + { + AllZone.Phase.setNeedToNextPhase(true); + } + public void declare_attackers() { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Burn.declare_attackers) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + public void declare_blockers() { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Burn.declare_blockers()) = true"); + AllZone.Phase.setNeedToNextPhase(true); + + } + + public void declare_blockers_after() { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Burn.declare_blockers_after()) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + //end of Human's turn + public void end_of_turn() { + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Burn.end_of_turn()) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + //must shuffle this + public Card[] getLibrary() { + CardFactory cf = AllZone.CardFactory; + CardList library = new CardList(); + for(int i = 0; i < 4; i++) { + library.add(cf.getCard("Lightning Bolt", Constant.Player.Computer)); + library.add(cf.getCard("Shock", Constant.Player.Computer)); + library.add(cf.getCard("Pyroclasm", Constant.Player.Computer)); + } + for(int i = 0; i < 3; i++) { + library.add(cf.getCard("Nevinyrral's Disk", Constant.Player.Computer)); + library.add(cf.getCard("Lava Spike", Constant.Player.Computer)); + } + for(int i = 0; i < 2; i++) { + library.add(cf.getCard("Hidetsugu's Second Rite", Constant.Player.Computer)); + library.add(cf.getCard("Char", Constant.Player.Computer)); + library.add(cf.getCard("Flamebreak", Constant.Player.Computer)); + library.add(cf.getCard("Mox Ruby", Constant.Player.Computer)); + } + + + // library.add(cf.getCard("Tanglebloom", Constant.Player.Computer)); + + for(int i = 0; i < 14; i++) + library.add(cf.getCard("Mountain", Constant.Player.Computer)); + + if(library.size() != 40) + throw new RuntimeException("ComputerAI_Burn : getLibrary() error, library size is " + library.size()); + + return library.toArray(); + } + + public void stack_not_empty() { + //same as Input.stop() method + //ends the method + //different than methods because this isn't a phase like Main1 or Declare Attackers + AllZone.InputControl.resetInput(); + AllZone.InputControl.updateObservers(); + } +} diff --git a/src/ComputerAI_Burn2.java b/src/ComputerAI_Burn2.java new file mode 100644 index 00000000000..638bad01a2e --- /dev/null +++ b/src/ComputerAI_Burn2.java @@ -0,0 +1,176 @@ +//import java.util.*; +import javax.swing.SwingUtilities; + + +public class ComputerAI_Burn2 implements Computer { + private volatile boolean playLand = true; + + public void main1() { + if(playLand) { + playLand = false; + ComputerUtil.playLand(); + + Card c[] = AllZone.Computer_Hand.getCards(); + if(c.length != 0) { +// System.out.print("hand - "); +// for(int i = 0; i < c.length; i++) +// System.out.print(c[i] +" "); +// System.out.println(); + } + } + Runnable run = new Runnable() { + @SuppressWarnings("null") + public void run() { + synchronized(ComputerAI_Burn2.this) { + if(AllZone.Stack.size() == 0 + && AllZone.Phase.is(Constant.Phase.Main1, Constant.Player.Computer)) { + SpellAbilityList list = null; //Move3.getBestMove(); + if(list.toString().trim().length() != 0) { +// System.out.println("Spell List - " +list); + } + if(list.size() != 0) { + SpellAbility sa = list.get(0); + if(ComputerUtil.canPlay(sa) && sa.canPlay()) { + if(sa.isSpell()) { + AllZone.Computer_Hand.remove(sa.getSourceCard()); + sa.getSourceCard().comesIntoPlay(); + } + + if(sa instanceof Ability_Tap) sa.getSourceCard().tap(); + + ComputerUtil.payManaCost(sa); + AllZone.Stack.add(sa); + } else throw new RuntimeException("ComputerAI_Burn2 error, cannot pay for spell " + + sa.getSourceCard() + " is spell? " + sa.isSpell() + " sa.canPlayAI()-" + + sa.canPlayAI() + " sa.canPlay()-" + sa.canPlay() + + " CardUtil.getConvertedManaCost(sa)-" + CardUtil.getConvertedManaCost(sa) + + " ComputerUtil.getAvailableMana().size()-" + + ComputerUtil.getAvailableMana().size()); + }//list.size != 0 + if(AllZone.Stack.size() == 0 + && AllZone.Phase.is(Constant.Phase.Main1, Constant.Player.Computer)) { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Burn2.running) = true; Note, this is untested, did it work?"); + AllZone.Phase.setNeedToNextPhase(true); + } + + }//if + }//synchronized + }//run() + };//Runnable + try { + SwingUtilities.invokeLater(run); +// Thread thread = new Thread(run); +// thread.start(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("ComputerAI_Burn : main1() error, " + ex); + } + + }//main1() + + public void main2() { + playLand = true; + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Burn2.main2) = true; Note, this is not tested, did it work?"); + AllZone.Phase.setNeedToNextPhase(true); + } + + public void declare_attackers_before() + { + AllZone.Phase.setNeedToNextPhase(true); + } + + public void declare_attackers() { + final Combat c = ComputerUtil.getAttackers(); + c.setAttackingPlayer(AllZone.Combat.getAttackingPlayer()); + c.setDefendingPlayer(AllZone.Combat.getDefendingPlayer()); + AllZone.Combat = c; + + Card[] att = c.getAttackers(); + for(int i = 0; i < att.length; i++) + att[i].tap(); + + AllZone.Computer_Play.updateObservers(); + + CombatUtil.showCombat(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Burn2.declare_attackers) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + public void declare_blockers() { + Combat c = ComputerUtil.getBlockers(); + c.setAttackingPlayer(AllZone.Combat.getAttackingPlayer()); + c.setDefendingPlayer(AllZone.Combat.getDefendingPlayer()); + AllZone.Combat = c; + + CombatUtil.showCombat(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Burn2.declare_blockers) = true"); + AllZone.Phase.setNeedToNextPhase(true); + + //System.out.println(Arrays.asList(c.getAttackers())); + //System.out.println(Arrays.asList(c.getBlockers())); + } + + public void declare_blockers_after() { + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Burn2.declre_blockers_after) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + //end of Human's turn + public void end_of_turn() { + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Burn2.end_of_turn) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + //must shuffle this + public Card[] getLibrary() { + CardFactory cf = AllZone.CardFactory; + CardList library = new CardList(); + for(int i = 0; i < 4; i++) { + library.add(cf.getCard("Lightning Bolt", Constant.Player.Computer)); + library.add(cf.getCard("Shock", Constant.Player.Computer)); + library.add(cf.getCard("Steel Wall", Constant.Player.Computer)); + } + for(int i = 0; i < 3; i++) { + library.add(cf.getCard("Char", Constant.Player.Computer)); + library.add(cf.getCard("Shock", Constant.Player.Computer)); +// library.add(cf.getCard("Nevinyrral's Disk", Constant.Player.Computer)); + } + for(int i = 0; i < 2; i++) { + library.add(cf.getCard("Pyroclasm", Constant.Player.Computer)); +// library.add(cf.getCard("Hidetsugu's Second Rite", Constant.Player.Computer)); +// library.add(cf.getCard("Char", Constant.Player.Computer)); + library.add(cf.getCard("Flamebreak", Constant.Player.Computer)); + } + + library.add(cf.getCard("Lava Spike", Constant.Player.Computer)); + + + // library.add(cf.getCard("Tanglebloom", Constant.Player.Computer)); + + for(int i = 0; i < 17; i++) + library.add(cf.getCard("Mountain", Constant.Player.Computer)); + + if(library.size() != 40) + throw new RuntimeException("ComputerAI_Burn : getLibrary() error, library size is " + library.size()); + + return library.toArray(); + } + + public void stack_not_empty() { + //same as Input.stop() method + //ends the method + //different than methods because this isn't a phase like Main1 or Declare Attackers + AllZone.InputControl.resetInput(); + AllZone.InputControl.updateObservers(); + } +} \ No newline at end of file diff --git a/src/ComputerAI_General.java b/src/ComputerAI_General.java new file mode 100644 index 00000000000..c93666d33e0 --- /dev/null +++ b/src/ComputerAI_General.java @@ -0,0 +1,304 @@ +import static forge.error.ErrorViewer.*; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.TreeSet; + + +public class ComputerAI_General implements Computer { + private boolean playLand = true; + private Collection playMain1Cards; + + @SuppressWarnings("unchecked") + // TreeSet type safety + public ComputerAI_General() { + //try to reduce the number of comparisons + playMain1Cards = new TreeSet(getMain1PlayHand()); + } + + public void main1() { + if(playLand) { + playLand = false; + ComputerUtil.playLand(); + for(String effect:AllZone.StateBasedEffects.getStateBasedMap().keySet()) { + Command com = GameActionUtil.commands.get(effect); + com.execute(); + } + GameActionUtil.executeCardStateEffects(); + } + +// AllZone.Phase.nextPhase(); + + playCards(Constant.Phase.Main1); + }//main1() + + public void main2() { + playLand = true; + + playCards(Constant.Phase.Main2); + } + + private void playCards(final String phase) { + SpellAbility[] sp = phase.equals(Constant.Phase.Main1)? getMain1():getMain2(); + + boolean nextPhase = ComputerUtil.playCards(sp); + + if(nextPhase) { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_General.playCards) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + }//playCards() + + + private ArrayList getMain1PlayHand() { + ArrayList play = new ArrayList(); + play.add("Man-o'-War"); + play.add("Fire Imp"); + play.add("Flametongue Kavu"); + play.add("Briarhorn"); + play.add("Inner-Flame Acolyte"); + play.add("Keening Banshee"); + play.add("Aggressive Urge"); + play.add("Amnesia"); + play.add("Angelic Blessing"); + play.add("Ashes to Ashes"); + + play.add("Beacon of Destruction"); + play.add("Blinding Light"); + play.add("Brute Force"); + play.add("Cackling Flames"); + + play.add("Char"); + play.add("Control Magic"); + play.add("Crib Swap"); + play.add("Dark Banishing"); + play.add("Devour in Shadow"); + + play.add("Do or Die"); + play.add("Douse in Gloom"); + play.add("Echoing Decay"); + play.add("Echoing Truth"); + play.add("Elvish Fury"); + play.add("Epic Proportions"); + + play.add("Erratic Explosion"); + play.add("Expunge"); + play.add("Faceless Butcher"); + play.add("Feral Lightning"); + play.add("Firebolt"); + play.add("Flamebreak"); + + play.add("Gaea's Anthem"); + play.add("Giant Growth"); + play.add("Glorious Anthem"); + play.add("Hex"); + play.add("Hidetsugu's Second Rite"); + play.add("Hymn to Tourach"); + + play.add("Ichor Slick"); + play.add("Infest"); + play.add("Inspirit"); + play.add("Kamahl, Pit Fighter"); + play.add("Kjeldoran War Cry"); + play.add("Lightning Bolt"); + + play.add("Might of Oaks"); + play.add("Nameless Inversion"); + play.add("Needle Storm"); + play.add("Oblivion Ring"); + play.add("Oubliette"); + play.add("Path of Anger's Flame"); + play.add("Peel from Reality"); + + play.add("Pestilence"); + play.add("Plague Wind"); + play.add("Pongify"); + play.add("Primal Boost"); + play.add("Psionic Blast"); + play.add("Pyrohemia"); + play.add("Repulse"); + play.add("Saltblast"); + + play.add("Shock"); + play.add("Shriekmaw"); + play.add("Sower of Temptation"); + play.add("Strangling Soot"); + + play.add("Sunlance"); + play.add("Swords to Plowshares"); + play.add("Take Possession"); + play.add("Tendrils of Corruption"); + play.add("Terror"); + play.add("Threaten"); + play.add("Tribal Flames"); + play.add("Tromp the Domains"); + + play.add("Volcanic Hammer"); + play.add("Wildsize"); + play.add("Wings of Velis Vel"); + play.add("Wit's End"); + play.add("Wrap in Vigor"); + + return play; + }//getMain1PlayCards() + + private SpellAbility[] getMain1() { + //Card list of all cards to consider + CardList hand = new CardList(AllZone.Computer_Hand.getCards()); + + hand = hand.filter(new CardListFilter() { + public boolean addCard(Card c) { + Collection play = playMain1Cards; + if(c.isLand()) return false; + if(play.contains(c.getName()) || (c.isCreature() && c.getKeyword().contains("Haste"))) return true; + return false; + } + }); + CardList all = new CardList(); + all.addAll(hand.toArray()); + all.addAll(AllZone.Computer_Play.getCards()); + + return getPlayable(all); + }//getMain1() + + + private SpellAbility[] getMain2() { + //Card list of all cards to consider + CardList all = new CardList(); + all.addAll(AllZone.Computer_Hand.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + all.addAll(CardFactoryUtil.getFlashbackCards(Constant.Player.Computer).toArray()); + all = all.filter(new CardListFilter() { + public boolean addCard(Card c) { + if(c.isLand()) return false; + return true; + } + }); + + return getPlayable(all); + }//getMain2() + + /** + * Returns the spellAbilities from the card list that the computer is able to play + */ + private SpellAbility[] getPlayable(CardList l) { + ArrayList spellAbility = new ArrayList(); + for(Card c:l) + for(SpellAbility sa:c.getSpellAbility()) + //This try/catch should fix the "computer is thinking" bug + try { + if(sa.canPlayAI() && ComputerUtil.canPayCost(sa)) spellAbility.add(sa); + } catch(Exception ex) { + showError(ex, "There is an error in the card code for %s:%n", c.getName(), ex.getMessage()); + } + return spellAbility.toArray(new SpellAbility[spellAbility.size()]); + } + + public void declare_attackers_before() + { + AllZone.Phase.setNeedToNextPhase(true); + } + + public void declare_attackers() { + final Combat c = ComputerUtil.getAttackers(); + c.setAttackingPlayer(AllZone.Combat.getAttackingPlayer()); + c.setDefendingPlayer(AllZone.Combat.getDefendingPlayer()); + + //check for planeswalker + Card walker = AllZone.GameAction.getPlaneswalker(Constant.Player.Human); + + if(walker != null && MyRandom.random.nextBoolean()) { + c.setPlaneswalker(walker); + AllZone.pwCombat = c; + } else AllZone.Combat = c; + + + Card[] att = c.getAttackers(); + for(int i = 0; i < att.length; i++) { + if(!att[i].getKeyword().contains("Vigilance")) att[i].tap(); + System.out.println("Computer just assigned " + att[i].getName() + " as an attacker."); + } + + AllZone.Computer_Play.updateObservers(); + + + CombatUtil.showCombat(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_General.declare_attackers) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + public void declare_blockers() { + CardList blockers = new CardList(AllZone.Computer_Play.getCards()); + Combat combat = getCombat(AllZone.pwCombat.getAttackers(), blockers); + + combat.setPlaneswalker(AllZone.pwCombat.getPlaneswalker()); + AllZone.pwCombat = combat; + + CardList remove = AllZone.pwCombat.getAllBlockers(); + for(int i = 0; i < remove.size(); i++) + blockers.remove(remove.get(i)); + + AllZone.Combat = getCombat(AllZone.Combat.getAttackers(), blockers); + + CombatUtil.showCombat(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_General) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + private Combat getCombat(Card[] attackers, CardList availableBlockers) { + ComputerUtil_Block2 com = new ComputerUtil_Block2(attackers, availableBlockers.toArray(), + AllZone.Computer_Life.getLife()); + + Combat c = com.getBlockers(); + c.setAttackingPlayer(AllZone.Combat.getAttackingPlayer()); + c.setDefendingPlayer(AllZone.Combat.getDefendingPlayer()); + + return c; + } + + + public void declare_blockers_after() { + + //AllZone.Phase.nextPhase(); + + //for debugging: System.out.println("need to nextPhase(ComputerAI_General) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + //end of Human's turn + public void end_of_turn() { + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_General.end_of_turn) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + //must shuffle this + public Card[] getLibrary() { + //CardFactory cf = AllZone.CardFactory; + CardList library = new CardList(); + /* + for(int i = 0; i < 10; i++) + { + library.add(cf.getCard("Kodama's Reach", Constant.Player.Computer)); + library.add(cf.getCard("Forest", Constant.Player.Computer)); + } + */ + return library.toArray(); + } + + public void stack_not_empty() { + //same as Input.stop() method + //ends the method + //different than methods because this isn't a phase like Main1 or Declare Attackers +// ComputerUtil.playCards(); this allows computer to play sorceries when it shouldn't + + AllZone.InputControl.resetInput(); + AllZone.InputControl.updateObservers(); + } +} diff --git a/src/ComputerAI_Input.java b/src/ComputerAI_Input.java new file mode 100644 index 00000000000..8758964e594 --- /dev/null +++ b/src/ComputerAI_Input.java @@ -0,0 +1,83 @@ +public class ComputerAI_Input extends Input +{ + private static final long serialVersionUID = -3091338639571662216L; + + private final Computer computer; + + public ComputerAI_Input(Computer i_computer) + { + computer = i_computer; + } + //wrapper method that ComputerAI_StackNotEmpty class calls + //ad-hoc way for ComptuerAI_StackNotEmpty to get to the Computer class + public void stackNotEmpty() + { + computer.stack_not_empty(); + } + public void showMessage() + { + ButtonUtil.disableAll(); + AllZone.Display.showMessage("Phase: " +AllZone.Phase.getPhase() +"\nComputer is thinking"); + + think(); + }//getMessage(); + private void think() + { + final String phase = AllZone.Phase.getPhase(); + + if(phase.equals(Constant.Phase.Main1)) + { + computer.main1(); + } + + else if (phase.equals(Constant.Phase.Combat_Declare_Attackers_InstantAbility)) + { + computer.declare_attackers_before(); + } + + else if(phase.equals(Constant.Phase.Combat_Declare_Attackers)) + { + computer.declare_attackers(); + } + else if(phase.equals(Constant.Phase.Combat_Declare_Blockers_InstantAbility)) + { + computer.declare_blockers_after(); + } + else if(phase.equals(Constant.Phase.Main2)) + { + computer.main2(); + } + else if(phase.equals(Constant.Phase.At_End_Of_Turn)) + { + AllZone.EndOfTurn.executeAt(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Input) = true"); + AllZone.Phase.setNeedToNextPhase(true); + + //Do not updateObservers here, do it in nextPhase + //AllZone.InputControl.updateObservers(); + } + else if(phase.equals(Constant.Phase.Until_End_Of_Turn)) + { + AllZone.EndOfTurn.executeUntil(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Input.think(),phase.equals(Until_End_Of_Turn) = true"); + AllZone.Phase.setNeedToNextPhase(true); + + //do not updateObservers() here! Do it in nextPhase(). + //AllZone.InputControl.updateObservers(); + } + + //takes place during the human's turn, like blocking etc... + else if(phase.equals(Constant.Phase.Combat_Declare_Blockers)) + { + computer.declare_blockers(); + } + else if(phase.equals(Constant.Phase.End_Of_Turn)) + { + computer.end_of_turn(); + } + }//think +} \ No newline at end of file diff --git a/src/ComputerAI_Rats2.java b/src/ComputerAI_Rats2.java new file mode 100644 index 00000000000..f8ed2779e9a --- /dev/null +++ b/src/ComputerAI_Rats2.java @@ -0,0 +1,140 @@ +import java.util.*; + +public class ComputerAI_Rats2 implements Computer +{ + private boolean playLand = true; + + private static Random random = new Random(); + + public void main1() + { + if(playLand) + { + playLand = false; + ComputerUtil.playLand(); + } + +// if(playActivatedAbilities() || playSorcery()) +// return; + Card[] c = AllZone.Computer_Hand.getCards(); + System.out.println("Computer Thinking " +new CardList(c)); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Rats2.main1) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + public void main2() + { + playLand = true; + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Rats2.main2) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + public void declare_blockers() + { + if(random.nextBoolean() || AllZone.Computer_Life.getLife() < 10) + { + //presumes all creatures the Computer owns are the same size, because they are Relentless Rats + Card block[] = CardUtil.toCard(PlayerZoneUtil.getUntappedCreatures(AllZone.Computer_Play)); + Card att[] = AllZone.Combat.getAttackers(); + int blockIndex = 0; + + for(int i = 0; i < att.length && blockIndex < block.length; i++) + { + if(att[i].getNetDefense() <= block[blockIndex].getNetAttack() && + CombatUtil.canBlock(att[i], block[blockIndex])) + AllZone.Combat.addBlocker(att[i], block[blockIndex++]); + } + } + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(Computer_AI_Rats2.declare_blockers) = true"); + AllZone.Phase.setNeedToNextPhase(true); + }//declare_blockers() + + public void declare_attackers_before() + { + AllZone.Phase.setNeedToNextPhase(true); + } + + public void declare_attackers() + { + Card[] a = CardUtil.toCard(PlayerZoneUtil.getUntappedCreatures(AllZone.Computer_Play)); + Card[] b = CardUtil.toCard(PlayerZoneUtil.getUntappedCreatures(AllZone.Human_Play)); +//for(int i = 0; i a = new ArrayList(); + CardFactory cf = AllZone.CardFactory; + + //computer library + for(int i = 0; i < 18; i++) + a.add(cf.getCard("Swamp", Constant.Player.Computer)); + // for(int i = 0; i < 3; i++) + // a.add(cf.getCard("Steel Wall", Constant.Player.Computer)); + + for(int i = 0; i < 0;i ++) + { + a.add(cf.getCard("Nantuko Shade", Constant.Player.Computer)); + a.add(cf.getCard("Hymn to Tourach", Constant.Player.Computer)); + } + for(int i = 0; i < 2;i ++) + { + a.add(cf.getCard("Royal Assassin", Constant.Player.Computer)); + } + while(a.size() < 40) + a.add(cf.getCard("Relentless Rats", Constant.Player.Computer)); + + + return CardUtil.toCard(a); + }//getLibrary() + + public void declare_blockers_after(){playInstantAndAbilities();} + public void end_of_turn() {playInstantAndAbilities();} + + private void playInstantAndAbilities() + { + // if(playActivatedAbilities()) + // return; + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Rats2.playInstantAndAbilities) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + public void stack_not_empty() + { + AllZone.InputControl.resetInput(); + AllZone.InputControl.updateObservers(); + } +} \ No newline at end of file diff --git a/src/ComputerAI_StackNotEmpty.java b/src/ComputerAI_StackNotEmpty.java new file mode 100644 index 00000000000..b53ff63f3bd --- /dev/null +++ b/src/ComputerAI_StackNotEmpty.java @@ -0,0 +1,10 @@ +public class ComputerAI_StackNotEmpty extends Input +{ + private static final long serialVersionUID = -3995969852275185353L; + + public void showMessage() + { + AllZone.Display.showMessage("Phase: " +AllZone.Phase.getPhase() +"\nComputer is thinking"); + AllZone.Computer.stackNotEmpty(); + } +} diff --git a/src/ComputerAI_Testing.java b/src/ComputerAI_Testing.java new file mode 100644 index 00000000000..af968bff633 --- /dev/null +++ b/src/ComputerAI_Testing.java @@ -0,0 +1,59 @@ +public class ComputerAI_Testing implements Computer +{ + + //must shuffle this + public Card[] getLibrary() {return new Card[] {};} + + public void stack_not_empty() + { + System.out.println("Computer: not empty"); + //same as Input.stop() method + //ends the method + //different than methods because this isn't a phase like Main1 or Declare Attackers + AllZone.InputControl.resetInput(); + AllZone.InputControl.updateObservers(); + } + + public void main1() {AllZone.Phase.nextPhase();} + + public void declare_attackers_before() + { + AllZone.Phase.setNeedToNextPhase(true); + } + + public void declare_attackers(){ + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Testing.declare_attackers) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + public void declare_blockers(){ + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Testing.declare_blockers) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + //can play Instants and Abilities + public void declare_blockers_after(){ + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Testing.declare_blockers_after) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + public void main2(){ + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Testing.main2) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + + //end of Human's turn + public void end_of_turn(){ + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(ComputerAI_Testing.end_of_turn) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } +} \ No newline at end of file diff --git a/src/ComputerAI_counterSpells.java b/src/ComputerAI_counterSpells.java new file mode 100644 index 00000000000..53162720601 --- /dev/null +++ b/src/ComputerAI_counterSpells.java @@ -0,0 +1,117 @@ + +public class ComputerAI_counterSpells { + + public static void counter_Spell(SpellAbility sa) + { + if (sa.getSourceCard().isCreature()) + counter_CreatureSpell(sa); + + else + counter_NonCreatureSpell(sa); + } + + public static void counter_CreatureSpell(SpellAbility sa) + { + if (!hasPlayableCounterSpells() && !hasPlayableCreatureCounterSpells()) + return; + + CardList counterSpells = new CardList(); + if (hasPlayableCreatureCounterSpells()) + counterSpells = getPlayableCreatureCounterSpells(); + else + counterSpells = getPlayableCounterSpells(); + + boolean countered = false; + for (Card var:counterSpells) + { + if (countered) + break; + else if (CardUtil.getConvertedManaCost(var.getManaCost()) <= CardUtil.getConvertedManaCost(sa) || + (var.getName().equals("Overwhelming Intellect") && CardUtil.getConvertedManaCost(sa) >= 3 )) + { + SpellAbility sp = var.getSpellAbility()[0]; + //ComputerUtil.playNoStack(sp); + ComputerUtil.playStack(sp); + countered = true; + } + } + + } + + public static void counter_NonCreatureSpell(SpellAbility sa) + { + if (!hasPlayableCounterSpells()) + return; + + CardList counterSpells = new CardList(); + counterSpells = getPlayableCounterSpells(); + + boolean countered = false; + for (Card var:counterSpells) + { + if (countered) + break; + else if (CardUtil.getConvertedManaCost(var.getManaCost()) <= CardUtil.getConvertedManaCost(sa)) + { + SpellAbility sp = var.getSpellAbility()[0]; + //ComputerUtil.playNoStack(sp); + ComputerUtil.playStack(sp); + countered = true; + } + } + } + + public static boolean hasPlayableCounterSpells() + { + return getPlayableCounterSpells().size() > 0; + } + + public static boolean hasPlayableCreatureCounterSpells() + { + return getPlayableCreatureCounterSpells().size() > 0; + } + + public static CardList getPlayableCounterSpells() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList list = new CardList(hand.getCards()); + list = list.filter(new CardListFilter() + { + + + public boolean addCard(Card c) { + if (c.getSpellAbility().length == 0) + return false; + + SpellAbility sa = c.getSpellAbility()[0]; + return c.getName().equals("Counterspell") || c.getName().equals("Cancel") || + c.getName().equals("Remand") || c.getName().equals("Mystic Snake") || + c.getName().equals("Absorb") || c.getName().equals("Undermine") || + c.getName().equals("Punish Ignorance") || c.getName().equals("Dismiss") || + c.getName().equals("Last Word") + && ComputerUtil.canPayCost(sa); + } + }); + + return list; + } + public static CardList getPlayableCreatureCounterSpells() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList list = new CardList(hand.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) { + if (c.getSpellAbility().length == 0) + return false; + SpellAbility sa = c.getSpellAbility()[0]; + return c.getName().equals("Exclude") || c.getName().equals("Overwhelming Intellect") || + c.getName().equals("Preemptive Strike") || c.getName().equals("False Summoning") || + c.getName().equals("Essence Scatter") || c.getName().equals("Remove Soul") + && ComputerUtil.canPayCost(sa); + } + }); + + return list; + } +} diff --git a/src/ComputerUtil.java b/src/ComputerUtil.java new file mode 100644 index 00000000000..34c63d8a4c8 --- /dev/null +++ b/src/ComputerUtil.java @@ -0,0 +1,382 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +//import java.util.HashMap; +//import java.util.Map; +import java.util.Random; + +public class ComputerUtil +{ + @SuppressWarnings("unused") // random +private static Random random = new Random(); + + //if return true, go to next phase + static public boolean playCards() + { + return playCards(getSpellAbility()); + } + + //if return true, go to next phase + static public boolean playCards(SpellAbility[] all) + { + //not sure "playing biggest spell" matters? + sortSpellAbilityByCost(all); +// MyRandom.shuffle(all); + + for(int i = 0; i < all.length; i++) + { + if(canPayCost(all[i]) && all[i].canPlay() && all[i].canPlayAI()) + { + + if(all[i].isSpell() && AllZone.GameAction.isCardInZone(all[i].getSourceCard(),AllZone.Computer_Hand)) + AllZone.Computer_Hand.remove(all[i].getSourceCard()); + + if(all[i] instanceof Ability_Tap) + all[i].getSourceCard().tap(); + + payManaCost(all[i]); + all[i].chooseTargetAI(); + AllZone.Stack.add(all[i]); + + return false; + } + }//while + return true; + }//playCards() + + //this is used for AI's counterspells + final static public void playStack(SpellAbility sa) + { + if (canPayCost(sa)) + { + if (AllZone.GameAction.isCardInZone(sa.getSourceCard(),AllZone.Computer_Hand)) + AllZone.Computer_Hand.remove(sa.getSourceCard()); + + + if (sa.getSourceCard().getKeyword().contains("Cantrip")) + AllZone.GameAction.drawCard(sa.getSourceCard().getController()); + payManaCost(sa); + + AllZone.Stack.add(sa); + } + + } + + final static public void playNoStack(SpellAbility sa) + { + if(canPayCost(sa)) + { + if(sa.isSpell()) + { + if (AllZone.GameAction.isCardInZone(sa.getSourceCard(),AllZone.Computer_Hand)) + AllZone.Computer_Hand.remove(sa.getSourceCard()); + //probably doesn't really matter anyways + //sa.getSourceCard().comesIntoPlay(); - messes things up, maybe for the future fix this + } + + if(sa instanceof Ability_Tap) + sa.getSourceCard().tap(); + + if (sa.getSourceCard().getKeyword().contains("Cantrip")) + AllZone.GameAction.drawCard(sa.getSourceCard().getController()); + + payManaCost(sa); + sa.resolve(); + + //destroys creatures if they have lethal damage, etc.. + AllZone.GameAction.checkStateEffects(); + } + }//play() + + //gets Spell's of cards in hand and Abilities of cards in play + //checks to see + //1. if canPlay() returns true, 2. can pay for mana + static public SpellAbility[] getSpellAbility() + { + CardList all = new CardList(); + all.addAll(AllZone.Computer_Play.getCards()); + all.addAll(AllZone.Computer_Hand.getCards()); + all.addAll(CardFactoryUtil.getFlashbackCards(Constant.Player.Computer).toArray()); + + all = all.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if(c.isBasicLand()) + return false; + + return true; + } + }); + + + ArrayList spellAbility = new ArrayList(); + for(int outer = 0; outer < all.size(); outer++) + { + SpellAbility[] sa = all.get(outer).getSpellAbility(); + for(int i = 0; i < sa.length; i++) + if(sa[i].canPlayAI() && canPayCost(sa[i]) /*&& sa[i].canPlay()*/) + spellAbility.add(sa[i]);//this seems like it needs to be copied, not sure though + } + + SpellAbility[] sa = new SpellAbility[spellAbility.size()]; + spellAbility.toArray(sa); + return sa; + } + static public boolean canPlay(SpellAbility sa) + { + return sa.canPlayAI() && canPayCost(sa); + } + static public boolean canPayCost(SpellAbility sa) + { + if(sa.getManaCost().equals(("0"))) + return true; + + CardList land = getAvailableMana(); + + if(sa.getSourceCard().isLand() /*&& sa.isTapAbility()*/) + { + land.remove(sa.getSourceCard()); + } + + ManaCost cost = new ManaCost(sa.getManaCost()); + ArrayList colors = new ArrayList(); + + for(int i = 0; i < land.size(); i++) + { + colors = getColors(land.get(i)); + int once = 0; + + for(int j =0; j < colors.size(); j++) + { + if(cost.isNeeded(colors.get(j)) && once == 0) + { + //System.out.println(j + " color:" +colors.get(j)); + cost.subtractMana(colors.get(j)); + System.out.println("thinking, I just subtracted " + colors.get(j) + ", cost is now: " + cost.toString()); + once++; + } + + if(cost.isPaid()) { + //System.out.println("Cost is paid."); + return true; + } + } + } + return false; + }//canPayCost() + + + static public void payManaCost(SpellAbility sa) + { + if(sa.getManaCost().equals(("0"))) + return; + + CardList land = getAvailableMana(); + + //this is to prevent errors for land cards that have abilities that cost mana. + if(sa.getSourceCard().isLand() /*&& sa.isTapAbility()*/) + { + land.remove(sa.getSourceCard()); + } + + ManaCost cost = new ManaCost(sa.getManaCost()); + ArrayList colors = new ArrayList(); + + for(int i = 0; i < land.size(); i++) + { + colors = getColors(land.get(i)); + + for(int j = 0; j map = new HashMap(); + map.put("tap: add B", Constant.Color.Black); + map.put("tap: add W", Constant.Color.White); + map.put("tap: add G", Constant.Color.Green); + map.put("tap: add R", Constant.Color.Red); + map.put("tap: add U", Constant.Color.Blue); + map.put("tap: add 1", Constant.Color.Colorless); + + //this fails on Vine Trellis and probably 9th Pain Lands + try{ + Object o = land.getKeyword().get(0); + return map.get(o).toString(); + }catch(Exception ex)//I hope this fixes "the problem" that I can't re-create + { + return Constant.Color.Colorless; + } + } + */ + public static ArrayList getColors(Card land) + { + ArrayList colors = new ArrayList(); + if (land.getKeyword().contains("tap: add B")) + colors.add(Constant.Color.Black); + if (land.getKeyword().contains("tap: add W")) + colors.add(Constant.Color.White); + if (land.getKeyword().contains("tap: add G")) + colors.add(Constant.Color.Green); + if (land.getKeyword().contains("tap: add R")) + colors.add(Constant.Color.Red); + if (land.getKeyword().contains("tap: add U")) + colors.add(Constant.Color.Blue); + if (land.getKeyword().contains("tap: add 1")) + colors.add(Constant.Color.Colorless); + + return colors; + + } +/* + //only works with mono-colored spells + static public void payManaCost(int convertedCost) + { + CardList land = getAvailableMana(); + //converted colered mana requirements into colorless + ManaCost cost = new ManaCost("" +convertedCost); + Card c; + for(int i = 0; i < land.size(); i++) + { + if(cost.isPaid()) + break; + + land.get(i).tap(); + cost.subtractMana(Constant.Color.Red); + }//for + if(! cost.isPaid()) + throw new RuntimeException("ComputerUtil : payManaCost() cost was not paid"); + }//payManaCost() +*/ + + static public CardList getAvailableMana() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + CardList mana = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + //if(c.isCreature() && c.hasSickness()) + // return false; + + for (Ability_Mana am : c.getBasicMana()) + if (am.canPlay()) return true; + return false; + } + });//CardListFilter + + CardList sortedMana = new CardList(); + + for (int i=0; i landList = PlayerZoneUtil.getCardType(AllZone.Computer_Hand, "Land"); + if(! landList.isEmpty()) + { + AllZone.Computer_Hand.remove(landList.get(0)); + AllZone.Computer_Play.add(landList.get(0)); + + AllZone.GameAction.checkStateEffects(); + } + } + static public void untapDraw() + { + AllZone.GameAction.drawCard(Constant.Player.Computer); + + CardList permanent = new CardList(AllZone.Computer_Play.getCards()); + for(int i = 0; i < permanent.size(); i++) + permanent.get(i).untap(); + } + static public CardList getPossibleAttackers() + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.isCreature() && CombatUtil.canAttack(c); + } + }); + return list; + } + static public Combat getAttackers() + { + ComputerUtil_Attack2 att = new ComputerUtil_Attack2( + AllZone.Computer_Play.getCards(), + AllZone.Human_Play.getCards() , AllZone.Human_Life.getLife()); + + return att.getAttackers(); + } + static public Combat getBlockers() + { + ComputerUtil_Block2 block = new ComputerUtil_Block2( + AllZone.Combat.getAttackers() , + AllZone.Computer_Play.getCards(), AllZone.Computer_Life.getLife()); + + return block.getBlockers(); + } + +@SuppressWarnings("unchecked") // Comparator needs type +static void sortSpellAbilityByCost(SpellAbility sa[]) + { + //sort from highest cost to lowest + //we want the highest costs first + Comparator c = new Comparator() + { + public int compare(Object a, Object b) + { + int a1 = CardUtil.getConvertedManaCost((SpellAbility)a); + int b1 = CardUtil.getConvertedManaCost((SpellAbility)b); + + //puts creatures in front of spells + if(((SpellAbility)a).getSourceCard().isCreature()) + a1 += 1; + + if(((SpellAbility)b).getSourceCard().isCreature()) + b1 += 1; + + + return b1 - a1; + } + };//Comparator + Arrays.sort(sa, c); + }//sortSpellAbilityByCost() +} \ No newline at end of file diff --git a/src/ComputerUtil_Attack2.java b/src/ComputerUtil_Attack2.java new file mode 100644 index 00000000000..b513fb85a8f --- /dev/null +++ b/src/ComputerUtil_Attack2.java @@ -0,0 +1,358 @@ +import java.util.*; + + //doesHumanAttackAndWin() uses the global variable AllZone.Computer_Life + public class ComputerUtil_Attack2 + { + //possible attackers and blockers + private CardList attackers; + private CardList blockers; + private int blockerLife; + + private Random random = new Random(); + private final int randomInt = random.nextInt(); + + private CardList humanList; //holds human player creatures + private CardList computerList;//holds computer creatures + + public ComputerUtil_Attack2(Card[] possibleAttackers, Card[] possibleBlockers, int blockerLife) + { + this(new CardList(possibleAttackers), new CardList(possibleBlockers), blockerLife); + } + + public ComputerUtil_Attack2(CardList possibleAttackers, CardList possibleBlockers, int blockerLife) + { + humanList = new CardList(possibleBlockers.toArray()); + humanList = humanList.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature(); + } + }); + + computerList = new CardList(possibleAttackers.toArray()); + computerList = computerList.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature(); + } + }); + + attackers = getUntappedCreatures(possibleAttackers, true); + blockers = getUntappedCreatures(possibleBlockers , false); + this.blockerLife = blockerLife; + + final ArrayList valuable = new ArrayList(); + valuable.add("Kamahl, Pit Fighter"); + valuable.add("Elvish Piper"); + + attackers = attackers.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (0 < getAttack(c) || c.getName().equals("Guiltfeeder")) && ! valuable.contains(c.getName()); + } + }); + }//constructor + public CardList getUntappedCreatures(CardList in, final boolean checkCanAttack) + { + CardList list = new CardList(in.toArray()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + boolean b = c.isCreature() && c.isUntapped(); + + if(checkCanAttack) + return b && CombatUtil.canAttack(c); + + return b; + } + }); + return list; + }//getUntappedCreatures() + + //this checks to make sure that the computer player + //doesn't lose when the human player attacks + //this method is used by getAttackers() + public int getStartIndex() + { + CardListUtil.sortAttack(humanList); + + for(int i = 0; i < computerList.size(); i++) + if(!doesHumanAttackAndWin(i)) + return i; + + return computerList.size(); + } + + //this uses a global variable, which isn't perfect + public boolean doesHumanAttackAndWin(int nBlockingCreatures) + { + int totalAttack = 0; + int stop = humanList.size() - nBlockingCreatures; + + for(int i = 0; i < stop; i++) + totalAttack += getAttack(humanList.get(i)); + + //-3 so the computer will try to stay at 3 life + return (AllZone.Computer_Life.getLife() - 3) <= totalAttack; + } + + private boolean doAssault() + { + //I think this is right but the assault code may still be a little off + CardListUtil.sortAttackLowFirst(attackers); + + int totalAttack = 0; + //presumes the Human will block + for(int i = 0; i < (attackers.size() - blockers.size()); i++) + totalAttack += getAttack(attackers.get(i)); + + return blockerLife <= totalAttack; + }//doAssault() + + public Combat getAttackers() + { + //if this method is called multiple times during a turn, + //it will always return the same value + //randomInt is used so that the computer doesn't always + //do the same thing on turn 3 if he had the same creatures in play + //I know this is a little confusing + random.setSeed(AllZone.Phase.getTurn() + randomInt); + + Combat combat = new Combat(); + + for (int i=0; i= 3 || + GameActionUtil.isRafiqInPlay(Constant.Player.Computer) || + GameActionUtil.getBattleGraceAngels(Constant.Player.Computer) >= 2) && !doAssault()) + { + int biggest = 0; + Card att = null; + for(int i=0; i biggest) { + biggest = getAttack(attackers.get(i)); + att = attackers.get(i); + } + } + if (att!= null) + combat.addAttacker(att); + } + //do assault (all creatures attack) if the computer would win the game + //or if the computer has 4 creatures and the player has 1 + else if(doAssault() || (humanList.size() == 1 && 3 < attackers.size())) + { + for(int i = 0; i < attackers.size(); i++) + combat.addAttacker(attackers.get(i)); + } + else + { + Card bigDef; + Card bigAtt; + + //should the computer randomly not attack with one attacker? + //this should only happen 10% of the time when the computer + //has at least 3 creatures + boolean notAttack = (Math.abs(random.nextInt(100)) <= 10); + if(notAttack && 3 <= attackers.size()) + { + attackers.shuffle(); + attackers.remove(0); + } + + //this has to be before the sorting below + //because this sorts attackers + int i = getStartIndex(); //new + + //so the biggest creature will usually attack + //I think this works, not sure, may have to change it + //sortNonFlyingFirst has to be done first, because it reverses everything + CardListUtil.sortNonFlyingFirst(attackers); + CardListUtil.sortAttackLowFirst(attackers); + + for(; i < attackers.size(); i++) + { + + bigAtt = getBiggestAttack(attackers.get(i)); + bigDef = getBiggestDefense(attackers.get(i)); + + /* + System.out.println("bigDef: " + bigDef.getName()); + System.out.println("attackers.get(i): " + attackers.get(i).getName()); + if (CombatUtil.canDestroyBlocker(bigDef, attackers.get(i))) + System.out.println(attackers.get(i).getName() + " can destroy blocker " +bigDef.getName()); + */ + + //if attacker can destroy biggest blocker or + //biggest blocker cannot destroy attacker + if(CombatUtil.canDestroyBlocker(bigDef, attackers.get(i)) || + (! CombatUtil.canDestroyAttacker(attackers.get(i), bigAtt))){ + combat.addAttacker(attackers.get(i)); + } + else if(attackers.get(i).getSacrificeAtEOT()){ + combat.addAttacker(attackers.get(i)); + } + } + }//getAttackers() + + return combat; + }//getAttackers() + + //returns 0/1 Card if no blockers found + public Card getBiggestAttack(Card attack) + { + CardListUtil.sortAttack(blockers); + for(int i = 0; i < blockers.size(); i++) + if(CombatUtil.canBlock(attack, blockers.get(i))) + return blockers.get(i); + + return AllZone.CardFactory.getCard("Birds of Paradise", ""); + } + + + + //returns 1/1 Card if no blockers found + public Card getBiggestDefense(Card attack) + { + CardListUtil.sortDefense(blockers); + for(int i = 0; i < blockers.size(); i++) + if(CombatUtil.canBlock(attack, blockers.get(i))) + return blockers.get(i); + + return AllZone.CardFactory.getCard("Elvish Piper", ""); + } + + public int countExaltedCreatures() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList list = new CardList(); + list.addAll(play.getCards()); + list = list.filter(new CardListFilter(){ + + public boolean addCard(Card c) { + return c.getKeyword().contains("Exalted"); + } + + }); + + return list.size(); + } + + public void assignDamage(CardList list, int damage) + { + CardListUtil.sortAttack(list); + + int kill; + for(int i = 0; i < list.size(); i++) + { + kill = list.get(i).getKillDamage(); + if(kill <= damage) + { + damage -= kill; + list.get(i).setAssignedDamage(kill); + } + } + }//assignDamage() + + public int getAttack(Card c) + { + int n = c.getNetAttack(); + + if(CombatUtil.isDoranInPlay()) + n = c.getNetDefense(); + + if(c.getKeyword().contains("Double Strike")) + n *= 2; + + return n; + } + } + + /* + //this returns the attacking power that is needed to destroy + //Card c and takes into account first and double strike + // + //Doran, the Siege Tower doesn't change a card's defense + //used by sortDefense() + private int getDefense(Card c) + { + int n = c.getNetDefense(); + + //is the defense is less than attack and the card has + //first or double strike? + if(hasStrike(c) && n < getAttack_FirstStrike(c)) + n = getAttack_FirstStrike(c); + + return n; + } + + //does this card have first or double strike? + private boolean hasStrike(Card c) + { + return c.getKeyword.contains("First Strike") || + c.getKeyword.contains("Double Strike") + } + + //the higher the defense the better + @SuppressWarnings("unchecked") // Comparator needs + private void sortDefense(CardList list) + { + Comparator com = new Comparator() + { + public int compare(Object a1, Object b1) + { + Card a = (Card)a1; + Card b = (Card)b1; + + return getDefense(b) - getDefense(a); + } + }; + list.sort(com); + }//sortDefense() + + //use this method if you need to know about first strike + public int getAttack_FirstStrike(Card c) + { + int n = getAttack(c); + + //adding 1 is a little bit hacky bit it shows + //that first strike is a little better + //than a average creature + if(c.getKeyword().contains("First Strike")) + n += 1; + + return n; + } + + //returns lowest attack first + private void sortAttackLowFirst(CardList list) + { + sortAttack(list); + list.reverse(); + return list; + } + + //the higher the attack the better + @SuppressWarnings("unchecked") // Comparator needs type + private void sortAttack(CardList list) + { + Comparator com = new Comparator() + { + public int compare(Object a1, Object b1) + { + Card a = (Card)a1; + Card b = (Card)b1; + + return getAttack_FirstStrike(b) - getAttack_FirstStrike(a); + } + }; + list.sort(com); + }//sortAttack() + */ diff --git a/src/ComputerUtil_Block2.java b/src/ComputerUtil_Block2.java new file mode 100644 index 00000000000..459a228e675 --- /dev/null +++ b/src/ComputerUtil_Block2.java @@ -0,0 +1,323 @@ +import java.util.*; + +public class ComputerUtil_Block2 +{ + private CardList attackers; + private CardList possibleBlockers; + private int blockersLife; + + //making this static helped in testing + //random.nextBoolean() wasn't true 50% of the time + private static Random random = new Random(); + private final int randomInt = random.nextInt(); + + public ComputerUtil_Block2(Card[] attackers, Card[] possibleBlockers, int blockerLife) + { + this(new CardList(attackers), new CardList(possibleBlockers), blockerLife); + } + + public ComputerUtil_Block2(CardList in_attackers, CardList in_possibleBlockers, int in_blockersLife) + { + attackers = new CardList(in_attackers.toArray()); + possibleBlockers = getUntappedCreatures(new CardList(in_possibleBlockers.toArray())); + + //so the computer won't just have 1 life left + //the computer will try to stay at 3 life + blockersLife = in_blockersLife; + if(3 < blockersLife) + blockersLife -= 3;; + + attackers.shuffle(); + CardListUtil.sortAttackLowFirst(possibleBlockers); + + possibleBlockers = removeValuableBlockers(possibleBlockers); + } + private CardList getUntappedCreatures(CardList list) + { + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && c.isUntapped(); + } + }); + return list; + }//getUntappedCreatures() + + private CardList removeValuableBlockers(CardList in) + { + final String[] noBlock = {"Elvish Piper", "Urborg Syphon-Mage", "Sparksmith", "Royal Assassin", "Marble Titan", "Kamahl, Pit Fighter"}; + + CardList out = in.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + for(int i = 0; i < noBlock.length; i++) + if(c.getName().equals(noBlock[i])) + return false; + + return true; + } + });//CardListFilter + + return out; + } + + //checks for flying and stuff like that + private CardList getPossibleBlockers(Card attacker) + { + CardList list = new CardList(); + for(int i = 0; i < possibleBlockers.size(); i++) + if(CombatUtil.canBlock(attacker, possibleBlockers.get(i))) + list.add(possibleBlockers.get(i)); + + return list; + } + + //finds a blocker that destroys the attacker, the blocker is not destroyed + //returns null if no blocker is found + Card safeSingleBlock(Card attacker) + { + CardList c = getPossibleBlockers(attacker); + + for(int i = 0; i < c.size(); i++) + if(CombatUtil.canDestroyAttacker(attacker, c.get(i)) && + (! CombatUtil.canDestroyBlocker(c.get(i), attacker))) + return c.get(i); + + return null; + }//safeSingleBlock() + + //finds a blocker, both the attacker and blocker are destroyed + //returns null if no blocker is found + Card tradeSingleBlock(Card attacker) + { + CardList c = getPossibleBlockers(attacker); + + for(int i = 0; i < c.size(); i++) + if(CombatUtil.canDestroyAttacker(attacker, c.get(i))) + { + //do not block a non-flyer with a flyer + if((! c.get(i).getKeyword().contains("Flying")) || attacker.getKeyword().contains("Flying")) + return c.get(i); + } + return null; + }//tradeSingleBlock() + + + + //finds a blocker, neither attacker and blocker are destroyed + //returns null if no blocker is found + Card shieldSingleBlock(Card attacker) + { + CardList c = getPossibleBlockers(attacker); + + for(int i = 0; i < c.size(); i++) + if(! CombatUtil.canDestroyBlocker(c.get(i), attacker)) + return c.get(i); + + return null; + }//shieldSingleBlock() + + + //finds multiple blockers + //returns an array of size 0 if not multiple blocking + Card[] multipleBlock(Card attacker) + { + CardList c = getPossibleBlockers(attacker); + + int defense = getDefense(attacker) - attacker.getDamage(); + //if attacker cannot be destroyed + if(defense > CardListUtil.sumAttack(c)) + return new Card[] {}; + + CardList block = new CardList(); + c.shuffle(); + + while(defense > CardListUtil.sumAttack(block)) + block.add(c.remove(0)); + + Card check[] = block.toArray(); + + //no single blockers, that should be handled somewhere else + if(check.length == 1) + return new Card[] {}; + + return check; + }//multipleBlock() + + + //finds a blocker, both the attacker lives and blockers dies + //returns null if no blocker is found + Card chumpSingleBlock(Card attacker) + { + if(blockersLife <= CardListUtil.sumAttack(attackers)) + { + CardList c = getPossibleBlockers(attacker); + CardListUtil.sortAttackLowFirst(c); + if(! c.isEmpty()) + return c.get(0); + } + return null; + }//tradeSingleBlock() + + //force block if lethal damage somehow slips through checks (happens often with doublestrike) + Card forceBlock(Card attacker) + { + CardList c = getPossibleBlockers(attacker); + CardListUtil.sortAttackLowFirst(c); + + if(! c.isEmpty()) + return c.get(0); + return null; + } + + + private void testing(String s) + { + boolean print = false; + if(print) + System.out.println("combat testing: " +s); + } + + + private int sumUnblockedAttackers(Combat combat) + { + int sum = 0; + Card c[] = combat.getAttackers(); + for(int i = 0; i < c.length; i++) + if(! combat.isBlocked(c[i])) + sum += getAttack(c[i]); + + return sum; + } + + public Combat getBlockers() + { + //if this method is called multiple times during a turn, + //it will always return the same value + //randomInt is used so that the computer doesn't always + //do the same thing on turn 3 if he had the same creatures in play + //I know this is a little confusing + random.setSeed(AllZone.Phase.getTurn() + randomInt); + Card c; + Combat combat = new Combat(); + boolean shouldBlock; + + //if this isn't done, the attackers are shown backwards 3,2,1, + //reverse the order here because below reverses the order again + attackers.reverse(); + + //add attackers to combat + //this has to be done before the code below because sumUnblockedAttackers() + //uses combat to get the attackers and total their power + for(int i = 0; i < attackers.size(); i++) + combat.addAttacker(attackers.get(i)); + + for(int i = 0; i < attackers.size(); i++) + { + + boolean doubleStrike = false; + if(attackers.get(i).hasDoubleStrike() || attackers.get(i).getKeyword().contains("Double Strike")) + doubleStrike = true; + + //the computer blocks 50% of the time or if the computer would lose the game + shouldBlock = random.nextBoolean() || blockersLife <= sumUnblockedAttackers(combat); + + + testing("shouldBlock - " +shouldBlock); + c = null; + + + //safe block - attacker dies, blocker lives + //if there is only one attacker it might be a trap + //if holding a Giant Growth and a 2/2 attacking into a 3/3 + if(shouldBlock) + { + c = safeSingleBlock(attackers.get(i)); + if(c != null) + testing("safe"); + } + + if(c == null && shouldBlock) + { + //shield block - attacker lives, blocker lives + c = shieldSingleBlock(attackers.get(i)); + if(c != null) + testing("shield"); + } + + if(c == null && shouldBlock) + { + //trade block - attacker dies, blocker dies + c = tradeSingleBlock(attackers.get(i)); + + if(c != null) + testing("trading"); + } + + + if(c == null && shouldBlock) + { + //chump block - attacker lives, blocker dies + c = chumpSingleBlock(attackers.get(i)); + if(c != null) + testing("chumping"); + } + + if(c == null && doubleStrike && AllZone.Computer_Life.getLife() <= (getAttack(attackers.get(i))*2)) + { + c = forceBlock(attackers.get(i)); + if (c != null) + testing("forcing"); + } + + if(c != null) + { + + //if (!c.getKeyword().contains("This card can block any number of creatures.")) + possibleBlockers.remove(c); + combat.addBlocker(attackers.get(i), c); + } + + //multiple blockers + if(c == null && shouldBlock) + { + Card[] m = multipleBlock(attackers.get(i)); + for(int inner = 0; inner < m.length; inner++) + { + //to prevent a single flyer from blocking a single non-flyer + //tradeSingleBlock() checks for a flyer blocking a non-flyer also + if(m.length != 1) + { + possibleBlockers.remove(m[inner]); + combat.addBlocker(attackers.get(i), m[inner]); + } + }//for + }//if + }//for attackers + + return combat; + }//getBlockers() + + //Doran, the Siege Tower doesn't change a card's defense + public int getDefense(Card c) + { + return c.getNetDefense(); + } + + //this doesn't take into account first strike, + //use CombatUtil.canDestroyAttacker() + public int getAttack(Card c) + { + int n = c.getNetAttack(); + + if(CombatUtil.isDoranInPlay()) + n = c.getNetDefense(); + + if(c.getKeyword().contains("Double Strike")) + n *= 2; + + return n; + } +} \ No newline at end of file diff --git a/src/Computer_Cleanup.java b/src/Computer_Cleanup.java new file mode 100644 index 00000000000..c73cc394e85 --- /dev/null +++ b/src/Computer_Cleanup.java @@ -0,0 +1,23 @@ +import java.util.Random; + +public class Computer_Cleanup extends Input +{ + private static final long serialVersionUID = -145924458598185438L; + + public void showMessage() + { + Random r = new Random(); + Card[] c = AllZone.Computer_Hand.getCards(); + while(7 < c.length) + { + AllZone.GameAction.discard(c[r.nextInt(c.length)]); + c = AllZone.Computer_Hand.getCards(); + } + + CombatUtil.removeAllDamage(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(Computer_Cleanup.showMessage()) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } +} diff --git a/src/Computer_Draw.java b/src/Computer_Draw.java new file mode 100644 index 00000000000..c6ade7a2b64 --- /dev/null +++ b/src/Computer_Draw.java @@ -0,0 +1,13 @@ +public class Computer_Draw extends Input +{ + private static final long serialVersionUID = -815953053902719496L; + + public void showMessage() + { + AllZone.GameAction.drawCard(Constant.Player.Computer); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(Computer_Draw.showMessage) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } +} diff --git a/src/Computer_Race.java b/src/Computer_Race.java new file mode 100644 index 00000000000..4106cfc154b --- /dev/null +++ b/src/Computer_Race.java @@ -0,0 +1,162 @@ +public class Computer_Race +{ + public boolean willWinRace(CardList attackList, int attackLife, CardList blockList, int blockLife) + { + + + + + return true; + }//willWinRace() + + //if all of attackList attacked, and blockList goodBlocked(), + //what attackers would still be attacking? + public CardList getUnblocked(CardList attackList, CardList blockList) + { + //copy + attackList = new CardList(attackList.toArray()); + blockList = new CardList(blockList.toArray()); + + //need to match smallest blocker with biggest attacker + CardListUtil.sortAttack(attackList); + CardListUtil.sortAttackLowFirst(blockList); + + CardList unblocked = new CardList(); + + for(int i = 0; i < attackList.size(); i++) + { + Card attack = attackList.get(i); + CardList block = getPossibleBlockers(attack, blockList); + + CardList check = goodBlock(attack, block); + if(check == null) + unblocked.add(attack); + else + for(int z = 0; z < check.size(); z++) + blockList.remove(check.get(z)); + } + + return unblocked; + }//getUnblocked() + + //may return null + //null means there are no good blockers in blockList + //check for the 3 criteria below + //(attacker live and blocker live) + //(attacker die and blocker live) + //(attacker die and blocker die) + public CardList goodBlock(Card attacker, CardList blockList) + { + Card c; + CardList check; + + c = safeSingleBlock(attacker, blockList); + check = checkGoodBlock(c); + if(check != null) + return check; + + c = shieldSingleBlock(attacker, blockList); + check = checkGoodBlock(c); + if(check != null) + return check; + + c = tradeSingleBlock(attacker, blockList); + check = checkGoodBlock(c); + if(check != null) + return check; + + Card[] m = this.multipleBlock(attacker, blockList); + if(m.length != 0) + return new CardList(m); + + return null; + } + //goodBlock() uses this method + public CardList checkGoodBlock(Card c) + { + if(c != null) + { + CardList list = new CardList(); + list.add(c); + return list; + } + return null; + }//checkGoodBlock() + + //(attacker dies, blocker lives) + //returns null if no blocker is found + Card safeSingleBlock(Card attacker, CardList blockList) + { + CardList c = blockList; + + for(int i = 0; i < c.size(); i++) + if(CombatUtil.canDestroyAttacker(attacker, c.get(i)) && + (! CombatUtil.canDestroyBlocker(c.get(i), attacker))) + return c.get(i); + + return null; + }//safeSingleBlock() + + //(attacker dies, blocker dies) + //returns null if no blocker is found + Card tradeSingleBlock(Card attacker, CardList blockList) + { + CardList c = blockList; + + for(int i = 0; i < c.size(); i++) + if(CombatUtil.canDestroyAttacker(attacker, c.get(i))) + return c.get(i); + + return null; + }//tradeSingleBlock() + + //(attacker lives, blocker lives) + //returns null if no blocker is found + Card shieldSingleBlock(Card attacker, CardList blockList) + { + CardList c = blockList; + + for(int i = 0; i < c.size(); i++) + if(! CombatUtil.canDestroyBlocker(c.get(i), attacker)) + return c.get(i); + + return null; + }//shieldSingleBlock() + + //finds multiple blockers + //returns an array of size 0 if not multiple blocking + Card[] multipleBlock(Card attacker, CardList blockList) + { + CardList c = blockList; + + int defense = attacker.getNetDefense() - attacker.getDamage(); + //if attacker cannot be destroyed + if(defense > CardListUtil.sumAttack(c)) + return new Card[] {}; + + CardList block = new CardList(); + c.shuffle(); + + while(defense > CardListUtil.sumAttack(block)) + block.add(c.remove(0)); + + Card check[] = block.toArray(); + + //no single blockers, that should be handled somewhere else + if(check.length == 1) + return new Card[] {}; + + return check; + }//multipleBlock() + + //checks for flying and stuff like that + private CardList getPossibleBlockers(Card attacker, CardList blockList) + { + CardList list = new CardList(); + for(int i = 0; i < blockList.size(); i++) + if(CombatUtil.canBlock(attacker, blockList.get(i))) + list.add(blockList.get(i)); + + return list; + } +} \ No newline at end of file diff --git a/src/Constant.java b/src/Constant.java new file mode 100644 index 00000000000..d02e8a5c622 --- /dev/null +++ b/src/Constant.java @@ -0,0 +1,179 @@ +import javax.swing.ImageIcon; + +public interface Constant +{ + public static final String ProgramName = "MTG Forge - 10/2009 - http://mtgrares.blogspot.com"; + + //used to pass information between the GUI screens + public interface Runtime + { + public static final Deck[] HumanDeck = new Deck[1]; + public static final Deck[] ComputerDeck = new Deck[1]; + public static final String[] GameType = new String[1]; + public static final WinLose WinLose = new WinLose(); + public static final boolean[] smooth = new boolean[1]; + + public static final int[] width = new int[1]; + public static final int[] height = new int[1]; + + } + public interface GameType + { + public static final String Constructed = "constructed"; + public static final String Sealed = "sealed"; + public static final String Draft = "draft"; + } + public interface IO + { + //TODO: probably should read this from a file, or set from GUI +// public static final String baseDir = "c:\\Tim\\game testing\\"; + + public static final String deckFile = "all-decks2"; + public static final String boosterDeckFile = "booster-decks"; + + public static final String imageBaseDir = "pics"; + public static final String cardFile = "cards.txt"; + + public static final ImageIcon upIcon = new ImageIcon ("up.gif"); + public static final ImageIcon downIcon = new ImageIcon ("down.gif"); + public static final ImageIcon leftIcon = new ImageIcon ("left.gif"); + public static final ImageIcon rightIcon = new ImageIcon("right.gif"); + } + public interface Ability + { + public static final String Triggered = "Triggered"; + public static final String Activated = "Activated"; + } + public interface Phase + { + public static final String Untap = "Untap"; + public static final String Upkeep = "Upkeep"; + public static final String Draw = "Draw"; + public static final String Main1 = "Main1"; + //public static final String Begin_Combat = "Beginning of Combat"; + public static final String Combat_Before_Declare_Attackers_InstantAbility = "Before Attack Phase - Play Instants and Abilities"; + public static final String Combat_Declare_Attackers_InstantAbility = "Declare Attackers - Play Instants and Abilities"; + public static final String Combat_Declare_Attackers = "Declare Attackers"; + public static final String Combat_Declare_Blockers = "Declare Blockers"; + public static final String Combat_Declare_Blockers_InstantAbility = "Declare Blockers - Play Instants and Abilities"; + public static final String Combat_Damage = "Combat Damage"; + public static final String Combat_FirstStrikeDamage = "First Strike Damage"; + //public static final String End_Combat = "End of Combat"; + public static final String Main2 = "Main2"; + public static final String At_End_Of_Turn = "At End of Turn"; + public static final String End_Of_Turn = "End of Turn"; + public static final String Until_End_Of_Turn = "Until End of Turn"; + public static final String Cleanup = "Cleanup"; + } + public interface Zone + { + public static final String Hand = "Hand"; + public static final String Library = "Library"; + public static final String Graveyard = "Graveyard"; + public static final String Play = "Play"; + public static final String Removed_From_Play = "Removed from play"; + //public static final String Stack = "Stack"; + } + public interface Player + { + public static final String Human = "Human"; + public static final String Computer = "Computer"; + } + /* + public interface CardType + { + public static final String Artifact = "Artifact"; + public static final String Creature = "Creature"; + public static final String Enchantment = "Enchantment"; + public static final String Aura = "Aura"; + public static final String Instant = "Instant"; + public static final String Land = "Land"; + public static final String Legendary = "Legendary"; + public static final String Sorcery = "Sorcery"; + public static final String Basic = "Basic"; + } + */ + public interface Color + { + public static final String Black = "black"; + public static final String Blue = "blue"; + public static final String Green = "green"; + public static final String Red = "red"; + public static final String White = "white"; + + public static final String Colorless = "colorless"; + //color order "wubrg" + public static final String Colors[] = + {White, Blue, Black, Red, Green, Colorless}; + + public static final String onlyColors[] = {White, Blue, Black, Red, Green}; + } +}//Constant + +/* + public interface Keyword + { + public static final String Swampwalk = "Swampwalk"; + public static final String Plainswalk = "Plainswalk"; + public static final String Forestwalk = "Forestwalk"; + public static final String Islandwalk = "Islandwalk"; + public static final String Mountainwalk = "Mountainwalk"; + + public static final String Flying = "Flying"; + public static final String Fear = "Fear"; + public static final String Vigilance = "Vigilance"; + + + public static final String Double_Strike = "Double Strike"; + public static final String First_Strike = "First Strike"; + public static final String Haste = "Haste"; + public static final String Indestructable = "Indestructable"; + public static final String Landwalk = "Landwalk"; + public static final String Protection = "Protection"; + public static final String Regeneration = "Regeneration"; + public static final String Trample = "Trample"; + } + +// mirrodin block abilities + public static final String Affinity = "affinity"; + public static final String Modular = "modular"; + public static final String Sunburst = "sunburst"; + +//onslaught block + public static final String Cycling = "cycling"; + public static final String Land_Cycling = "land cycling"; + public static final String Morph = "morph"; + + +/* + public static final int Landwalk_Forest = 9; + public static final int Landwalk_Island = 10; + public static final int Landwalk_Plain = 11; + public static final int Landwalk__Swamp = 12; + public static final int Landwalk_Mountain = 13; + + public static final int Protection_Red = 14; + public static final int Protection_Black = 15; + public static final int Protection_White = 16; + public static final int Protection_Blue = 17; + public static final int Protection_Green = 18; + public static final int Protection_Artifact = 19; + +//taken from Mirror Golem + public static final int Protection_Creature = 20; + public static final int Protection_Enchantment = 21; + public static final int Protection_Instant = 22; + public static final int Protection_Land = 23; + public static final int Protection_Sorcery = 24; + + + public static final int Affinity_Artifact = 29; + public static final int Affinity_Forest = 30; + public static final int Affinity_Plain = 31; + public static final int Affinity_Swamp = 32; + public static final int Affinity_Island = 33; + public static final int Affinity_Moutain = 34; + } + */ + + diff --git a/src/Deck.java b/src/Deck.java new file mode 100644 index 00000000000..f1dd7e27310 --- /dev/null +++ b/src/Deck.java @@ -0,0 +1,76 @@ +import java.util.*; + +public class Deck implements java.io.Serializable +{ + private static final long serialVersionUID = -2188987217361601903L; + + //gameType is from Constant.GameType, like Constant.GameType.Regular + private String deckType; + + private boolean isRegular; + private boolean isSealed; + private boolean isDraft; + + private ArrayList main = new ArrayList(); + private ArrayList sideboard = new ArrayList(); + + //very important, do NOT change this + private String name = ""; + + //gameType is from Constant.GameType, like Constant.GameType.Regular + public Deck(String gameType) + { + deckType = gameType; + setDeckType(gameType); + } + public String getDeckType() {return deckType;} + + //can only call this method ONCE + private final void setDeckType(String deckType) + { + if(isRegular || isSealed || isDraft) + throw new RuntimeException("Deck : setDeckType() error, deck type has already been set"); + + if(deckType.equals(Constant.GameType.Constructed)) + isRegular = true; + else if(deckType.equals(Constant.GameType.Sealed)) + isSealed = true; + else if(deckType.equals(Constant.GameType.Draft)) + isDraft = true; + else + throw new RuntimeException("Deck : setDeckType() error, invalid deck type - " +deckType); + } + + public void setName(String s) {name = s;} + public String getName() {return name;}//may return null + + public void addMain(String cardName) {main.add(cardName);} + public int countMain() {return main.size();} + public String getMain(int index) {return main.get(index).toString();} + public String removeMain(int index) {return main.remove(index).toString();} + + public void addSideboard(String cardName) {sideboard.add(cardName);} + public int countSideboard() {return sideboard.size();} + public String getSideboard(int index) {return sideboard.get(index).toString();} + public String removeSideboard(int index) {return sideboard.remove(index).toString();} + + public boolean isDraft() {return isDraft;} + public boolean isSealed() {return isSealed;} + public boolean isRegular() {return isRegular;} + + public int hashcode() {return getName().hashCode();} + public String toString() {return getName();} +} + + + +class DeckSort implements Comparator +{ + public int compare(Object a, Object b) + { + String a1 = ((Deck)a).getName(); + String b1 = ((Deck)b).getName(); + + return a1.compareTo(b1); + } +} diff --git a/src/DeckIO.java b/src/DeckIO.java new file mode 100644 index 00000000000..c44a0410a3f --- /dev/null +++ b/src/DeckIO.java @@ -0,0 +1,203 @@ + + + + + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import forge.error.ErrorViewer; + + +//reads and write Deck objects +public class DeckIO { + private final File file; + private ArrayList deckList = new ArrayList(); + + //key is String of the humans deck + //data is Deck[] size of 8 + //humans deck is Deck[0] + private Map boosterMap = new HashMap(); + + public static void main(String[] args) { + Deck[] deck = new Deck[8]; + for(int i = 0; i < deck.length; i++) { + deck[i] = new Deck(Constant.GameType.Draft); + deck[i].setName("" + i); + } + + deck[0].addMain("Lantern Kami"); + + //DeckIO io = new DeckIO("booster-decks"); +// io.writeBoosterDeck(deck); +// io.close(); + +// io.deleteBoosterDeck("0"); +// System.out.println(io.getBoosterDecks().keySet().size()); +// io.close(); + } + + public DeckIO(String filename) { + this(new File(filename)); + } + + public DeckIO(File file) { + this.file = file; + + readFile(); + } + + public boolean isUnique(String deckName) { + Deck d; + for(int i = 0; i < deckList.size(); i++) { + d = deckList.get(i); + if(d.getName().equals(deckName)) return false; + } + return true; + } + + public boolean isUniqueDraft(String deckName) { + ArrayList key = new ArrayList(boosterMap.keySet()); + + for(int i = 0; i < key.size(); i++) { + if(key.get(i).equals(deckName)) return false; + } + return true; + } + + public boolean hasName(String deckName) { + ArrayList string = new ArrayList(); + + for(int i = 0; i < deckList.size(); i++) + string.add(deckList.get(i).toString()); + + Iterator it = boosterMap.keySet().iterator(); + while(it.hasNext()) + string.add(it.next().toString()); + + return string.contains(deckName); + } + + public Deck readDeck(String deckName) { + return deckList.get(findDeckIndex(deckName)); + } + + private int findDeckIndex(String deckName) { + int n = -1; + for(int i = 0; i < deckList.size(); i++) + if((deckList.get(i)).getName().equals(deckName)) n = i; + + if(n == -1) throw new RuntimeException("DeckIO : findDeckIndex() error, deck name not found - " + deckName); + + return n; + } + + public void writeDeck(Deck deck) { + if(deck.getDeckType().equals(Constant.GameType.Draft)) throw new RuntimeException( + "DeckIO : writeDeck() error, deck type is Draft"); + + deckList.add(deck); + } + + public void deleteDeck(String deckName) { + deckList.remove(findDeckIndex(deckName)); + } + + public Deck[] readBoosterDeck(String deckName) { + if(!boosterMap.containsKey(deckName)) throw new RuntimeException( + "DeckIO : readBoosterDeck() error, deck name not found - " + deckName); + + return boosterMap.get(deckName); + } + + public void writeBoosterDeck(Deck[] deck) { + checkBoosterDeck(deck); + + boosterMap.put(deck[0].toString(), deck); + }//writeBoosterDeck() + + public void deleteBoosterDeck(String deckName) { + if(!boosterMap.containsKey(deckName)) throw new RuntimeException( + "DeckIO : deleteBoosterDeck() error, deck name not found - " + deckName); + + boosterMap.remove(deckName); + } + + private void checkBoosterDeck(Deck[] deck) { + if(deck == null || deck.length != 8 || deck[0].getName().equals("") + || (!deck[0].getDeckType().equals(Constant.GameType.Draft))) { + throw new RuntimeException("DeckIO : checkBoosterDeck() error, invalid deck"); + } +// for(int i = 0; i < deck.length; i++) +// if(deck[i].getName().equals("")) +// throw new RuntimeException("DeckIO : checkBoosterDeck() error, deck does not have name - " +deck[i].getName()); + }//checkBoosterDeck() + + + public Deck[] getDecks() { + Deck[] out = new Deck[deckList.size()]; + deckList.toArray(out); + return out; + } + + public Map getBoosterDecks() { + return new HashMap(boosterMap); + } + + public void close() { + writeFile(); + } + + @SuppressWarnings("unchecked") + // ArrayList and Map have unchecked casts + private void readFile() { + try { +//~ + // Shouldn't ever get here, but just in case... + if(file == null) { + return; + } +//~ + if(!file.exists()) return; + + ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); + + deckList = (ArrayList) in.readObject(); + boosterMap = (Map) in.readObject(); + + in.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("DeckIO : read() error, " + ex); + } + } + + private void writeFile() { + try { +//~ + if(file == null) { + return; + } +//~ + if(!file.exists()) file.createNewFile(); + + ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file)); + + out.writeObject(deckList); + out.writeObject(boosterMap); + + out.flush(); + out.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("DeckIO : write() error, " + ex.getMessage()); + } + } +}//DeckIO \ No newline at end of file diff --git a/src/DefaultPlayerZone.java b/src/DefaultPlayerZone.java new file mode 100644 index 00000000000..b45e6d6f406 --- /dev/null +++ b/src/DefaultPlayerZone.java @@ -0,0 +1,114 @@ +import java.util.*; + +public class DefaultPlayerZone extends PlayerZone implements java.io.Serializable +{ + private static final long serialVersionUID = -5687652485777639176L; + + private ArrayList cards = new ArrayList(); + private String zoneName; + private String playerName; + private boolean update = true; + + public DefaultPlayerZone(String zone, String player) + { + zoneName = zone; + playerName = player; + } + //************ BEGIN - these methods fire updateObservers() ************* + public void add(Object o) + { + /* + if (is("Graveyard")) + System.out.println("GRAAAAAAAAAAAAAAAVE"); + */ + + Card c = (Card)o; + + if (is("Graveyard") + && c.getKeyword().contains("When this card is put into a graveyard from anywhere, reveal this card and shuffle it into its owner's library instead.")) + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, c.getOwner()); + lib.add(c); + AllZone.GameAction.shuffle(c.getOwner()); + return; + } + c.addObserver(this); + + c.setTurnInZone(AllZone.Phase.getTurn()); + + cards.add((Card)c); + update(); + } + public void update(Observable ob, Object object) + { + this.update(); + } + public void add(Card c, int index) + { + cards.add(index, c); + c.setTurnInZone(AllZone.Phase.getTurn()); + update(); + } + public void remove(Object c) + { + //TODO: put leaves play checks here + cards.remove((Card)c); + update(); + } + public void remove(int index) + { + cards.remove(index); + update(); + } + public void setCards(Card c[]) + { + cards = new ArrayList(Arrays.asList(c)); + update(); + } + //removes all cards + public void reset() + { + cards.clear(); + update(); + } + //************ END - these methods fire updateObservers() ************* + + public boolean is(String zone) + { + return zone.equals(zoneName); + } + public boolean is(String zone, String player) + { + return (zone.equals(zoneName) && player.equals(playerName)); + } + public String getPlayer() + { + return playerName; + } + public String getZone() + { + return zoneName; + } + public int size() + { + return cards.size(); + } + public Card get(int index) + { + return (Card)cards.get(index); + } + + public Card[] getCards() + { + Card c[] = new Card[cards.size()]; + cards.toArray(c); + return c; + } + public void update() + { + if(update) + updateObservers(); + } + public void setUpdate(boolean b) {update = b;} + public boolean getUpdate() {return update;} +} diff --git a/src/Display.java b/src/Display.java new file mode 100644 index 00000000000..4164e6f4a8a --- /dev/null +++ b/src/Display.java @@ -0,0 +1,18 @@ +public interface Display { + public T getChoice(String message, T[] choices); + + public T getChoiceOptional(String message, T[] choices); + + public void showMessage(String s); + public MyButton getButtonOK(); + public MyButton getButtonCancel(); +// public void showStatus(String message); + public void showCombat(String message); + + public void setVisible(boolean b); + + public boolean stopEOT(); + + //assigns combat damage, used by Combat.setAssignedDamage() + public void assignDamage(Card attacker, CardList blockers, int damage); +} diff --git a/src/EndOfTurn.java b/src/EndOfTurn.java new file mode 100644 index 00000000000..87be86eec34 --- /dev/null +++ b/src/EndOfTurn.java @@ -0,0 +1,65 @@ +//import java.util.*; + +//handles "until end of turn" and "at end of turn" commands from cards +public class EndOfTurn implements java.io.Serializable +{ + private static final long serialVersionUID = -3656715295379727275L; + + private CommandList at = new CommandList(); + private CommandList until = new CommandList(); + + public void addAt(Command c) {at.add(c);} + public void addUntil(Command c) {until.add(c);} + + public void executeAt() + { + //Pyrohemia and Pestilence + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + CardList creature = all.getType("Creature"); + + if(creature.isEmpty()) + { + CardList sacrifice = new CardList(); + sacrifice.addAll(all.getName("Pyrohemia").toArray()); + sacrifice.addAll(all.getName("Pestilence").toArray()); + + for(int i = 0; i < sacrifice.size(); i++) + AllZone.GameAction.sacrifice(sacrifice.get(i)); + } + + GameActionUtil.removeExaltedEffects(); + GameActionUtil.removeAttackedBlockedThisTurn(); + + AllZone.StateBasedEffects.rePopulateStateBasedList(); + + PlayerZone cz = AllZone.getZone(Constant.Zone.Removed_From_Play, Constant.Player.Computer); + PlayerZone hz = AllZone.getZone(Constant.Zone.Removed_From_Play, Constant.Player.Human); + + CardList c = new CardList(cz.getCards()); + CardList h = new CardList(hz.getCards()); + + System.out.println("number of cards in compy removed zone: " + c.size()); + System.out.println("number of cards in human removed zone: " + h.size()); + + execute(at); + }//executeAt() + + + public void executeUntil() {execute(until);} + + public int sizeAt() {return at.size();} + public int sizeUntil() {return until.size();} + + private void execute(CommandList c) + { + int length = c.size(); + + for(int i = 0; i < length; i++) + c.remove(0).execute(); + + + } +} diff --git a/src/ErrorViewer.java b/src/ErrorViewer.java new file mode 100644 index 00000000000..20ba172e4a3 --- /dev/null +++ b/src/ErrorViewer.java @@ -0,0 +1,120 @@ +/** + * ErrorViewer.java + * + * Created on 02.08.2009 + */ + +import static javax.swing.JOptionPane.*; + +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + + +/** + * The class ErrorViewer. Enables showing and saving error messages that occured in forge. + * + * @version V1.0 02.08.2009 + * @author Clemens Koza + */ +public class ErrorViewer { + private static JFileChooser c; + + /** + * Shows an error dialog taking the exception's message as the error message. + */ + public static void showError(Throwable ex) { + showError(ex, null); + } + + /** + * Shows an error dialog creating the error message by a formatting operation. + */ + public static void showError(Throwable ex, String format, Object... args) { + if(ex == null) return; + showError(ex, String.format(format, args)); + } + + /** + * Shows an error dialog with the specified error message. + */ + public static void showError(final Throwable ex, String message) { + if(ex == null) return; + + //As the first action, write to standard err for console debugging + if(message != null) System.err.println(message); + ex.printStackTrace(); + + final StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + + pw.println("An error has occured. You can copy/paste this message or save it to a file."); + pw.println("Please report this, plus what you tried to do, to:"); + pw.println("\thttp://www.slightlymagic.net/forum/viewforum.php?f=26"); + pw.println("If you don't want to register an account, you can mail it directly to"); + pw.println("\tmtgrares@yahoo.com"); + pw.println(); + pw.println(message != null? message:ex.getMessage()); + pw.println(); + pw.println("Detailed error trace:"); + ex.printStackTrace(pw); + + final JTextArea area = new JTextArea(sw.toString()); + area.setFont(new Font("Monospace", Font.PLAIN, 10)); + area.setEditable(false); + area.setLineWrap(true); + area.setWrapStyleWord(true); + + JScrollPane scroll = new JScrollPane(area); + Dimension dim = scroll.getPreferredSize(); + dim.width = 500; + scroll.setPreferredSize(dim); + + JButton save = new JButton("Save..."); + save.addActionListener(new ActionListener() { + //@Override + public void actionPerformed(ActionEvent e) { + if(c == null) c = new JFileChooser(); + + File f; + for(int i = 0;; i++) { + String name = String.format("%TF-%02d-%s.txt", System.currentTimeMillis(), i, + ex.getClass().getSimpleName()); + f = new File(name); + if(!f.exists()) break; + } + c.setSelectedFile(f); + c.showSaveDialog(null); + f = c.getSelectedFile(); + + try { + BufferedWriter bw = new BufferedWriter(new FileWriter(f)); + bw.write(area.getText()); + bw.close(); + } catch(IOException ex) { + showError(ex, "There was an error during saving, sorry!"); + } + } + }); + //Button is not modified, String gets the automatic listener to hide the dialog + Object[] options = {save, "Close"}; + JOptionPane pane = new JOptionPane(scroll, ERROR_MESSAGE, DEFAULT_OPTION, null, options, options[1]); + JDialog dlg = pane.createDialog("Error"); + dlg.setVisible(true); + dlg.dispose(); + } +} diff --git a/src/ExternalPanel.java b/src/ExternalPanel.java new file mode 100644 index 00000000000..08869bb364d --- /dev/null +++ b/src/ExternalPanel.java @@ -0,0 +1,90 @@ +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; + + +/** + * ExternalPanel.java + * + * Created on 13.08.2009 + */ + + +/** + * The class ExternalPanel. A panel with which some other component can be shown in an external window. + * + * @version V0.0 13.08.2009 + * @author Clemens Koza + */ +public class ExternalPanel extends JPanel { + + private static final long serialVersionUID = 9098962430872706173L; + private Component child, head; + private JFrame frame; + + public ExternalPanel(Component child) { + this(child, BorderLayout.EAST); + } + + public ExternalPanel(Component child, String side) { + super(new BorderLayout()); + add(this.child = child); + JButton b = new JButton(); + b.setPreferredSize(new Dimension(6, 6)); + b.setToolTipText("Click to move component into an extra Window"); + b.addActionListener(new ExternListener()); + head = b; + setHeadSide(side); + } + + public void setHeadSide(String side) { + remove(head); + add(head, side); + } + + @Override + protected void addImpl(Component comp, Object constraints, int index) { + if(comp != child && comp != head) throw new IllegalArgumentException(); + super.addImpl(comp, constraints, index); + } + + private final class ExternListener extends WindowAdapter implements ActionListener { + private void bringOut() { + frame = new JFrame(); + frame.addWindowListener(this); + frame.addWindowStateListener(this); + frame.add(child); + frame.getRootPane().setPreferredSize(child.getSize()); + frame.pack(); + frame.setVisible(true); + validate(); + repaint(); + } + + private void bringIn() { + add(child); + frame.dispose(); + frame = null; + validate(); + repaint(); + } + + public void actionPerformed(ActionEvent e) { + if(frame == null) bringOut(); + else bringIn(); + } + + @Override + public void windowClosing(WindowEvent e) { + bringIn(); + } + } +} diff --git a/src/FileUtil.java b/src/FileUtil.java new file mode 100644 index 00000000000..3aefb7febaa --- /dev/null +++ b/src/FileUtil.java @@ -0,0 +1,70 @@ +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import forge.error.ErrorViewer; + + +public class FileUtil { + public static boolean doesFileExist(String filename) { + File f = new File(filename); + return f.exists(); + } + + public static void writeFile(String filename, List data) { + writeFile(new File(filename), data); + } + + //writes each element of ArrayList on a separate line + //this is used to write a file of Strings + //this will create a new file if needed + //if filename already exists, it is deleted + public static void writeFile(File file, List data) { + try { + Collections.sort(data); + + BufferedWriter io = new BufferedWriter(new FileWriter(file)); + for(int i = 0; i < data.size(); i++) + io.write(data.get(i) + "\r\n"); + + io.flush(); + io.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("FileUtil : writeFile() error, problem writing file - " + file + " : " + ex); + } + }//writeFile() + + public static ArrayList readFile(String filename) { + return readFile(new File(filename)); + } + + //reads line by line and adds each line to the ArrayList + //this will return blank lines as well + //if filename not found, returns an empty ArrayList + public static ArrayList readFile(File file) { + ArrayList list = new ArrayList(); + BufferedReader in; + + try { + if(file == null || !file.exists()) return list; + + + in = new BufferedReader(new FileReader(file)); + + String line; + while((line = in.readLine()) != null) + list.add(line); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("FileUtil : readFile() error, " + ex); + } + + return list; + }//readFile() +} \ No newline at end of file diff --git a/src/GameAction.java b/src/GameAction.java new file mode 100644 index 00000000000..04582d8e863 --- /dev/null +++ b/src/GameAction.java @@ -0,0 +1,1259 @@ +import java.util.*; +import javax.swing.*; + + +public class GameAction +{ + // private StaticEffects staticEffects = new StaticEffects(); + + //returns null if playes does not have a Planeswalker + public Card getPlaneswalker(String player) + { + PlayerZone p = AllZone.getZone(Constant.Zone.Play, player); + CardList c = new CardList(p.getCards()); + c = c.getType("Planeswalker"); + + if(c.isEmpty()) + return null; + + return c.get(0); + } + + @SuppressWarnings("unused") // getCurrentCard +private Card getCurrentCard(int ID) + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Graveyard.getCards()); + all.addAll(AllZone.Human_Hand.getCards()); + all.addAll(AllZone.Human_Library.getCards()); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Human_Removed.getCards()); + + all.addAll(AllZone.Computer_Graveyard.getCards()); + all.addAll(AllZone.Computer_Hand.getCards()); + all.addAll(AllZone.Computer_Library.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + all.addAll(AllZone.Computer_Removed.getCards()); + + for(int i = 0; i < all.size(); i++) + if(all.get(i).getUniqueNumber() == ID) + return all.get(i); + + return null; + }//getCurrentCard() + + public Card moveTo(PlayerZone zone, Card c) + { + //c = getCurrentCard(c); - breaks things, seems to not be needed + //not 100% sure though, this might be broken + + + //here I did a switcheroo: remove card from zone first, + //THEN do copyCard, to ensure leavesPlay() effects will execute. + + PlayerZone p = AllZone.getZone(c); + //like if a Sorcery was resolved and needs to be put in the graveyard + //used by Input_Instant + if(p != null) + p.remove(c); + + //create new Card, which resets stats and anything that might have changed during play + if(! c.isToken()) + c = AllZone.CardFactory.copyCard(c); + + zone.add(c); + return c; + } + //card can be anywhere like in Hand or in Play + public void moveToGraveyard(Card c) + { + //must put card in OWNER's graveyard not controller's + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, c.getOwner()); + moveTo(grave, c); + } + + public void moveToTopOfLibrary(Card c) + { + PlayerZone p = AllZone.getZone(c); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, c.getOwner()); + + if(p != null) + p.remove(c); + if(! c.isToken()) + c = AllZone.CardFactory.copyCard(c); + + library.add(c, 0); + } + + public void discardRandom(String player) + { + Card[] c = AllZone.getZone(Constant.Zone.Hand, player).getCards(); + if(c.length != 0) + discard(CardUtil.getRandom(c)); + } + + public void discard(Card c) + { + discard_nath(c); + discard_megrim(c); + moveToGraveyard(c); + } + + public void discardRandom(String player, int numDiscard) + { + for (int i=0; i < numDiscard; i++) + { + Card[] c = AllZone.getZone(Constant.Zone.Hand, player).getCards(); + if (c.length != 0) + discard(CardUtil.getRandom(c)); + } + } + + public void discard(String player, int numDiscard) + { + if (player.equals(Constant.Player.Human)) + AllZone.InputControl.setInput(CardFactoryUtil.input_discard(numDiscard)); + else { + for (int i=0; i < numDiscard; i++) + AI_discard(); + } + } + + public void discardUnless(String player, int numDiscard, String uType) + { + if (player.equals(Constant.Player.Human)) + AllZone.InputControl.setInput(CardFactoryUtil.input_discardNumUnless(numDiscard, uType)); + else + AI_discardNumUnless(numDiscard, uType); + } + + public void AI_discardNumUnless(int numDiscard, String uType) + { + CardList hand = new CardList(); + hand.addAll(AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer).getCards()); + CardList tHand = hand.getType(uType); + + if (tHand.size() > 0) + { + CardListUtil.sortCMC(tHand); + tHand.reverse(); + discard(tHand.get(0)); + return; + } + for (int i=0; i < numDiscard; i++) + AI_discard(); + } + + public void AI_discard() + { + CardList hand = new CardList(); + hand.addAll(AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer).getCards()); + + CardList blIP = new CardList(); + blIP.addAll(AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer).getCards()); + blIP = blIP.getType("Basic"); + if (blIP.size() > 5) + { + CardList blIH = hand.getType("Basic"); + if (blIH.size() > 0) + { + discard(blIH.get(CardUtil.getRandomIndex(blIH))); + return; + } + + CardListUtil.sortAttackLowFirst(hand); + CardListUtil.sortNonFlyingFirst(hand); + discard(hand.get(0)); + return; + } + else + { + CardListUtil.sortCMC(hand); + discard(hand.get(0)); + return; + } + } + + public void handToLibrary(String player, int numToLibrary, String libPos) + { + if (player.equals(Constant.Player.Human)) + { + if (libPos.equals("Top") || libPos.equals("Bottom")) + libPos = libPos.toLowerCase(); + else + { + Object o = new Object(); + String s = "card"; + if (numToLibrary > 1) + s = "cards"; + + o = AllZone.Display.getChoice("Do you want to put the " + s + " on the top or bottom of your library?", new Object[] {"top", "bottom"}); + libPos = o.toString(); + } + AllZone.InputControl.setInput(CardFactoryUtil.input_putFromHandToLibrary(libPos, numToLibrary)); + } + else + { + for (int i=0; i < numToLibrary; i++) + { + if (libPos.equals("Top") || libPos.equals("Bottom")) + libPos = libPos.toLowerCase(); + else + { + Random r = new Random(); + if (r.nextBoolean()) + libPos = "top"; + else + libPos = "bottom"; + } + AI_handToLibrary(libPos); + } + } + } + + public void AI_handToLibrary(String libPos) + { + CardList hand = new CardList(); + hand.addAll(AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer).getCards()); + + CardList blIP = new CardList(); + blIP.addAll(AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer).getCards()); + blIP = blIP.getType("Basic"); + if (blIP.size() > 5) + { + CardList blIH = hand.getType("Basic"); + if (blIH.size() > 0) + { + Card card = blIH.get(CardUtil.getRandomIndex(blIH)); + AllZone.Computer_Hand.remove(card); + if (libPos.equals("top")) + AllZone.Computer_Library.add(card, 0); + else + AllZone.Computer_Library.add(card); + + return; + } + + CardListUtil.sortAttackLowFirst(hand); + CardListUtil.sortNonFlyingFirst(hand); + discard(hand.get(0)); + return; + } + else + { + CardListUtil.sortCMC(hand); + discard(hand.get(0)); + return; + } + } + + + public void discard_nath(Card discardedCard) + { + final String owner = discardedCard.getOwner(); + final String opponent = AllZone.GameAction.getOpponent(owner); + + PlayerZone opponentZone = AllZone.getZone(Constant.Zone.Play,opponent); + CardList opponentList = new CardList(opponentZone.getCards()); + + for(int i=0;i < opponentList.size();i++) + { + Card card = opponentList.get(i); + if (card.getName().equals("Nath of the Gilt-Leaf")) + { + Card c = new Card(); + + c.setOwner(card.getController()); + c.setController(card.getController()); + + c.setName("Elf Warrior"); + c.setImageName("G 1 1 Elf Warrior"); + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Elf"); + c.addType("Warrior"); + c.setBaseAttack(1); + c.setBaseDefense(1); + + opponentZone.add(c); + } + } + } + + public void discard_megrim(Card c) + { + //Whenever an opponent discards a card, Megrim deals 2 damage to that player. + //when a card is discarded, deal 2 damage to that player for each Megrim in play controlled by the opponent. + final String owner = c.getOwner(); + final String opponent = AllZone.GameAction.getOpponent(owner); + PlayerZone opponentZone = AllZone.getZone(Constant.Zone.Play,opponent); + CardList opponentList = new CardList(opponentZone.getCards()); + + //remove 2 life for each Megrim the opponent controls. + for(int i=0;i creature = PlayerZoneUtil.getCardType(AllZone.Computer_Play, "Creature"); + creature.addAll(PlayerZoneUtil.getCardType(AllZone.Human_Play , "Creature")); + + Card c; + Iterator it = creature.iterator(); + while(it.hasNext()) + { + c = (Card)it.next(); + + if (c.isEquipped()) + { + for (int i=0;i < c.getEquippedBy().size(); i++) + { + Card equipment = c.getEquippedBy().get(i); + if (!AllZone.GameAction.isCardInPlay(equipment)) + { + equipment.unEquipCard(c); + } + } + }//if isEquipped() + + if(c.getNetDefense() <= c.getDamage() && !c.getKeyword().contains("Indestructible")){ + destroy(c); + AllZone.Combat.removeFromCombat(c); //this is untested with instants and abilities but required for First Strike combat phase + } + + else if (c.getNetDefense() <= 0) + { + destroy(c); + AllZone.Combat.removeFromCombat(c); + } + + }//while it.hasNext() + + + ArrayList enchantments = PlayerZoneUtil.getCardType(AllZone.Computer_Play, "Enchantment"); + enchantments.addAll (PlayerZoneUtil.getCardType(AllZone.Human_Play , "Enchantment")); + + Iterator iterate = enchantments.iterator(); + while(iterate.hasNext()) + { + c = (Card)iterate.next(); + + if (c.isAura()) + { + for (int i=0;i < c.getEnchanting().size(); i++) + { + Card perm = c.getEnchanting().get(i); + if (!AllZone.GameAction.isCardInPlay(perm) || CardFactoryUtil.hasProtectionFrom(c, perm)) + { + c.unEnchantCard(perm); + destroy(c); + } + } + }//if isAura + + }//while iterate.hasNext() + + + //Make sure all equipment stops equipping previously equipped creatures that have left play. + ArrayList equip = PlayerZoneUtil.getCardType(AllZone.Computer_Play, "Equipment"); + equip.addAll(PlayerZoneUtil.getCardType(AllZone.Human_Play, "Equipment")); + + Iterator iter = equip.iterator(); + while(iter.hasNext()) + { + c = (Card)iter.next(); + if (c.isEquipping()) + { + Card equippedCreature = c.getEquipping().get(0); + if (!AllZone.GameAction.isCardInPlay(equippedCreature)) + c.unEquipCard(equippedCreature); + } + }//while iter.hasNext() + + + destroyLegendaryCreatures(); + destroyPlaneswalkers(); + }//checkStateEffects() + + + private void destroyPlaneswalkers() + { + //get all Planeswalkers + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getType("Planeswalker"); + + Card c; + for(int i = 0; i < list.size(); i++) + { + c = list.get(i); + if(c.getCounters(Counters.LOYALTY) <= 0) + AllZone.GameAction.moveToGraveyard(c); + } + } + + private void destroyLegendaryCreatures() + { + ArrayList a = PlayerZoneUtil.getCardType(AllZone.Human_Play , "Legendary"); + a.addAll (PlayerZoneUtil.getCardType(AllZone.Computer_Play, "Legendary")); + + while(! a.isEmpty()) + { + ArrayList b = getCardsNamed(a, ((Card)a.get(0)).getName()); + a.remove(0); + if(1 < b.size()) + { + for(int i = 0; i < b.size(); i++) + AllZone.GameAction.destroy((Card)b.get(i)); + } + } + }//destroyLegendaryCreatures() + + //ArrayList search is all Card objects, returns ArrayList of Cards + public ArrayList getCardsNamed(ArrayList search, String name) + { + ArrayList a = new ArrayList(); + Card c[] = CardUtil.toCard(search); + + for(int i = 0; i < c.length; i++) + { + if(c[i].getName().equals(name)) + a.add(c[i]); + } + return a; + } + public void sacrifice(Card c) + { + sacrificeDestroy(c); + } + public void destroyNoRegeneration(Card c) + { + if(! AllZone.GameAction.isCardInPlay(c) || c.getKeyword().contains("Indestructible")) + return; + + sacrificeDestroy(c); + } + private void sacrificeDestroy(Card c) + { + if(! isCardInPlay(c)) + return; + + boolean persist = false; + PlayerZone play = AllZone.getZone(c); + + if(c.getOwner().equals(Constant.Player.Human) || c.getOwner().equals(Constant.Player.Computer)) + ; + else + throw new RuntimeException("GameAction : destroy() invalid card.getOwner() - " +c +" " +c.getOwner()); + + play.remove(c); + + + if (c.getKeyword().contains("Persist") && c.getCounters(Counters.M1M1) == 0) + persist = true; + + //tokens don't go into the graveyard + //TODO: must change this if any cards have effects that trigger "when creatures go to the graveyard" + if(! c.isToken()) + //resets the card, untaps the card, removes anything "extra", resets attack and defense + moveToGraveyard(c); + + + c.destroy(); + if (c.isEquipped()) + skullClamp_destroy(c); + + if (persist){ + c.setDamage(0); + c.untap(); + PlayerZone ownerPlay = AllZone.getZone(Constant.Zone.Play, c.getOwner()); + PlayerZone grave = AllZone.getZone(c); + + if (c.isEquipped()) + c.unEquipAllCards(); + + grave.remove(c); + ownerPlay.add(c); + + c.setTempAttackBoost(0); + c.setTempDefenseBoost(0); + c.setExaltedBonus(false); + //reset more stuff ? + + c.addCounter(Counters.M1M1, 1); + } + + //if (c.getName().equals("Rancor") || c.getName().equals("Brilliant Halo") || c.getName().equals("Undying Rage")) + if (c.getKeyword().contains("When this card is put into a graveyard from the battlefield, return this card to its owner's hand")) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand,c.getOwner()); + moveTo(hand, c); + } + + else if (c.getName().equals("Nissa's Chosen")) + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, c.getOwner()); + moveTo(library, c); + } + + else if (c.getName().equals("Guan Yu, Sainted Warrior")) + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, c.getOwner()); + moveTo(library, c); + AllZone.GameAction.shuffle(c.getOwner()); + } + }//sacrificeDestroy() + public void destroy(Card c) + { + if(! AllZone.GameAction.isCardInPlay(c) || + (c.getKeyword().contains("Indestructible") && (!c.isCreature() || c.getNetDefense() > 0)) ) + return; + + if(c.getShield() > 0) + { + c.subtractShield(); + c.setDamage(0); + c.tap(); + return; + } + //System.out.println("Card " + c.getName() + " is getting sent to GY, and this turn it got damaged by: "); + for (Card crd : c.getReceivedDamageFromThisTurn().keySet() ) { + if (c.getReceivedDamageFromThisTurn().get(crd) > 0) + { + //System.out.println(crd.getName() ); + GameActionUtil.executeVampiricEffects(crd); + } + } + this.sacrificeDestroy(c); + } + + //because originally, MTGForge didn't keep track of cards removed from the game. + public void removeFromGame(Card c) + { + if (AllZone.GameAction.isCardRemovedFromGame(c) ) + return; + + PlayerZone zone = AllZone.getZone(c); //could be hand, grave, play, ... + PlayerZone removed = AllZone.getZone(Constant.Zone.Removed_From_Play, c.getOwner()); + + zone.remove(c); + if (!c.isToken()) + removed.add(c); + + } + + + private boolean shouldDraw = true; + private String lastPlayerToDraw = Constant.Player.Human; + + public void drawCard(String player) + { + //TODO: show that milled player looses + + boolean isDrawPhase = AllZone.Phase.getPhase().equals(Constant.Phase.Draw); + if(isDrawPhase){ + String currentPlayer = AllZone.Phase.getActivePlayer(); + if(!currentPlayer.equals(lastPlayerToDraw)){ + shouldDraw = true; + } + lastPlayerToDraw = currentPlayer; + + if(!shouldDraw){ + return; + } + //so they can't draw twice in a row during the draw phase + shouldDraw = false; + } + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player); + + if(library.size() != 0) + { + + Card c = library.get(0); + library.remove(0); + hand.add(c); + + GameActionUtil.executeDrawCardTriggeredEffects(player); + } + } + + //is this card a permanent that is in play? + public boolean isCardInPlay(Card c) + { + return PlayerZoneUtil.isCardInZone(AllZone.Computer_Play, c) || + PlayerZoneUtil.isCardInZone(AllZone.Human_Play , c); + } + + public boolean isCardInGrave(Card c) + { + return PlayerZoneUtil.isCardInZone(AllZone.Computer_Graveyard, c) || + PlayerZoneUtil.isCardInZone(AllZone.Human_Graveyard, c); + } + + public boolean isCardRemovedFromGame(Card c) + { + return PlayerZoneUtil.isCardInZone(AllZone.Computer_Removed, c) || + PlayerZoneUtil.isCardInZone(AllZone.Human_Removed, c); + } + + public String getOpponent(String p) + { + return p.equals(Constant.Player.Human) ? Constant.Player.Computer : Constant.Player.Human; + } + //TODO: shuffling seems to change a card's unique number but i'm not 100% sure + public void shuffle(String player) + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + Card c[] = library.getCards(); + + if(c.length <= 1) + return; + + ArrayList list = new ArrayList(Arrays.asList(c)); + //overdone but wanted to make sure it was really random + Random random = new Random(); + Collections.shuffle(list, random); + Collections.shuffle(list, random); + Collections.shuffle(list, random); + Collections.shuffle(list, random); + Collections.shuffle(list, random); + Collections.shuffle(list, random); + +// random = java.security.SecureRandom.getInstance("SHA1PRNG"); + + Object o; + for(int i = 0; i < list.size(); i++) + { + o = list.remove(random.nextInt(list.size())); + list.add(random.nextInt(list.size()), o); + } + + Collections.shuffle(list, random); + Collections.shuffle(list, random); + Collections.shuffle(list, random); + Collections.shuffle(list, random); + Collections.shuffle(list, random); + Collections.shuffle(list, random); + + + list.toArray(c); + library.setCards(c); + }//shuffle + public boolean isCardInZone(Card card, PlayerZone p) + { + ArrayList list = new ArrayList(Arrays.asList(p.getCards())); + return list.contains(card); + } + public PlayerLife getPlayerLife(String player) + { + if(player == null) + throw new RuntimeException("GameAction : getPlayerLife() player == null"); + + if(player.equals(Constant.Player.Human)) + return AllZone.Human_Life; + else if(player.equals(Constant.Player.Computer)) + return AllZone.Computer_Life; + else + throw new RuntimeException("GameAction : getPlayerLife() invalid player string " +player); + } + //removes all damage from player's creatures + public void removeDamage(String player) + { + PlayerZone p = AllZone.getZone(Constant.Zone.Play, player); + ArrayList a = PlayerZoneUtil.getCardType(p, "Creature"); + Card c[] = CardUtil.toCard(a); + for(int i = 0; i < c.length; i++) + c[i].setDamage(0); + } + public void newGame(Deck humanDeck, Deck computerDeck) + { +// AllZone.Computer = new ComputerAI_Input(new ComputerAI_General()); + System.gc(); //garbage collection... does it make a difference though? + lastPlayerToDraw = Constant.Player.Human; + + AllZone.Computer_Life.setLife(20); + AllZone.Human_Life.setLife(20); + + AllZone.Human_Life.setAssignedDamage(0); + AllZone.Computer_Life.setAssignedDamage(0); + + AllZone.Stack.reset(); + AllZone.Phase.reset(); + AllZone.Combat.reset(); + AllZone.Display.showCombat(""); + + AllZone.Human_Graveyard.reset(); + AllZone.Human_Hand.reset(); + AllZone.Human_Library.reset(); + AllZone.Human_Play.reset(); + AllZone.Human_Removed.reset(); + + AllZone.Computer_Graveyard.reset(); + AllZone.Computer_Hand.reset(); + AllZone.Computer_Library.reset(); + AllZone.Computer_Play.reset(); + AllZone.Computer_Removed.reset(); + + AllZone.InputControl.resetInput(); + + AllZone.StateBasedEffects.reset(); + + //clear Image caches, so the problem doesn't get slower and slower + //cached images are cleared in Gui_WinLose.quitButton_actionPerformed() + + + {//re-number cards just so their unique numbers are low, just for user friendliness + CardFactory c = AllZone.CardFactory; + Card card; + int nextUniqueNumber = 1; + + Random generator = new Random(); + + for(int i = 0; i < humanDeck.countMain(); i++) + { + card = c.getCard(humanDeck.getMain(i), Constant.Player.Human); + card.setUniqueNumber(nextUniqueNumber++); + if (card.isBasicLand()) + { + card.setRandomPicture(generator.nextInt(4)); + //System.out.println("human random number:" + card.getRandomPicture()); + } + AllZone.Human_Library.add(card); + + //get card picture so that it is in the image cache +// ImageCache.getImage(card); + } + + for(int i = 0; i < computerDeck.countMain(); i++) + { + card = c.getCard(computerDeck.getMain(i), Constant.Player.Computer); + card.setUniqueNumber(nextUniqueNumber++); + if (card.isBasicLand()) + { + card.setRandomPicture(generator.nextInt(4)); + //System.out.println("computer random number:" + card.getRandomPicture()); + } + AllZone.Computer_Library.add(card); + + //get card picture so that it is in the image cache +// ImageCache.getImage(card); + } + }//end re-numbering + + for(int i = 0; i < 100; i++) + this.shuffle(Constant.Player.Human); + + //do this instead of shuffling Computer's deck + boolean smoothLand = Constant.Runtime.smooth[0]; + + if(smoothLand) + { + Card[] c = smoothComputerManaCurve(AllZone.Computer_Library.getCards()); + AllZone.Computer_Library.setCards(c); + } + else + { + AllZone.Computer_Library.setCards(AllZone.Computer_Library.getCards()); + this.shuffle(Constant.Player.Computer); + } + + for(int i = 0; i < 7; i++) + { + this.drawCard(Constant.Player.Computer); + this.drawCard(Constant.Player.Human); + } + /* + Card mp = new Card(); + mp.setName("Mana Pool"); + //mp.addType("Land"); + mp.addIntrinsicKeyword("Indestructible"); + mp.addIntrinsicKeyword("Shroud"); + AllZone.Human_Play.add(mp); + */ + + Card mp = AllZone.ManaPool; + AllZone.Human_Play.add(mp); + + AllZone.Stack.reset();//this works, it clears the stack of Upkeep effects like Bitterblossom + AllZone.InputControl.setInput(new Input_Mulligan()); + }//newGame() + + //this is where the computer cheats + //changes AllZone.Computer_Library + private Card[] smoothComputerManaCurve(Card[] in) + { + CardList library = new CardList(in); + library.shuffle(); + + //remove all land, keep non-basicland in there, shuffled + CardList land = library.getType("Land"); + for(int i = 0; i < land.size(); i++) + if (land.get(i).isLand()) + library.remove(land.get(i)); + + //non-basic lands are removed, because the computer doesn't seem to + //effectively use them very well + land = threadLand(land); + + //mana weave, total of 7 land + library.add(7, land.get(0)); + library.add(8, land.get(1)); + library.add(9, land.get(2)); + library.add(10, land.get(3)); + library.add(11, land.get(4)); + + library.add(13, land.get(5)); + library.add(16, land.get(6)); + + //add the rest of land to the end of the deck + for(int i = 0; i < land.size(); i++) + if(! library.contains(land.get(i))) + library.add(land.get(i)); + + + //check + for(int i = 0; i < library.size(); i++) + System.out.println(library.get(i)); + + + + + return library.toArray(); + }//smoothComputerManaCurve() + + @SuppressWarnings("unused") // getComputerLand +private CardList getComputerLand(CardList in) + { + CardList land = new CardList(); + land = in.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isLand(); + } + }); + + return land; + }//getComputerLand() + + //non-basic lands are removed, because the computer doesn't seem to + //effectively used them very well + public CardList threadLand(CardList in) + { + //String[] basicLand = {"Forest", "Swamp", "Mountain", "Island", "Plains"}; //unused + + //Thread stuff with as large a spread of colors as possible: + String[] allLand = {"Bayou", "Volcanic Island", "Savannah", "Badlands", "Tundra", + "Taiga", "Underground Sea", "Plateau", "Tropical Island", "Scrubland", + "Overgrown Tomb", "Steam Vents", "Temple Garden", "Blood Crypt", "Hallowed Fountain", + "Stomping Ground", "Watery Grave", "Sacred Foundry", "Breeding Pool", "Godless Shrine", + "Pendelhaven", "Flagstones of Trokair", + "Forest", "Swamp", "Mountain", "Island", "Plains", + "Tree of Tales", "Vault of Whispers", "Great Furnace", "Seat of the Synod", "Ancient Den", + "Treetop Village", "Ghitu Encampment", "Faerie Conclave", "Forbidding Watchtower", + "Savage Lands", "Arcane Sanctum", "Jungle Shrine", "Crumbling Necropolis", "Seaside Citadel", + "Elfhame Palace", "Coastal Tower", "Salt Marsh", + "Kher Keep", "Library of Alexandria", "Dryad Arbor" }; + + + + ArrayList land = new ArrayList(); + + //get different CardList of all Forest, Swamps, etc... + CardList check; + for(int i = 0; i < allLand.length; i++) + { + check = in.getName(allLand[i]); + + if(! check.isEmpty()) + land.add(check); + } +/* + //get non-basic land CardList + check = in.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isLand() && !c.isBasicLand(); + } + }); + if(! check.isEmpty()) + land.add(check); +*/ + + //thread all separate CardList's of land together to get something like + //Mountain, Plains, Island, Mountain, Plains, Island + CardList out = new CardList(); + + int i = 0; + while(! land.isEmpty()) + { + i = (i + 1) % land.size(); + + check = (CardList) land.get(i); + if(check.isEmpty()) + { + //System.out.println("removed"); + land.remove(i); + i--; + continue; + } + + out.add(check.get(0)); + check.remove(0); + }//while + + return out; + }//threadLand() + + + @SuppressWarnings("unused") // getDifferentLand +private int getDifferentLand(CardList list, String land) + { + int out = 0; + + return out; + } + + + //decides who goes first when starting another game, used by newGame() + public void chooseWhoPlaysFirst() + { + //lets the user decides who plays first + boolean humanChoose = false; + if(Constant.Runtime.WinLose.getWin() == 0 && Constant.Runtime.WinLose.getLose() == 0) + humanChoose = MyRandom.random.nextBoolean(); + else if(! Constant.Runtime.WinLose.didWinRecently()) + humanChoose = true; + + //does the player go first? + boolean humanFirst; + + if(humanChoose) + { + int n = JOptionPane.showConfirmDialog(null, "Do you want to play first?", "", JOptionPane.YES_NO_OPTION); + if(n == JOptionPane.YES_OPTION) + humanFirst = true; + else + humanFirst = false; + } + else//computer randomly decides who goes first + humanFirst = MyRandom.random.nextBoolean(); + + String message; + if(humanFirst) + message = "You play first"; + else + { + message = "Computer plays first"; + AllZone.Phase.setPhase(Constant.Phase.Main1, Constant.Player.Computer); + } + + //show message if player doesn't get to choose + if(! humanChoose) + JOptionPane.showMessageDialog(null, message); + }//choooseWhoPlaysFirst() + + //if Card had the type "Aura" this method would always return true, since local enchantments are always attached to something + //if Card is "Equipment", returns true if attached to something + public boolean isAttachee(Card c) + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + list.addAll (AllZone.Human_Play.getCards()); + + for(int i = 0; i < list.size(); i++) + { + CardList check = new CardList(list.getCard(i).getAttachedCards()); + if(check.contains(c)) + return true; + } + + return false; + }//isAttached(Card c) + + public boolean canTarget(String targetPlayer) + { + return true; + } + public boolean canTarget(Card target, Card source) + { + if(target.getKeyword().contains("Cannot be target of spells or abilities")) + return false; + + return true; + } + public void playCard(Card c) + { + + //TODO: add code for cards like Standstill ?? + + SpellAbility[] choices = canPlaySpellAbility(c.getSpellAbility()); + SpellAbility sa; +/* + System.out.println(choices.length); + for(int i = 0; i < choices.length; i++) + System.out.println(choices[i]); +*/ + if(choices.length == 0) + return; + else if(choices.length == 1) + sa = choices[0]; + else + sa = (SpellAbility) AllZone.Display.getChoiceOptional("Choose", choices); + + if(sa == null) + return; + + playSpellAbility(sa); + } + public void playSpellAbility(SpellAbility sa) + { + + if (sa.getManaCost().equals("0") && sa.getBeforePayMana() == null){ + AllZone.Stack.add(sa); + if (sa.isTapAbility()) + sa.getSourceCard().tap(); + return; + } + + if(sa.getBeforePayMana() == null) + AllZone.InputControl.setInput(new Input_PayManaCost(sa)); + else + AllZone.InputControl.setInput(sa.getBeforePayMana()); + } + public SpellAbility[] canPlaySpellAbility(SpellAbility[] sa) + { + ArrayList list = new ArrayList(); + + for(int i = 0; i < sa.length; i++) + if(sa[i].canPlay()) + list.add(sa[i]); + + SpellAbility[] array = new SpellAbility[list.size()]; + list.toArray(array); + return array; + }//canPlaySpellAbility() + + public void skullClamp_destroy(Card c) + { + CardList equipment = new CardList(); + equipment.addAll(c.getEquippedBy().toArray()); + equipment = equipment.getName("Skullclamp"); + + if (equipment.size() == 0) + return; + + final Card crd = c; + + final Ability draw = new Ability(crd,"0") + { + public void resolve() { + String s = crd.getOwner(); + //System.out.println("owner of " + crd.getName() + " = " + s); + AllZone.GameAction.drawCard(s); + AllZone.GameAction.drawCard(s); + } + }; + draw.setStackDescription("Skullclamp - " + c.getController() + " draws 2 cards (" + c.getName() +")."); + + for (int i=0; i 1) + System.out.println("(MULTIPLE blockers):"); + System.out.println("Assigned " + damage + " damage to " + card); + for (int i=0;i= 1) + { + for (Card c : card.getReceivedDamageFromThisTurn().keySet() ) { + if (card.getReceivedDamageFromThisTurn().get(c) > 0) + { + int power; + System.out.println("addDamage: " +card.getName() + " has received damage from " + c.getName() ); + + if (c.getKeyword().contains("Wither")) + { + power = card.getReceivedDamageFromThisTurn().get(c); + damageToAdd = damageToAdd - power; + card.addCounter(Counters.M1M1, power); + } + if (c.getName().equals("Spiritmonger") || c.getName().equals("Mirri the Cursed")) + { + final Card thisCard = c; + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + thisCard.addCounter(Counters.P1P1, 1); + } + }; // ability2 + + ability2.setStackDescription(c.getName() + " - gets a +1/+1 counter"); + AllZone.Stack.add(ability2); + } + if (c.getKeyword().contains("Deathtouch")) + { + AllZone.GameAction.destroy(card); + AllZone.Combat.removeFromCombat(card); + } + } + } + } + System.out.println("Adding " + damageToAdd + " damage to " + card.getName()); + if (isCardInPlay(card)) + card.addDamage(damageToAdd); + } + + public void addLife(String player, int life) + { + // place holder for future life gain modification rules + + getPlayerLife(player).addLife(life); + } + + public void subLife(String player, int life) + { + // place holder for future life loss modification rules + + getPlayerLife(player).subtractLife(life); + } + + public void addDamage(String player, int damage) + { + // place holder for future damage modification rules (prevention?) + + getPlayerLife(player).subtractLife(damage); + } + + + public static void main(String[] args) + { + GameAction gameAction = new GameAction(); + GenerateConstructedDeck gen = new GenerateConstructedDeck(); + + for(int i = 0; i < 2000; i++) + { + CardList list = gen.generateDeck(); + + Card[] card = gameAction.smoothComputerManaCurve(list.toArray()); + + CardList check = new CardList(); + for(int a = 0; a < 30; a++) + check.add(card[a]); + + if(check.getType("Land").size() != 7) + { + System.out.println("error - " +check); + break; + } + }//for + } +} \ No newline at end of file diff --git a/src/GameActionUtil.java b/src/GameActionUtil.java new file mode 100644 index 00000000000..54b50438ec0 --- /dev/null +++ b/src/GameActionUtil.java @@ -0,0 +1,10853 @@ +import java.util.*; + +public class GameActionUtil +{ + + public static void executeUpkeepEffects() + { + + upkeep_removeDealtDamageToOppThisTurn(); + //upkeep_Echo(); + // upkeep_CheckEmptyDeck_Lose(); //still a little buggy + upkeep_Phyrexian_Arena(); + upkeep_Land_Tax(); + upkeep_Greener_Pastures(); + upkeep_Squee(); + upkeep_Sporesower_Thallid(); + upkeep_Scute_Mob(); + upkeep_Heartmender(); + upkeep_AEther_Vial(); + upkeep_Ratcatcher(); + upkeep_Nath(); + upkeep_Cunning_Lethemancer(); + upkeep_Sensation_Gorger(); + upkeep_Winnower_Patrol(); + upkeep_Nightshade_Schemers(); + upkeep_Wandering_Graybeard(); + upkeep_Wolf_Skull_Shaman(); + upkeep_Leaf_Crowned_Elder(); + upkeep_Debtors_Knell(); + upkeep_Reya(); + upkeep_Emeria(); + upkeep_Oversold_Cemetery(); + upkeep_Wort(); + upkeep_Nether_Spirit(); + upkeep_Nettletooth_Djinn(); + upkeep_Fledgling_Djinn(); + upkeep_Juzam_Djinn(); + upkeep_Grinning_Demon(); + upkeep_Seizan_Perverter_of_Truth(); + upkeep_Serendib_Efreet(); + upkeep_Sleeper_Agent(); + upkeep_Cursed_Land(); + upkeep_Pillory_of_the_Sleepless(); + upkeep_Bringer_of_the_Green_Dawn(); + upkeep_Bringer_of_the_Blue_Dawn(); + upkeep_Bringer_of_the_White_Dawn(); + upkeep_Dragon_Broodmother(); //put this before bitterblossom and mycoloth, so that they will resolve FIRST + upkeep_Bitterblossom(); + upkeep_Battle_of_Wits(); + upkeep_Felidar_Sovereign(); + upkeep_Klass(); + upkeep_Convalescence(); + upkeep_Convalescent_Care(); + upkeep_Defense_of_the_Heart(); + upkeep_Mycoloth(); + upkeep_Spore_Counters(); + upkeep_Aven_Riftwatcher(); + upkeep_Calciderm(); + upkeep_Blastoderm(); + upkeep_Eldrazi_Monument(); + upkeep_Blaze_Counters(); + upkeep_Dark_Confidant(); // keep this one semi-last + + upkeep_BlackVice(); // keep this one last, since it happens at the end + // of the upkeep. + upkeep_Howling_Mine(); // keep this one even laster, since it would + // cause black vise to do an extra point of + // damage if black vise was in play + upkeep_Font_of_Mythos(); + + upkeep_AI_Aluren(); // experimental, just have the AI dump his small + // creats in play when aluren is there + } + + public static void executePlayCardEffects(SpellAbility sa) + { + // experimental: + // this method check for cards that have triggered abilities whenever a + // card gets played + // (called in MagicStack.java) + Card c = sa.getSourceCard(); + + playCard_Standstill(c); + playCard_SolKanar(c); + playCard_Gilt_Leaf_Archdruid(c); + playCard_Reki(c); + playCard_Vedalken_Archmage(c); + playCard_Sigil_of_the_Empty_Throne(c); + playCard_Merrow_Levitator(c); + playCard_Primordial_Sage(c); + playCard_Quirion_Dryad(c); + playCard_Enchantress_Draw(c); + playCard_Mold_Adder(c); + playCard_Fable_of_Wolf_and_Owl(c); + } + + public static void playCard_Standstill(Card c) + { + PlayerZone hplay = AllZone.getZone(Constant.Zone.Play, + Constant.Player.Human); + PlayerZone cplay = AllZone.getZone(Constant.Zone.Play, + Constant.Player.Computer); + + CardList list = new CardList(); + list.addAll(hplay.getCards()); + list.addAll(cplay.getCards()); + + list = list.getName("Standstill"); + + for (int i = 0; i < list.size(); i++) + { + final String drawer = AllZone.GameAction.getOpponent(c + .getController()); + final Card card = list.get(0); + + Ability ability2 = new Ability(card, "0") + { + public void resolve() + { + // sac standstill + AllZone.GameAction.sacrifice(card); + // player who didn't play spell, draws 3 cards + AllZone.GameAction.drawCard(drawer); + AllZone.GameAction.drawCard(drawer); + AllZone.GameAction.drawCard(drawer); + } + }; // ability2 + + ability2.setStackDescription(card.getName() + " - " + + c.getController() + " played a spell, " + drawer + + " draws three cards."); + AllZone.Stack.add(ability2); + + } + + } + + public static void playCard_SolKanar(Card c) + { + PlayerZone hplay = AllZone.getZone(Constant.Zone.Play, + Constant.Player.Human); + PlayerZone cplay = AllZone.getZone(Constant.Zone.Play, + Constant.Player.Computer); + + CardList list = new CardList(); + list.addAll(hplay.getCards()); + list.addAll(cplay.getCards()); + + list = list.getName("Sol'kanar the Swamp King"); + + if (list.size() > 0 + && CardUtil.getColors(c).contains(Constant.Color.Black)) + { + final Card card = list.get(0); + final String controller = card.getController(); + + Ability ability2 = new Ability(card, "0") + { + public void resolve() + { + PlayerLife life = AllZone.GameAction + .getPlayerLife(controller); + life.addLife(1); + } + }; // ability2 + + ability2.setStackDescription(card.getName() + " - " + + c.getController() + " played a black spell, " + + card.getController() + " gains 1 life."); + AllZone.Stack.add(ability2); + } + + } + + public static void playCard_Enchantress_Draw(Card c) + { + + PlayerZone play = AllZone + .getZone(Constant.Zone.Play, c.getController()); + + CardList list = new CardList(); + list.addAll(play.getCards()); + + list = list.filter(new CardListFilter() + { + public boolean addCard(Card crd) + { + if (crd.getName().equals("Verduran Enchantress") || crd.getName().equals("Enchantress's Presence") || + crd.getName().equals("Mesa Enchantress") || crd.getName().equals("Argothian Enchantress")) + return true; + else + return false; + } + }); + //list = list.getName("Verduran Enchantress"); + + if (c.isEnchantment()) + { + for (int i = 0; i < list.size(); i++) + { + final Card card = list.get(0); + + Ability ability2 = new Ability(card, "0") + { + public void resolve() + { + // draws a card + AllZone.GameAction.drawCard(card.getController()); + } + }; // ability2 + + ability2.setStackDescription(card.getName() + " - " + + c.getController() + + " plays an enchantment spell and draws a card"); + AllZone.Stack.add(ability2); + + } // for + }// if isEnchantment() + } + + public static void playCard_Gilt_Leaf_Archdruid(Card c) + { + + PlayerZone play = AllZone + .getZone(Constant.Zone.Play, c.getController()); + + CardList list = new CardList(); + list.addAll(play.getCards()); + + list = list.getName("Gilt-Leaf Archdruid"); + if (c.getType().contains("Druid") || c.getKeyword().contains("Changeling")) + { + for (int i = 0; i < list.size(); i++) + { + final Card card = list.get(0); + + Ability ability2 = new Ability(card, "0") + { + public void resolve() + { + // draws a card + AllZone.GameAction.drawCard(card.getController()); + } + }; // ability2 + + ability2.setStackDescription(card.getName() + " - " + + c.getController() + + " plays a Druid spell and draws a card"); + AllZone.Stack.add(ability2); + + } // for + }// if druid + } + + public static void playCard_Reki(Card c) + { + + PlayerZone play = AllZone + .getZone(Constant.Zone.Play, c.getController()); + + CardList list = new CardList(); + list.addAll(play.getCards()); + + list = list.getName("Reki, the History of Kamigawa"); + if (c.getType().contains("Legendary")) + { + for (int i = 0; i < list.size(); i++) + { + final Card card = list.get(0); + + Ability ability2 = new Ability(card, "0") + { + public void resolve() + { + // draws a card + AllZone.GameAction.drawCard(card.getController()); + } + }; // ability2 + + ability2.setStackDescription(card.getName() + " - " + + c.getController() + + " plays a Legendary spell and draws a card"); + AllZone.Stack.add(ability2); + + } // for + }// if legendary + } + + public static void playCard_Vedalken_Archmage(Card c) + { + + PlayerZone play = AllZone + .getZone(Constant.Zone.Play, c.getController()); + + CardList list = new CardList(); + list.addAll(play.getCards()); + + list = list.getName("Vedalken Archmage"); + if (c.getType().contains("Artifact")) + { + for (int i = 0; i < list.size(); i++) + { + final Card card = list.get(0); + + Ability ability2 = new Ability(card, "0") + { + public void resolve() + { + // draws a card + AllZone.GameAction.drawCard(card.getController()); + } + }; // ability2 + + ability2.setStackDescription(card.getName() + " - " + + c.getController() + + " plays an Artifact spell and draws a card"); + AllZone.Stack.add(ability2); + + } // for + }// if artifact + } + + public static void playCard_Sigil_of_the_Empty_Throne(Card c) + { + + final PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + final String controller = c.getController(); + + CardList list = new CardList(); + list.addAll(play.getCards()); + + list = list.getName("Sigil of the Empty Throne"); + if (c.isEnchantment()) + { + for (int i = 0; i < list.size(); i++) + { + final Card card = list.get(0); + + Ability ability2 = new Ability(card, "0") + { + public void resolve() + { + + Card card = new Card(); + + card.setOwner(controller); + card.setController(controller); + + card.setName("Angel"); + card.setImageName("W 4 4 Angel"); + card.setManaCost("W"); + card.setToken(true); + + card.addType("Creature"); + card.addType("Angel"); + card.addIntrinsicKeyword("Flying"); + card.setBaseAttack(4); + card.setBaseDefense(4); + + play.add(card); + } + }; // ability2 + + ability2 + .setStackDescription(card.getName() + + " - " + + c.getController() + + " puts a 4/4 White Angel token with flying into play."); + AllZone.Stack.add(ability2); + + } // for + }// if isEnchantment() + } + + public static void playCard_Merrow_Levitator(Card c) + { + final PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + + + CardList list = new CardList(); + list.addAll(play.getCards()); + + list = list.getName("Merrow Levitator"); + + if (CardUtil.getColors(c).contains(Constant.Color.Blue)) + { + for (int i = 0; i < list.size(); i++) + { + final Card card = list.get(i); + + Ability ability2 = new Ability(card, "0") + { + public void resolve() + { + if (card.isTapped()) + card.untap(); + } + }; // ability2 + + ability2 + .setStackDescription(card.getName() + + " - " + + " untaps"); + AllZone.Stack.add(ability2); + + } // for + }// if is blue spell + }//merrow levitator + + public static void playCard_Primordial_Sage(Card c) + { + + PlayerZone play = AllZone + .getZone(Constant.Zone.Play, c.getController()); + + CardList list = new CardList(); + list.addAll(play.getCards()); + + list = list.getName("Primordial Sage"); + if (c.getType().contains("Creature")) + { + for (int i = 0; i < list.size(); i++) + { + final Card card = list.get(0); + + Ability ability2 = new Ability(card, "0") + { + public void resolve() + { + // draws a card + AllZone.GameAction.drawCard(card.getController()); + } + }; // ability2 + + ability2.setStackDescription(card.getName() + " - " + + c.getController() + + " plays a Creature spell and draws a card"); + AllZone.Stack.add(ability2); + + } // for + }// if Creature + }//primordial sage + + public static void playCard_Quirion_Dryad(Card c) + { + String controller = c.getController(); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, + controller); + + CardList list = new CardList(); + list.addAll(play.getCards()); + + list = list.getName("Quirion Dryad"); + + if (list.size() > 0 && (CardUtil.getColors(c).contains(Constant.Color.White) || + CardUtil.getColors(c).contains(Constant.Color.Blue) || + CardUtil.getColors(c).contains(Constant.Color.Black) || + CardUtil.getColors(c).contains(Constant.Color.Red))) + { + for (int i=0;i 0 && (CardUtil.getColors(c).contains(Constant.Color.White) || + CardUtil.getColors(c).contains(Constant.Color.Blue) || + CardUtil.getColors(c).contains(Constant.Color.Black) )) + { + for (int i=0;i 0){ + if (CardUtil.getColors(c).contains(Constant.Color.Blue)) + { + for (int i=0;i 0) + { + final Card crd = list.get(0); + final Ability ability = new Ability(list.get(0), "0") + { + public void chooseTargetAI() + { + + CardList cards = CardFactoryUtil.AI_getHumanCreature(1, crd, false); + cards.shuffle(); + + if(cards.isEmpty() || AllZone.Human_Life.getLife() < 5) + setTargetPlayer(Constant.Player.Human); + else + setTargetCard(cards.get(0)); + } + public void resolve() + { + if(controller.equals("Human")) + { + String opp = AllZone.GameAction.getOpponent(controller); + PlayerZone oppPlay = AllZone.getZone(Constant.Zone.Play, opp); + + String[] choices = { "Yes", "No, target a creature instead" }; + + Object q = AllZone.Display.getChoiceOptional("Select computer as target?", choices); + if (q.equals("Yes")) + AllZone.GameAction.getPlayerLife(Constant.Player.Computer).subtractLife(1); + else + { + CardList cards = new CardList(oppPlay.getCards()); + CardList oppCreatures = new CardList(); + for (int i=0;i 0) + { + Object o = AllZone.Display.getChoiceOptional("Pick target creature", oppCreatures.toArray()); + Card c = (Card)o; + c.addDamage(1); + } + } + } + + else + { + + if(getTargetCard() != null) + { + if(AllZone.GameAction.isCardInPlay(getTargetCard())) + getTargetCard().addDamage(1); + } + else + AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(1); + } + }//resolve() + };//SpellAbility + + ability.setStackDescription(list.get(0) + " - Deals 1 damage to target creature or player"); + AllZone.Stack.add(ability); + + + }//if + + } + public static void drawCardTriggered_Hoofprints_of_the_Stag(String player) + { + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + CardList list = new CardList(playZone.getCards()); + + list = list.getName("Hoofprints of the Stag"); + + for(int i=0;i nothing + // happens + // 2. creature has no exalted bonus, exalted in play, only attacking + // creature -> give exalted + // 3. creature has no exalted bonus, exalted in play, more attacking + // creatures -> nothing happens + // 4. creature has exalted bonus, no exalted in play -> remove exalted + // 5. creature has exalted bonus, exalted in play, only attacking + // creature -> nothing happens + // 6. creature has exalted bonus, exalted in play, more attacking + // creatures -> remove exalted + + //int power = c.getNetAttack(); + //int toughness = c.getNetDefense(); + + if (c.hasExaltedBonus()) + { + if (exalted == false) + { + c.setExaltedBonus(false); + + c.addTempAttackBoost(-c.getExaltedMagnitude()); + c.addTempDefenseBoost(-c.getExaltedMagnitude()); + + if (isRafiqInPlay(c.getController())) + c.removeExtrinsicKeyword("Double Strike"); + + int battleGraceAngels = getBattleGraceAngels(c.getController()); + for (int j = 0; j < battleGraceAngels; j++) + { + c.removeExtrinsicKeyword("Lifelink"); + } + } else + // exalted in play == true + { + if (numberOfAttackers > 1 || attackersDeclared > 1) + { + c.setExaltedBonus(false); + + c.addTempAttackBoost(-c.getExaltedMagnitude()); + c.addTempDefenseBoost(-c.getExaltedMagnitude()); + + if (isRafiqInPlay(c.getController())) + c.removeExtrinsicKeyword("Double Strike"); + + int battleGraceAngels = getBattleGraceAngels(c + .getController()); + for (int j = 0; j < battleGraceAngels; j++) + { + c.removeExtrinsicKeyword("Lifelink"); + } + } + } + } else + // no exaltedBonus on creature + { + if (exalted == true && numberOfAttackers == 1 || attackersDeclared == 1) + { + c.setExaltedBonus(true); + c.setExaltedMagnitude(exaltedCreatures.size()); + + c.addTempAttackBoost(c.getExaltedMagnitude()); + c.addTempDefenseBoost(c.getExaltedMagnitude()); + + if (isRafiqInPlay(c.getController())) + c.addExtrinsicKeyword("Double Strike"); + + int battleGraceAngels = getBattleGraceAngels(c.getController()); + for (int j = 0; j < battleGraceAngels; j++) + { + //System.out.println("adding instance of lifelink."); + c.addExtrinsicKeyword("Lifelink"); + } + //System.out.println("keywordsize: " +c.getKeywordSize()); + } + } + + } + + public static void removeExaltedEffects() // at EOT + { + PlayerZone playerZone = AllZone.getZone(Constant.Zone.Play, + Constant.Player.Human); + PlayerZone computerZone = AllZone.getZone(Constant.Zone.Play, + Constant.Player.Computer); + + CardList cards = new CardList(); + cards.addAll(playerZone.getCards()); + cards.addAll(computerZone.getCards()); + + for (int i = 0; i < cards.size(); i++) + { + Card crd = cards.get(i); + + //int power = crd.getNetAttack(); + //int toughness = crd.getNetDefense(); + + if (crd.hasExaltedBonus()) + { + crd.setExaltedBonus(false); + crd.addTempAttackBoost(-crd.getExaltedMagnitude()); + crd.addTempDefenseBoost(-crd.getExaltedMagnitude()); + + if (isRafiqInPlay(crd.getController())) + crd.removeExtrinsicKeyword("Double Strike"); + + int battleGraceAngels = getBattleGraceAngels(crd + .getController()); + for (int j = 0; j < battleGraceAngels; j++) + { + crd.removeExtrinsicKeyword("Lifelink"); + } + + } + + } + + } + + public static boolean isRafiqInPlay(String player) + { + PlayerZone playerZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList cards = new CardList(); + cards.addAll(playerZone.getCards()); + + cards = cards.getName("Rafiq of the Many"); + + if (cards.size() >= 1) // should only be 1, since Rafiq is Legendary + return true; + else + return false; + + } + + public static int getBattleGraceAngels(String player) + { + PlayerZone playerZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList cards = new CardList(); + cards.addAll(playerZone.getCards()); + + cards = cards.getName("Battlegrace Angel"); + + return cards.size(); + } + + public static void executeAllyEffects(Card c) + { + if (c.getName().equals("Kazandu Blademaster") || c.getName().equals("Makindi Shieldmate") || + c.getName().equals("Nimana Sell-Sword") || c.getName().equals("Ondu Cleric") || + c.getName().equals("Oran-Rief Survivalist") ||c.getName().equals("Tuktuk Grunts") || + c.getName().equals("Umara Raptor")) + ally_Generic_P1P1(c); + else if (c.getName().equals("Turntimber Ranger")) + ally_Turntimber_Ranger(c); + + } + + private static boolean showAllyDialog(Card c) + { + String[] choices = { "Yes", "No" }; + + Object q = null; + + q = AllZone.Display.getChoiceOptional("Use " + c.getName() + "'s Ally ability?", choices); + + if (q == null || q.equals("No")) + return false; + else + return true; + } + + private static void ally_Generic_P1P1(Card c) + { + final Card crd = c; + + Ability ability = new Ability(c, "0") + { + public void resolve() + { + crd.addCounter(Counters.P1P1, 1); + } + }; + ability.setStackDescription(c.getName() + " - Ally: gets a +1/+1 counter."); + + if (c.getController().equals(Constant.Player.Human)) { + if (showAllyDialog(c)) + AllZone.Stack.add(ability); + } + + else if (c.getController().equals(Constant.Player.Computer)) + AllZone.Stack.add(ability); + } + + private static void ally_Turntimber_Ranger(Card c) + { + final Card crd = c; + Ability ability = new Ability(c, "0") + { + public void resolve() + { + Card card = new Card(); + + card.setName("Wolf"); + card.setImageName("G 2 2 Wolf"); + + card.setOwner(crd.getController()); + card.setController(crd.getController()); + + card.setManaCost("G"); + card.setToken(true); + + card.addType("Creature"); + card.addType("Wolf"); + card.setBaseAttack(2); + card.setBaseDefense(2); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, crd.getController()); + play.add(card); + + crd.addCounter(Counters.P1P1, 1); + } + }; + + ability.setStackDescription(c.getName() + " - Ally: " + c.getController() + " puts a 2/2 green Wolf creature token onto the battlefield, and adds a +1/+1 on " +c.getName() +"."); + + if (c.getController().equals(Constant.Player.Human)){ + if (showAllyDialog(c)) + AllZone.Stack.add(ability); + } + + else if (c.getController().equals(Constant.Player.Computer)) { + + PlayerZone cPlay = AllZone.Computer_Play; + CardList list = new CardList(); + list.addAll(cPlay.getCards()); + + CardList cl = list.filter(new CardListFilter() + { + public boolean addCard(Card crd) { + return crd.getName().equals("Conspiracy") && crd.getChosenType().equals("Ally"); + } + }); + + list = list.getName("Wolf"); + + if ((list.size() > 15 && cl.size() > 0)) + ; + else + AllZone.Stack.add(ability); + } + } + + + public static void executeLandfallEffects(Card c) + { + if (c.getName().equals("Rampaging Baloths")) + landfall_Rampaging_Baloths(c); + else if (c.getName().equals("Emeria Angel")) + landfall_Emeria_Angel(c); + else if (c.getName().equals("Ob Nixilis, the Fallen")) + landfall_Ob_Nixilis(c); + else if (c.getName().equals("Ior Ruin Expedition")) + landfall_Ior_Ruin_Expedition(c); + else if (c.getName().equals("Lotus Cobra")) + landfall_Lotus_Cobra(c); + } + + private static boolean showLandfallDialog(Card c) + { + String[] choices = { "Yes", "No" }; + + Object q = null; + + q = AllZone.Display.getChoiceOptional("Use " + c.getName() + " Landfall?", choices); + + if (q == null || q.equals("No")) + return false; + else + return true; + } + + private static void landfall_Rampaging_Baloths(Card c) + { + final Card crd = c; + Ability ability = new Ability(c, "0") + { + public void resolve() + { + Card card = new Card(); + + card.setName("Beast"); + card.setImageName("G 4 4 Beast"); + + card.setOwner(crd.getController()); + card.setController(crd.getController()); + + card.setManaCost("G"); + card.setToken(true); + + card.addType("Creature"); + card.addType("Beast"); + card.setBaseAttack(4); + card.setBaseDefense(4); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, crd.getController()); + play.add(card); + } + }; + + ability.setStackDescription(c.getName() + " - Landfall: " + c.getController() + " puts a 4/4 green Beast creature token onto the battlefield."); + + if (c.getController().equals(Constant.Player.Human)){ + if (showLandfallDialog(c)) + AllZone.Stack.add(ability); + } + + else if (c.getController().equals(Constant.Player.Computer)) + AllZone.Stack.add(ability); + + } + + private static void landfall_Emeria_Angel(Card c) + { + final Card crd = c; + Ability ability = new Ability(c, "0") + { + public void resolve() + { + Card card = new Card(); + + + card.setName("Bird"); + card.setImageName("W 1 1 Bird"); + + card.setOwner(crd.getController()); + card.setController(crd.getController()); + + card.setManaCost("G"); + card.setToken(true); + + card.addType("Creature"); + card.addType("Bird"); + card.setBaseAttack(1); + card.setBaseDefense(1); + + card.addIntrinsicKeyword("Flying"); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, crd.getController()); + play.add(card); + } + }; + + ability.setStackDescription(c.getName() + " - Landfall: " + c.getController() + " puts a 1/1 white Bird creature token with flying onto the battlefield."); + + if (c.getController().equals(Constant.Player.Human)) { + if (showLandfallDialog(c)) + AllZone.Stack.add(ability); + } + + else if (c.getController().equals(Constant.Player.Computer)) + AllZone.Stack.add(ability); + }//landfall_Emeria_Angel + + private static void landfall_Ob_Nixilis(Card c) + { + final Card crd = c; + Ability ability = new Ability(c, "0") + { + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(AllZone.GameAction.getOpponent(crd.getController())); + life.subtractLife(3); + crd.addCounter(Counters.P1P1, 3); + } + }; + + ability.setStackDescription("Landfall: " + AllZone.GameAction.getOpponent(c.getController()) + " loses 3 life and " + c.getName() + " gets three +1/+1 counters."); + + if (c.getController().equals(Constant.Player.Human)) { + if (showLandfallDialog(c)) + AllZone.Stack.add(ability); + } + else if (c.getController().equals(Constant.Player.Computer)) + AllZone.Stack.add(ability); + } + + private static void landfall_Ior_Ruin_Expedition(Card c) + { + final Card crd = c; + Ability ability = new Ability(c, "0") + { + public void resolve() + { + crd.addCounter(Counters.QUEST, 1); + } + }; + + ability.setStackDescription(c.getName() + " - gets a Quest counter."); + + if (c.getController().equals(Constant.Player.Human)) { + if (showLandfallDialog(c)) + AllZone.Stack.add(ability); + } + + else if (c.getController().equals(Constant.Player.Computer)) + AllZone.Stack.add(ability); + } + + private static void landfall_Lotus_Cobra(Card c) + { + Ability ability = new Ability(c, "0") + { + public void resolve() + { + String color = new String(); + + Object o = AllZone.Display.getChoice("Choose mana color",Constant.Color.Colors); + color = (String)o; + + if (color.equals("white")) + color = "W"; + else if (color.equals("blue")) + color = "U"; + else if (color.equals("black")) + color = "B"; + else if (color.equals("red")) + color = "R"; + else if (color.equals("green")) + color = "G"; + + CardList list = new CardList(AllZone.getZone(Constant.Zone.Play, Constant.Player.Human).getCards()); + list = list.getName("Mana Pool"); + Card mp = list.getCard(0); + + mp.addExtrinsicKeyword("ManaPool:"+ color); + } + }; + + ability.setStackDescription(c.getName() + " - add one mana of any color to your mana pool."); + + if (c.getController().equals(Constant.Player.Human)) { + if (showLandfallDialog(c)) + AllZone.Stack.add(ability); + } + + } + + public static void executeLifeLinkEffects(Card c) + { + final String player = c.getController(); + int pwr = c.getNetAttack(); + if (CombatUtil.isDoranInPlay()) + pwr = c.getNetDefense(); + + final int power = pwr; + + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(player); + life.addLife(power); + } + }; // ability2 + + ability2.setStackDescription(c.getName() + " (Lifelink) - " + player + + " gains " + power + " life."); + AllZone.Stack.add(ability2); + } + + public static void executeLifeLinkEffects(Card c, int n) + { + final String player = c.getController(); + + final int power = n; + + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + PlayerLife life = AllZone.GameAction.getPlayerLife(player); + life.addLife(power); + } + }; // ability2 + + ability2.setStackDescription(c.getName() + " (Lifelink) - " + player + + " gains " + power + " life."); + AllZone.Stack.add(ability2); + } + + public static void executeGuiltyConscienceEffects(Card c) + { + int pwr = c.getNetAttack(); + if (CombatUtil.isDoranInPlay()) + pwr = c.getNetDefense(); + final int damage = pwr; + + final Card crd = c; + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + crd.addDamage(damage); + } + }; // ability2 + + ability2.setStackDescription("Guilty Conscience deals " +damage +" damage to " +c.getName()); + AllZone.Stack.add(ability2); + } + + public static void executeGuiltyConscienceEffects(Card c, int n) + { + final int damage = n; + final Card crd = c; + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + crd.addDamage(damage); + } + }; // ability2 + + ability2.setStackDescription("Guilty Conscience deals " +n +" damage to " +c.getName()); + AllZone.Stack.add(ability2); + } + + //this is for cards like Sengir Vampire + public static void executeVampiricEffects(Card c) + { + ArrayList a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) { + if (AllZone.GameAction.isCardInPlay(c) && a.get(i).toString().startsWith("Whenever a creature dealt damage by this card this turn is put into a graveyard, put")) + { + final Card thisCard = c; + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + if (AllZone.GameAction.isCardInPlay(thisCard)) + thisCard.addCounter(Counters.P1P1, 1); + } + }; // ability2 + + ability2.setStackDescription(c.getName() + " - gets a +1/+1 counter"); + AllZone.Stack.add(ability2); + } + + } + + } + + public static void executePlayerCombatDamageEffects(Card c) + { + + if (c.getName().equals("Hypnotic Specter")) + playerCombatDamage_Hypnotic_Specter(c); + else if (c.getName().equals("Shadowmage Infiltrator") + || c.getName().equals("Thieving Magpie") + || c.getName().equals("Garza Zol, Plague Queen") + || c.getName().equals("Lu Xun, Scholar General")) + playerCombatDamage_Shadowmage_Infiltrator(c); + else if (c.getName().equals("Goblin Lackey")) + playerCombatDamage_Goblin_Lackey(c); + else if (c.getName().equals("Warren Instigator")) + playerCombatDamage_Warren_Instigator(c); + else if (c.getName().equals("Guiltfeeder")) + playerCombatDamage_Guiltfeeder(c); + else if (c.getName().equals("Spawnwrithe")) + playerCombatDamage_Spawnwrithe(c); + else if (c.getName().equals("Glint-Eye Nephilim") || c.getName().equals("Cold-Eyed Selkie") ) + playerCombatDamage_Glint_Eye_Nephilim(c); + else if (c.getName().equals("Hystrodon") && !c.isFaceDown()) + playerCombatDamage_Hystrodon(c); + else if (c.getName().equals("Slith Strider") || c.getName().equals("Slith Ascendant") || + c.getName().equals("Slith Bloodletter") || c.getName().equals("Slith Firewalker") || + c.getName().equals("Slith Predator")) + playerCombatDamage_Slith(c); + else if (c.getName().equals("Whirling Dervish") || c.getName().equals("Dunerider Outlaw")) + playerCombatDamage_Whirling_Dervish(c); + else if (c.getName().equals("Oros, the Avenger")) + playerCombatDamage_Oros(c); + else if (c.getName().equals("Rootwater Thief")) + playerCombatDamage_Rootwater_Thief(c); + else if (c.getName().equals("Treva, the Renewer")) + playerCombatDamage_Treva(c); + + + if (c.getNetAttack() > 0) + c.setDealtCombatDmgToOppThisTurn(true); + + } + + public static void executePlayerCombatDmgOptionalEffects(Card[] c) + { + for (int i=0;i< c.length;i++) + { + if (c[i].getName().equals("Treva, the Renewer")) + { + SpellAbility[] sa = c[i].getSpellAbility(); + if (c[i].getController().equals(Constant.Player.Human)) + AllZone.GameAction.playSpellAbility(sa[1]); + else + ComputerUtil.playNoStack(sa[1]); + } + + else if (c[i].getName().equals("Rootwater Thief")) + { + SpellAbility[] sa = c[i].getSpellAbility(); + if (c[i].getController().equals(Constant.Player.Human)) + AllZone.GameAction.playSpellAbility(sa[2]); //because sa[1] is the kpump u: flying + else + ComputerUtil.playNoStack(sa[2]); + } + + + }//for + } + private static void playerCombatDamage_Oros(Card c) + { + System.out.println("Oros swung unblocked."); + SpellAbility[] sa = c.getSpellAbility(); + if (c.getController().equals(Constant.Player.Human)) + AllZone.GameAction.playSpellAbility(sa[1]); + else + ComputerUtil.playNoStack(sa[1]); + + + } + + private static void playerCombatDamage_Rootwater_Thief(Card c) + { + SpellAbility[] sa = c.getSpellAbility(); + if (c.getController().equals(Constant.Player.Human)) + AllZone.GameAction.playSpellAbility(sa[2]); //because sa[1] is the kpump u: flying + else + ComputerUtil.playNoStack(sa[2]); + + + } + private static void playerCombatDamage_Treva(Card c) + { + SpellAbility[] sa = c.getSpellAbility(); + if (c.getController().equals(Constant.Player.Human)) + AllZone.GameAction.playSpellAbility(sa[1]); + else + ComputerUtil.playNoStack(sa[1]); + + } + + private static void playerCombatDamage_Slith(Card c) + { + final int power = c.getNetAttack(); + final Card card = c; + + if (power > 0) + { + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + card.addCounter(Counters.P1P1, 1); + } + };// ability2 + + ability2.setStackDescription(c.getName() + " - gets a +1/+1 counter."); + AllZone.Stack.add(ability2); + } // if + } + + private static void playerCombatDamage_Whirling_Dervish(Card c) + { + final int power = c.getNetAttack(); + final Card card = c; + + if (power > 0) + { + final Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + card.addCounter(Counters.P1P1, 1); + } + };// ability2 + + ability2.setStackDescription(c.getName() + " - gets a +1/+1 counter."); + + Command dealtDmg = new Command() + { + private static final long serialVersionUID = 2200679209414069339L; + public void execute() + { + AllZone.Stack.add(ability2); + } + }; + AllZone.EndOfTurn.addAt(dealtDmg); + + } // if + } + + private static void playerCombatDamage_Hystrodon(Card c) + { + final String player = c.getController(); + final int power = c.getNetAttack(); + + if (power > 0) + { + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + AllZone.GameAction.drawCard(player); + } + };// ability2 + + ability2.setStackDescription(c.getName() + " - " + player + + " draws a card."); + AllZone.Stack.add(ability2); + } // if + + } + + private static void playerCombatDamage_Glint_Eye_Nephilim(Card c) + { + final String player = c.getController(); + final int power = c.getNetAttack(); + + if (power > 0) + { + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + for (int i = 0; i < power; i++) + { + AllZone.GameAction.drawCard(player); + } + } + };// ability2 + + ability2.setStackDescription(c.getName() + " - " + player + + " draws " + power + " card(s)."); + AllZone.Stack.add(ability2); + } // if + + } + + private static void playerCombatDamage_Spawnwrithe(Card c) + { + final String player = c.getController(); + + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + Card card = new Card(); + + card.setName("Spawnwrithe"); + + card.setOwner(player); + card.setController(player); + + card.setManaCost("2 G"); + card.setToken(true); + card + .setText("Whenever Spawnwrithe deals combat damage to a player, put a token into play that's a copy of Spawnwrithe."); + + card.addType("Creature"); + card.addType("Elemental"); + card.addIntrinsicKeyword("Trample"); + card.setBaseAttack(2); + card.setBaseDefense(2); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card + .getController()); + play.add(card); + } + };// ability2 + + ability2.setStackDescription(c.getName() + " - " + player + + " puts copy into play."); + AllZone.Stack.add(ability2); + } + + private static void playerCombatDamage_Guiltfeeder(Card c) + { + final String player = c.getController(); + final String opponent = AllZone.GameAction.getOpponent(player); + + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + + PlayerZone graveyard = AllZone.getZone(Constant.Zone.Graveyard, + opponent); + CardList cardsInGrave = new CardList(graveyard.getCards()); + PlayerLife life = AllZone.GameAction.getPlayerLife(opponent); + + life.subtractLife(cardsInGrave.size()); + + } + };// ability2 + + ability2.setStackDescription(c.getName() + " - " + opponent + + " loses life equal to cards in graveyard."); + AllZone.Stack.add(ability2); + + } + + private static void playerCombatDamage_Goblin_Lackey(Card c) + { + if (c.getNetAttack() > 0) + { + final Card card = c; + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + + CardList goblins = new CardList(hand.getCards()); + //goblins = goblins.getType("Goblin"); + goblins = goblins.filter(new CardListFilter() + { + + public boolean addCard(Card c) { + return (c.getType().contains("Goblin") || c.getKeyword().contains("Changeling")) && c.isPermanent(); + } + + }); + + if(goblins.size() > 0) + { + if (card.getController().equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Select a Goblin to put into play", goblins.toArray()); + + if (o!=null) + { + Card gob = (Card)o; + hand.remove(gob); + play.add(gob); + } + } + else + { + Card gob = goblins.get(0); + hand.remove(gob); + play.add(gob); + } + } + } + }; + ability2.setStackDescription(c.getName() + " - " + c.getController() + " puts a goblin into play from his or her hand."); + AllZone.Stack.add(ability2); + } + } + + private static void playerCombatDamage_Warren_Instigator(Card c) + { + if (c.getNetAttack() > 0) + { + final Card card = c; + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + + CardList goblins = new CardList(hand.getCards()); + //goblins = goblins.getType("Goblin"); + goblins = goblins.filter(new CardListFilter() + { + + public boolean addCard(Card c) { + return (c.getType().contains("Goblin") || c.getKeyword().contains("Changeling")) && c.isCreature(); + } + + }); + + if(goblins.size() > 0) + { + if (card.getController().equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Select a Goblin to put into play", goblins.toArray()); + + if (o!=null) + { + Card gob = (Card)o; + hand.remove(gob); + play.add(gob); + } + } + else + { + Card gob = goblins.get(0); + hand.remove(gob); + play.add(gob); + } + } + } + }; + ability2.setStackDescription(c.getName() + " - " + c.getController() + " puts a goblin into play from his or her hand."); + AllZone.Stack.add(ability2); + } + }//warren instigator + + + + + private static void playerCombatDamage_Shadowmage_Infiltrator(Card c) + { + final String player = c.getController(); + + if (c.getNetAttack() > 0) + { + Ability ability2 = new Ability(c, "0") + { + public void resolve() + { + + AllZone.GameAction.drawCard(player); + } + };// ability2 + + ability2.setStackDescription(c.getName() + " - " + player + + " draws a card."); + AllZone.Stack.add(ability2); + } + + } + + private static void playerCombatDamage_Hypnotic_Specter(Card c) + { + final String player = c.getController(); + final String opponent = AllZone.GameAction.getOpponent(player); + + if (c.getNetAttack() > 0) + { + Ability ability = new Ability(c, "0") + { + public void resolve() + { + AllZone.GameAction.discardRandom(opponent); + } + };// ability + + ability.setStackDescription("Hypnotic Specter - " + opponent + + " discards one card at random"); + AllZone.Stack.add(ability); + } + } + + @SuppressWarnings("unused") // upkeep_CheckEmptyDeck_Lose + private static void upkeep_CheckEmptyDeck_Lose() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone libraryZone = AllZone.getZone(Constant.Zone.Library, player); + + System.out.println("libraryZone.size: " + libraryZone.size() + + " phase: " + AllZone.Phase.getPhase() + "Turn: " + + AllZone.Phase.getTurn()); + if (libraryZone.size() == 0 + && AllZone.Phase.getPhase().equals(Constant.Phase.Untap) + && AllZone.Phase.getTurn() > 1) + { + PlayerLife life = AllZone.GameAction.getPlayerLife(player); + life.setLife(0); + // TODO display this somehow!!! + }// if + }// upkeep_CheckEmptyDeck_Lose + + private static void upkeep_AI_Aluren() + { + PlayerZone AIHand = AllZone.getZone(Constant.Zone.Hand, + Constant.Player.Computer); + PlayerZone AIPlay = AllZone.getZone(Constant.Zone.Play, + Constant.Player.Computer); + + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + + list = list.getName("Aluren"); + + CardList creatures = new CardList(); + + for (int i = 0; i < AIHand.size(); i++) + { + if (AIHand.get(i).getType().contains("Creature") + && CardUtil.getConvertedManaCost(AIHand.get(i) + .getManaCost()) <= 3) + creatures.add(AIHand.get(i)); + } + + if (list.size() > 0 && creatures.size() > 0) + { + for (int i = 0; i < creatures.size(); i++) + { + Card c = creatures.getCard(i); + AIHand.remove(c); + AIPlay.add(c); + c.setSickness(true); + + } + } + + } + + private static void upkeep_Land_Tax() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Land Tax"); + + PlayerZone oppPlayZone = AllZone.getZone(Constant.Zone.Play, + AllZone.GameAction.getOpponent(player)); + + CardList self = new CardList(playZone.getCards()); + CardList opp = new CardList(oppPlayZone.getCards()); + + self = self.getType("Land"); + opp = opp.getType("Land"); + + if (self.size() < opp.size()) + { + + for (int i = 0; i < list.size(); i++) + { + Ability ability = new Ability(list.get(i), "0") + { + public void resolve() + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, + player); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, + player); + + CardList lands = new CardList(lib.getCards()); + lands = lands.getType("Basic"); + + if (player.equals("Human") && lands.size() > 0) + { + String[] choices = + { "Yes", "No" }; + Object choice = AllZone.Display.getChoice( + "Use Land Tax?", choices); + if (choice.equals("Yes")) + { + Object o = AllZone.Display + .getChoiceOptional( + "Pick a basic land card to put into your hand", + lands.toArray()); + if (o != null) + { + Card card = (Card) o; + lib.remove(card); + hand.add(card); + lands.remove(card); + + if (lands.size() > 0) + { + o = AllZone.Display + .getChoiceOptional( + "Pick a basic land card to put into your hand", + lands.toArray()); + if (o != null) + { + card = (Card) o; + lib.remove(card); + hand.add(card); + lands.remove(card); + if (lands.size() > 0) + { + o = AllZone.Display + .getChoiceOptional( + "Pick a basic land card to put into your hand", + lands.toArray()); + if (o != null) + { + card = (Card) o; + lib.remove(card); + hand.add(card); + lands.remove(card); + } + } + } + + } + } + AllZone.GameAction.shuffle("Human"); + }// if choice yes + } // player equals human + else if (player.equals("Computer") && lands.size() > 0) + { + Card card = lands.get(0); + lib.remove(card); + hand.add(card); + lands.remove(card); + + if (lands.size() > 0) + { + card = lands.get(0); + lib.remove(card); + hand.add(card); + lands.remove(card); + + if (lands.size() > 0) + { + card = lands.get(0); + lib.remove(card); + hand.add(card); + lands.remove(card); + } + } + AllZone.GameAction.shuffle("Computer"); + } + } + + };// Ability + ability + .setStackDescription("Land Tax - search library for up to three basic land cards and put them into your hand"); + AllZone.Stack.add(ability); + + }// for + }// if fewer lands than opponent + + } + + private static void upkeep_Squee() + { + final String player = AllZone.Phase.getActivePlayer(); + //PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); //unused + PlayerZone graveyard = AllZone.getZone(Constant.Zone.Graveyard, player); + + CardList list = new CardList(graveyard.getCards()); + list = list.getName("Squee, Goblin Nabob"); + + final CardList squees = list; + final int[] index = new int[1]; + index[0] = 0; + + for (int i = 0; i < list.size(); i++) + { + Ability ability = new Ability(list.get(i), "0") + { + + public void resolve() + { + PlayerZone graveyard = AllZone.getZone( + Constant.Zone.Graveyard, player); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, + player); + + if (player.equals("Human")) + { + String[] choices = + { "Yes", "No" }; + Object o = AllZone.Display + .getChoiceOptional( + "Return Squee from your graveyard to your hand?", + choices); + if (o.equals("Yes")) + { + Card c = squees.get(index[0]); + graveyard.remove(c); + hand.add(c); + } + } else if (player.equals("Computer")) + { + Card c = squees.get(index[0]); + graveyard.remove(c); + hand.add(c); + } + index[0] = index[0] + 1; + } + + };// Ability + ability + .setStackDescription("Squee gets returned from graveyard to hand."); + AllZone.Stack.add(ability); + } // if creatures > 0 + + } + + private static void upkeep_AEther_Vial() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("AEther Vial"); + + if (list.size() > 0) + { + for (int i = 0; i < list.size(); i++) + { + final Card thisCard = list.get(i); + Ability ability = new Ability(list.get(i), "") + { + public void resolve() { + // TODO Auto-generated method stub + String[] choices = { "Yes", "No" }; + + Object q = null; + if (player.equals(Constant.Player.Human)){ + q = AllZone.Display.getChoiceOptional("Put a counter on AEther Vial? (" + thisCard.getCounters(Counters.CHARGE) + ")", choices); + if (q == null || q.equals("No")) + return; + if (q.equals("Yes")) + { + + thisCard.addCounter(Counters.CHARGE, 1); + } + } + else if (player.equals(Constant.Player.Computer)) + { + + thisCard.addCounter(Counters.CHARGE, 1); + } + + } + + }; + ability.setStackDescription(list.get(i).getName() + " (" + list.get(i).getCounters(Counters.CHARGE) + " counters) - Put a charge counter on AEther Vial?"); + AllZone.Stack.add(ability); + }//for + } + + } + + private static void upkeep_Scute_Mob() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Scute Mob"); + + if (list.size() > 0) + { + for (int i = 0; i < list.size(); i++) + { + CardList lands = new CardList(playZone.getCards()); + lands = lands.getType("Land"); + + if (lands.size() >= 5) + { + final Card c = list.get(i); + Ability ability = new Ability(list.get(i), "0") + { + public void resolve() + { + c.addCounter(Counters.P1P1, 4); + } + + };// Ability + ability + .setStackDescription("Scute Mob - put four +1/+1 counters on Scute Mob."); + AllZone.Stack.add(ability); + } + } // for + } // if creatures > 0 + }//Scute Mob + + + private static void upkeep_Sporesower_Thallid() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Sporesower Thallid"); + + if (list.size() > 0) + { + for (int i = 0; i < list.size(); i++) + { + + Ability ability = new Ability(list.get(i), "0") + { + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, + player); + + CardList fungi = new CardList(play.getCards()); + fungi = fungi.getType("Fungus"); + + for (int j = 0; j < fungi.size(); j++) + { + Card c = fungi.get(j); + c.addCounter(Counters.SPORE, 1); + } + + } + + };// Ability + ability + .setStackDescription("Sporesower - put a spore counter on each fungus you control."); + AllZone.Stack.add(ability); + } // for + } // if creatures > 0 + } + + private static void upkeep_Heartmender() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Heartmender"); + + if (list.size() > 0) + { + for (int i = 0; i < list.size(); i++) + { + + Ability ability = new Ability(list.get(i), "0") + { + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, + player); + + CardList creats = new CardList(play.getCards()); + creats = creats.filter(new CardListFilter() + { + + public boolean addCard(Card c) { + return c.getCounters(Counters.M1M1) > 0; + } + + }); + + for (int j = 0; j < creats.size(); j++) + { + Card c = creats.get(j); + if (c.getCounters(Counters.M1M1) > 0) + c.addCounter(Counters.M1M1, -1); + } + + } + + };// Ability + ability + .setStackDescription("Heartmender - Remove a -1/-1 counter from each creature you control."); + AllZone.Stack.add(ability); + } // for + } // if creatures > 0 + }//heartmender + + private static void upkeep_Ratcatcher() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + //PlayerZone hand = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + + CardList creatures = new CardList(library.getCards()); + creatures = creatures.getType("Rat"); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Ratcatcher"); + + if (creatures.size() > 0 && list.size() > 0) + { + for (int i = 0; i < list.size(); i++) + { + + Ability ability = new Ability(list.get(i), "0") + { + public void resolve() + { + PlayerZone lib = AllZone.getZone(Constant.Zone.Library, + player); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, + player); + + CardList rats = new CardList(lib.getCards()); + rats = rats.getType("Rat"); + + if (rats.size() > 0) + { + if (player.equals("Human")) + { + Object o = AllZone.Display.getChoiceOptional( + "Pick a Rat to put into your hand", rats + .toArray()); + if (o != null) + { + Card card = (Card) o; + lib.remove(card); + hand.add(card); + } + } else if (player.equals("Computer")) + { + Card card = rats.get(0); + lib.remove(card); + hand.add(card); + + } + AllZone.GameAction.shuffle(player); + } + } + + };// Ability + ability + .setStackDescription("Ratcatcher - search library for a rat and put into your hand"); + AllZone.Stack.add(ability); + } // for + } // if creatures > 0 + } + + private static void upkeep_Nath() + { + final String player = AllZone.Phase.getActivePlayer(); + final String opponent = AllZone.GameAction.getOpponent(player); + + PlayerZone zone1 = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(zone1.getCards()); + list = list.getName("Nath of the Gilt-Leaf"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + //PlayerZone hand = AllZone.getZone(Constant.Zone.Hand,Constant.Player.Human); //unused + + AllZone.GameAction.discardRandom(opponent); + + } + }; // ability + ability.setStackDescription("Nath of the Gilt-Leaf - " + opponent + + " discards a card at random."); + AllZone.Stack.add(ability); + } + } + + private static void upkeep_Cunning_Lethemancer() + { + final String player = AllZone.Phase.getActivePlayer(); + //final String opponent = AllZone.GameAction.getOpponent(player); + + PlayerZone zone1 = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(zone1.getCards()); + list = list.getName("Cunning Lethemancer"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, + Constant.Player.Human); + + CardList cardsInHand = new CardList(hand.getCards()); + + if (cardsInHand.size() > 0) + { + Object o = AllZone.Display + .getChoiceOptional("Select Card to discard", + cardsInHand.toArray()); + Card c = (Card) o; + AllZone.GameAction.discard(c); + } + + AllZone.GameAction.discardRandom(Constant.Player.Computer); + + } + }; // ability + ability + .setStackDescription("Cunning Lethemancer - Everyone discards a card."); + AllZone.Stack.add(ability); + } + } + /* + private static void upkeep_Sensation_Gorger() + { + final String player = AllZone.Phase.getActivePlayer(); + final String opponent = AllZone.GameAction.getOpponent(player); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Sensation Gorger"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + + if (library.size() <= 0) + { + return; + } + + if (list.get(i).getController().equals("Human")) + { + String[] choices = { "Yes", "No" }; + Object o = AllZone.Display.getChoiceOptional("Use " + list.get(i).getName() + "'s ability this turn?", choices); + + if (o.equals("No")) + return; + } + + // System.out.println("top of deck: " + library.get(i).getName()); + String creatureType = library.get(i).getType().toString(); + String cardName = library.get(i).getName(); + + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, + player); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, + player); + + // PlayerZone oppLibrary = + // AllZone.getZone(Constant.Zone.Library, opponent); + PlayerZone oppHand = AllZone.getZone(Constant.Zone.Hand, + opponent); + + String creatureType = library.get(0).getType().toString(); + + if (creatureType.contains("Goblin") + || creatureType.contains("Shaman")) + { + Card[] c = hand.getCards(); + for(int q = 0; q < c.length; q++) + AllZone.GameAction.discard(c[q]); + + Card[] oc = oppHand.getCards(); + for(int j = 0; j < oc.length; j++) + AllZone.GameAction.discard(oc[j]); + + for(int z = 0; z < 4; z++) + { + AllZone.GameAction.drawCard(Constant.Player.Computer); + AllZone.GameAction.drawCard(Constant.Player.Human); + } + + } + + }// resolve() + };// Ability + if (creatureType.contains("Goblin") + || creatureType.contains("Shaman")) + ability.setStackDescription("Sensation Gorger - " + player + + " reveals: " + cardName + + ", everyone discards their hands and draws 4 cards."); + else + ability.setStackDescription("Sensation Gorger - " + player + + " reveals top card: " + cardName + "."); + + AllZone.Stack.add(ability); + }// for + }// upkeep_Sensation_Gorger() + */ + + private static void upkeep_Sensation_Gorger() + { + final String player = AllZone.Phase.getActivePlayer(); + final String opponent = AllZone.GameAction.getOpponent(player); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Sensation Gorger"); + + for (int i = 0; i < list.size(); i++) + { + + if (library.size() <= 0) + { + return; + } + + if (list.get(i).getController().equals("Human")) + { + String[] choices = { "Yes", "No" }; + Object o = AllZone.Display.getChoiceOptional("Use " + list.get(i).getName() + "'s ability?", choices); + + if (o == null ) + return; + if (o.equals("No")) + return; + } + + // System.out.println("top of deck: " + library.get(i).getName()); + //String creatureType = library.get(i).getType().toString(); + //String cardName = library.get(i).getName(); + + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand,player); + + PlayerZone oppHand = AllZone.getZone(Constant.Zone.Hand, + opponent); + + String creatureType = library.get(0).getType().toString(); + + if (creatureType.contains("Goblin") + || creatureType.contains("Shaman") || library.get(0).getKeyword().contains("Changeling")) + { + Card[] c = hand.getCards(); + for(int q = 0; q < c.length; q++) + AllZone.GameAction.discard(c[q]); + + Card[] oc = oppHand.getCards(); + for(int j = 0; j < oc.length; j++) + AllZone.GameAction.discard(oc[j]); + + for(int z = 0; z < 4; z++) + { + AllZone.GameAction.drawCard(Constant.Player.Computer); + AllZone.GameAction.drawCard(Constant.Player.Human); + } + + } + }// for + }// upkeep_Sensation_Gorger() + + private static void upkeep_Winnower_Patrol() + { + final String player = AllZone.Phase.getActivePlayer(); + //final String opponent = AllZone.GameAction.getOpponent(player); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Winnower Patrol"); + + // final Ability ability; + for (int i = 0; i < list.size(); i++) + { + if (library.size() <= 0) + { + return; + } + // System.out.println("top of deck: " + library.get(i).getName()); + String creatureType = library.get(0).getType().toString(); + String cardName = library.get(0).getName(); + + + System.out.println("CardName: " + list.get(i) + " id: " + + list.get(i).getUniqueNumber()); + + final int cardIndex = i; + + final Ability ability = new Ability(list.get(i), "0") + { + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, + player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, + player); + + String creatureType = library.get(cardIndex).getType() + .toString(); + + + if (creatureType.contains("Elf") + || creatureType.contains("Warrior") || library.get(cardIndex).getKeyword().contains("Changeling")) + { + + CardList list = new CardList(play.getCards()); + list = list.getName("Winnower Patrol"); + + Card c = list.get(cardIndex); // must get same winnower + // patrol + System.out.println("cardIndex: " + cardIndex + + " name: " + c.getName()); + int attack = c.getBaseAttack(); + int defense = c.getBaseDefense(); + + attack++; + defense++; + + c.setBaseAttack(attack); + c.setBaseDefense(defense); + + } + + }// resolve() + };// Ability + if (creatureType.contains("Elf") + || creatureType.contains("Warrior")) + ability.setStackDescription("Winnower Patrol - " + player + + " reveals: " + cardName + + ", and Winnower Patrol gets +1/+1."); + else + ability.setStackDescription("Winnower Patrol - " + player + + " reveals top card: " + cardName + "."); + + AllZone.Stack.add(ability); + }// for + }// upkeep_Winnower_Patrol() + + private static void upkeep_Nightshade_Schemers() + { + final String player = AllZone.Phase.getActivePlayer(); + final String opponent = AllZone.GameAction.getOpponent(player); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Nightshade Schemers"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + if (library.size() <= 0) + { + return; + } + // System.out.println("top of deck: " + library.get(i).getName()); + String creatureType = library.get(0).getType().toString(); + String cardName = library.get(0).getName(); + + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + //PlayerZone play = AllZone.getZone(Constant.Zone.Play,player); //unused + PlayerZone library = AllZone.getZone(Constant.Zone.Library,player); + + String creatureType = library.get(0).getType().toString(); + + if (creatureType.contains("Faerie") + || creatureType.contains("Wizard") || library.get(0).getKeyword().contains("Changeling")) + { + AllZone.GameAction.getPlayerLife(opponent) + .subtractLife(2); + } + + }// resolve() + };// Ability + if (creatureType.contains("Faerie") + || creatureType.contains("Wizard")) + ability.setStackDescription("Nightshade Schemers - " + player + + " reveals: " + cardName + ", and " + opponent + + " loses 2 life."); + else + ability.setStackDescription("Nightshade Schemers - " + player + + " reveals top card: " + cardName + "."); + + AllZone.Stack.add(ability); + }// for + }// upkeep_Nightshade_Schemers() + + private static void upkeep_Wandering_Graybeard() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Wandering Graybeard"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + if (library.size() <= 0) + { + return; + } + // System.out.println("top of deck: " + library.get(i).getName()); + String creatureType = library.get(0).getType().toString(); + String cardName = library.get(0).getName(); + + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + //PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); //unused + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + + String creatureType = library.get(0).getType().toString(); + + + if (creatureType.contains("Giant") || creatureType.contains("Wizard") || library.get(0).getKeyword().contains("Changeling")) + { + AllZone.GameAction.getPlayerLife(player).addLife(4); + } + + }// resolve() + };// Ability + if (creatureType.contains("Giant") + || creatureType.contains("Wizard")) + ability.setStackDescription("Wandering Graybeard - " + player + + " reveals: " + cardName + ", and gains 4 life."); + else + ability.setStackDescription("Wandering Graybeard - " + player + + " reveals top card: " + cardName + "."); + + AllZone.Stack.add(ability); + }// for + }// upkeep_Wandering_Graybeard() + + private static void upkeep_Wolf_Skull_Shaman() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Wolf-Skull Shaman"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + if (library.size() <= 0) + { + return; + } + // System.out.println("top of deck: " + library.get(i).getName()); + String creatureType = library.get(0).getType().toString(); + String cardName = library.get(0).getName(); + + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, + player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, + player); + + String creatureType = library.get(0).getType().toString(); + + if (creatureType.contains("Elf") + || creatureType.contains("Shaman") || library.get(0).getKeyword().contains("Changeling")) + { + Card c = new Card(); + + c.setOwner(player); + c.setController(player); + + c.setName("Wolf"); + c.setImageName("G 2 2 Wolf"); + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Wolf"); + + c.setBaseAttack(2); + c.setBaseDefense(2); + + play.add(c); + + } + + }// resolve() + };// Ability + if (creatureType.contains("Elf") || creatureType.contains("Shaman")) + ability.setStackDescription("Wolf-Skull Shaman - " + player + + " reveals: " + cardName + + ", and puts 2/2 Wolf into play."); + else + ability.setStackDescription("Wolf-Skull Shaman - " + player + + " reveals top card: " + cardName + "."); + + AllZone.Stack.add(ability); + }// for + }// upkeep_Wolf_Skull_Shaman() + + private static void upkeep_Leaf_Crowned_Elder() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Leaf-Crowned Elder"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + if (library.size() <= 0) + { + return; + } + // System.out.println("top of deck: " + library.get(i).getName()); + String creatureType = library.get(0).getType().toString(); + String cardName = library.get(0).getName(); + + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, + player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, + player); + + String creatureType = library.get(0).getType().toString(); + + if (creatureType.contains("Treefolk") + || creatureType.contains("Shaman") || library.get(0).getKeyword().contains("Changeling")) + { + Card c = library.get(0); + library.remove(c); + play.add(c); + } + + }// resolve() + };// Ability + if (creatureType.contains("Treefolk") + || creatureType.contains("Shaman")) + ability.setStackDescription("Leaf-Crowned Elder - " + player + + " puts into play: " + cardName + "."); + else + ability.setStackDescription("Leaf-Crowned Elder - " + player + + " reveals top card: " + cardName + "."); + + AllZone.Stack.add(ability); + }// for + }// upkeep_Leaf_Crowned_Elder() + + + + private static void upkeep_Dark_Confidant() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Dark Confidant"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + if (library.size() <= 0) + { + return; + } + // System.out.println("top of deck: " + library.get(i).getName()); + final int convertedManaCost = CardUtil.getConvertedManaCost(library + .get(i).getManaCost()); + String cardName = library.get(i).getName(); + + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + PlayerZone library = AllZone.getZone(Constant.Zone.Library, + player); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, + player); + AllZone.GameAction.getPlayerLife(player).subtractLife( + convertedManaCost); + + // AllZone.GameAction.drawCard(player); + // !!!can't just draw card, since it won't work with jpb's + // fix!!! + Card c = library.get(0); + library.remove(c); + hand.add(c); + + }// resolve() + };// Ability + ability.setStackDescription("Dark Confidant - " + player + + " loses " + convertedManaCost + + " life and draws top card(" + cardName + ")."); + + AllZone.Stack.add(ability); + }// for + }// upkeep_Dark_Confidant() + + private static void upkeep_Debtors_Knell() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, player); + PlayerZone oppGrave = AllZone.getZone(Constant.Zone.Graveyard, AllZone.GameAction.getOpponent(player)); + + CardList creatures = new CardList(); + creatures.addAll(grave.getCards()); + creatures.addAll(oppGrave.getCards()); + creatures = creatures.getType("Creature"); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Debtors' Knell"); + + if (creatures.size() > 0 && list.size() > 0) + for (int i = 0; i 0 + + } + + private static void upkeep_Emeria() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone graveyard = AllZone.getZone(Constant.Zone.Graveyard, player); + + CardList creatures = new CardList(graveyard.getCards()); + creatures = creatures.getType("Creature"); + + CardList land = new CardList(playZone.getCards()); + land = land.getType("Plains"); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Emeria, the Sky Ruin"); + + if (land.size() >= 7 && creatures.size() >= 1) + { + for (int i=0;i= 4) + { + for (int i=0;i= 4) + { + if (player.equals("Human")) + { + Object o = AllZone.Display.getChoiceOptional( + "Pick a creature to return to hand", creatures.toArray()); + if (o != null) + { + Card card = (Card) o; + graveyard.remove(card); + hand.add(card); + } + } + else if (player.equals("Computer")) + { + Card card = creatures.get(0); + graveyard.remove(card); + hand.add(card); + + } + } + } + + };// Ability + ability.setStackDescription("Oversold Cemetary returns creature from the graveyard to its owner's hand."); + AllZone.Stack.add(ability); + + } + } + + }//Oversold Cemetery + + private static void upkeep_Reya() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone graveyard = AllZone.getZone(Constant.Zone.Graveyard, player); + + CardList creatures = new CardList(graveyard.getCards()); + creatures = creatures.getType("Creature"); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Reya Dawnbringer"); + + if (creatures.size() > 0 && list.size() > 0) + { + Ability ability = new Ability(list.get(0), "0") + { + public void resolve() + { + PlayerZone graveyard = AllZone.getZone( + Constant.Zone.Graveyard, player); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, + player); + + CardList creatures = new CardList(graveyard.getCards()); + creatures = creatures.getType("Creature"); + + if (player.equals("Human")) + { + Object o = AllZone.Display.getChoiceOptional( + "Pick a creature to put into play", creatures + .toArray()); + if (o != null) + { + Card card = (Card) o; + graveyard.remove(card); + playZone.add(card); + } + } else if (player.equals("Computer")) + { + Card card = creatures.get(0); + graveyard.remove(card); + playZone.add(card); + + } + } + + };// Ability + ability + .setStackDescription("Reya returns creature from graveyard back to play"); + AllZone.Stack.add(ability); + } // if creatures > 0 + } // reya + + private static void upkeep_Wort() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone graveyard = AllZone.getZone(Constant.Zone.Graveyard, player); + + CardList creatures = new CardList(graveyard.getCards()); + creatures = creatures.getType("Goblin"); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Wort, Boggart Auntie"); + + if (creatures.size() > 0 && list.size() > 0) + { + Ability ability = new Ability(list.get(0), "0") + { + public void resolve() + { + PlayerZone graveyard = AllZone.getZone( + Constant.Zone.Graveyard, player); + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, + player); + + CardList creatures = new CardList(graveyard.getCards()); + creatures = creatures.getType("Goblin"); + + if (player.equals("Human")) + { + Object o = AllZone.Display.getChoiceOptional( + "Pick a goblin to put into your hand", + creatures.toArray()); + if (o != null) + { + Card card = (Card) o; + graveyard.remove(card); + hand.add(card); + } + } else if (player.equals("Computer")) + { + Card card = creatures.get(0); + graveyard.remove(card); + hand.add(card); + + } + } + + };// Ability + ability + .setStackDescription("Wort returns creature from graveyard to " + + player + "'s hand"); + AllZone.Stack.add(ability); + } // if creatures > 0 + } // Wort + + private static void upkeep_Nether_Spirit() + { + final String player = AllZone.Phase.getActivePlayer(); + final PlayerZone graveyard = AllZone.getZone(Constant.Zone.Graveyard, player); + final PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList all = new CardList(graveyard.getCards()); + all = all.getType("Creature"); + + CardList list = new CardList(graveyard.getCards()); + list = list.getName("Nether Spirit"); + + if (all.size() == 1 && list.size() == 1) + { + final Card nether = list.get(0); + Ability ability = new Ability(list.get(0), "0") + { + public void resolve() + { + graveyard.remove(nether); + playZone.add(nether); + } + }; + + boolean returnNether = false; + + if (player.equals(Constant.Player.Human)) + { + String[] choices = { "Yes", "No" }; + + Object q = AllZone.Display.getChoiceOptional("Return Nether Spirit to play?", choices); + if (q.equals("Yes")) + returnNether = true; + } + + if (player.equals(Constant.Player.Computer) || returnNether) { + ability.setStackDescription("Nether Spirit returns to play."); + AllZone.Stack.add(ability); + } + } //if + }//nether spirit + + private static void upkeep_Spore_Counters() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getType("Creature"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + if (c.getName().equals("Deathspore Thallid") + || c.getName().equals("Elvish Farmer") + || c.getName().equals("Feral Thallid") + || c.getName().equals("Mycologist") + || c.getName().equals("Pallid Mycoderm") + || c.getName().equals("Psychotrope Thallid") + || c.getName().equals("Savage Thallid") + || c.getName().equals("Thallid") + || c.getName().equals("Thallid Devourer") + || c.getName().equals("Thallid Germinator") + || c.getName().equals("Thallid Shell-Dweller") + || c.getName().equals("Thorn Thallid") + || c.getName().equals("Utopia Mycon") + || c.getName().equals("Vitaspore Thallid")) + { + c.addCounter(Counters.SPORE, 1); + } + } + } + + private static void upkeep_Aven_Riftwatcher() + { + // get all Aven Riftwatcher in play under the control of this player + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + CardList list = new CardList(playZone.getCards()); + list = list.getName("Aven Riftwatcher"); + if (list.size() > 0) + { + for (int i = 0; i < list.size(); i++) + { + Card card = list.get(i); + card.setCounter(Counters.AGE, + card.getCounters(Counters.AGE) - 1); + if (card.getCounters(Counters.AGE) <= 0) + { + AllZone.GameAction.sacrifice(card); + } + } + } + } + + private static void upkeep_Calciderm() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + CardList list = new CardList(playZone.getCards()); + list = list.getName("Calciderm"); + if (list.size() > 0) + { + for (int i = 0; i < list.size(); i++) + { + Card card = list.get(i); + card.setCounter(Counters.AGE, + card.getCounters(Counters.AGE) - 1); + if (card.getCounters(Counters.AGE) <= 0) + { + AllZone.GameAction.sacrifice(card); + } + } + } + } + + private static void upkeep_Blastoderm() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + CardList list = new CardList(playZone.getCards()); + list = list.getName("Blastoderm"); + if (list.size() > 0) + { + for (int i = 0; i < list.size(); i++) + { + Card card = list.get(i); + if (card.getCounters(Counters.FADE) <= 0) + { + AllZone.GameAction.sacrifice(card); + } + card.setCounter(Counters.FADE, card.getCounters(Counters.FADE) - 1); + + } + } + } + + + private static void upkeep_Defense_of_the_Heart() + { + final String player = AllZone.Phase.getActivePlayer(); + final String opponent = AllZone.GameAction.getOpponent(player); + + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + // check if opponent has 3 or more creatures in play + PlayerZone opponentZone = AllZone.getZone(Constant.Zone.Play, opponent); + CardList opponentList = new CardList(opponentZone.getCards()); + opponentList = opponentList.getType("Creature"); + //System.out.println("opponent has " + opponentList.size() + " creatures"); + + for (int i = 0; i < opponentList.size(); i++) + { + Card tmpCard = opponentList.get(i); + System.out.println("opponent has: " + tmpCard); + } + + if (3 > opponentList.size()) + { + // they do not have 3 or more creatures in play, so Defense of the + // Heart would not be able to be sacrificed. + return; + } + + // opponent has more than 3 creatures in play, so check if Defense of + // the Heart is in play and sacrifice it for the effect. + CardList list = new CardList(playZone.getCards()); + list = list.getName("Defense of the Heart"); + + if (0 < list.size()) + { + // loop through the number of Defense of the Heart's that player + // controls. They could control 1, 2, 3, or 4 of them. + for (int i = 0; i < list.size(); i++) + { + final Card card = list.get(i); + Ability ability = new Ability(list.get(0), "0") + { + public void resolve() + { + PlayerZone library = AllZone.getZone( + Constant.Zone.Library, card.getController()); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, + card.getController()); + + // sacrifice Defense of the Heart + AllZone.GameAction.sacrifice(card); + // search library for a creature, put it into play + Card creature1 = getCreatureFromLibrary(); + if (creature1 != null) + { + library.remove(creature1); + play.add(creature1); + } + + // search library for a second creature, put it into + // play + Card creature2 = getCreatureFromLibrary(); + if (creature2 != null) + { + // if we got this far the effect was good + library.remove(creature2); + play.add(creature2); + } + + AllZone.GameAction.shuffle(card.getController()); + + } + + public Card getCreatureFromLibrary() + { + PlayerZone library = AllZone.getZone( + Constant.Zone.Library, card.getController()); + + CardList creatureList = new CardList(library.getCards()); + creatureList = creatureList.getType("Creature"); + + if (Constant.Player.Computer.equals(card + .getController())) + { + return CardFactoryUtil + .AI_getBestCreature(creatureList); + } else + { + Object o = AllZone.Display.getChoiceOptional( + "Choose a creature card", creatureList + .toArray()); + if (o != null) + { + Card creature = (Card) o; + return creature; + } else + { + return null; + } + } + }// getCreatureFromLibrary + };// Ability + + ability + .setStackDescription("Defense of the Heart - " + + player + + " sacrifices Defense of the Heart to search their library for up to two creature cards and put those creatures into play. Then shuffle's their library."); + AllZone.Stack.add(ability); + card.addSpellAbility(ability); + + } + }// if + }// upkeep_Defense of the Heart + + private static void upkeep_Convalescence() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + final PlayerLife pLife = AllZone.GameAction.getPlayerLife(player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Convalescence"); + + for (int i = 0; i < list.size(); i++) + { + Ability ability = new Ability(list.get(i), "0") + { + + public void resolve() + { + pLife.addLife(1); + } + };// Ability + ability.setStackDescription("Convalescence - " + player + + " gain 1 life"); + + if ((pLife.getLife() + i) <= 10) + { + AllZone.Stack.add(ability); + } + }// for + }// upkeep_Convalescence() + + private static void upkeep_Convalescent_Care() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerLife pLife = AllZone.GameAction.getPlayerLife(player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Convalescent Care"); + + for (int i = 0; i < list.size(); i++) + { + /* + Ability ability = new Ability(list.get(i), "0") + { + + public void resolve() + { + + pLife.addLife(3); + AllZone.GameAction.drawCard(player); + } + };// Ability + ability.setStackDescription("Convalescent Care - " + player + + " gains 3 life and draws a card"); + + if ((pLife.getLife() + i) <= 5) + { + AllZone.Stack.add(ability); + } + */ + if ((pLife.getLife()) <= 5) + { + pLife.addLife(3); + AllZone.GameAction.drawCard(player); + } + + }// for + }// upkeep_Convalescence() + + // Currently we don't determine the difference between beginning and end of + // upkeep in MTG forge. + // So Black Vise's effects happen at the beginning of the upkeep instead of + // at the end. + private static void upkeep_BlackVice() + { + // sanity check. If a player has <= 4 cards black vise does nothing. + final String player = AllZone.Phase.getActivePlayer(); + final int playerHandSize = AllZone.getZone(Constant.Zone.Hand, player) + .size(); + + if (playerHandSize <= 4) + { + return; + } + + // if a player has 5 or more cards black vise does damage + // so, check if opponent of the current player has Black Vise + String opponent = AllZone.GameAction.getOpponent(player); + + PlayerZone opponentPlayZone = AllZone.getZone(Constant.Zone.Play, + opponent); + + CardList blackVice = new CardList(opponentPlayZone.getCards()); + blackVice = blackVice.getName("Black Vise"); + + // determine how much damage to deal the current player + final int damage = playerHandSize - 4; + + // if there are 1 or more black vises owned by the opponent of the + // current player have each of them deal damage. + if (0 < blackVice.size()) + { + for (int i = 0; i < blackVice.size(); i++) + { + Ability ability = new Ability(blackVice.get(0), "0") + { + public void resolve() + { + PlayerLife life = AllZone.GameAction + .getPlayerLife(player); + life.setLife(life.getLife() - damage); + } + };// Ability + + ability.setStackDescription("Black Vise deals " + damage + + " to " + player); + AllZone.Stack.add(ability); + } + }// if + }// upkeep_BlackVice + + private static void upkeep_Klass() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList elf = new CardList(playZone.getCards()); + elf = elf.getType("Elf"); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Klaas, Elf Friend"); + + if (0 < list.size() && 10 <= elf.size()) + { + Ability ability = new Ability(list.get(0), "0") + { + public void resolve() + { + String opponent = AllZone.GameAction.getOpponent(player); + PlayerLife life = AllZone.GameAction + .getPlayerLife(opponent); + life.setLife(0); + } + };// Ability + + ability.setStackDescription("Klaas, Elf Friend - " + player + + " wins the game"); + AllZone.Stack.add(ability); + }// if + }// upkeep_Klass + + private static void upkeep_Felidar_Sovereign() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + PlayerLife plife = AllZone.GameAction.getPlayerLife(player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Felidar Sovereign"); + + if (0 < list.size() && plife.getLife() >= 40) + { + Ability ability = new Ability(list.get(0), "0") + { + public void resolve() + { + String opponent = AllZone.GameAction.getOpponent(player); + PlayerLife life = AllZone.GameAction.getPlayerLife(opponent); + life.setLife(0); + } + };// Ability + + ability.setStackDescription("Felidar Sovereign - " + player + + " wins the game"); + AllZone.Stack.add(ability); + }// if + }// upkeep_Felidar_Sovereign + + private static void upkeep_Battle_of_Wits() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone libraryZone = AllZone.getZone(Constant.Zone.Library, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Battle of Wits"); + + if (0 < list.size() && 200 <= libraryZone.size()) + { + Ability ability = new Ability(list.get(0), "0") + { + public void resolve() + { + String opponent = AllZone.GameAction.getOpponent(player); + PlayerLife life = AllZone.GameAction + .getPlayerLife(opponent); + life.setLife(0); + } + };// Ability + + ability.setStackDescription("Battle of Wits - " + player + + " wins the game"); + AllZone.Stack.add(ability); + }// if + }// upkeep_Battle_of_Wits + + private static void upkeep_Sleeper_Agent() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Sleeper Agent"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(player).subtractLife(2); + } + }; + + ability.setStackDescription("Sleeper Agent deals 2 damage to its controller."); + + AllZone.Stack.add(ability); + } + } + + private static void upkeep_Cursed_Land() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + //list = list.getName("Cursed Land"); + list = list.filter(new CardListFilter() + { + + public boolean addCard(Card c) { + return c.isLand() && c.isEnchanted(); + } + }); + + if (list.size() > 0) + { + ArrayList enchants = new ArrayList(); + Ability ability; + for (int i = 0; i < list.size(); i++) + { + enchants = list.get(i).getEnchantedBy(); + for (Card enchant : enchants) { + if (enchant.getName().equals("Cursed Land")) + { + //final Card c = enchant; + ability = new Ability(enchant, "0") + { + + public void resolve() + { + //if (c.getController().equals(player)) + AllZone.GameAction.getPlayerLife(player).subtractLife(1); + } + }; + + ability.setStackDescription("Cursed Land deals one damage to enchanted land's controller."); + + AllZone.Stack.add(ability); + + + } + } + } + + }//list > 0 + }//cursed land + + private static void upkeep_Pillory_of_the_Sleepless() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + //list = list.getName("Cursed Land"); + list = list.filter(new CardListFilter() + { + + public boolean addCard(Card c) { + return c.isCreature() && c.isEnchanted(); + } + }); + + if (list.size() > 0) + { + ArrayList enchants = new ArrayList(); + Ability ability; + for (int i = 0; i < list.size(); i++) + { + enchants = list.get(i).getEnchantedBy(); + for (Card enchant : enchants) { + if (enchant.getName().equals("Pillory of the Sleepless")) + { + //final Card c = enchant; + ability = new Ability(enchant, "0") + { + public void resolve() + { + //if (c.getController().equals(player)) + AllZone.GameAction.getPlayerLife(player).subtractLife(1); + } + }; + ability.setStackDescription("Pillory of the Sleepless deals one damage to enchanted creature's controller."); + + AllZone.Stack.add(ability); + } + } + } + + }//list > 0 + }//cursed land + + + private static void upkeep_Greener_Pastures() + { + + + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + PlayerZone oppPlayZone = AllZone.getZone(Constant.Zone.Play, AllZone.GameAction.getOpponent(player)); + + CardList self = new CardList(playZone.getCards()); + CardList opp = new CardList(oppPlayZone.getCards()); + + self = self.getType("Land"); + opp = opp.getType("Land"); + + if ((self.size() == opp.size()) || opp.size() > self.size()) + return; + else //active player has more lands + { + String mostLandsPlayer = ""; + if (self.size() > opp.size()) + mostLandsPlayer = player; + + final String mostLands = mostLandsPlayer; + + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Greener Pastures"); + + Ability ability; + + + for (int i = 0; i < list.size(); i++) + { + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + Card c = new Card(); + + c.setOwner(mostLands); + c.setController(mostLands); + + + c.setName("Saproling"); + c.setImageName("G 1 1 Saproling"); + c.setManaCost("G"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Saproling"); + + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, + mostLands); + play.add(c); + }// resolve() + };// Ability + ability.setStackDescription("Greener Pastures - " + mostLands + " puts a 1/1 green Saproling token into play."); + + AllZone.Stack.add(ability); + }// for + + }//else + }// upkeep_Greener_Pastures() + + private static void upkeep_Bitterblossom() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Bitterblossom"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(player).subtractLife(1); + Card c = new Card(); + + c.setOwner(player); + c.setController(player); + + c.setName("Faerie Rogue"); + c.setImageName("B 1 1 Faerie Rogue"); + c.setManaCost("B"); + c.setToken(true); + + c.addType("Creature"); + c.addType("Faerie"); + c.addType("Rogue"); + c.addIntrinsicKeyword("Flying"); + + c.setBaseAttack(1); + c.setBaseDefense(1); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, + player); + play.add(c); + }// resolve() + };// Ability + ability.setStackDescription("Bitterblossom - deals 1 damage to " + + player + " and put a 1/1 token into play."); + + AllZone.Stack.add(ability); + }// for + }// upkeep_Bitterblossom() + + private static void upkeep_Eldrazi_Monument() + { + final String player = AllZone.Phase.getActivePlayer(); + final PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Eldrazi Monument"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + final Card card = list.get(i); + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + CardList creats = new CardList(playZone.getCards()); + creats = creats.getType("Creature"); + + if (creats.size() < 1) + { + AllZone.GameAction.sacrifice(card); + return; + } + + if (player.equals(Constant.Player.Human)) + { + Object o = AllZone.Display.getChoiceOptional("Select creature to sacrifice", creats.toArray()); + Card sac = (Card)o; + if (sac == null){ + creats.shuffle(); + sac = creats.get(0); + } + AllZone.GameAction.sacrifice(sac); + } + else//computer + { + CardListUtil.sortAttackLowFirst(creats); + AllZone.GameAction.sacrifice(creats.get(0)); + } + } + }; + ability.setStackDescription("Eldrazi Monument - " + + player + " sacrifices a creature."); + AllZone.Stack.add(ability); + } + + }//upkeep_Eldrazi_Monument + + private static void upkeep_Blaze_Counters() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList blaze = new CardList(playZone.getCards()); + blaze = blaze.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.isLand() && c.getCounters(Counters.BLAZE) > 0; + } + }); + + if (blaze.size() > 0) + { + final int lands = blaze.size(); + Ability ability = new Ability(blaze.get(0), "0") + { + public void resolve() { + AllZone.GameAction.getPlayerLife(player).subtractLife(lands); + } + }; + ability.setStackDescription("Obsidian Fireheart - " + player + " gets dealt " + lands + " damage."); + AllZone.Stack.add(ability); + + } + + } + + private static void upkeep_Mycoloth() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + final int[] number = new int[1]; + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Mycoloth"); + + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + final Card card = list.get(i); + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + number[0] = card.getNetPTCounters(); + + for(int j=0; j 0 && list.size() > 0) + { + Ability ability; + for (int i = 0; i < list.size(); i++) + { + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + String[] choices = { "Yes", "No" }; + + Object q = null; + if (player.equals(Constant.Player.Human)){ + q = AllZone.Display.getChoiceOptional("Use Bringer of the White Dawn?", choices); + if (q == null || q.equals("No")) + return; + } + if (q.equals("Yes")) + { + PlayerZone graveyard = AllZone.getZone( + Constant.Zone.Graveyard, player); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, + player); + + CardList arts = new CardList(graveyard.getCards()); + arts = arts.getType("Artifact"); + + Object o = AllZone.Display.getChoiceOptional("Pick an artifact to put into play", arts.toArray()); + if (o != null) + { + Card card = (Card) o; + graveyard.remove(card); + playZone.add(card); + } + + } + + else if (player.equals(Constant.Player.Computer)) + { + PlayerZone graveyard = AllZone.getZone( + Constant.Zone.Graveyard, player); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, + player); + + CardList arts = new CardList(graveyard.getCards()); + arts = arts.getType("Artifact"); + + Card card = arts.get(0); + graveyard.remove(card); + playZone.add(card); + } + + }// resolve() + };// Ability + ability.setStackDescription("Bringer of the White Dawn - " + + player + " returns an artifact to play."); + + + AllZone.Stack.add(ability); + }// for + }//if + }// upkeep_Bringer_of_the_White_Dawn() + + + + private static void upkeep_Serendib_Efreet() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Serendib Efreet"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(player).subtractLife(1); + } + };// Ability + ability.setStackDescription("Serendib Efreet - deals 1 damage to " + + player); + + AllZone.Stack.add(ability); + }// for + }// upkeep_Serendib_Efreet() + + private static void upkeep_Nettletooth_Djinn() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Nettletooth Djinn"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(player).subtractLife(1); + } + };// Ability + ability + .setStackDescription("Nettletooth Djinn - deals 1 damage to " + + player); + + AllZone.Stack.add(ability); + }// for + }// upkeep_Nettletooth_Djinn() + + private static void upkeep_Howling_Mine() + { + final String player = AllZone.Phase.getActivePlayer(); + + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + + // does not check to see if Howling Mine is untapped + list = list.getName("Howling Mine"); + + for (int i = 0; i < list.size(); i++) + AllZone.GameAction.drawCard(player); + }// upkeep_Howling_Mine() + + private static void upkeep_Font_of_Mythos() + { + final String player = AllZone.Phase.getActivePlayer(); + + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + + // does not check to see if Howling Mine is untapped + list = list.getName("Font of Mythos"); + + for (int i = 0; i < list.size(); i++) + { + AllZone.GameAction.drawCard(player); + AllZone.GameAction.drawCard(player); + } + }// upkeep_Font_of_Mythos() + + private static void upkeep_Phyrexian_Arena() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(); + list.addAll(play.getCards()); + + list = list.getName("Phyrexian Arena"); + + for (int i = 0; i < list.size(); i++) { + AllZone.GameAction.drawCard(player); + AllZone.GameAction.getPlayerLife(player).subtractLife(1); + } + }// upkeep_Phyrexian_Arena + + private static void upkeep_Seizan_Perverter_of_Truth() + { + final String player = AllZone.Phase.getActivePlayer(); + + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + + list = list.getName("Seizan, Perverter of Truth"); + + if (list.size() == 0) + return; + + Ability ability = new Ability(list.get(0), "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(player).subtractLife(2); + } + }; + ability.setStackDescription("Seizan, Perverter of Truth - " + player + + " loses 2 life and draws 2 cards"); + + AllZone.Stack.add(ability); + + //drawing cards doesn't seem to work during upkeep if it's in an ability + AllZone.GameAction.drawCard(player); + AllZone.GameAction.drawCard(player); + }// upkeep_Seizan_Perverter_of_Truth() + + private static void upkeep_Grinning_Demon() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Grinning Demon"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + if (!list.get(i).isFaceDown()) + { + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(player).subtractLife(2); + } + };// Ability + ability.setStackDescription("Grinning Demon - " +player + " loses 2 life"); + + AllZone.Stack.add(ability); + } + }// for + }// upkeep_Juzam_Djinn() + + private static void upkeep_Juzam_Djinn() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Juzam Djinn"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(player).subtractLife(1); + } + };// Ability + ability.setStackDescription("Juzam Djinn - deals 1 damage to " + + player); + + AllZone.Stack.add(ability); + }// for + }// upkeep_Juzam_Djinn() + + private static void upkeep_Fledgling_Djinn() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("Fledgling Djinn"); + + Ability ability; + for (int i = 0; i < list.size(); i++) + { + ability = new Ability(list.get(i), "0") + { + public void resolve() + { + AllZone.GameAction.getPlayerLife(player).subtractLife(1); + } + };// Ability + ability.setStackDescription("Fledgling Djinn - deals 1 damage to " + + player); + + AllZone.Stack.add(ability); + }// for + }// upkeep_Fledgling_Djinn() + + public static void executeCardStateEffects() + { + Wonder.execute(); + Anger.execute(); + Valor.execute(); + Brawn.execute(); + + Baru.execute(); + Reach_of_Branches.execute(); + + Essence_Warden.execute(); + Soul_Warden.execute(); + Wirewood_Hivemaster.execute(); + //Angelic_Chorus.execute(); + + /* + Conspiracy.execute(); + Serra_Avatar.execute(); + Ajani_Avatar_Token.execute(); + Windwright_Mage.execute(); + + Baru.execute(); + Reach_of_Branches.execute(); + + Essence_Warden.execute(); + Soul_Warden.execute(); + Wirewood_Hivemaster.execute(); + Angelic_Chorus.execute(); + + Kithkin_Rabble.execute(); + Nightmare.execute(); + Korlash.execute(); + + Kird_Ape.execute(); + Yavimaya_Enchantress.execute(); + Knight_of_the_Reliquary.execute(); + Master_of_Etherium.execute(); + Master_of_Etherium_Pump.execute(); + Master_of_Etherium_Other.execute(); + Relentless_Rats_Other.execute(); + Wizened_Cenn_Pump.execute(); + Wizened_Cenn_Other.execute(); + + Covetous_Dragon.execute(); + + Shared_Triumph.execute(); + Crucible_of_Fire.execute(); + Glorious_Anthem.execute(); + Gaeas_Anthem.execute(); + Bad_Moon.execute(); + Crusade.execute(); + Muraganda_Petroglyphs.execute(); + + Engineered_Plague.execute(); + Night_of_Souls_Betrayal.execute(); + + Thelonite_Hermit.execute(); + Kaysa.execute(); + Meng_Huo.execute(); + Tolsimir.execute(); + Imperious_Perfect.execute(); + Mad_Auntie.execute(); + + Wonder.execute(); + Anger.execute(); + Valor.execute(); + Brawn.execute(); + + Veteran_Armorer.execute(); + Radiant_Archangel.execute(); + Castle.execute(); + Castle_Raptors.execute(); + + Mobilization.execute(); + Serras_Blessing.execute(); + Concordant_Crossroads.execute(); + Mass_Hysteria.execute(); + Fervor.execute(); + + Rolling_Stones.execute(); + Kobold_Overlord.execute(); + Kinsbaile_Cavalier.execute(); + + Sliver_Legion.execute(); + Muscle_Sliver.execute(); + + Bonesplitter_Sliver.execute(); + Might_Sliver.execute(); + Watcher_Sliver.execute(); + + Winged_Sliver.execute(); + Synchronous_Sliver.execute(); + Fury_Sliver.execute(); + Plated_Sliver.execute(); + Essence_Sliver.execute(); + Sinew_Sliver.execute(); + Horned_Sliver.execute(); + + Heart_Sliver.execute(); + Reflex_Sliver.execute(); + Gemhide_Sliver.execute(); + + Blade_Sliver.execute(); + Battering_Sliver.execute(); + + Marrow_Gnawer.execute(); + + Joiner_Adept.execute(); + */ + + }// executeCardStateEffects() + + public static Command Conspiracy = new Command() + { + private static final long serialVersionUID = -752798545956593342L; + + CardList gloriousAnthemList = new CardList(); + public void execute() + { + //String keyword = "Defender"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + //System.out.println("prev type: " +c.getPrevType()); + c.setType(c.getPrevType()); + } + + list.clear(); + + PlayerZone[] zone = new PlayerZone[4]; + + CardList cl = new CardList(); + cl.addAll(AllZone.Human_Play.getCards()); + cl.addAll(AllZone.Computer_Play.getCards()); + cl = cl.getName("Conspiracy"); + + for (int i=0;i < cl.size(); i++) + { + Card card = cl.get(i); + String player = card.getController(); + zone[0] = AllZone.getZone(Constant.Zone.Hand, player); + zone[1] = AllZone.getZone(Constant.Zone.Library, player); + zone[2] = AllZone.getZone(Constant.Zone.Graveyard, player); + zone[3] = AllZone.getZone(Constant.Zone.Play, player); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Creature"); + + //System.out.println("zone[" + outer + "] = " + creature.size()); + + for (int j = 0; j < creature.size(); j++) + { + boolean art = false; + boolean ench = false; + + c = creature.get(j); + + if (c.isArtifact()) + art = true; + if (c.isEnchantment()) + ench = true; + + if (c.getPrevType().size()== 0) + c.setPrevType(c.getType()); + c.setType(new ArrayList()); + c.addType("Creature"); + if (art) + c.addType("Artifact"); + if (ench) + c.addType("Enchantment"); + c.addType(card.getChosenType()); + + gloriousAnthemList.add(c); + } + } + }// for inner + }// execute() + };//Conspiracy + + public static Command Engineered_Plague = new Command() + { + private static final long serialVersionUID = -7941528835392424702L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + } + + list.clear(); + CardList cards = new CardList(); + cards.addAll(AllZone.Human_Play.getCards()); + cards.addAll(AllZone.Computer_Play.getCards()); + cards = cards.getName("Engineered Plague"); + + for (int outer = 0; outer < cards.size(); outer++) + { + Card card = cards.get(outer); + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType(card.getChosenType()); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if(c.getType().contains(card.getChosenType()) || c.getKeyword().contains("Changeling")) + { + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + + gloriousAnthemList.add(c); + } + + + }// for inner + }// for outer + }// execute() + }; //Engineered Plague + + public static Command Night_of_Souls_Betrayal = new Command() + { + private static final long serialVersionUID = 867116049464930958L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + } + + list.clear(); + CardList cards = new CardList(); + cards.addAll(AllZone.Human_Play.getCards()); + cards.addAll(AllZone.Computer_Play.getCards()); + cards = cards.getName("Night of Souls' Betrayal"); + + for (int outer = 0; outer < cards.size(); outer++) + { + //Card card = cards.get(outer); //unused + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Creature"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + + gloriousAnthemList.add(c); + + }// for inner + }// for outer + }// execute() + }; //Night of Souls' Betrayal + + + public static Command Rolling_Stones = new Command() + { + private static final long serialVersionUID = -3317318747868440229L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Defender"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addIntrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Rolling Stones"); + + for (int outer = 0; outer < zone.length; outer++) + { + //CardList creature = new CardList(zone[outer].getCards()); + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Creature"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (c.getKeyword().contains(keyword) + && c.getType().contains("Wall")) + { + c.removeIntrinsicKeyword(keyword); + gloriousAnthemList.add(c); + } + }// for inner + }// for outer + }// execute() + }; //Rolling Stones + + public static Command Kobold_Overlord = new Command() + { + private static final long serialVersionUID = 4620370378774187573L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "First Strike"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Kobold Overlord"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Kobold"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (!c.getKeyword().contains("First Strike")) + { + c.addExtrinsicKeyword(keyword); + gloriousAnthemList.add(c); + } + }// for inner + }// for outer + }// execute() + }; + + //moved to Card.addExtrinsicAbilities + + public static Command Joiner_Adept = new Command() + { + private static final long serialVersionUID = -2543659953307485051L; + + CardList gloriousAnthemList = new CardList(); + + String[] keyword = + { "tap: add B", "tap: add W", "tap: add G", "tap: add U", "tap: add R" }; + + final void addMana(Card c) + { + for (int i = 0; i < keyword.length; i++) + { + //don't add an extrinsic mana ability if the land can already has the same intrinsic mana ability + //eg. "tap: add G" + if (!c.getIntrinsicManaAbilitiesDescriptions().contains(keyword[i])) + { + //c.addExtrinsicKeyword(keyword[i]); + SpellAbility mana = new Ability_Mana(c, keyword[i]) + { + private static final long serialVersionUID = 2384540533244132975L; + }; + + mana.setType("Extrinsic"); + c.addSpellAbility(mana); + } + } + } + + final void removeMana(Card c) + { + + /* + for (int i = 0; i < keyword.length; i++) + c.removeExtrinsicKeyword(keyword[i]); + */ + c.removeAllExtrinsicManaAbilities(); + } + + public void execute() + { + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + removeMana(c); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Joiner Adept"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length && outer < 1; outer++) // 1 + // is + // a + // cheat + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Land"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + addMana(c); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Muscles_Sliver + + public static Command Battering_Sliver = new Command() + { + private static final long serialVersionUID = -2214824705109236342L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Trample"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Battering Sliver"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword(keyword); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Blade Sliver + + public static Command Marrow_Gnawer = new Command() + { + private static final long serialVersionUID = -2500490393763095527L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Fear"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Marrow-Gnawer"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Rat"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword(keyword); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Marrow-Gnawer + + public static Command Blade_Sliver = new Command() + { + private static final long serialVersionUID = 5059367392983499740L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + int pumpAttack = 1; + int pumpDefense = 0; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(-pumpAttack); + c.addSemiPermanentDefenseBoost(-pumpDefense); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Blade Sliver"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addSemiPermanentAttackBoost(pumpAttack); + c.addSemiPermanentDefenseBoost(pumpDefense); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Muscles_Sliver + + public static Command Gemhide_Sliver = new Command() + { + private static final long serialVersionUID = -2941784982910968772L; + + CardList gloriousAnthemList = new CardList(); + + String[] keyword = + { "tap: add B", "tap: add W", "tap: add G", "tap: add U", "tap: add R" }; + + final void addMana(Card c) + { + + for (int i = 0; i < keyword.length; i++){ + if (!c.getIntrinsicManaAbilitiesDescriptions().contains(keyword[i])) { + //c.addExtrinsicKeyword(keyword[i]); + SpellAbility mana = new Ability_Mana(c, keyword[i]) + { + private static final long serialVersionUID = -8909660504657778172L; + }; + mana.setType("Extrinsic"); + c.addSpellAbility(mana); + } + } + } + + final void removeMana(Card c) + { + /* + for (int i = 0; i < keyword.length; i++) + c.removeExtrinsicKeyword(keyword[i]); + */ + c.removeAllExtrinsicManaAbilities(); + } + + public void execute() + { + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + removeMana(c); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Gemhide Sliver"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length && outer < 1; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + addMana(c); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Muscles_Sliver + + public static Command Heart_Sliver = new Command() + { + private static final long serialVersionUID = -3213253353499680447L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Haste"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Heart Sliver"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword(keyword); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Heart_Sliver + + public static Command Reflex_Sliver = new Command() + { + private static final long serialVersionUID = -6606809422365563893L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Haste"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Reflex Sliver"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword(keyword); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Reflex_Sliver + + public static Command Horned_Sliver = new Command() + { + private static final long serialVersionUID = 4789073152424705372L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Trample"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Horned Sliver"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword(keyword); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Muscles_Sliver + + public static Command Sinew_Sliver = new Command() + { + private static final long serialVersionUID = -4633694634393704728L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + int pumpAttack = 1; + int pumpDefense = 1; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(-pumpAttack); + c.addSemiPermanentDefenseBoost(-pumpDefense); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Sinew Sliver"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addSemiPermanentAttackBoost(pumpAttack); + c.addSemiPermanentDefenseBoost(pumpDefense); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Muscles_Sliver + + public static Command Winged_Sliver = new Command() + { + private static final long serialVersionUID = -1840399835079335499L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Flying"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Winged Sliver"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword(keyword); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Muscles_Sliver + + public static Command Serras_Blessing = new Command() + { + private static final long serialVersionUID = -6904191523315339355L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Vigilance"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Serra's Blessing"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Creature"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (!c.getKeyword().contains(keyword)) + { + c.addExtrinsicKeyword(keyword); + gloriousAnthemList.add(c); + } + }// for inner + }// for outer + }// execute() + }; + + public static Command Cover_of_Darkness = new Command() + { + private static final long serialVersionUID = -6707183535529395830L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword("Fear"); + } + + list.clear(); + CardList cards = new CardList(); + cards.addAll(AllZone.Human_Play.getCards()); + cards.addAll(AllZone.Computer_Play.getCards()); + cards = cards.getName("Cover of Darkness"); + + for (int outer = 0; outer < cards.size(); outer++) + { + Card card = cards.get(outer); + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType(card.getChosenType()); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if(c.getType().contains(card.getChosenType()) || c.getKeyword().contains("Changeling")) + { + c.addExtrinsicKeyword("Fear"); + gloriousAnthemList.add(c); + } + + + }// for inner + }// for outer + }// execute() + }; //Cover of Darkness + + public static Command Steely_Resolve = new Command() + { + + private static final long serialVersionUID = 2005579284163773044L; + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword("Shroud"); + } + + list.clear(); + CardList cards = new CardList(); + cards.addAll(AllZone.Human_Play.getCards()); + cards.addAll(AllZone.Computer_Play.getCards()); + cards = cards.getName("Steely Resolve"); + + for (int outer = 0; outer < cards.size(); outer++) + { + Card card = cards.get(outer); + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType(card.getChosenType()); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if(c.getType().contains(card.getChosenType()) || c.getKeyword().contains("Changeling")) + { + c.addExtrinsicKeyword("Shroud"); + gloriousAnthemList.add(c); + } + + + }// for inner + }// for outer + }// execute() + }; //Steely Resolve + + public static Command Mobilization = new Command() + { + private static final long serialVersionUID = 2005579284163773044L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Vigilance"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Mobilization"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Soldier"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (!c.getKeyword().contains(keyword)) + { + c.addExtrinsicKeyword(keyword); + gloriousAnthemList.add(c); + } + }// for inner + }// for outer + }// execute() + }; //mobilization + + public static Command That_Which_Was_Taken = new Command() + { + private static final long serialVersionUID = -4142514935709694293L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Indestructible"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("That Which Was Taken"); + + if (zone.length>0) + { + CardList cards = new CardList(); + cards.addAll(AllZone.Human_Play.getCards()); + cards.addAll(AllZone.Computer_Play.getCards()); + + for (int i = 0; i < cards.size(); i++) + { + c = cards.get(i); + if (!c.getKeyword().contains(keyword) && c.getCounters(Counters.DIVINITY) > 0) + { + c.addExtrinsicKeyword(keyword); + gloriousAnthemList.add(c); + } + }// for inner + }// for outer + }// execute() + }; + + + public static Command Concordant_Crossroads = new Command() + { + private static final long serialVersionUID = -6811663469245799727L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Haste"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Concordant Crossroads"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Creature"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (!c.getKeyword().contains(keyword)) + { + c.addExtrinsicKeyword(keyword); + gloriousAnthemList.add(c); + } + }// for inner + }// for outer + }// execute() + }; + + public static Command Mass_Hysteria = new Command() + { + private static final long serialVersionUID = 8171915479339460306L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Haste"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Mass Hysteria"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Creature"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (!c.getKeyword().contains(keyword)) + { + c.addExtrinsicKeyword(keyword); + gloriousAnthemList.add(c); + } + }// for inner + }// for outer + }// execute() + }; + + public static Command Fervor = new Command() + { + private static final long serialVersionUID = -826876381048543684L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Haste"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Fervor"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Creature"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (!c.getKeyword().contains(keyword)) + { + c.addExtrinsicKeyword(keyword); + gloriousAnthemList.add(c); + } + }// for inner + }// for outer + }// execute() + }; + + public static Command Madrush_Cyclops = new Command() + { + + private static final long serialVersionUID = -2379786355503597363L; + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Haste"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Madrush Cyclops"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Creature"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (!c.getKeyword().contains(keyword)) + { + c.addExtrinsicKeyword(keyword); + gloriousAnthemList.add(c); + } + }// for inner + }// for outer + }// execute() + };//Madrush Cyclops + + + public static Command Sun_Quan = new Command() + { + + private static final long serialVersionUID = -2379786355503597363L; + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Horsemanship"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Sun Quan, Lord of Wu"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Creature"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (!c.getKeyword().contains(keyword)) + { + c.addExtrinsicKeyword(keyword); + gloriousAnthemList.add(c); + } + }// for inner + }// for outer + }// execute() + };//Sun Quan + + public static Command Kinsbaile_Cavalier = new Command() + { + private static final long serialVersionUID = -4124745123035715658L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Double Strike"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Kinsbaile Cavalier"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Knight"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword(keyword); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + }; + + public static Command Wrens_Run_Packmaster = new Command() + { + + private static final long serialVersionUID = 6089293045852070662L; + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Deathtouch"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Wren's Run Packmaster"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Wolf"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword(keyword); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + }; + + + + public static Command Fury_Sliver = new Command() + { + private static final long serialVersionUID = -2379786355503597363L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Double Strike"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Fury Sliver"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword(keyword); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + }; + + public static Command Crystalline_Sliver = new Command() + { + + private static final long serialVersionUID = 6089293045852070662L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Shroud"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Crystalline Sliver"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword(keyword); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + }; + + public static Command Sidewinder_Sliver = new Command() + { + + private static final long serialVersionUID = 4336346186741907749L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Flanking"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Sidewinder Sliver"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword(keyword); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + }; + + public static Command Essence_Sliver = new Command() + { + private static final long serialVersionUID = 6089293045852070662L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Lifelink"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Essence Sliver"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword(keyword); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + }; + + public static Command Synchronous_Sliver = new Command() + { + private static final long serialVersionUID = 4336346186741907749L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + String keyword = "Vigilance"; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword(keyword); + } + + list.clear(); + PlayerZone[] zone = getZone("Synchronous Sliver"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword(keyword); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + }; + + public static Command Bonesplitter_Sliver = new Command() + { + private static final long serialVersionUID = -3463429634177142721L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + int pumpAttack = 2; + int pumpDefense = 0; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(-pumpAttack); + c.addSemiPermanentDefenseBoost(-pumpDefense); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Bonesplitter Sliver"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addSemiPermanentAttackBoost(pumpAttack); + c.addSemiPermanentDefenseBoost(pumpDefense); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Muscles_Sliver + + public static Command Might_Sliver = new Command() + { + private static final long serialVersionUID = 1618762378975019557L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + int pumpAttack = 2; + int pumpDefense = 2; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(-pumpAttack); + c.addSemiPermanentDefenseBoost(-pumpDefense); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Might Sliver"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addSemiPermanentAttackBoost(pumpAttack); + c.addSemiPermanentDefenseBoost(pumpDefense); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Muscles_Sliver + + public static Command Plated_Sliver = new Command() + { + private static final long serialVersionUID = 7670935990022098909L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + int pumpAttack = 0; + int pumpDefense = 1; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(-pumpAttack); + c.addSemiPermanentDefenseBoost(-pumpDefense); + } + + list.clear(); + PlayerZone[] zone = getZone("Plated Sliver"); + + // for each zone found add +0/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addSemiPermanentAttackBoost(pumpAttack); + c.addSemiPermanentDefenseBoost(pumpDefense); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Watcher_Sliver + + public static Command Watcher_Sliver = new Command() + { + private static final long serialVersionUID = -3148897786330400205L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + int pumpAttack = 0; + int pumpDefense = 2; + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(-pumpAttack); + c.addSemiPermanentDefenseBoost(-pumpDefense); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Watcher Sliver"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addSemiPermanentAttackBoost(pumpAttack); + c.addSemiPermanentDefenseBoost(pumpDefense); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Watcher_Sliver + + public static Command Muscle_Sliver = new Command() + { + private static final long serialVersionUID = -2791476542570951362L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Muscle Sliver"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Muscles_Sliver + + public static Command Sliver_Legion = new Command() + { + private static final long serialVersionUID = -4564640511791858445L; + + CardList gloriousAnthemList = new CardList(); + int pump = 0; + + public void execute() + { + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(-pump); + c.addSemiPermanentDefenseBoost(- pump); + } + + // add +pump/+pump to cards + list.clear(); + PlayerZone[] zone = getZone("Sliver Legion"); + + // get all Slivers + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + CardList allSliver = all.getType("Sliver"); + pump = allSliver.size(); + + // for each zone found add +pump/+pump to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Sliver"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addSemiPermanentAttackBoost(pump); + c.addSemiPermanentDefenseBoost(pump); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute() + };// Sliver_Legion + + public static Command Serra_Avatar = new Command() + { + private static final long serialVersionUID = -7560281839252561370L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Serra Avatar"); + + for (int i = 0; i < list.size(); i++) + { + Card card = list.get(i); + int n = AllZone.GameAction.getPlayerLife(card.getController()) + .getLife(); + card.setBaseAttack(n); + card.setBaseDefense(n); + }// for + }// execute + };// Serra Avatar + + public static Command Ajani_Avatar_Token = new Command() + { + private static final long serialVersionUID = 3027329837165436727L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.getName().equals("Avatar") && c.getImageName().equals("W N N Avatar"); + } + }); + for (int i = 0; i < list.size(); i++) + { + Card card = list.get(i); + int n = AllZone.GameAction.getPlayerLife(card.getController()).getLife(); + card.setBaseAttack(n); + card.setBaseDefense(n); + }// for + }// execute + };// Serra Avatar + + public static Command Windwright_Mage = new Command() + { + private static final long serialVersionUID = 7208941897570511298L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Windwright Mage"); + + // Cardlist artifacts = new CardList() + + for (int i = 0; i < list.size(); i++) + { + Card card = list.get(i); + + String player = card.getController(); + PlayerZone graveyard = AllZone.getZone(Constant.Zone.Graveyard, + player); + + CardList artifacts = new CardList(graveyard.getCards()); + artifacts = artifacts.getType("Artifact"); + + if (artifacts.size() > 0) + { + if (!card.getKeyword().contains("Flying")) + { + card.addExtrinsicKeyword("Flying"); + } + } else + { + // this is tricky, could happen that flying is wrongfully + // removed... not sure? + card.removeExtrinsicKeyword("Flying"); + } + + }// for + }// execute + };// Windwright Mage + + // Reach of Branches + public static Command Reach_of_Branches = new Command() + { + private static final long serialVersionUID = 9191592685635589492L; + + CardList oldForest = new CardList(); + + public void execute() + { + // count card "Reach of Branches" in graveyard + final String player = AllZone.Phase.getActivePlayer(); + final PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, + player); + CardList tempList = new CardList(grave.getCards()); + final CardList nCard = tempList.getName("Reach of Branches"); + + // get all Forest that player has + final PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + CardList newForest = new CardList(play.getCards()); + newForest = newForest.getType("Forest"); + + // if "Reach of Branches" is in graveyard and played a Forest + if (0 < nCard.size() && newForest(oldForest, newForest)) + { + SpellAbility ability = new Ability(new Card(), "0") + { + public void resolve() + { + // return all Reach of Branches to hand + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, + player); + for (int i = 0; i < nCard.size(); i++) + { + grave.remove(nCard.get(i)); + hand.add(nCard.get(i)); + } + }// resolve() + };// SpellAbility + ability + .setStackDescription("Reach of Branches - return card to " + + player + "'s hand"); + AllZone.Stack.add(ability); + }// if + + // potential problem: if a Forest is bounced to your hand + // "Reach Branches" + // won't trigger when you play that Forest + oldForest.addAll(newForest.toArray()); + }// execute + + // check if newList has anything that oldList doesn't have + boolean newForest(CardList oldList, CardList newList) + { + // check if a Forest came into play under your control + for (int i = 0; i < newList.size(); i++) + if (!oldList.contains(newList.get(i))) + return true; + + return false; + }// newForest() + };// Reach of Branches + + public static Command Mad_Auntie = new Command() + { + private static final long serialVersionUID = 7969640438477308299L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Mad Auntie"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Goblin"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute + };// Mad_Auntie() + + public static Command Imperious_Perfect = new Command() + { + private static final long serialVersionUID = 5835056455026735693L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Imperious Perfect"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Elf"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + + gloriousAnthemList.add(c); + }// for inner + }// for outer + }// execute + };// Imperious_Perfect() + + public static Command Baru = new Command() + { + private static final long serialVersionUID = 7535910275326543185L; + + CardList old = new CardList(); + + public void execute() + { + // get all Forests + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + CardList current = all.getType("Forest"); + + for (int outer = 0; outer < current.size(); outer++) + { + if (old.contains(current.get(outer))) + continue; + + final CardList test = all.getName("Baru, Fist of Krosa"); + SpellAbility ability = new Ability(new Card(), "0") + { + public void resolve() + { + Card c = null; + if (!test.isEmpty()) + c = test.get(0); + + CardList all = new CardList(AllZone.getZone( + Constant.Zone.Play, c.getController()) + .getCards()); + + all = all.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature() && CardUtil.getColors(c).contains(Constant.Color.Green); + } + }); + + for (int i = 0; i < all.size(); i++) + { + all.get(i).addTempAttackBoost(1); + all.get(i).addTempDefenseBoost(1); + all.get(i).addExtrinsicKeyword("Trample"); + + final Card c1 = all.get(i); + AllZone.EndOfTurn.addUntil(new Command() + { + private static final long serialVersionUID = 3659932873866606966L; + + public void execute() + { + c1.addTempAttackBoost(-1); + c1.addTempDefenseBoost(-1); + c1.removeExtrinsicKeyword("Trample"); + } + }); + }// for + } + }; + ability + .setStackDescription("Baru, Fist of Krosa - creatures get +1/+1 until end of turn."); + + if (!all.getName("Baru, Fist of Krosa").isEmpty()) + AllZone.Stack.push(ability); + }// outer for + + old = current; + }// execute() + };// Baru + public static Command Essence_Warden = new Command() + { + private static final long serialVersionUID = 6515549135916060107L; + + // Hold old creatures + CardList old = new CardList(); // Hold old Essence Wardens + CardList essence = new CardList(); + + public void execute() + { + // get all creatures + CardList current = new CardList(); + current.addAll(AllZone.Human_Play.getCards()); + current.addAll(AllZone.Computer_Play.getCards()); + current = current.getType("Creature"); + + // Holds Essence Warden's in play + CardList wardenList = current.getName("Essence Warden"); + + // Holds Essence Warden's that are new to play + CardList newWarden = new CardList(); + + // Go through the list of Essence Warden's in play + for (int i = 0; i < wardenList.size(); i++) + { + Card c = wardenList.get(i); + + // Check to see which Essence Warden's in play are new + if (!essence.contains(c)) + { + newWarden.add(c); + wardenList.remove(c); + i -= 1; // Must do as a card was just removed + } + + current.remove(c); + } + + for (int outer = 0; outer < wardenList.size(); outer++) + { + // Gain life for new creatures in play - excluding any new + // Essence Wardens + final int[] n = new int[1]; + for (int i = 0; i < current.size(); i++) + { + if (!old.contains(current.getCard(i))) + { + n[0]++; + } + } + + // Gain life for new Essence Wardens + n[0] += newWarden.size(); + + final PlayerLife life = AllZone.GameAction + .getPlayerLife(wardenList.get(outer).getController()); + SpellAbility ability = new Ability(new Card(), "0") + { + + public void resolve() + { + life.addLife(n[0]); + } + }; + ability.setStackDescription(wardenList.get(outer).getName() + + " - " + wardenList.get(outer).getController() + + " gains " + n[0] + " life"); + + if (n[0] != 0) + { + AllZone.Stack.push(ability); + } + }// outer for + + essence = wardenList; + essence.addAll(newWarden.toArray()); + old = current; + }// execute() + };// essence warden + public static Command Soul_Warden = new Command() + { + private static final long serialVersionUID = 5099736949744748496L; + + // Hold old creatures + CardList old = new CardList(); // Hold old Soul Wardens + CardList soul = new CardList(); + + public void execute() + { + // get all creatures + CardList current = new CardList(); + current.addAll(AllZone.Human_Play.getCards()); + current.addAll(AllZone.Computer_Play.getCards()); + current = current.getType("Creature"); + + // Holds Soul Warden's in play + CardList wardenList = current.getName("Soul Warden"); + + // Holds Soul Warden's that are new to play + CardList newWarden = new CardList(); + + // Go through the list of Soul Warden's in play + for (int i = 0; i < wardenList.size(); i++) + { + Card c = wardenList.get(i); + + // Check to see which Soul Warden's in play are new + if (!soul.contains(c)) + { + newWarden.add(c); + wardenList.remove(c); + i -= 1; // Must do as a card was just removed + } + + current.remove(c); + } + + for (int outer = 0; outer < wardenList.size(); outer++) + { + // Gain life for new creatures in play - excluding any new Soul + // Wardens + final int[] n = new int[1]; + for (int i = 0; i < current.size(); i++) + { + if (!old.contains(current.getCard(i))) + { + n[0]++; + } + } + + // Gain life for new Soul Wardens + n[0] += newWarden.size(); + + final PlayerLife life = AllZone.GameAction + .getPlayerLife(wardenList.get(outer).getController()); + SpellAbility ability = new Ability(new Card(), "0") + { + + public void resolve() + { + life.addLife(n[0]); + } + }; + ability.setStackDescription(wardenList.get(outer).getName() + + " - " + wardenList.get(outer).getController() + + " gains " + n[0] + " life"); + + if (n[0] != 0) + { + AllZone.Stack.push(ability); + } + }// outer for + + soul = wardenList; + soul.addAll(newWarden.toArray()); + old = current; + }// execute() + };// soul warden + + public static Command Wirewood_Hivemaster = new Command() + { + private static final long serialVersionUID = -6440532066018273862L; + + // Hold old creatures + CardList old = new CardList(); // Hold old Wirewood Hivemasters + CardList wirewood = new CardList(); + + public void execute() + { + // get all creatures + CardList current = new CardList(); + current.addAll(AllZone.Human_Play.getCards()); + current.addAll(AllZone.Computer_Play.getCards()); + current = current.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return !c.isToken() && (c.getType().contains("Elf") || c.getKeyword().contains("Changeling") ); + } + + }); + + // Holds Soul Warden's in play + CardList hivemasterList = current.getName("Wirewood Hivemaster"); + + // Holds Soul Warden's that are new to play + CardList newHivemaster = new CardList(); + + // Go through the list of Soul Warden's in play + for (int i = 0; i < hivemasterList.size(); i++) + { + Card c = hivemasterList.get(i); + + // Check to see which Soul Warden's in play are new + if (!wirewood.contains(c)) + { + newHivemaster.add(c); + hivemasterList.remove(c); + i -= 1; // Must do as a card was just removed + } + + current.remove(c); + } + + for (int outer = 0; outer < hivemasterList.size(); outer++) + { + + final int[] n = new int[1]; + for (int i = 0; i < current.size(); i++) + { + if (!old.contains(current.getCard(i))) + { + n[0]++; + } + } + + // Gain life for new Soul Wardens + n[0] += newHivemaster.size(); + + final String player = hivemasterList.get(outer).getController(); + SpellAbility ability = new Ability(new Card(), "0") + { + + public void resolve() + { + for(int i=0; i 1 ) + { + //may be problematic, should be fine though + c.setIntrinsicKeyword(new ArrayList()); + c.addIntrinsicKeyword("Trample"); + } + else + { + c.removeIntrinsicKeyword("Trample"); + } + + c.setBaseAttack(countTreeForests(c)); + c.setBaseDefense(c.getBaseAttack()); + } + }// execute() + + private boolean hasTreefolk(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + + CardList tree = new CardList(); + tree.addAll(play.getCards()); + + tree = tree.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return (c.getKeyword().contains("Changeling") || c.getType().contains("Treefolk")) && !c.getName().equals("Dauntless Dourbark"); + } + }); + if (tree.size()>0) + return true; + else + return false; + } + + private int countTreeForests(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + CardList list = new CardList(play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.getType().contains("Treefolk") || c.getKeyword().contains("Changeling") || c.getType().contains("Forest"); + } + }); + + return list.size(); + } + }; + + + public static Command Kird_Ape = new Command() + { + private static final long serialVersionUID = 3448725650293971110L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Kird Ape"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + if (hasForest(c)) + { + c.setBaseAttack(2); + c.setBaseDefense(3); + } + else + { + c.setBaseAttack(1); + c.setBaseDefense(1); + } + } + }// execute() + + private boolean hasForest(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + + CardList land = new CardList(); + land.addAll(play.getCards()); + + land = land.getType("Forest"); + if (land.size()>0) + return true; + else + return false; + } + }; + + public static Command Vexing_Beetle = new Command() + { + + private static final long serialVersionUID = 4599996155083227853L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Vexing Beetle"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + if (!oppHasCreature(c)) + { + c.setBaseAttack(6); + c.setBaseDefense(6); + } + else + { + c.setBaseAttack(3); + c.setBaseDefense(3); + } + } + }// execute() + + private boolean oppHasCreature(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, AllZone.GameAction.getOpponent(c.getController())); + + CardList creats = new CardList(); + creats.addAll(play.getCards()); + + creats = creats.getType("Creature"); + if (creats.size()>0) + return true; + else + return false; + } + }; + + public static Command Sedge_Troll = new Command() + { + + private static final long serialVersionUID = -6021569379906767611L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Sedge Troll"); + + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + if (hasSwamp(c)) + { + c.setBaseAttack(3); + c.setBaseDefense(3); + } + else + { + c.setBaseAttack(2); + c.setBaseDefense(2); + } + } + + }// execute() + + private boolean hasSwamp(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + + CardList land = new CardList(); + land.addAll(play.getCards()); + + land = land.getType("Swamp"); + if (land.size()>0) + return true; + else + return false; + } + }; + + public static Command Hedge_Troll = new Command() + { + + private static final long serialVersionUID = -8843070116088984774L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Hedge Troll"); + + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + if (hasPlains(c)) + { + c.setBaseAttack(3); + c.setBaseDefense(3); + } + else + { + c.setBaseAttack(2); + c.setBaseDefense(2); + } + } + + }// execute() + + private boolean hasPlains(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + + CardList land = new CardList(); + land.addAll(play.getCards()); + + land = land.getType("Plains"); + if (land.size()>0) + return true; + else + return false; + } + }; + + + public static Command Wild_Nacatl = new Command() + { + private static final long serialVersionUID = 6863244333398587274L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Wild Nacatl"); + + if (list.size() > 0) + { + //Card crd = list.get(0); + + + for (int i = 0; i < list.size(); i++) + { + int pt = 1; + Card c = list.get(i); + if (hasPlains(c)) + pt++; + if (hasMountain(c)) + pt++; + + + c.setBaseAttack(pt); + c.setBaseDefense(pt); + + } + } + }// execute() + + private boolean hasPlains(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + + CardList land = new CardList(); + land.addAll(play.getCards()); + + land = land.getType("Plains"); + if (land.size()>0) + return true; + else + return false; + } + + private boolean hasMountain(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + + CardList land = new CardList(); + land.addAll(play.getCards()); + + land = land.getType("Mountain"); + if (land.size()>0) + return true; + else + return false; + } + + }; + + public static Command Liu_Bei = new Command() + { + + private static final long serialVersionUID = 4235093010715735727L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Liu Bei, Lord of Shu"); + + if (list.size() > 0) + { + //Card crd = list.get(0); //unused + + for (int i = 0; i < list.size(); i++) + { + + Card c = list.get(i); + if (getsBonus(c)){ + c.setBaseAttack(4); + c.setBaseDefense(6); + } + else + { + c.setBaseAttack(2); + c.setBaseDefense(4); + } + + } + } + }// execute() + + private boolean getsBonus(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + + CardList list = new CardList(); + list.addAll(play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.getName().equals("Guan Yu, Sainted Warrior") || c.getName().equals("Zhang Fei, Fierce Warrior"); + } + + }); + + return list.size() > 0; + } + + };//Liu_Bei + + public static Command Nimble_Mongoose = new Command() + { + private static final long serialVersionUID = -8155356899650795833L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Nimble Mongoose"); + + if (list.size() > 0) + { + //Card crd = list.get(0); //unused + + for (int i = 0; i < list.size(); i++) + { + + Card c = list.get(i); + if (hasThreshold(c)){ + c.setBaseAttack(3); + c.setBaseDefense(3); + } + else + { + c.setBaseAttack(1); + c.setBaseDefense(1); + } + + } + } + }// execute() + + private boolean hasThreshold(Card c) + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, c.getController()); + + CardList gy = new CardList(); + gy.addAll(grave.getCards()); + + if (gy.size()>=7) + return true; + else + return false; + } + + };//Nimble_Mongoose + + public static Command Mystic_Enforcer = new Command() + { + + private static final long serialVersionUID = 4569052031336290843L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Mystic Enforcer"); + + if (list.size() > 0) + { + //Card crd = list.get(0); //unused + + for (int i = 0; i < list.size(); i++) + { + + Card c = list.get(i); + if (hasThreshold(c)){ + c.setBaseAttack(6); + c.setBaseDefense(6); + if (!c.getIntrinsicKeyword().contains("Flying")) + c.addIntrinsicKeyword("Flying"); + } + else + { + c.setBaseAttack(3); + c.setBaseDefense(3); + if (c.getIntrinsicKeyword().contains("Flying")) + c.removeIntrinsicKeyword("Flying"); + } + + } + } + }// execute() + + private boolean hasThreshold(Card c) + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, c.getController()); + + CardList gy = new CardList(); + gy.addAll(grave.getCards()); + + if (gy.size()>=7) + return true; + else + return false; + } + + };//Mystic_Enforcer + + public static Command Bant_Sureblade = new Command() + { + + private static final long serialVersionUID = 1987511205573387864L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Bant Sureblade"); + + if (list.size() > 0) + { + //Card crd = list.get(0); //unused + + for (int i = 0; i < list.size(); i++) + { + + Card c = list.get(i); + if (CardFactoryUtil.controlsAnotherMulticoloredPermanent(c)){ + c.setBaseAttack(3); + c.setBaseDefense(2); + if (!c.getIntrinsicKeyword().contains("First Strike")) + c.addIntrinsicKeyword("First Strike"); + } + else + { + c.setBaseAttack(2); + c.setBaseDefense(1); + if (c.getIntrinsicKeyword().contains("First Strike")) + c.removeIntrinsicKeyword("First Strike"); + } + + } + } + }// execute() + + };//Bant_Sureblade + + public static Command Esper_Stormblade = new Command() + { + + private static final long serialVersionUID = 1799759665613654307L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Esper Stormblade"); + + if (list.size() > 0) + { + //Card crd = list.get(0); //unused + + for (int i = 0; i < list.size(); i++) + { + + Card c = list.get(i); + if (CardFactoryUtil.controlsAnotherMulticoloredPermanent(c)){ + c.setBaseAttack(3); + c.setBaseDefense(2); + if (!c.getIntrinsicKeyword().contains("Flying")) + c.addIntrinsicKeyword("Flying"); + } + else + { + c.setBaseAttack(2); + c.setBaseDefense(1); + if (c.getIntrinsicKeyword().contains("Flying")) + c.removeIntrinsicKeyword("Flying"); + } + + } + } + }// execute() + + };//Esper_Stormblade + + public static Command Grixis_Grimblade = new Command() + { + + private static final long serialVersionUID = 5895665460018262987L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Grixis Grimblade"); + + if (list.size() > 0) + { + //Card crd = list.get(0); //unused + + for (int i = 0; i < list.size(); i++) + { + + Card c = list.get(i); + if (CardFactoryUtil.controlsAnotherMulticoloredPermanent(c)){ + c.setBaseAttack(3); + c.setBaseDefense(2); + if (!c.getIntrinsicKeyword().contains("Deathtouch")) + c.addIntrinsicKeyword("Deathtouch"); + } + else + { + c.setBaseAttack(2); + c.setBaseDefense(1); + if (c.getIntrinsicKeyword().contains("Deathtouch")) + c.removeIntrinsicKeyword("Deathtouch"); + } + + } + } + }// execute() + + };//Grixis_Grimblade + + public static Command Jund_Hackblade = new Command() + { + + private static final long serialVersionUID = -4386978825641506610L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Jund Hackblade"); + + if (list.size() > 0) + { + //Card crd = list.get(0); //unused + + for (int i = 0; i < list.size(); i++) + { + + Card c = list.get(i); + if (CardFactoryUtil.controlsAnotherMulticoloredPermanent(c)){ + c.setBaseAttack(3); + c.setBaseDefense(2); + if (!c.getIntrinsicKeyword().contains("Haste")) + c.addIntrinsicKeyword("Haste"); + } + else + { + c.setBaseAttack(2); + c.setBaseDefense(1); + if (c.getIntrinsicKeyword().contains("Haste")) + c.removeIntrinsicKeyword("Haste"); + } + + } + } + }// execute() + + };//Jund_Hackblade + + public static Command Naya_Hushblade = new Command() + { + private static final long serialVersionUID = 3953482302338689497L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Naya Hushblade"); + + if (list.size() > 0) + { + //Card crd = list.get(0); //unused + + for (int i = 0; i < list.size(); i++) + { + + Card c = list.get(i); + if (CardFactoryUtil.controlsAnotherMulticoloredPermanent(c)){ + c.setBaseAttack(3); + c.setBaseDefense(2); + if (!c.getIntrinsicKeyword().contains("Shroud")) + c.addIntrinsicKeyword("Shroud"); + } + else + { + c.setBaseAttack(2); + c.setBaseDefense(1); + if (c.getIntrinsicKeyword().contains("Shroud")) + c.removeIntrinsicKeyword("Shroud"); + } + + } + } + }// execute() + + };//Naya_Hushblade + + + public static Command Werebear = new Command() + { + + private static final long serialVersionUID = 4599996155083227853L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Werebear"); + + if (list.size() > 0) + { + //Card crd = list.get(0); //unused + + for (int i = 0; i < list.size(); i++) + { + + Card c = list.get(i); + if (hasThreshold(c)){ + c.setBaseAttack(4); + c.setBaseDefense(4); + } + else + { + c.setBaseAttack(1); + c.setBaseDefense(1); + } + + } + } + }// execute() + + private boolean hasThreshold(Card c) + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, c.getController()); + + CardList gy = new CardList(); + gy.addAll(grave.getCards()); + + if (gy.size()>=7) + return true; + else + return false; + } + + }; + + public static Command Divinity_of_Pride = new Command() + { + private static final long serialVersionUID = -8809209646381095625L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Divinity of Pride"); + + if (list.size() > 0) + { + //Card crd = list.get(0); //unused + + for (int i = 0; i < list.size(); i++) + { + + Card c = list.get(i); + if (moreThan25Life(c)){ + c.setBaseAttack(8); + c.setBaseDefense(8); + } + else + { + c.setBaseAttack(4); + c.setBaseDefense(4); + } + + } + } + }// execute() + + private boolean moreThan25Life(Card c) + { + PlayerLife life = AllZone.GameAction.getPlayerLife(c.getController()); + + if (life.getLife() >= 25) + return true; + else + return false; + } + + }; + + + public static Command Yavimaya_Enchantress = new Command() + { + private static final long serialVersionUID = -5650088477640877743L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Yavimaya Enchantress"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + c.setBaseAttack(2 + countEnchantments()); + c.setBaseDefense(2 + countEnchantments()); + } + }// execute() + + private int countEnchantments() + { + PlayerZone cplay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + PlayerZone hplay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + + CardList ench = new CardList(); + ench.addAll(hplay.getCards()); + ench.addAll(cplay.getCards()); + + ench = ench.getType("Enchantment"); + return ench.size(); + } + }; + + public static Command Knight_of_the_Reliquary = new Command() + { + private static final long serialVersionUID = -8511276284636573216L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Knight of the Reliquary"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + c.setBaseAttack(2 + countLands(c)); + c.setBaseDefense(2 + countLands(c)); + } + }// execute() + + private int countLands(Card c) + { + PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, c.getController()); + + CardList land = new CardList(); + land.addAll(grave.getCards()); + + land = land.getType("Land"); + return land.size(); + } + }; + + public static Command Relentless_Rats_Other = new Command() + { + private static final long serialVersionUID = -7731719556755491679L; + + int otherRats=0; + + private int countOtherRats(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + CardList rats = new CardList(play.getCards()); + rats = rats.getName("Relentless Rats"); + return rats.size()-1; + + } + + public void execute() + { + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + + creature = creature.getName("Relentless Rats"); + + for (int i = 0; i < creature.size(); i++) + { + Card c = creature.get(i); + otherRats = countOtherRats(c); + c.setOtherAttackBoost(otherRats); + c.setOtherDefenseBoost(otherRats); + + }// for inner + }// execute() + + }; + + public static Command Privileged_Position = new Command() + { + private static final long serialVersionUID = -6677858046910868126L; + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList cList = gloriousAnthemList; + Card c; + + for (int i = 0; i < cList.size(); i++) + { + c = cList.get(i); + c.removeExtrinsicKeyword("This card can't be the target of spells or abilities your opponents control."); + } + cList.clear(); + PlayerZone[] zone = getZone("Privileged Position"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList perms = new CardList(zone[outer].getCards()); + + for (int i = 0; i < perms.size(); i++) + { + c = perms.get(i); + if (c.isPermanent() + && !c.getName().equals("Privileged Position") + && !c.getExtrinsicKeyword().contains("This card can't be the target of spells or abilities your opponents control.")) + { + c.addExtrinsicKeyword("This card can't be the target of spells or abilities your opponents control."); + gloriousAnthemList.add(c); + } + + } // for + } // for + + }// execute() + + };//Priviliged_Position + + public static Command Privileged_Position_Other = new Command() + { + private static final long serialVersionUID = -220264241686906985L; + int otherPPs=0; + + private int countOtherPPs(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + CardList pps = new CardList(play.getCards()); + pps = pps.getName("Privileged Position"); + return pps.size()-1; + + } + + public void execute() + { + + + CardList pp = new CardList(); + pp.addAll(AllZone.Human_Play.getCards()); + pp.addAll(AllZone.Computer_Play.getCards()); + + pp = pp.getName("Privileged Position"); + + for (int i = 0; i < pp.size(); i++) + { + Card c = pp.get(i); + otherPPs = countOtherPPs(c); + if (otherPPs > 0) + c.addExtrinsicKeyword("This card can't be the target of spells or abilities your opponents control."); + //else if + }// for inner + }// execute() + + };//Privileged_Position_Other + + + public static Command Elvish_Archdruid_Pump = new Command() + { + + private static final long serialVersionUID = -4549774958203921994L; + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList cList = gloriousAnthemList; + Card c; + + for (int i = 0; i < cList.size(); i++) + { + c = cList.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + } + cList.clear(); + PlayerZone[] zone = getZone("Elvish Archdruid"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Elf"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (c.isCreature() + && !c.getName().equals("Elvish Archdruid")) + { + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + gloriousAnthemList.add(c); + } + + } // for + } // for + + }// execute() + + };//Elvish_Archdruid_Pump + + + public static Command Elvish_Archdruid_Other = new Command() + { + + private static final long serialVersionUID = -8097280193598506523L; + int otherDruids=0; + + private int countOtherDruids(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + CardList druids = new CardList(play.getCards()); + druids = druids.getName("Elvish Archdruid"); + return druids.size()-1; + + } + + public void execute() + { + + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + + creature = creature.getName("Elvish Archdruid"); + + for (int i = 0; i < creature.size(); i++) + { + Card c = creature.get(i); + otherDruids = countOtherDruids(c); + c.setOtherAttackBoost(otherDruids); + c.setOtherDefenseBoost(otherDruids); + + }// for inner + }// execute() + + };//Elvish_Archdruid_Other + + public static Command Wizened_Cenn_Pump = new Command() + { + private static final long serialVersionUID = 542524781150091105L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList cList = gloriousAnthemList; + Card c; + + for (int i = 0; i < cList.size(); i++) + { + c = cList.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + } + cList.clear(); + PlayerZone[] zone = getZone("Wizened Cenn"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Kithkin"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (c.isCreature() + && !c.getName().equals("Wizened Cenn")) + { + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + gloriousAnthemList.add(c); + } + + } // for + } // for + + }// execute() + + };//Wizened_Cenn_Pump + + public static Command Wizened_Cenn_Other = new Command() + { + private static final long serialVersionUID = -7242601069504800797L; + + int otherCenns=0; + + private int countOtherCenns(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + CardList cenns = new CardList(play.getCards()); + cenns = cenns.getName("Wizened Cenn"); + return cenns.size()-1; + + } + + public void execute() + { + + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + + creature = creature.getName("Wizened Cenn"); + + for (int i = 0; i < creature.size(); i++) + { + Card c = creature.get(i); + otherCenns = countOtherCenns(c); + c.setOtherAttackBoost(otherCenns); + c.setOtherDefenseBoost(otherCenns); + + }// for inner + }// execute() + + };//Wizened Cenn Other + + public static Command Elvish_Champion_Pump = new Command() + { + + private static final long serialVersionUID = -2128898623878576243L; + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList cList = gloriousAnthemList; + Card c; + + for (int i = 0; i < cList.size(); i++) + { + c = cList.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + c.removeExtrinsicKeyword("Forestwalk"); + } + cList.clear(); + PlayerZone[] zone = getZone("Elvish Champion"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Elf"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (c.isCreature() + && !c.getName().equals("Elvish Champion")) + { + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + c.addExtrinsicKeyword("Forestwalk"); + gloriousAnthemList.add(c); + } + + } // for + } // for + + }// execute() + + };//Elvish_Champion_Pump + + public static Command Elvish_Champion_Other = new Command() + { + + private static final long serialVersionUID = -8294068492084097409L; + int otherLords=0; + + private int countOtherLords() + { + PlayerZone hPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + PlayerZone cPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList lords = new CardList(); + lords.addAll(hPlay.getCards()); + lords.addAll(cPlay.getCards()); + lords = lords.getName("Elvish Champion"); + return lords.size()-1; + + } + + public void execute() + { + + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + + creature = creature.getName("Elvish Champion"); + + for (int i = 0; i < creature.size(); i++) + { + Card c = creature.get(i); + otherLords = countOtherLords(); + c.setOtherAttackBoost(otherLords); + c.setOtherDefenseBoost(otherLords); + if (!c.getExtrinsicKeyword().contains("Forestwalk") && otherLords > 0) + c.addExtrinsicKeyword("Forestwalk"); + + }// for inner + }// execute() + + };//Elvish_Champion_Other + + + public static Command Goblin_King_Pump = new Command() + { + + private static final long serialVersionUID = -2128898623878576243L; + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList cList = gloriousAnthemList; + Card c; + + for (int i = 0; i < cList.size(); i++) + { + c = cList.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + c.removeExtrinsicKeyword("Mountainwalk"); + } + cList.clear(); + PlayerZone[] zone = getZone("Goblin King"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Goblin"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (c.isCreature() + && !c.getName().equals("Goblin King")) + { + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + c.addExtrinsicKeyword("Mountainwalk"); + gloriousAnthemList.add(c); + } + + } // for + } // for + + }// execute() + + };//Goblin_King_Pump + + public static Command Goblin_King_Other = new Command() + { + + private static final long serialVersionUID = -8294068492084097409L; + int otherLords=0; + + private int countOtherLords() + { + PlayerZone hPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + PlayerZone cPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList lords = new CardList(); + lords.addAll(hPlay.getCards()); + lords.addAll(cPlay.getCards()); + lords = lords.getName("Goblin King"); + return lords.size()-1; + + } + + public void execute() + { + + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + + creature = creature.getName("Goblin King"); + + for (int i = 0; i < creature.size(); i++) + { + Card c = creature.get(i); + otherLords = countOtherLords(); + c.setOtherAttackBoost(otherLords); + c.setOtherDefenseBoost(otherLords); + if (!c.getExtrinsicKeyword().contains("Mountainwalk") && otherLords > 0) + c.addExtrinsicKeyword("Mountainwalk"); + //else if (c.getExtrinsicKeyword().contains("Mountainwalk") && otherLords == 0 ) + + + }// for inner + }// execute() + + };//Goblin_King_Other + + + public static Command Lord_of_Atlantis_Pump = new Command() + { + + private static final long serialVersionUID = -2128898623878576243L; + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList cList = gloriousAnthemList; + Card c; + + for (int i = 0; i < cList.size(); i++) + { + c = cList.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + c.removeExtrinsicKeyword("Islandwalk"); + } + cList.clear(); + PlayerZone[] zone = getZone("Lord of Atlantis"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Merfolk"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (c.isCreature() + && !c.getName().equals("Lord of Atlantis")) + { + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + c.addExtrinsicKeyword("Islandwalk"); + gloriousAnthemList.add(c); + } + + } // for + } // for + + }// execute() + + };//Lord_of_Atlantis_Pump + + public static Command Lord_of_Atlantis_Other = new Command() + { + + private static final long serialVersionUID = -8294068492084097409L; + int otherLords=0; + + private int countOtherLords() + { + PlayerZone hPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + PlayerZone cPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList lords = new CardList(); + lords.addAll(hPlay.getCards()); + lords.addAll(cPlay.getCards()); + lords = lords.getName("Lord of Atlantis"); + return lords.size()-1; + + } + + public void execute() + { + + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + + creature = creature.getName("Lord of Atlantis"); + + for (int i = 0; i < creature.size(); i++) + { + Card c = creature.get(i); + otherLords = countOtherLords(); + c.setOtherAttackBoost(otherLords); + c.setOtherDefenseBoost(otherLords); + if (!c.getExtrinsicKeyword().contains("Islandwalk") && otherLords > 0) + c.addExtrinsicKeyword("Islandwalk"); + + }// for inner + }// execute() + + };//Lord_of_Atlantis_Other + + + public static Command Field_Marshal_Pump = new Command() + { + private static final long serialVersionUID = -2429608928111507712L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList cList = gloriousAnthemList; + Card c; + + for (int i = 0; i < cList.size(); i++) + { + c = cList.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + c.removeExtrinsicKeyword("First Strike"); + } + cList.clear(); + PlayerZone[] zone = getZone("Field Marshal"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Soldier"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (c.isCreature() + && !c.getName().equals("Field Marshal")) + { + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + c.addExtrinsicKeyword("First Strike"); + gloriousAnthemList.add(c); + } + + } // for + } // for + + }// execute() + + };//Field Marshal Pump + + public static Command Field_Marshal_Other = new Command() + { + private static final long serialVersionUID = 8252431904723630691L; + + int otherMarshals=0; + + private int countOtherMarshals() + { + PlayerZone hPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + PlayerZone cPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList marshals = new CardList(); + marshals.addAll(hPlay.getCards()); + marshals.addAll(cPlay.getCards()); + marshals = marshals.getName("Field Marshal"); + return marshals.size()-1; + + } + + public void execute() + { + + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + + creature = creature.getName("Field Marshal"); + + for (int i = 0; i < creature.size(); i++) + { + Card c = creature.get(i); + otherMarshals = countOtherMarshals(); + c.setOtherAttackBoost(otherMarshals); + c.setOtherDefenseBoost(otherMarshals); + if (!c.getExtrinsicKeyword().contains("First Strike") && otherMarshals > 0) + c.addExtrinsicKeyword("First Strike"); + + }// for inner + }// execute() + + };//Field Marshal Other + + public static Command Aven_Brigadier_Soldier_Pump = new Command() + { + private static final long serialVersionUID = -2052700621466065388L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList cList = gloriousAnthemList; + Card c; + + for (int i = 0; i < cList.size(); i++) + { + c = cList.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + } + cList.clear(); + PlayerZone[] zone = getZone("Aven Brigadier"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Soldier"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (c.isCreature() && !c.getName().equals("Aven Brigadier")) + { + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + gloriousAnthemList.add(c); + } + + } // for + } // for + + }// execute() + + };//Aven Brigadier Soldier Pump + + public static Command Aven_Brigadier_Bird_Pump = new Command() + { + private static final long serialVersionUID = 69906668683163765L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList cList = gloriousAnthemList; + Card c; + + for (int i = 0; i < cList.size(); i++) + { + c = cList.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + } + cList.clear(); + PlayerZone[] zone = getZone("Aven Brigadier"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Bird"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (c.isCreature() && !c.getName().equals("Aven Brigadier")) + { + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + gloriousAnthemList.add(c); + } + + } // for + } // for + + }// execute() + + };//Aven Brigadier Bird Pump + + public static Command Aven_Brigadier_Other = new Command() + { + private static final long serialVersionUID = 3214384167995760060L; + + int otherBrigadiers = 0; + + private int countOtherBrigadiers() + { + PlayerZone hPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + PlayerZone cPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList brigadiers = new CardList(); + + brigadiers.addAll(hPlay.getCards()); + brigadiers.addAll(cPlay.getCards()); + brigadiers = brigadiers.getName("Aven Brigadier"); + return brigadiers.size()-1; + + } + + public void execute() + { + + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + + creature = creature.getName("Aven Brigadier"); + + for (int i = 0; i < creature.size(); i++) + { + Card c = creature.get(i); + otherBrigadiers = countOtherBrigadiers(); + c.setOtherAttackBoost(2*otherBrigadiers); + c.setOtherDefenseBoost(2*otherBrigadiers); + }// for inner + }// execute() + + };//brigadiers other + + public static Command Scion_of_Oona_Pump = new Command() + { + private static final long serialVersionUID = 8659017444482040867L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList cList = gloriousAnthemList; + Card c; + + for (int i = 0; i < cList.size(); i++) + { + c = cList.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + c.removeExtrinsicKeyword("Shroud"); + } + cList.clear(); + PlayerZone[] zone = getZone("Scion of Oona"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Faerie"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (c.isCreature() + && !c.getName().equals("Scion of Oona")) + { + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + c.addExtrinsicKeyword("Shroud"); + gloriousAnthemList.add(c); + } + + } // for + } // for + + }// execute() + + };//Scion of Oona Pump + + + public static Command Scion_of_Oona_Other = new Command() + { + private static final long serialVersionUID = -2317464426622768435L; + + int otherScions=0; + + private int countOtherScions(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + CardList scions = new CardList(play.getCards()); + scions = scions.getName("Scion of Oona"); + return scions.size()-1; + + } + + public void execute() + { + + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + + creature = creature.getName("Scion of Oona"); + + for (int i = 0; i < creature.size(); i++) + { + Card c = creature.get(i); + otherScions = countOtherScions(c); + c.setOtherAttackBoost(otherScions); + c.setOtherDefenseBoost(otherScions); + if (!c.getExtrinsicKeyword().contains("Shroud") && otherScions > 0) + c.addExtrinsicKeyword("Shroud"); + + }// for inner + }// execute() + }; //Scion of Oona other + + + public static Command Covetous_Dragon = new Command() + { + private static final long serialVersionUID = -8898010588711890705L; + + int artifacts = 0; + public void execute() + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + + creature = creature.getName("Covetous Dragon"); + + for (int i = 0; i < creature.size(); i++) + { + Card c = creature.get(i); + artifacts = countArtifacts(c); + if (artifacts == 0) + { + AllZone.GameAction.sacrifice(c); + } + } + + }//execute() + + private int countArtifacts(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + CardList artifacts = new CardList(play.getCards()); + artifacts = artifacts.getType("Artifact"); + return artifacts.size(); + } + + + }; + + public static Command Tethered_Griffin = new Command() + { + + private static final long serialVersionUID = 572286202401670996L; + int enchantments = 0; + public void execute() + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + + creature = creature.getName("Tethered Griffin"); + + for (int i = 0; i < creature.size(); i++) + { + Card c = creature.get(i); + enchantments = countEnchantments(c); + if (enchantments == 0) + { + AllZone.GameAction.sacrifice(c); + } + } + + }//execute() + + private int countEnchantments(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + CardList enchantments = new CardList(play.getCards()); + enchantments = enchantments.getType("Enchantment"); + return enchantments.size(); + } + + + }; + + public static Command Zuberi = new Command() + { + private static final long serialVersionUID = -6283266522827930762L; + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList cList = gloriousAnthemList; + Card c; + + for (int i = 0; i < cList.size(); i++) + { + c = cList.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + } + cList.clear(); + PlayerZone[] zone = getZone("Zuberi, Golden Feather"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Griffin"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (c.isCreature() + && !c.getName().equals("Zuberi, Golden Feather")) + { + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + gloriousAnthemList.add(c); + } + + } // for + } // for + + }// execute() + + + }; + + public static Command Master_of_Etherium_Other = new Command() + { + private static final long serialVersionUID = -3325892185484133742L; + + int otherMasters=0; + + private int countOtherMasters(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + CardList masters = new CardList(play.getCards()); + masters = masters.getName("Master of Etherium"); + return masters.size()-1; + + } + + public void execute() + { + + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + + creature = creature.getName("Master of Etherium"); + + for (int i = 0; i < creature.size(); i++) + { + Card c = creature.get(i); + otherMasters = countOtherMasters(c); + c.setOtherAttackBoost(otherMasters); + c.setOtherDefenseBoost(otherMasters); + + }// for inner + }// execute() + }; + + public static Command Master_of_Etherium = new Command() + { + private static final long serialVersionUID = -5406532269375480827L; + + @SuppressWarnings("unused") // gloriousAnthemList + CardList gloriousAnthemList = new CardList(); + + @SuppressWarnings("unused") // otherMasters + int otherMasters=0; + + public void execute() + { + // get all cards + + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Master of Etherium"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + + c.setBaseAttack(countArtifacts(c)); + c.setBaseDefense(c.getBaseAttack()); + + + } + + }// execute() + + private int countArtifacts(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + CardList artifacts = new CardList(play.getCards()); + artifacts = artifacts.getType("Artifact"); + return artifacts.size(); + } + + + };// Master of etherium + + public static Command Master_of_Etherium_Pump = new Command() + { + private static final long serialVersionUID = -1736492817816019320L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + // now, apply the +1/+1 to all other artifacts controlled: + + CardList cList = gloriousAnthemList; + Card c; + + for (int i = 0; i < cList.size(); i++) + { + c = cList.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + } + + // add +1/+1 to cards + cList.clear(); + PlayerZone[] zone = getZone("Master of Etherium"); + + // for each zone found add +1/+1 to each card + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Artifact"); + + for (int i = 0; i < creature.size(); i++) + { + + c = creature.get(i); + if (c.isCreature() + && !c.getName().equals("Master of Etherium")) + { + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + gloriousAnthemList.add(c); + } + + } // for + } // for + + /* + * CardList masters = new CardList(); + * masters.addAll(AllZone.Human_Play.getCards()); + * masters.addAll(AllZone.Computer_Play.getCards()); masters = + * masters.getName("Master of Etherium"); + * + * for (int i=0; i < masters.size(); i++) { c = masters.get(i); int + * otherMasters = countOtherMasters(c); + * System.out.println("otherMasters: " +otherMasters); if + * (otherMasters > 0) { for (int j=0; j < otherMasters; j++) { + * System.out.println("j: " + j + " for card "); + * c.setAttack(c.getAttack() + 1); c.setDefense(c.getDefense() + 1); + * gloriousAnthemList.add(c); } } } + */ + + }// execute() + + @SuppressWarnings("unused") // countArtifacts + private int countArtifacts(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + CardList artifacts = new CardList(play.getCards()); + artifacts = artifacts.getType("Artifact"); + return artifacts.size(); + } + + @SuppressWarnings("unused") // countOtherMasters + private int countOtherMasters(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + CardList masters = new CardList(play.getCards()); + masters = masters.getName("Master of Etherium"); + return masters.size() - 1; + + } + };// Master of etherium pump + + + public static Command Loxodon_Punisher = new Command() + { + + private static final long serialVersionUID = -7746134566580289667L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Loxodon Punisher"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + c.setBaseAttack(countEquipment(c)*2); + c.setBaseDefense(c.getBaseAttack()+1); + } + + }// execute() + + private int countEquipment(Card c) + { + CardList equipment = new CardList(c.getEquippedBy().toArray()); + return equipment.size(); + } + }; + + public static Command Rabid_Wombat = new Command() + { + + private static final long serialVersionUID = -7746134566580289667L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Rabid Wombat"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + c.setBaseAttack(countAuras(c)*2); + c.setBaseDefense(c.getBaseAttack()+1); + } + + }// execute() + + private int countAuras(Card c) + { + CardList auras = new CardList(c.getEnchantedBy().toArray()); + return auras.size(); + } + }; + + public static Command Uril = new Command() + { + private static final long serialVersionUID = 8168928048322850517L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Uril, the Miststalker"); + + if (list.size() > 0) + { + Card c = list.get(0); + c.setBaseAttack(countAuras(c)*2); + c.setBaseDefense(c.getBaseAttack()+1); + } + + }// execute() + + private int countAuras(Card c) + { + CardList auras = new CardList(c.getEnchantedBy().toArray()); + return auras.size(); + } + }; + + + public static Command Kithkin_Rabble = new Command() + { + private static final long serialVersionUID = 6686690505949642328L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Kithkin Rabble"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + c.setBaseAttack(countWhitePermanents(c)); + c.setBaseDefense(c.getBaseAttack()); + } + + }// execute() + + private int countWhitePermanents(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + CardList whitePermanents = new CardList(play.getCards()); + whitePermanents = whitePermanents.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return CardUtil.getColors(c).contains(Constant.Color.White); + } + + }); + return whitePermanents.size(); + } + }; + + public static Command Nightmare = new Command() + { + private static final long serialVersionUID = 1987511205573387864L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Nightmare"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + c.setBaseAttack(countSwamps(c)); + c.setBaseDefense(c.getBaseAttack()); + } + + }// execute() + + private int countSwamps(Card c) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c + .getController()); + CardList swamps = new CardList(play.getCards()); + swamps = swamps.getType("Swamp"); + return swamps.size(); + } + }; + + public static Command Aven_Trailblazer = new Command() + { + private static final long serialVersionUID = 2731050781896531776L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Aven Trailblazer"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + c.setBaseDefense(countLandTypes(c)); + } + + }// execute() + + int countLandTypes(Card card) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList land = new CardList(play.getCards()); + + String basic[] = {"Forest", "Plains", "Mountain", "Island", "Swamp"}; + int count = 0; + + for(int i = 0; i < basic.length; i++) + { + CardList c = land.getType(basic[i]); + if(! c.isEmpty()) + count++; + } + return count; + } + }; + + public static Command Rakdos_Pit_Dragon = new Command() + { + private static final long serialVersionUID = -8778900687347191964L; + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Rakdos Pit Dragon"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + if (hellbent(c.getController()) && !c.getIntrinsicKeyword().contains("Double Strike")) + c.addIntrinsicKeyword("Double Strike"); + else if (!hellbent(c.getController()) && c.getIntrinsicKeyword().contains("Double Strike")) + c.removeIntrinsicKeyword("Double Strike"); + } + } + private boolean hellbent(String player) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player); + + CardList list = new CardList(); + list.addAll(hand.getCards()); + + return list.size() == 0; + } + + };//Rakdos Pit Dragon + + public static Command Nyxathid = new Command() + { + + private static final long serialVersionUID = -8778900687347191964L; + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Nyxathid"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + int pt = 7 - countCards(AllZone.GameAction.getOpponent(c.getController())); + c.setBaseAttack(pt); + c.setBaseDefense(pt); + } + } + private int countCards(String player) + { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player); + + CardList list = new CardList(); + list.addAll(hand.getCards()); + + return list.size(); + } + + };//Nyxathid + + + public static Command Lord_of_Extinction = new Command() + { + private static final long serialVersionUID = -8778900687347191964L; + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Lord of Extinction"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + c.setBaseAttack(countCards()); + c.setBaseDefense(c.getBaseAttack()); + } + } + private int countCards() + { + PlayerZone compGrave = AllZone.getZone(Constant.Zone.Graveyard, Constant.Player.Computer); + PlayerZone humGrave = AllZone.getZone(Constant.Zone.Graveyard, Constant.Player.Human); + CardList list = new CardList(); + list.addAll(compGrave.getCards()); + list.addAll(humGrave.getCards()); + + return list.size(); + } + + };//Lord of Extinction + + + + public static Command Terravore = new Command() + { + private static final long serialVersionUID = -7848248012651247059L; + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Terravore"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + c.setBaseAttack(countLands()); + c.setBaseDefense(c.getBaseAttack()); + } + } + private int countLands() + { + PlayerZone compGrave = AllZone.getZone(Constant.Zone.Graveyard, Constant.Player.Computer); + PlayerZone humGrave = AllZone.getZone(Constant.Zone.Graveyard, Constant.Player.Human); + CardList list = new CardList(); + list.addAll(compGrave.getCards()); + list.addAll(humGrave.getCards()); + + list = list.filter(new CardListFilter(){ + public boolean addCard(Card c) { + return c.isLand(); + } + }); + + return list.size(); + } + + };//terravore + + public static Command Magnivore = new Command() + { + + private static final long serialVersionUID = 6569701555927133445L; + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Magnivore"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + c.setBaseAttack(countSorcs()); + c.setBaseDefense(c.getBaseAttack()); + } + } + private int countSorcs() + { + PlayerZone compGrave = AllZone.getZone(Constant.Zone.Graveyard, Constant.Player.Computer); + PlayerZone humGrave = AllZone.getZone(Constant.Zone.Graveyard, Constant.Player.Human); + CardList list = new CardList(); + list.addAll(compGrave.getCards()); + list.addAll(humGrave.getCards()); + + list = list.filter(new CardListFilter(){ + public boolean addCard(Card c) { + return c.isSorcery(); + } + }); + + return list.size(); + } + + };//magnivore + + public static Command Tarmogoyf = new Command() + { + private static final long serialVersionUID = 5895665460018262987L; + + public void execute() + { + // get all creatures + CardList list = new CardList(); + list.addAll(AllZone.Human_Play.getCards()); + list.addAll(AllZone.Computer_Play.getCards()); + list = list.getName("Tarmogoyf"); + + for (int i = 0; i < list.size(); i++) + { + Card c = list.get(i); + c.setBaseAttack(countDiffTypes()); + c.setBaseDefense(c.getBaseAttack()+1); + } + + }// execute() + + private int countDiffTypes() + { + PlayerZone compGrave = AllZone.getZone(Constant.Zone.Graveyard, Constant.Player.Computer); + PlayerZone humGrave = AllZone.getZone(Constant.Zone.Graveyard, Constant.Player.Human); + CardList list = new CardList(); + list.addAll(compGrave.getCards()); + list.addAll(humGrave.getCards()); + + int count = 0; + for (int q=0;q= 7) { + c = creature.get(j); + c.addSemiPermanentAttackBoost(5); + c.addSemiPermanentDefenseBoost(5); + gloriousAnthemList.add(c); + } + + + }// for inner + }// for outer + }// execute() + };// Spidersilk Armor + + public static Command Spidersilk_Armor = new Command() + { + + private static final long serialVersionUID = -1151510755451414602L; + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword("Reach"); + c.addSemiPermanentDefenseBoost(-1); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Spidersilk Armor"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Creature"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword("Reach"); + c.addSemiPermanentDefenseBoost(1); + gloriousAnthemList.add(c); + + + }// for inner + }// for outer + }// execute() + };// Spidersilk Armor + + public static Command Eldrazi_Monument = new Command() + { + + private static final long serialVersionUID = -3591110487441151195L; + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.removeExtrinsicKeyword("Flying"); + c.removeExtrinsicKeyword("Indestructible"); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + } + + // add +1/+1 to cards + list.clear(); + PlayerZone[] zone = getZone("Eldrazi Monument"); + + for (int outer = 0; outer < zone.length; outer++) + { + CardList creature = new CardList(zone[outer].getCards()); + creature = creature.getType("Creature"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + c.addExtrinsicKeyword("Flying"); + c.addExtrinsicKeyword("Indestructible"); + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + gloriousAnthemList.add(c); + + + }// for inner + }// for outer + }// execute() + };// Eldrazi_Monument + + + + public static Command Shared_Triumph = new Command() + { + private static final long serialVersionUID = -6427402366896716659L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + } + + list.clear(); + CardList cards = new CardList(); + cards.addAll(AllZone.Human_Play.getCards()); + cards.addAll(AllZone.Computer_Play.getCards()); + cards = cards.getName("Shared Triumph"); + + for (int outer = 0; outer < cards.size(); outer++) + { + Card card = cards.get(outer); + + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType(card.getChosenType()); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if(c.getType().contains(card.getChosenType()) || c.getKeyword().contains("Changeling")) + { + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + gloriousAnthemList.add(c); + } + + + }// for inner + }// for outer + }// execute() + }; //Shared Triumph + + + public static Command Thelonite_Hermit = new Command() + { + private static final long serialVersionUID = 1876182498187900500L; + + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(-1); + c.addSemiPermanentDefenseBoost(-1); + + } + + // add +1/+1 to black cards + list.clear(); + PlayerZone[] zone = getZone("Thelonite Hermit"); + + // for each zone found add +1/+1 to each black card + for (int outer = 0; outer < zone.length; outer++) + { + // CardList creature = new CardList(zone[outer].getCards()); + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Creature"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if (c.getType().contains("Saproling")) + { + c.addSemiPermanentAttackBoost(1); + c.addSemiPermanentDefenseBoost(1); + + gloriousAnthemList.add(c); + + } + + + }// for inner + }// for outer + }// execute() + };// Thelonite Hermit + + + + public static Command Muraganda_Petroglyphs = new Command() + { + private static final long serialVersionUID = -6715848091817213517L; + CardList gloriousAnthemList = new CardList(); + + public void execute() + { + CardList list = gloriousAnthemList; + Card c; + // reset all cards in list - aka "old" cards + for (int i = 0; i < list.size(); i++) + { + c = list.get(i); + c.addSemiPermanentAttackBoost(-2); + c.addSemiPermanentDefenseBoost(-2); + } + + // add +2/+2 to vanilla cards + list.clear(); + PlayerZone[] zone = getZone("Muraganda Petroglyphs"); + + // for each zone found add +2/+2 to each vanilla card + for (int outer = 0; outer < zone.length; outer++) + { + // CardList creature = new CardList(zone[outer].getCards()); + CardList creature = new CardList(); + creature.addAll(AllZone.Human_Play.getCards()); + creature.addAll(AllZone.Computer_Play.getCards()); + creature = creature.getType("Creature"); + + for (int i = 0; i < creature.size(); i++) + { + c = creature.get(i); + if ((c.getText().equals("") && c.getKeyword().size() == 0) || c.isFaceDown()) + { + c.addSemiPermanentAttackBoost(2); + c.addSemiPermanentDefenseBoost(2); + + gloriousAnthemList.add(c); + } + + + }// for inner + }// for outer + }// execute() + };// Muraganda_Petroglyphs + + // returns all PlayerZones that has at least 1 Glorious Anthem + // if Computer has 2 Glorious Anthems, AllZone.Computer_Play will be + // returned twice + private static PlayerZone[] getZone(String cardName) + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + ArrayList zone = new ArrayList(); + for (int i = 0; i < all.size(); i++) + if (all.get(i).getName().equals(cardName) && !all.get(i).isFaceDown()) + zone.add(AllZone.getZone(all.get(i))); + + PlayerZone[] z = new PlayerZone[zone.size()]; + zone.toArray(z); + return z; + } + + public static HashMap commands = new HashMap(); + static { + commands.put("Conspiracy", Conspiracy); + commands.put("Serra_Avatar", Serra_Avatar); + commands.put("Ajani_Avatar_Token", Ajani_Avatar_Token); + commands.put("Windwright_Mage", Windwright_Mage); + + //commands.put("Baru", Baru); + //commands.put("Reach_of_Branches", Reach_of_Branches); + + //commands.put("Essence_Warden", Essence_Warden); + //commands.put("Soul_Warden", Soul_Warden); + //commands.put("Wirewood_Hivemaster", Wirewood_Hivemaster); + //commands.put("Angelic_Chorus", Angelic_Chorus); + + commands.put("Uril", Uril); + commands.put("Rabid_Wombat", Rabid_Wombat); + commands.put("Kithkin_Rabble", Kithkin_Rabble); + commands.put("Nightmare", Nightmare); + commands.put("Aven_Trailblazer", Aven_Trailblazer); + commands.put("Rakdos_Pit_Dragon", Rakdos_Pit_Dragon); + commands.put("Nyxathid", Nyxathid); + commands.put("Lord_of_Extinction", Lord_of_Extinction); + commands.put("Terravore", Terravore); + commands.put("Magnivore", Magnivore); + commands.put("Tarmogoyf", Tarmogoyf); + commands.put("Dakkon", Dakkon); + commands.put("Korlash", Korlash); + + commands.put("Dauntless_Dourbark", Dauntless_Dourbark); + commands.put("Vexing_Beetle", Vexing_Beetle); + commands.put("Kird_Ape", Kird_Ape); + commands.put("Sedge_Troll", Sedge_Troll); + commands.put("Hedge_Troll", Hedge_Troll); + commands.put("Wild_Nacatl", Wild_Nacatl); + commands.put("Liu_Bei", Liu_Bei); + commands.put("Mystic_Enforcer", Mystic_Enforcer); + commands.put("Bant_Sureblade", Bant_Sureblade); + commands.put("Esper_Stormblade", Esper_Stormblade); + commands.put("Grixis_Grimblade", Grixis_Grimblade); + commands.put("Jund_Hackblade", Jund_Hackblade); + commands.put("Naya_Hushblade", Naya_Hushblade); + commands.put("Nimble_Mongoose", Nimble_Mongoose); + commands.put("Werebear", Werebear); + commands.put("Divinity_of_Pride", Divinity_of_Pride); + commands.put("Yavimaya_Enchantress", Yavimaya_Enchantress); + commands.put("Knight_of_the_Reliquary", Knight_of_the_Reliquary); + commands.put("Zuberi", Zuberi); + commands.put("Master_of_Etherium", Master_of_Etherium); + commands.put("Master_of_Etherium_Pump", Master_of_Etherium_Pump); + commands.put("Master_of_Etherium_Other", Master_of_Etherium_Other); + commands.put("Relentless_Rats_Other", Relentless_Rats_Other); + commands.put("Privileged_Position", Privileged_Position); + commands.put("Privileged_Position_Other", Privileged_Position_Other); + commands.put("Elvish_Archdruid_Pump", Elvish_Archdruid_Pump); + commands.put("Elvish_Archdruid_Other", Elvish_Archdruid_Other); + commands.put("Elvish_Champion_Pump", Elvish_Champion_Pump); + commands.put("Elvish_Champion_Other", Elvish_Champion_Other); + commands.put("Wizened_Cenn_Pump", Wizened_Cenn_Pump); + commands.put("Wizened_Cenn_Other", Wizened_Cenn_Other); + commands.put("Lord_of_Atlantis_Pump", Lord_of_Atlantis_Pump); + commands.put("Lord_of_Atlantis_Other", Lord_of_Atlantis_Other); + commands.put("Goblin_King_Pump", Goblin_King_Pump); + commands.put("Goblin_King_Other", Goblin_King_Other); + commands.put("Field_Marshal_Pump", Field_Marshal_Pump); + commands.put("Field_Marshal_Other", Field_Marshal_Other); + commands.put("Aven_Brigadier_Soldier_Pump", Aven_Brigadier_Soldier_Pump); + commands.put("Aven_Brigadier_Bird_Pump", Aven_Brigadier_Bird_Pump); + commands.put("Aven_Brigadier_Other", Aven_Brigadier_Other); + commands.put("Scion_of_Oona_Pump", Scion_of_Oona_Pump); + commands.put("Scion_of_Oona_Other", Scion_of_Oona_Other); + + commands.put("Covetous_Dragon", Covetous_Dragon); + commands.put("Tethered_Griffin", Tethered_Griffin); + + commands.put("Shared_Triumph", Shared_Triumph); + commands.put("Crucible_of_Fire", Crucible_of_Fire); + commands.put("Glorious_Anthem", Glorious_Anthem); + commands.put("Gaeas_Anthem", Gaeas_Anthem); + commands.put("Bad_Moon", Bad_Moon); + commands.put("Crusade", Crusade); + commands.put("Honor_of_the_Pure", Honor_of_the_Pure); + commands.put("Beastmaster_Ascension", Beastmaster_Ascension); + commands.put("Spidersilk_Armor", Spidersilk_Armor); + commands.put("Eldrazi_Monument", Eldrazi_Monument); + commands.put("Muraganda_Petroglyphs", Muraganda_Petroglyphs); + + commands.put("Engineered_Plague", Engineered_Plague); + commands.put("Night_of_Souls_Betrayal", Night_of_Souls_Betrayal); + + commands.put("Thelonite_Hermit", Thelonite_Hermit); + commands.put("Jacques", Jacques); + commands.put("Kaysa", Kaysa); + commands.put("Meng_Huo", Meng_Huo); + commands.put("Eladamri", Eladamri); + commands.put("Tolsimir", Tolsimir); + commands.put("Imperious_Perfect", Imperious_Perfect); + commands.put("Mad_Auntie", Mad_Auntie); + + commands.put("Veteran_Armorer", Veteran_Armorer); + commands.put("Radiant_Archangel", Radiant_Archangel); + commands.put("Castle", Castle); + commands.put("Castle_Raptors", Castle_Raptors); + + commands.put("Mobilization", Mobilization); + commands.put("Serras_Blessing", Serras_Blessing); + commands.put("Cover_of_Darkness", Cover_of_Darkness); + commands.put("Steely_Resolve", Steely_Resolve); + commands.put("Concordant_Crossroads", Concordant_Crossroads); + commands.put("Mass_Hysteria", Mass_Hysteria); + commands.put("Fervor", Fervor); + commands.put("Madrush_Cyclops", Madrush_Cyclops); + + commands.put("Sun_Quan", Sun_Quan); + + commands.put("Rolling_Stones", Rolling_Stones); + commands.put("Kobold_Overlord", Kobold_Overlord); + commands.put("Kinsbaile_Cavalier", Kinsbaile_Cavalier); + commands.put("Wrens_Run_Packmaster", Wrens_Run_Packmaster); + + commands.put("Sliver_Legion", Sliver_Legion); + commands.put("Muscle_Sliver", Muscle_Sliver); + + commands.put("Bonesplitter_Sliver", Bonesplitter_Sliver); + commands.put("Might_Sliver", Might_Sliver); + commands.put("Watcher_Sliver", Watcher_Sliver); + + commands.put("Winged_Sliver", Winged_Sliver); + commands.put("Synchronous_Sliver", Synchronous_Sliver); + commands.put("Fury_Sliver", Fury_Sliver); + commands.put("Plated_Sliver", Plated_Sliver); + commands.put("Crystalline_Sliver", Crystalline_Sliver); + commands.put("Sidewinder_Sliver", Sidewinder_Sliver); + commands.put("Essence_Sliver", Essence_Sliver); + commands.put("Sinew_Sliver", Sinew_Sliver); + commands.put("Horned_Sliver", Horned_Sliver); + + commands.put("Heart_Sliver", Heart_Sliver); + commands.put("Reflex_Sliver", Reflex_Sliver); + commands.put("Gemhide_Sliver", Gemhide_Sliver); + + commands.put("Blade_Sliver", Blade_Sliver); + commands.put("Battering_Sliver", Battering_Sliver); + + commands.put("Marrow_Gnawer", Marrow_Gnawer); + + commands.put("Joiner_Adept", Joiner_Adept); + System.out.println("size of commands: " + commands.size()); + + } + +} \ No newline at end of file diff --git a/src/GenerateConstructedDeck.java b/src/GenerateConstructedDeck.java new file mode 100644 index 00000000000..0149be111d7 --- /dev/null +++ b/src/GenerateConstructedDeck.java @@ -0,0 +1,297 @@ +import java.util.*; + +public class GenerateConstructedDeck +{ + private String color1; + private String color2; + + private Map map = new HashMap(); + + public GenerateConstructedDeck() {setupMap();} + + private void setupMap() + { + map.put(Constant.Color.Black , "Swamp"); + map.put(Constant.Color.Blue , "Island"); + map.put(Constant.Color.Green , "Forest"); + map.put(Constant.Color.Red , "Mountain"); + map.put(Constant.Color.White , "Plains"); + } + + public CardList generateDeck() + { + CardList deck; + + int check; + + do{ + deck = get2ColorDeck(); + check = deck.getType("Creature").size(); + + }while(check < 16 || 24 < check); + + addLand(deck); + + if(deck.size() != 60) + throw new RuntimeException("GenerateConstructedDeck() : generateDeck() error, deck size it not 60, deck size is " +deck.size()); + + return deck; + } + //25 lands + private void addLand(CardList list) + { + Card land; + for(int i = 0; i < 13; i++) + { + land = AllZone.CardFactory.getCard(map.get(color1).toString(), Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(map.get(color2).toString(), Constant.Player.Computer); + list.add(land); + } + }//addLand() + private CardList getCards() + { + return filterBadCards(AllZone.CardFactory.getAllCards()); + }//getCards() + private CardList get2ColorDeck() + { + CardList deck = get2Colors(getCards()); + + CardList out = new CardList(); + deck.shuffle(); + + //trim deck size down to 34 cards, presumes 26 land, for a total of 60 cards + for(int i = 0; i < 34 && i < deck.size(); i++) + out.add(deck.get(i)); + + return out; + } + private CardList get2Colors(CardList in) + { + int a; + int b; + + do{ + a = CardUtil.getRandomIndex(Constant.Color.onlyColors); + b = CardUtil.getRandomIndex(Constant.Color.onlyColors); + }while(a == b);//do not want to get the same color twice + + color1 = Constant.Color.onlyColors[a]; + color2 = Constant.Color.onlyColors[b]; + + CardList out = new CardList(); + out.addAll(CardListUtil.getColor(in, color1).toArray()); + out.addAll(CardListUtil.getColor(in, color2).toArray()); + out.shuffle(); + + CardList artifact = in.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + //is this really a colorless artifact and not something + //wierd like Sarcomite Myr which is a colored artifact + return c.isArtifact() && + CardUtil.getColors(c).contains(Constant.Color.Colorless) && + !Gui_NewGame.removeArtifacts.isSelected(); + } + }); + out.addAll(artifact.toArray()); + + out = out.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if(c.isCreature() && + c.getNetAttack() <= 1 && + Gui_NewGame.removeSmallCreatures.isSelected()) + { + return false; + } + + return true; + } + }); + + out = filterBadCards(out); + return out; + } + + private CardList filterBadCards(CardList list) + { + //remove "bad" and multi-colored cards + final ArrayList remove = new ArrayList(); + remove.add("Sarcomite Myr"); + remove.add("Force of Savagery"); + remove.add("Darksteel Colossus"); + remove.add("Jokulhaups"); + remove.add("Steel Wall"); + remove.add("Ornithopter"); + remove.add("Amnesia"); + remove.add("Battle of Wits"); + remove.add("Ashes to Ashes"); + remove.add("Haunted Angel"); + remove.add("Sky Swallower"); + remove.add("Magus of the Library"); + remove.add("The Unspeakable"); + remove.add("Wall of Kelp"); + + remove.add("Incendiary Command"); + remove.add("Memnarch"); + remove.add("Plague Wind"); + remove.add("Klaas, Elf Friend"); + remove.add("Delirium Skeins"); + + remove.add("Undying Beast"); + remove.add("Wit's End"); + + remove.add("Blinding Light"); + remove.add("Hymn to Tourach"); + + //not fully implemented: + + remove.add("Aether Membrane"); + remove.add("Arashi, the Sky Asunder"); + remove.add("Hand of Cruelty"); + remove.add("Hand of Honor"); + + //useless, or combo cards: + + remove.add("Aluren"); + remove.add("Conspiracy"); + remove.add("Crucible of Fire"); + remove.add("Verduran Enchantress"); + remove.add("Enchantress's Presence"); + remove.add("Mesa Enchantress"); + remove.add("Moat"); + remove.add("Magus of the Moat"); + remove.add("Relentless Rats"); + remove.add("Vedalken Archmage"); + remove.add("Hatching Plans"); + remove.add("Sensation Gorger"); + + //semi useless + + remove.add("Wren's Run Packmaster"); + remove.add("Nova Chaser"); + remove.add("Supreme Exemplar"); + remove.add("Goblin Ringleader"); + remove.add("Sylvan Messenger"); + remove.add("Tromp the Domains"); + remove.add("Legacy Weapon"); + + //cards the AI cannot play (effectively): + + remove.add("Sensei's Divining Top"); + remove.add("Standstill"); + //remove.add("Counterspell"); + //remove.add("Exclude"); + //remove.add("False Summoning"); + //remove.add("Essence Scatter"); + //remove.add("Preemptive Strike"); + //remove.add("Punish Ignorance"); + //remove.add("Remand"); + //remove.add("Mystic Snake"); + //remove.add("Absorb"); + //remove.add("Undermine"); + //remove.add("Overwhelming Intellect"); + remove.add("AEther Vial"); + remove.add("Covetous Dragon"); + remove.add("Terramorphic Expanse"); + remove.add("Earthcraft"); + remove.add("Burst of Speed"); + remove.add("Magnify"); + remove.add("Nature's Cloak"); + remove.add("Resuscitate"); + remove.add("Shield Wall"); + remove.add("Solidarity"); + remove.add("Steadfastness"); + remove.add("Tortoise Formation"); + + //manapool stuff: + remove.add("Dark Ritual"); + remove.add("Seething Song"); + remove.add("Sol Ring"); + remove.add("Gaea's Cradle"); + remove.add("Priest of Titania"); + remove.add("Tolarian Academy"); + remove.add("Serra's Sanctum"); + remove.add("Basalt Monolith"); + remove.add("Grim Monolith"); + remove.add("Black Lotus"); + remove.add("Composite Golem"); + remove.add("Thran Dynamo"); + remove.add("Elvish Archdruid"); + remove.add("Sunglasses of Urza"); + remove.add("Ceta Discple"); + remove.add("Agent of Stromgald"); + remove.add("Apprentice Wizard"); + remove.add("Azorius Signet"); + remove.add("Bog Initiate"); + remove.add("Boros Signet"); + remove.add("Celestial Prism"); + remove.add("Dimir Signet"); + remove.add("Fire Sprites"); + remove.add("Fyndhorn Elder"); + remove.add("Gilded Lotus"); + remove.add("Golgari Signet"); + remove.add("Greenweaver Druid"); + remove.add("Gruul Signet"); + remove.add("Helionaut"); + remove.add("Izzet Signet"); + remove.add("Knotvine Mystic"); + remove.add("Mana Cylix"); + remove.add("Mana Prism"); + remove.add("Nantuko Elder"); + remove.add("Nomadic Elf"); + remove.add("Orochi Leafcaller"); + remove.add("Orzhov Signet"); + remove.add("Prismatic Lens"); + remove.add("Rakdos Signet"); + remove.add("Sea Scryer"); + remove.add("Selesnya Signet"); + remove.add("Simic Signet"); + remove.add("Sisay's Ring"); + remove.add("Skyshroud Elf"); + remove.add("Ur-Golem's Eye"); + remove.add("Viridian Acolyte"); + remove.add("Worn Powerstone"); + + + final ArrayList goodLand = new ArrayList(); + //goodLand.add("Faerie Conclave"); + //goodLand.add("Forbidding Watchtower"); + //goodLand.add("Treetop Village"); + + CardList out = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + ArrayList list = CardUtil.getColors(c); + if (list.size() == 2) + { + if (!(list.contains(color1) && list.contains(color2))) + return false; + } + return CardUtil.getColors(c).size() <= 2 && //only dual colored gold cards + !c.isLand() && //no land + !remove.contains(c.getName()) || //OR very important + goodLand.contains(c.getName()); + } + }); + + return out; + }//filterBadCards() + public static void main(String[] args) + { + GenerateConstructedDeck g = new GenerateConstructedDeck(); + + for(int i = 0; i < 50; i++) + { + CardList c = g.generateDeck(); + System.out.println(c.getType("Creature").size() +" - " +c.size()); + } + System.exit(1); + + }//main +} \ No newline at end of file diff --git a/src/GenerateConstructedMultiColorDeck.java b/src/GenerateConstructedMultiColorDeck.java new file mode 100644 index 00000000000..7bb4bd886f4 --- /dev/null +++ b/src/GenerateConstructedMultiColorDeck.java @@ -0,0 +1,557 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class GenerateConstructedMultiColorDeck +{ + private String color1; + private String color2; + private String color3; + private String color4; + private String color5; + + private Map map = new HashMap(); + private Map multiMap = new HashMap(); + + public GenerateConstructedMultiColorDeck() + { + setupBasicLandMap(); + setupMultiMap(); + } + + private void setupBasicLandMap() + { + map.put(Constant.Color.Black , "Swamp"); + map.put(Constant.Color.Blue , "Island"); + map.put(Constant.Color.Green , "Forest"); + map.put(Constant.Color.Red , "Mountain"); + map.put(Constant.Color.White , "Plains"); + } + + private void setupMultiMap() + { + multiMap.put(Constant.Color.Black + Constant.Color.Blue, new String[] {"Underground Sea", "Watery Grave"}); + multiMap.put(Constant.Color.Black + Constant.Color.Green, new String[] {"Bayou", "Overgrown Tomb"}); + multiMap.put(Constant.Color.Black + Constant.Color.Red , new String[]{"Badlands", "Blood Crypt"}); + multiMap.put(Constant.Color.Black + Constant.Color.White, new String[] {"Scrubland", "Godless Shrine"}); + multiMap.put(Constant.Color.Blue + Constant.Color.Black, new String[] {"Underground Sea", "Watery Grave"}); + multiMap.put(Constant.Color.Blue + Constant.Color.Green, new String[] {"Tropical Island", "Breeding Pool"}); + multiMap.put(Constant.Color.Blue +Constant.Color.Red, new String[]{"Volcanic Island", "Steam Vents"}); + multiMap.put(Constant.Color.Blue +Constant.Color.White, new String[] {"Tundra", "Hallowed Fountain"}); + multiMap.put(Constant.Color.Green +Constant.Color.Black, new String[] {"Bayou", "Overgrown Tomb"}); + multiMap.put(Constant.Color.Green +Constant.Color.Blue, new String[] {"Tropical Island", "Breeding Pool"}); + multiMap.put(Constant.Color.Green +Constant.Color.Red , new String[]{"Taiga", "Stomping Ground"}); + multiMap.put(Constant.Color.Green +Constant.Color.White, new String[] {"Savannah", "Temple Garden"}); + multiMap.put(Constant.Color.Red +Constant.Color.Black, new String[] {"Badlands", "Blood Crypt"}); + multiMap.put(Constant.Color.Red +Constant.Color.Blue, new String[] {"Volcanic Island", "Steam Vents"}); + multiMap.put(Constant.Color.Red +Constant.Color.Green, new String[]{"Taiga", "Stomping Ground"}); + multiMap.put(Constant.Color.Red +Constant.Color.White, new String[] {"Plateau", "Sacred Foundry"}); + multiMap.put(Constant.Color.White +Constant.Color.Black, new String[] {"Scrubland", "Godless Shrine"}); + multiMap.put(Constant.Color.White +Constant.Color.Blue, new String[] {"Tundra", "Hallowed Fountain"}); + multiMap.put(Constant.Color.White +Constant.Color.Green, new String[]{"Savannah", "Temple Garden"}); + multiMap.put(Constant.Color.White +Constant.Color.Red , new String[] {"Plateau", "Sacred Foundry"}); + } + + + public CardList generate3ColorDeck() + { + CardList deck; + + int check; + + do{ + deck = get3ColorDeck(); + check = deck.getType("Creature").size(); + + }while(check < 16 || 24 < check); + + addLand(deck, 3); + + if(deck.size() != 60) + throw new RuntimeException("GenerateConstructedDeck() : generateDeck() error, deck size it not 60, deck size is " +deck.size()); + + return deck; + } + + public CardList generate5ColorDeck() + { + CardList deck; + + /* + int check; + + do{ + deck = get5ColorDeck(); + check = deck.getType("Creature").size(); + + }while(check < 15 || 25 < check); + */ + + deck = get5ColorDeck(); + + addLand(deck, 5); + + if(deck.size() != 61) + throw new RuntimeException("GenerateConstructedDeck() : generateDeck() error, deck size it not 60, deck size is " +deck.size()); + + return deck; + } + + private void addLand(CardList list, int colors) + { + if (colors==3) + { + int numberBasic = 2; + Card land; + for(int i = 0; i < numberBasic; i++) + { + + land = AllZone.CardFactory.getCard(map.get(color1).toString(), Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(map.get(color2).toString(), Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(map.get(color3).toString(), Constant.Player.Computer); + list.add(land); + } + + int numberDual = 4; + for (int i = 0; i < numberDual;i++) + { + land = AllZone.CardFactory.getCard(multiMap.get(color1+color2)[0], Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(multiMap.get(color1+color3)[0], Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(multiMap.get(color2+color3)[0], Constant.Player.Computer); + list.add(land); + } + for (int i=0; i<2;i++) + { + land = AllZone.CardFactory.getCard(multiMap.get(color1+color2)[1], Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(multiMap.get(color1+color3)[1], Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(multiMap.get(color2+color3)[1], Constant.Player.Computer); + list.add(land); + } + } + else if (colors == 5) + { + int numberBasic = 1; + Card land; + for(int i = 0; i < numberBasic; i++) + { + + land = AllZone.CardFactory.getCard(map.get(color1).toString(), Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(map.get(color2).toString(), Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(map.get(color3).toString(), Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(map.get(color4).toString(), Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(map.get(color5).toString(), Constant.Player.Computer); + list.add(land); + } + + + int numberDual = 2; + for (int i = 0; i < numberDual;i++) + { + land = AllZone.CardFactory.getCard(multiMap.get(color1+color2)[0], Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(multiMap.get(color1+color3)[0], Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(multiMap.get(color1+color4)[0], Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(multiMap.get(color1+color5)[0], Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(multiMap.get(color2+color3)[0], Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(multiMap.get(color2+color4)[0], Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(multiMap.get(color2+color5)[0], Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(multiMap.get(color3+color4)[0], Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(multiMap.get(color3+color5)[0], Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(multiMap.get(color4+color5)[0], Constant.Player.Computer); + list.add(land); + } + + } + }//addLand() + private CardList getCards(int colors) + { + return filterBadCards(AllZone.CardFactory.getAllCards(), colors); + }//getCards() + + private CardList get3ColorDeck() + { + CardList deck = get3Colors(getCards(3)); + + CardList out = new CardList(); + deck.shuffle(); + + //trim deck size down to 36 cards, presumes 24 land, for a total of 60 cards + for(int i = 0; i < 36 && i < deck.size(); i++) + out.add(deck.get(i)); + + return out; + } + + private CardList get5ColorDeck() + { + CardList deck = get5Colors(getCards(5)); + + CardList out = new CardList(); + deck.shuffle(); + + //trim deck size down to 36 cards, presumes 24 land, for a total of 60 cards + for(int i = 0; i < 36 && i < deck.size(); i++) + out.add(deck.get(i)); + + return out; + } + + private CardList get3Colors(CardList in) + { + int a; + int b; + int c; + + a = CardUtil.getRandomIndex(Constant.Color.onlyColors); + do{ + b = CardUtil.getRandomIndex(Constant.Color.onlyColors); + c = CardUtil.getRandomIndex(Constant.Color.onlyColors); + }while(a == b || a == c || b == c );//do not want to get the same color thrice + + color1 = Constant.Color.onlyColors[a]; + color2 = Constant.Color.onlyColors[b]; + color3 = Constant.Color.onlyColors[c]; + + CardList out = new CardList(); + out.addAll(CardListUtil.getColor(in, color1).toArray()); + out.addAll(CardListUtil.getColor(in, color2).toArray()); + out.addAll(CardListUtil.getColor(in, color3).toArray()); + out.shuffle(); + + CardList artifact = in.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + //is this really a colorless artifact and not something + //wierd like Sarcomite Myr which is a colored artifact + return c.isArtifact() && + CardUtil.getColors(c).contains(Constant.Color.Colorless) && + !Gui_NewGame.removeArtifacts.isSelected(); + } + }); + out.addAll(artifact.toArray()); + + out = out.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if(c.isCreature() && + c.getNetAttack() <= 1 && + Gui_NewGame.removeSmallCreatures.isSelected()) + { + return false; + } + + return true; + } + }); + + out = filterBadCards(out, 3); + return out; + } + + private CardList get5Colors(CardList in) + { + + color1 = Constant.Color.Black; + color2 = Constant.Color.Blue; + color3 = Constant.Color.Green; + color4 = Constant.Color.Red; + color5 = Constant.Color.White; + + CardList out = new CardList(); + /* + out.addAll(CardListUtil.getColor(in, color1).toArray()); + out.addAll(CardListUtil.getColor(in, color2).toArray()); + out.addAll(CardListUtil.getColor(in, color3).toArray()); + out.addAll(CardListUtil.getColor(in, color4).toArray()); + out.addAll(CardListUtil.getColor(in, color5).toArray()); + */ + out.addAll(CardListUtil.getGoldCards(in).toArray()); + out.shuffle(); + + CardList artifact = in.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + //is this really a colorless artifact and not something + //wierd like Sarcomite Myr which is a colored artifact + return c.isArtifact() && + CardUtil.getColors(c).contains(Constant.Color.Colorless) && + !Gui_NewGame.removeArtifacts.isSelected(); + } + }); + out.addAll(artifact.toArray()); + + out = out.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if(c.isCreature() && + c.getNetAttack() <= 1 && + Gui_NewGame.removeSmallCreatures.isSelected()) + { + return false; + } + + return true; + } + }); + + out = filterBadCards(out, 3); + return out; + } + + + private CardList filterBadCards(CardList list, int colors) + { + //remove "bad" and multi-colored cards + final ArrayList remove = new ArrayList(); + remove.add("Sarcomite Myr"); + remove.add("Force of Savagery"); + remove.add("Darksteel Colossus"); + remove.add("Jokulhaups"); + remove.add("Steel Wall"); + remove.add("Ornithopter"); + remove.add("Amnesia"); + remove.add("Battle of Wits"); + remove.add("Ashes to Ashes"); + remove.add("Haunted Angel"); + remove.add("Sky Swallower"); + remove.add("Magus of the Library"); + remove.add("The Unspeakable"); + remove.add("Wall of Kelp"); + + remove.add("Incendiary Command"); + remove.add("Memnarch"); + remove.add("Plague Wind"); + remove.add("Klaas, Elf Friend"); + remove.add("Delirium Skeins"); + + remove.add("Undying Beast"); + remove.add("Wit's End"); + + remove.add("Blinding Light"); + remove.add("Hymn to Tourach"); + + //not fully implemented: + + remove.add("Aether Membrane"); + remove.add("Arashi, the Sky Asunder"); + remove.add("Hand of Cruelty"); + remove.add("Hand of Honor"); + + //useless, or combo cards: + + remove.add("Aluren"); + remove.add("Conspiracy"); + remove.add("Crucible of Fire"); + remove.add("Verduran Enchantress"); + remove.add("Enchantress's Presence"); + remove.add("Mesa Enchantress"); + remove.add("Moat"); + remove.add("Magus of the Moat"); + remove.add("Relentless Rats"); + remove.add("Vedalken Archmage"); + remove.add("Hatching Plans"); + remove.add("Sensation Gorger"); + + //semi useless + + remove.add("Wren's Run Packmaster"); + remove.add("Nova Chaser"); + remove.add("Supreme Exemplar"); + remove.add("Goblin Ringleader"); + remove.add("Sylvan Messenger"); + remove.add("Tromp the Domains"); + remove.add("Legacy Weapon"); + + //cards the AI cannot play (effectively): + + remove.add("Sensei's Divining Top"); + remove.add("Standstill"); + //remove.add("Counterspell"); + //remove.add("Exclude"); + //remove.add("False Summoning"); + //remove.add("Essence Scatter"); + //remove.add("Preemptive Strike"); + //remove.add("Punish Ignorance"); + //remove.add("Remand"); + //remove.add("Mystic Snake"); + //remove.add("Absorb"); + //remove.add("Undermine"); + //remove.add("Overwhelming Intellect"); + remove.add("AEther Vial"); + remove.add("Covetous Dragon"); + remove.add("Terramorphic Expanse"); + remove.add("Earthcraft"); + remove.add("Burst of Speed"); + remove.add("Magnify"); + remove.add("Nature's Cloak"); + remove.add("Resuscitate"); + remove.add("Shield Wall"); + remove.add("Solidarity"); + remove.add("Steadfastness"); + remove.add("Tortoise Formation"); + + //manapool stuff: + remove.add("Dark Ritual"); + remove.add("Seething Song"); + remove.add("Sol Ring"); + remove.add("Gaea's Cradle"); + remove.add("Priest of Titania"); + remove.add("Tolarian Academy"); + remove.add("Serra's Sanctum"); + remove.add("Basalt Monolith"); + remove.add("Grim Monolith"); + remove.add("Black Lotus"); + remove.add("Composite Golem"); + remove.add("Thran Dynamo"); + remove.add("Elvish Archdruid"); + remove.add("Sunglasses of Urza"); + remove.add("Ceta Discple"); + remove.add("Agent of Stromgald"); + remove.add("Apprentice Wizard"); + remove.add("Azorius Signet"); + remove.add("Bog Initiate"); + remove.add("Boros Signet"); + remove.add("Celestial Prism"); + remove.add("Dimir Signet"); + remove.add("Fire Sprites"); + remove.add("Fyndhorn Elder"); + remove.add("Gilded Lotus"); + remove.add("Golgari Signet"); + remove.add("Greenweaver Druid"); + remove.add("Gruul Signet"); + remove.add("Helionaut"); + remove.add("Izzet Signet"); + remove.add("Knotvine Mystic"); + remove.add("Mana Cylix"); + remove.add("Mana Prism"); + remove.add("Nantuko Elder"); + remove.add("Nomadic Elf"); + remove.add("Orochi Leafcaller"); + remove.add("Orzhov Signet"); + remove.add("Prismatic Lens"); + remove.add("Rakdos Signet"); + remove.add("Sea Scryer"); + remove.add("Selesnya Signet"); + remove.add("Simic Signet"); + remove.add("Sisay's Ring"); + remove.add("Skyshroud Elf"); + remove.add("Ur-Golem's Eye"); + remove.add("Viridian Acolyte"); + remove.add("Worn Powerstone"); + + + final ArrayList goodLand = new ArrayList(); + //goodLand.add("Faerie Conclave"); + //goodLand.add("Forbidding Watchtower"); + //goodLand.add("Treetop Village"); + + CardList out = new CardList(); + if (colors == 3) + { + + out = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + ArrayList list = CardUtil.getColors(c); + + if (list.size() == 3) + { + if (!list.contains(color1) || !list.contains(color2) || !list.contains(color3)) + return false; + } + + + else if (list.size() == 2) + { + if (!(list.contains(color1) && list.contains(color2)) && + !(list.contains(color1) && list.contains(color3)) && + !(list.contains(color2) && list.contains(color3))) + return false; + } + + return CardUtil.getColors(c).size() <= 3 && + !c.isLand() && //no land + !remove.contains(c.getName()) || //OR very important + goodLand.contains(c.getName()); + } + }); + } + + else if (colors == 5) + { + out = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return CardUtil.getColors(c).size() >= 2 && //only get multicolored cards + !c.isLand() && //no land + !remove.contains(c.getName()) || //OR very important + goodLand.contains(c.getName()); + } + }); + + } + + return out; + }//filterBadCards() + public static void main(String[] args) + { + GenerateConstructedMultiColorDeck g = new GenerateConstructedMultiColorDeck(); + + for(int i = 0; i < 10; i++) + { + System.out.println("***GENERATING DECK***"); + CardList c = g.generate3ColorDeck(); + System.out.println(c.getType("Creature").size() +" - " +c.size()); + for (int j=0; j map = new HashMap(); + + static + { + map.put(Constant.Color.Black , "Swamp"); + map.put(Constant.Color.Blue , "Island"); + map.put(Constant.Color.Green , "Forest"); + map.put(Constant.Color.Red , "Mountain"); + map.put(Constant.Color.White , "Plains"); + } + + public static void main(String[] args) + { + CardList cardPool = new CardList(); + ReadBoosterPack booster = new ReadBoosterPack(); + + for(int outer = 0; outer < 10000; outer++) + { + cardPool.clear(); + for(int i = 0; i < 21; i++) + cardPool.addAll(booster.getBoosterPack().toArray()); + + makeDeck7(cardPool); + if(cardPool.size() != 205) + { + System.out.println(cardPool.size() +" should be "); + break; + } + }//for outer + } + + //Deck[] size is 7 + public static Deck[] makeDeck7(CardList cardPool) + { + Deck[] out = new Deck[5]; + //int index = 0; // unused + + for(int i = 0; i < out.length; i++) + out[i] = makeAndTestDeck(cardPool); + + test(out); + return out; + }//makeDeck7() + + public static void test(Deck[] deck) + { + for(int i = 0; i < deck.length; i++) + { + if(deck[i] == null || deck[i].countMain() != 40) + throw new RuntimeException("GenerateDraftDeck : test() error, deck is wrong"); + } + } + + + //returned Deck may be null + //this method changes cardPool, and takes cards out of it + //the remaining cards in cardPool are unused + public static Deck makeAndTestDeck(CardList cardPool) + { + CardList test = makeDeck(cardPool, 11, Constant.GameType.Draft); + if(test == null) + { + for(int i = 0; i < 100; i++) + test = makeDeck(cardPool, 11, Constant.GameType.Draft); + } + + if(test == null) + return null; + + //convert CardList into Deck + //remove cards from cardPool + Deck out = new Deck(Constant.GameType.Draft); + for(int i = 0; i < test.size(); i++) + { + cardPool.remove(test.get(i)); + out.addMain(test.get(i).getName()); + } + + return out; + }//makeAndTestDeck() + + public static CardList makeDeck(CardList cardPool, int minCreatureCount, String gameType) + { + CardList test = null; + boolean pass = false; + for(int i = 0; i < 5; i++) + { + test = make2ColorDeck(new CardList(cardPool.toArray())); + if(minCreatureCount <= test.getType("Creature").size()) + { + pass = true; + break; + } + }//for + if((! pass) || (test.size() != 40)) + return null; + + return test; + }//makeDeck() + + + private static CardList make2ColorDeck(CardList in) + { + final ArrayList remove = new ArrayList(); + remove.add("Force of Savagery"); + remove.add("Darksteel Colossus"); + remove.add("Jokulhaups"); + remove.add("Steel Wall"); + remove.add("Ornithopter"); + remove.add("Sarcomite Myr"); + + in = in.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return CardUtil.getColors(c).size() == 1 && !remove.contains(c.getName()); + } + }); + + String[] color = get2Colors(); + CardList out = new CardList(); + + out.addAll(CardListUtil.getColor(in, color[0]).toArray()); + out.addAll(CardListUtil.getColor(in, color[1]).toArray()); + + CardList trim = new CardList(); + for(int i = 0; i < 22 && i < out.size(); i++) + trim.add(out.get(i)); + + addLand(trim, color); + + return trim; + } + + //the 2 colors will be different + private static String[] get2Colors() + { + int a; + int b; + + do{ + a = CardUtil.getRandomIndex(Constant.Color.onlyColors); + b = CardUtil.getRandomIndex(Constant.Color.onlyColors); + }while(a == b);//do not want to get the same color twice + + String color1 = Constant.Color.onlyColors[a]; + String color2 = Constant.Color.onlyColors[b]; + + return new String[] {color1, color2}; + }//get2Colors() + + private static void addLand(CardList list, String[] color) + { + Card land; + for(int i = 0; i < 9; i++) + { + land = AllZone.CardFactory.getCard(map.get(color[0]).toString(), Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(map.get(color[1]).toString(), Constant.Player.Computer); + list.add(land); + } + }//addLand() +} + +/* +import java.util.*; + +public class GenerateSealedDeck +{ + private String color1; + private String color2; + + public CardList generateDeck() + { + CardList deck; + do{ + deck = get2ColorDeck(); + }while(deck.getType("Creature").size() < 16); + + addLand(deck); + + if(deck.size() != 40) + throw new RuntimeException("GenerateSealedDeck() : generateDeck() error, deck size it not 40, deck size is " +deck.size()); + + return deck; + } + private CardList get2ColorDeck() + { + ReadBoosterPack booster = new ReadBoosterPack(); + CardList deck; + do{ + deck = get2Colors(booster.getBoosterPack5()); + }while(deck.size() < 22); + + CardList out = new CardList(); + deck.shuffle(); + +//trim deck size down to 22 cards, presumes 18 land + for(int i = 0; i < 22; i++) + out.add(deck.get(i)); + + return out; + } +} + + +*/ \ No newline at end of file diff --git a/src/GenerateSealedDeck.java b/src/GenerateSealedDeck.java new file mode 100644 index 00000000000..d398b928bc6 --- /dev/null +++ b/src/GenerateSealedDeck.java @@ -0,0 +1,151 @@ +import java.util.*; + +public class GenerateSealedDeck +{ + private String color1; + private String color2; + + private Map map = new HashMap(); + + public GenerateSealedDeck() {setupMap();} + + private void setupMap() + { + map.put(Constant.Color.Black , "Swamp"); + map.put(Constant.Color.Blue , "Island"); + map.put(Constant.Color.Green , "Forest"); + map.put(Constant.Color.Red , "Mountain"); + map.put(Constant.Color.White , "Plains"); + } + + public CardList generateDeck() + { + CardList deck; + do{ + deck = get2ColorDeck(); + }while(deck.getType("Creature").size() < 12 || 16 < deck.getType("Creature").size()); + + addLand(deck); + + if(deck.size() != 40) + throw new RuntimeException("GenerateSealedDeck() : generateDeck() error, deck size it not 40, deck size is " +deck.size()); + + return deck; + } + private void addLand(CardList list) + { + Card land; + for(int i = 0; i < 9; i++) + { + land = AllZone.CardFactory.getCard(map.get(color1).toString(), Constant.Player.Computer); + list.add(land); + + land = AllZone.CardFactory.getCard(map.get(color2).toString(), Constant.Player.Computer); + list.add(land); + } + }//addLand() + private CardList get2ColorDeck() + { + ReadBoosterPack booster = new ReadBoosterPack(); + CardList deck; + do{ + deck = get2Colors(booster.getBoosterPack5()); + }while(deck.size() < 22); + + CardList out = new CardList(); + deck.shuffle(); + + //trim deck size down to 22 cards, presumes 18 land + for(int i = 0; i < 22 && i < deck.size(); i++) + out.add(deck.get(i)); + + return out; + } + private CardList get2Colors(CardList in) + { + int a; + int b; + + do{ + a = CardUtil.getRandomIndex(Constant.Color.onlyColors); + b = CardUtil.getRandomIndex(Constant.Color.onlyColors); + }while(a == b);//do not want to get the same color twice + + color1 = Constant.Color.onlyColors[a]; + color2 = Constant.Color.onlyColors[b]; + + CardList out = new CardList(); + out.addAll(CardListUtil.getColor(in, color1).toArray()); + out.addAll(CardListUtil.getColor(in, color2).toArray()); + + CardList artifact = in.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + //is this really a colorless artifact and not something + //wierd like Sarcomite Myr which is a colored artifact + return c.isArtifact() && + CardUtil.getColors(c).contains(Constant.Color.Colorless) && + !Gui_NewGame.removeArtifacts.isSelected(); + } + }); + out.addAll(artifact.toArray()); + + out = out.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if(c.isCreature() && + c.getNetAttack() <= 1 && + Gui_NewGame.removeSmallCreatures.isSelected()) + { + return false; + } + + return true; + } + }); + + out = filterBadCards(out); + return out; + } + private CardList filterBadCards(CardList list) + { + //remove "bad" and multi-colored cards + final ArrayList remove = new ArrayList(); + remove.add("Force of Savagery"); + remove.add("Darksteel Colossus"); + remove.add("Jokulhaups"); + remove.add("Steel Wall"); + remove.add("Ornithopter"); + remove.add("Sarcomite Myr"); + + CardList out = list.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return CardUtil.getColors(c).size() == 1 && !remove.contains(c.getName()); + } + }); + + return out; + }//filterBadCards() + public static void main(String[] args) + { + GenerateSealedDeck g = new GenerateSealedDeck(); + + for(int i = 0; i < 100; i++) + { + System.out.println(i); + g.generateDeck(); + } + +/* + for(int i = 0; i < 10; i++) + { + CardList c = g.generateDeck(); + System.out.println(c.getType("Creature").size()); + } +*/ + } +} \ No newline at end of file diff --git a/src/GuiDisplay.java b/src/GuiDisplay.java new file mode 100644 index 00000000000..442063954e8 --- /dev/null +++ b/src/GuiDisplay.java @@ -0,0 +1,313 @@ +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Rectangle; + +import javax.swing.BorderFactory; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; + + +public class GuiDisplay extends JFrame { + private static final long serialVersionUID = -7044669689870299753L; + + private JScrollPane jScrollPane1 = new JScrollPane(); + private JTextArea messageArea = new JTextArea(); + private JPanel buttonPanel = new JPanel(); + private FlowLayout flowLayout1 = new FlowLayout(); + private JPanel jPanel2 = new JPanel(); + private JLabel oppLifeLabel = new JLabel(); + private BorderLayout borderLayout1 = new BorderLayout(); + private JPanel jPanel3 = new JPanel(); + private BorderLayout borderLayout2 = new BorderLayout(); + private JScrollPane jScrollPane3 = new JScrollPane(); + private JPanel jPanel4 = new JPanel(); + private BorderLayout borderLayout3 = new BorderLayout(); + private JLabel playerLifeLabel = new JLabel(); + @SuppressWarnings("unused") + // border1 + private Border border1; + private JPanel jPanel5 = new JPanel(); + private JScrollPane jScrollPane4 = new JScrollPane(); + private JPanel jPanel6 = new JPanel(); + private GridLayout gridLayout1 = new GridLayout(); + private JPanel oppLandPanel = new JPanel(); + private JPanel oppCreaturePanel = new JPanel(); + private JPanel playerCreaturePanel = new JPanel(); + private JPanel playerLandPanel = new JPanel(); + private JPanel playerHandPanel = new JPanel(); + private JLabel jLabel3 = new JLabel(); + private JPanel jPanel12 = new JPanel(); + private GridLayout gridLayout2 = new GridLayout(); + private JPanel jPanel13 = new JPanel(); + private JPanel jPanel14 = new JPanel(); + private JPanel jPanel15 = new JPanel(); + private JPanel jPanel16 = new JPanel(); + private JPanel jPanel17 = new JPanel(); + private JLabel jLabel4 = new JLabel(); + private JLabel jLabel5 = new JLabel(); + private JLabel jLabel6 = new JLabel(); + private JLabel jLabel7 = new JLabel(); + private JLabel jLabel8 = new JLabel(); + private JPanel jPanel18 = new JPanel(); + private JLabel jLabel9 = new JLabel(); + private JPanel jPanel19 = new JPanel(); + private Border border2; + private TitledBorder titledBorder1; + private BorderLayout borderLayout4 = new BorderLayout(); + private JLabel jLabel11 = new JLabel(); + private JLabel jLabel12 = new JLabel(); + private JLabel playerHandLabel = new JLabel(); + private JLabel playerLibraryLabel = new JLabel(); + private JLabel playerGraveLabel = new JLabel(); + private JScrollPane jScrollPane2 = new JScrollPane(); + private JLabel jLabel18 = new JLabel(); + private JLabel jLabel19 = new JLabel(); + private JLabel jLabel20 = new JLabel(); + private JLabel oppHandLabel = new JLabel(); + private JLabel oppLibraryLabel = new JLabel(); + private JLabel oppGraveLabel = new JLabel(); + private JPanel stackPanel = new JPanel(); + private GridLayout gridLayout3 = new GridLayout(); + private JPanel jPanel9 = new JPanel(); + private JPanel picturePanel = new JPanel(); + private JTextArea combatArea = new JTextArea(); + private GridLayout gridLayout4 = new GridLayout(); + private JPanel jPanel7 = new JPanel(); + private GridLayout gridLayout5 = new GridLayout(); + private JLabel cdLabel1 = new JLabel(); + private JLabel cdLabel2 = new JLabel(); + private JLabel cdLabel3 = new JLabel(); + private JLabel cdLabel4 = new JLabel(); + private JLabel cdLabel5 = new JLabel(); + private JScrollPane jScrollPane5 = new JScrollPane(); + private JTextArea cdArea = new JTextArea(); + + public static void main(String[] args) { + GuiDisplay g = new GuiDisplay(); + + //Use both so that when "un"maximizing, the frame isn't tiny + g.setSize(1024, 740); + g.setExtendedState(Frame.MAXIMIZED_BOTH); + + g.setVisible(true); + } + + public GuiDisplay() { + try { + jbInit(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + } + + private void jbInit() throws Exception { + border1 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + border2 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder1 = new TitledBorder(border2, "Stack"); + this.getContentPane().setLayout(null); + messageArea.setLineWrap(true); + messageArea.setWrapStyleWord(true); + buttonPanel.setBorder(BorderFactory.createEtchedBorder()); + buttonPanel.setBounds(new Rectangle(12, 105, 214, 38)); + buttonPanel.setLayout(flowLayout1); + jPanel2.setBorder(new TitledBorder( + BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)), "Computer")); + jPanel2.setBounds(new Rectangle(137, 149, 89, 78)); + jPanel2.setLayout(borderLayout1); + oppLifeLabel.setFont(new java.awt.Font("Dialog", 0, 47)); + oppLifeLabel.setToolTipText("Click here to target the computer"); + oppLifeLabel.setHorizontalAlignment(SwingConstants.CENTER); + oppLifeLabel.setText("20"); + jPanel3.setBorder(new TitledBorder( + BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)), "Combat")); + jPanel3.setBounds(new Rectangle(6, 401, 230, 169)); + jPanel3.setLayout(borderLayout2); + jPanel4.setBorder(new TitledBorder( + BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)), "Human")); + jPanel4.setBounds(new Rectangle(154, 604, 90, 83)); + jPanel4.setLayout(borderLayout3); + playerLifeLabel.setFont(new java.awt.Font("Dialog", 0, 47)); + playerLifeLabel.setToolTipText("Click here to target yourself"); + playerLifeLabel.setHorizontalAlignment(SwingConstants.CENTER); + playerLifeLabel.setText("20"); + jScrollPane3.setBorder(BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140))); + jPanel5.setBounds(new Rectangle(776, 12, 214, 663)); + jPanel5.setLayout(gridLayout3); + jPanel6.setLayout(gridLayout1); + gridLayout1.setHgap(10); + gridLayout1.setRows(5); + gridLayout1.setVgap(10); + oppLandPanel.setBorder(BorderFactory.createEtchedBorder()); + oppLandPanel.setToolTipText("Computer\'s Land"); + oppCreaturePanel.setBorder(BorderFactory.createEtchedBorder()); + oppCreaturePanel.setToolTipText("Computer\'s Creatures"); + playerHandPanel.setBorder(BorderFactory.createEtchedBorder()); + playerHandPanel.setToolTipText("Cards in your hand"); + playerCreaturePanel.setBorder(BorderFactory.createEtchedBorder()); + playerCreaturePanel.setToolTipText("Your Creatures"); + playerLandPanel.setBorder(BorderFactory.createEtchedBorder()); + playerLandPanel.setToolTipText("Your Land"); + jLabel3.setFont(new java.awt.Font("Dialog", 0, 18)); + jLabel3.setText("Hand: "); + jLabel3.setBounds(new Rectangle(39, 608, 60, 28)); + jPanel12.setToolTipText("Mana Pool"); + jPanel12.setBounds(new Rectangle(1, 571, 246, 30)); + jPanel12.setLayout(gridLayout2); + gridLayout2.setColumns(6); + gridLayout2.setHgap(5); + gridLayout2.setRows(0); + jLabel4.setFont(new java.awt.Font("Dialog", 0, 16)); + jLabel4.setHorizontalAlignment(SwingConstants.CENTER); + jLabel4.setText("10"); + jPanel13.setBackground(Color.white); + jLabel5.setFont(new java.awt.Font("Dialog", 0, 16)); + jLabel5.setForeground(Color.white); + jLabel5.setText("10"); + jPanel14.setBackground(Color.black); + jPanel14.setForeground(Color.white); + jPanel15.setBackground(Color.blue); + jPanel15.setToolTipText(""); + jLabel6.setFont(new java.awt.Font("Dialog", 0, 16)); + jLabel6.setForeground(Color.white); + jLabel6.setText("10"); + jLabel7.setFont(new java.awt.Font("Dialog", 0, 16)); + jLabel7.setForeground(Color.white); + jLabel7.setText("10"); + jPanel16.setBackground(Color.red); + jLabel8.setFont(new java.awt.Font("Dialog", 0, 16)); + jLabel8.setForeground(Color.white); + jLabel8.setText("10"); + jPanel17.setBackground(Color.gray); + jLabel9.setFont(new java.awt.Font("Dialog", 0, 16)); + jLabel9.setText("10"); + jPanel18.setBackground(Color.green); + jScrollPane4.setBounds(new Rectangle(244, 12, 525, 685)); + jScrollPane1.setBounds(new Rectangle(12, 6, 214, 91)); + jPanel19.setBorder(titledBorder1); + jPanel19.setBounds(new Rectangle(6, 233, 230, 169)); + jPanel19.setLayout(borderLayout4); + jLabel11.setFont(new java.awt.Font("Dialog", 0, 18)); + jLabel11.setText("Library: "); + jLabel11.setBounds(new Rectangle(39, 639, 71, 23)); + jLabel12.setFont(new java.awt.Font("Dialog", 0, 18)); + jLabel12.setText("Grave: "); + jLabel12.setBounds(new Rectangle(39, 664, 60, 26)); + playerHandLabel.setFont(new java.awt.Font("Dialog", 0, 18)); + playerHandLabel.setHorizontalAlignment(SwingConstants.RIGHT); + playerHandLabel.setText("7"); + playerHandLabel.setBounds(new Rectangle(91, 608, 32, 28)); + playerLibraryLabel.setFont(new java.awt.Font("Dialog", 0, 18)); + playerLibraryLabel.setHorizontalAlignment(SwingConstants.RIGHT); + playerLibraryLabel.setText("32"); + playerLibraryLabel.setBounds(new Rectangle(91, 639, 32, 23)); + playerGraveLabel.setFont(new java.awt.Font("Dialog", 0, 18)); + playerGraveLabel.setHorizontalAlignment(SwingConstants.RIGHT); + playerGraveLabel.setText("2"); + playerGraveLabel.setBounds(new Rectangle(91, 664, 32, 26)); + jScrollPane2.setBorder(BorderFactory.createEtchedBorder()); + jLabel18.setFont(new java.awt.Font("Dialog", 0, 18)); + jLabel18.setText("Hand:"); + jLabel18.setBounds(new Rectangle(28, 152, 66, 20)); + jLabel19.setFont(new java.awt.Font("Dialog", 0, 18)); + jLabel19.setText("Library:"); + jLabel19.setBounds(new Rectangle(28, 181, 70, 20)); + jLabel20.setFont(new java.awt.Font("Dialog", 0, 18)); + jLabel20.setText("Grave:"); + jLabel20.setBounds(new Rectangle(28, 210, 76, 20)); + oppHandLabel.setFont(new java.awt.Font("Dialog", 0, 18)); + oppHandLabel.setHorizontalAlignment(SwingConstants.RIGHT); + oppHandLabel.setText("6"); + oppHandLabel.setBounds(new Rectangle(59, 152, 55, 20)); + oppLibraryLabel.setFont(new java.awt.Font("Dialog", 0, 18)); + oppLibraryLabel.setHorizontalAlignment(SwingConstants.RIGHT); + oppLibraryLabel.setText("30"); + oppLibraryLabel.setBounds(new Rectangle(59, 181, 55, 20)); + oppGraveLabel.setFont(new java.awt.Font("Dialog", 0, 18)); + oppGraveLabel.setHorizontalAlignment(SwingConstants.RIGHT); + oppGraveLabel.setText("2"); + oppGraveLabel.setBounds(new Rectangle(59, 210, 55, 20)); + gridLayout3.setColumns(1); + gridLayout3.setRows(2); + gridLayout3.setVgap(5); + picturePanel.setBorder(BorderFactory.createEtchedBorder()); + jPanel9.setBorder(BorderFactory.createEtchedBorder()); + jPanel9.setLayout(gridLayout4); + gridLayout4.setColumns(1); + gridLayout4.setRows(2); + jPanel7.setLayout(gridLayout5); + gridLayout5.setColumns(1); + gridLayout5.setRows(5); + cdArea.setLineWrap(true); + cdArea.setWrapStyleWord(true); + cdLabel4.setHorizontalAlignment(SwingConstants.LEFT); + cdLabel1.setHorizontalAlignment(SwingConstants.CENTER); + cdLabel2.setHorizontalAlignment(SwingConstants.CENTER); + cdLabel3.setHorizontalAlignment(SwingConstants.CENTER); + cdLabel5.setHorizontalAlignment(SwingConstants.LEFT); + this.getContentPane().add(jScrollPane1, null); + this.getContentPane().add(buttonPanel, null); + this.getContentPane().add(jScrollPane4, null); + this.getContentPane().add(jPanel3, null); + jPanel3.add(jScrollPane3, BorderLayout.CENTER); + jPanel12.add(jPanel13, null); + jPanel13.add(jLabel4, null); + jPanel12.add(jPanel14, null); + jPanel14.add(jLabel5, null); + jPanel12.add(jPanel15, null); + jPanel15.add(jLabel6, null); + jPanel12.add(jPanel16, null); + jPanel16.add(jLabel7, null); + jPanel12.add(jPanel18, null); + jPanel18.add(jLabel9, null); + jPanel12.add(jPanel17, null); + jPanel17.add(jLabel8, null); + this.getContentPane().add(jLabel12, null); + this.getContentPane().add(playerHandLabel, null); + this.getContentPane().add(jLabel3, null); + this.getContentPane().add(jLabel11, null); + this.getContentPane().add(playerLibraryLabel, null); + this.getContentPane().add(playerGraveLabel, null); + this.getContentPane().add(jLabel19, null); + this.getContentPane().add(jLabel18, null); + this.getContentPane().add(oppHandLabel, null); + this.getContentPane().add(jLabel20, null); + this.getContentPane().add(oppLibraryLabel, null); + this.getContentPane().add(oppGraveLabel, null); + this.getContentPane().add(jPanel5, null); + this.getContentPane().add(jPanel2, null); + jPanel2.add(oppLifeLabel, BorderLayout.CENTER); + this.getContentPane().add(jPanel19, null); + jPanel19.add(jScrollPane2, BorderLayout.CENTER); + jScrollPane2.getViewport().add(stackPanel, null); + this.getContentPane().add(jPanel4, null); + jPanel4.add(playerLifeLabel, BorderLayout.CENTER); + this.getContentPane().add(jPanel12, null); + jScrollPane4.getViewport().add(jPanel6, null); + jPanel6.add(oppLandPanel, null); + jPanel6.add(oppCreaturePanel, null); + jPanel6.add(playerCreaturePanel, null); + jPanel6.add(playerLandPanel, null); + jPanel6.add(playerHandPanel, null); + jScrollPane1.getViewport().add(messageArea, null); + jPanel5.add(jPanel9, null); + jScrollPane3.getViewport().add(combatArea, null); + jPanel7.add(cdLabel1, null); + jPanel7.add(cdLabel2, null); + jPanel7.add(cdLabel3, null); + jPanel7.add(cdLabel4, null); + jPanel7.add(cdLabel5, null); + jPanel9.add(jPanel7, null); + jPanel9.add(jScrollPane5, null); + jPanel5.add(picturePanel, null); + jScrollPane5.getViewport().add(cdArea, null); + } +} \ No newline at end of file diff --git a/src/GuiDisplay2.java b/src/GuiDisplay2.java new file mode 100644 index 00000000000..7e81301ca47 --- /dev/null +++ b/src/GuiDisplay2.java @@ -0,0 +1,961 @@ + + + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; +import java.util.Observable; +import java.util.Observer; + +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import forge.gui.ListChooser; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + +public class GuiDisplay2 extends javax.swing.JFrame implements Display, NewConstants { + private static final long serialVersionUID = 8974795337536720207L; + + private GuiInput inputControl; + public static JCheckBoxMenuItem eotCheckboxForMenu = new JCheckBoxMenuItem("Stop at End of Turn", false); + + public boolean stopEOT() { + return eotCheckboxForMenu.isSelected(); + } + + + public GuiDisplay2() { + initComponents(); + + addObservers(); + addListeners(); + addMenu(); + + inputControl = new GuiInput(); + } + + @Override + public void setVisible(boolean visible) { + if(visible) { + //causes an error if put in the constructor, causes some random null pointer exception + AllZone.InputControl.updateObservers(); + + //Use both so that when "un"maximizing, the frame isn't tiny + setSize(1024, 740); + setExtendedState(Frame.MAXIMIZED_BOTH); + } + super.setVisible(visible); + } + + public void assignDamage(Card attacker, CardList blockers, int damage) { + new Gui_MultipleBlockers(attacker, blockers, damage, this); + } + + private void addMenu() { + JMenuItem humanGraveyard = new JMenuItem("View Graveyard"); + humanGraveyard.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent actionEvent) { + Card c[] = AllZone.Human_Graveyard.getCards(); + + if(AllZone.NameChanger.shouldChangeCardName()) c = AllZone.NameChanger.changeCard(c); + + if(c.length == 0) AllZone.Display.getChoiceOptional("Player's Grave", new String[] {"no cards"}); + else AllZone.Display.getChoiceOptional("Player's Grave", c); + } + }); + + JMenuItem computerGraveyard = new JMenuItem("Computer - View Graveyard"); + computerGraveyard.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent actionEvent) { + Card c[] = AllZone.Computer_Graveyard.getCards(); + + if(AllZone.NameChanger.shouldChangeCardName()) c = AllZone.NameChanger.changeCard(c); + + if(c.length == 0) AllZone.Display.getChoiceOptional("Computer's Grave", new String[] {"no cards"}); + else AllZone.Display.getChoiceOptional("Computer's Grave", c); + } + }); + + + JMenuItem concedeGame = new JMenuItem("Concede Game"); + concedeGame.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent actionEvent) { + dispose(); + Constant.Runtime.WinLose.addLose(); + new Gui_WinLose(); + } + }); + + + JMenuItem gameMenu = new JMenu("Menu"); + gameMenu.add(humanGraveyard); + gameMenu.add(computerGraveyard); + // gameMenu.add(this.eotCheckboxForMenu); // The static field GuiDisplay2.eotCheckboxForMenu should be accessed in a static way + gameMenu.add(GuiDisplay2.eotCheckboxForMenu); + gameMenu.add(new JSeparator()); + gameMenu.add(concedeGame); + + JMenuBar menuBar = new JMenuBar(); + menuBar.add(gameMenu); + menuBar.add(new MenuItem_HowToPlay()); + this.setJMenuBar(menuBar); + }//addMenu() + + public MyButton getButtonOK() { + MyButton ok = new MyButton() { + public void select() { + inputControl.selectButtonOK(); + } + + public boolean isSelectable() { + return okButton.isEnabled(); + } + + public void setSelectable(boolean b) { + okButton.setEnabled(b); + } + + public String getText() { + return okButton.getText(); + } + + public void setText(String text) { + okButton.setText(text); + } + + public void reset() { + okButton.setText("OK"); + } + }; + return ok; + }//getButtonOK() + + public MyButton getButtonCancel() { + MyButton cancel = new MyButton() { + public void select() { + inputControl.selectButtonCancel(); + } + + public boolean isSelectable() { + return cancelButton.isEnabled(); + } + + public void setSelectable(boolean b) { + cancelButton.setEnabled(b); + } + + public String getText() { + return cancelButton.getText(); + } + + public void setText(String text) { + cancelButton.setText(text); + } + + public void reset() { + cancelButton.setText("Cancel"); + } + }; + return cancel; + }//getButtonCancel() + + public void showCombat(String message) { + combatArea.setText(message); + } + + public void showMessage(String s) { + messageArea.setText(s); + } + + //returned Object could be null + public T getChoiceOptional(String message, T[] choices) { + ListChooser c = new ListChooser(message, 0, 1, choices); + final JList list = c.getJList(); + if(choices[0] instanceof Card) { + list.addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent ev) { + if(list.getSelectedValue() instanceof Card) updateCardDetail((Card) list.getSelectedValue()); + } + }); + } + if(!c.show()) return null; + + return c.getSelectedValue(); + }//getChoiceOptional() + + // returned Object will never be null + public T getChoice(String message, T[] choices) { + ListChooser c = new ListChooser(message, 1, choices); + final JList list = c.getJList(); + if(choices[0] instanceof Card) { + list.addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent ev) { + if(list.getSelectedValue() instanceof Card) updateCardDetail((Card) list.getSelectedValue()); + } + }); + } + c.show(); + return c.getSelectedValue(); + }//getChoice() + + private void addListeners() { + //mouse Card Detail + playerHandPanel.addMouseMotionListener(GuiDisplayUtil.getCardDetailMouse(this)); + playerLandPanel.addMouseMotionListener(GuiDisplayUtil.getCardDetailMouse(this)); + playerCreaturePanel.addMouseMotionListener(GuiDisplayUtil.getCardDetailMouse(this)); + + oppLandPanel.addMouseMotionListener(GuiDisplayUtil.getCardDetailMouse(this)); + oppCreaturePanel.addMouseMotionListener(GuiDisplayUtil.getCardDetailMouse(this)); + + + //opponent life mouse listener + oppLifeLabel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + inputControl.selectPlayer(Constant.Player.Computer); + } + }); + + //self life mouse listener + playerLifeLabel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + inputControl.selectPlayer(Constant.Player.Human); + } + }); + + //self play (land) ---- Mouse + playerLandPanel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + Object o = playerLandPanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) { + CardPanel cardPanel = (CardPanel) o; + inputControl.selectCard(cardPanel.getCard(), AllZone.Human_Play); + } + } + }); + //self play (no land) ---- Mouse + playerCreaturePanel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + Object o = playerCreaturePanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) { + CardPanel cardPanel = (CardPanel) o; + inputControl.selectCard(cardPanel.getCard(), AllZone.Human_Play); + } + } + }); + //self hand ---- Mouse + playerHandPanel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + Object o = playerHandPanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) { + CardPanel cardPanel = (CardPanel) o; + inputControl.selectCard(cardPanel.getCard(), AllZone.Human_Hand); + } + } + }); + //***************************************************************** + //computer + + //computer play (land) ---- Mouse + oppLandPanel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + Object o = oppLandPanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) { + CardPanel cardPanel = (CardPanel) o; + inputControl.selectCard(cardPanel.getCard(), AllZone.Computer_Play); + } + } + }); + + //computer play (no land) ---- Mouse + oppCreaturePanel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + Object o = oppCreaturePanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) { + CardPanel cardPanel = (CardPanel) o; + inputControl.selectCard(cardPanel.getCard(), AllZone.Computer_Play); + } + } + }); + + }//addListener() + + public void updateCardDetail(Card c) { + if(c == null) return; + + cdLabel1.setText(""); + cdLabel2.setText(""); + cdLabel3.setText(""); + cdLabel4.setText(""); + cdLabel5.setText(""); + cdArea.setText(""); + + //do not change the name of tokens + if(!(c.isToken() || c.getName().equals(""))) { + //change name, probably need to fix this + //cards that change creatures like Angelic Blessing don't show + //that the creature has flying, or Coastal Hornclaw's flying ability + //c = AllZone.CardFactory.copyCard(c); + if(AllZone.NameChanger.shouldChangeCardName()) c = AllZone.NameChanger.changeCard(c); + } + + if(c.isLand()) cdLabel1.setText(c.getName()); + else cdLabel1.setText(c.getName() + " - " + c.getManaCost()); + + cdLabel2.setText(GuiDisplayUtil.formatCardType(c)); + + if(c.isCreature()) { + String stats = "" + c.getNetAttack() + " / " + c.getNetDefense(); + cdLabel3.setText(stats); + } + + if(c.isCreature()) cdLabel4.setText("Damage: " + c.getDamage() + " Assigned Damage: " + + c.getAssignedDamage()); + + if(c.isPlaneswalker()) cdLabel4.setText("Assigned Damage: " + c.getAssignedDamage()); + + String uniqueID = c.getUniqueNumber() + " "; + cdLabel5.setText("Card ID " + uniqueID); + + this.cdArea.setText(c.getText()); + + cdPanel.setBorder(GuiDisplayUtil.getBorder(c)); + + //picture + picturePanel.removeAll(); + picturePanel.add(GuiDisplayUtil.getPicture(c)); + picturePanel.revalidate(); + }//updateCardDetail() + + private void addObservers() { + //Human Hand, Graveyard, and Library totals + {//make sure to not interfer with anything below, since this is a very long method + Observer o = new Observer() { + public void update(Observable a, Object b) { + playerHandLabel.setText("" + AllZone.Human_Hand.getCards().length); + playerGraveLabel.setText("" + AllZone.Human_Graveyard.getCards().length); + playerLibraryLabel.setText("" + AllZone.Human_Library.getCards().length); + } + }; + AllZone.Human_Hand.addObserver(o); + AllZone.Human_Graveyard.addObserver(o); + AllZone.Human_Library.addObserver(o); + } + + //opponent Hand, Graveyard, and Library totals + {//make sure to not interfer with anything below, since this is a very long method + Observer o = new Observer() { + public void update(Observable a, Object b) { + oppHandLabel.setText("" + AllZone.Computer_Hand.getCards().length); + oppGraveLabel.setText("" + AllZone.Computer_Graveyard.getCards().length); + oppLibraryLabel.setText("" + AllZone.Computer_Library.getCards().length); + } + }; + AllZone.Computer_Hand.addObserver(o); + AllZone.Computer_Graveyard.addObserver(o); + AllZone.Computer_Library.addObserver(o); + } + + + //opponent life + oppLifeLabel.setText("" + AllZone.Computer_Life.getLife()); + AllZone.Computer_Life.addObserver(new Observer() { + public void update(Observable a, Object b) { + int life = AllZone.Computer_Life.getLife(); + oppLifeLabel.setText("" + life); + } + }); + AllZone.Computer_Life.updateObservers(); + + //player life + playerLifeLabel.setText("" + AllZone.Human_Life.getLife()); + AllZone.Human_Life.addObserver(new Observer() { + public void update(Observable a, Object b) { + int life = AllZone.Human_Life.getLife(); + playerLifeLabel.setText("" + life); + } + }); + AllZone.Human_Life.updateObservers(); + + //stack + AllZone.Stack.addObserver(new Observer() { + public void update(Observable a, Object b) { + stackPanel.removeAll(); + MagicStack stack = AllZone.Stack; + int count = 1; + JLabel label; + + for(int i = stack.size() - 1; 0 <= i; i--) { + String text = stack.peek(i).getStackDescription(); + + //change card name + if(AllZone.NameChanger.shouldChangeCardName()) { + Card c = stack.peek(i).getSourceCard(); + text = AllZone.NameChanger.changeString(c, text); + } + + label = new JLabel("" + (count++) + ". " + text); + + //update card detail + final CardPanel cardPanel = new CardPanel(stack.peek(i).getSourceCard()); + cardPanel.setLayout(new BorderLayout()); + cardPanel.add(label); + cardPanel.addMouseMotionListener(new MouseMotionAdapter() { + @Override + public void mouseMoved(MouseEvent me) { + GuiDisplay2.this.updateCardDetail(cardPanel.getCard()); + }//mouseMoved + }); + + stackPanel.add(cardPanel); + } + + stackPanel.revalidate(); + stackPanel.repaint(); + } + }); + AllZone.Stack.updateObservers(); + //END, stack + + + //self hand + AllZone.Human_Hand.addObserver(new Observer() { + public void update(Observable a, Object b) { + PlayerZone pZone = (PlayerZone) a; + JPanel p = playerHandPanel; + p.removeAll(); + + Card c[] = pZone.getCards(); + + //change card names + if(AllZone.NameChanger.shouldChangeCardName()) { + AllZone.Human_Hand.setUpdate(false); + c = AllZone.NameChanger.changeCard(c); + AllZone.Human_Hand.setUpdate(true); + } + + JPanel panel; + for(int i = 0; i < c.length; i++) { + panel = GuiDisplayUtil.getCardPanel(c[i]); + p.add(panel); + } + p.revalidate(); + p.repaint(); + } + }); + AllZone.Human_Hand.updateObservers(); + //END, self hand + + //self play (land) + AllZone.Human_Play.addObserver(new Observer() { + public void update(Observable a, Object b) { + //PlayerZone pZone = (PlayerZone)a; //unused + JPanel p = playerLandPanel; + p.removeAll(); + + Card[] c = AllZone.Human_Play.getCards(); + + //change card names + if(AllZone.NameChanger.shouldChangeCardName()) { + AllZone.Human_Play.setUpdate(false); + c = AllZone.NameChanger.changeCard(c); + AllZone.Human_Play.setUpdate(true); + } + + GuiDisplayUtil.setupLandPanel(p, c); + + p.revalidate(); + p.repaint(); + } + }); + AllZone.Human_Play.updateObservers(); + //END - self play (only land) + + + //self play (no land) + AllZone.Human_Play.addObserver(new Observer() { + public void update(Observable a, Object b) { + //PlayerZone pZone = (PlayerZone)a; //unused + JPanel p = playerCreaturePanel; + p.removeAll(); + + Card[] c = AllZone.Human_Play.getCards(); + + //change card names + if(AllZone.NameChanger.shouldChangeCardName()) { + AllZone.Human_Play.setUpdate(false); + c = AllZone.NameChanger.changeCard(c); + AllZone.Human_Play.setUpdate(true); + } + + GuiDisplayUtil.setupNoLandPanel(p, c); + + p.revalidate(); + p.repaint(); + } + }); + AllZone.Human_Play.updateObservers(); + //END - self play (no land) + + + //computer play (no land) + AllZone.Computer_Play.addObserver(new Observer() { + public void update(Observable a, Object b) { + //PlayerZone pZone = (PlayerZone)a; //unused + JPanel p = oppCreaturePanel; + p.removeAll(); + + Card[] c = AllZone.Computer_Play.getCards(); + + //change card names + if(AllZone.NameChanger.shouldChangeCardName()) { + AllZone.Computer_Play.setUpdate(false); + c = AllZone.NameChanger.changeCard(c); + AllZone.Computer_Play.setUpdate(true); + } + + GuiDisplayUtil.setupNoLandPanel(p, c); + + p.revalidate(); + p.repaint(); + } + }); + AllZone.Computer_Play.updateObservers(); + //END - computer play (no land) + + //computer play (land) + AllZone.Computer_Play.addObserver(new Observer() { + public void update(Observable a, Object b) { + //PlayerZone pZone = (PlayerZone)a; //unused + JPanel p = oppLandPanel; + p.removeAll(); + + Card[] c = AllZone.Computer_Play.getCards(); + + //change card names + if(AllZone.NameChanger.shouldChangeCardName()) { + AllZone.Computer_Play.setUpdate(false); + c = AllZone.NameChanger.changeCard(c); + AllZone.Computer_Play.setUpdate(true); + } + + GuiDisplayUtil.setupLandPanel(p, c); + + p.revalidate(); + p.repaint(); + } + }); + AllZone.Computer_Play.updateObservers(); + //END - computer play (only land) + + }//addObservers() + + /** + * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. + * The content of this method is always regenerated by the Form Editor. + */ + private void initComponents()//GEN-BEGIN:initComponents + { + jMenuBar2 = new javax.swing.JMenuBar(); + jScrollPane1 = new javax.swing.JScrollPane(); + messageArea = new javax.swing.JTextArea(); + jPanel1 = new javax.swing.JPanel(); + cancelButton = new javax.swing.JButton(); + okButton = new javax.swing.JButton(); + jScrollPane2 = new javax.swing.JScrollPane(); + stackPanel = new javax.swing.JPanel(); + jPanel2 = new javax.swing.JPanel(); + jScrollPane3 = new javax.swing.JScrollPane(); + combatArea = new javax.swing.JTextArea(); + jPanel5 = new javax.swing.JPanel(); + jScrollPane4 = new javax.swing.JScrollPane(); + jPanel6 = new javax.swing.JPanel(); + oppLandPanel = new javax.swing.JPanel(); + oppCreaturePanel = new javax.swing.JPanel(); + playerCreaturePanel = new javax.swing.JPanel(); + playerLandPanel = new javax.swing.JPanel(); + playerHandPanel = new javax.swing.JPanel(); + jPanel3 = new javax.swing.JPanel(); + oppLifeLabel = new javax.swing.JLabel(); + jPanel7 = new javax.swing.JPanel(); + playerLifeLabel = new javax.swing.JLabel(); + cdPanel = new javax.swing.JPanel(); + jPanel9 = new javax.swing.JPanel(); + cdLabel1 = new javax.swing.JLabel(); + cdLabel2 = new javax.swing.JLabel(); + cdLabel3 = new javax.swing.JLabel(); + cdLabel4 = new javax.swing.JLabel(); + cdLabel5 = new javax.swing.JLabel(); + jPanel10 = new javax.swing.JPanel(); + jScrollPane5 = new javax.swing.JScrollPane(); + cdArea = new javax.swing.JTextArea(); + picturePanel = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + oppHandLabel = new javax.swing.JLabel(); + oppLibraryLabel = new javax.swing.JLabel(); + oppGraveLabel = new javax.swing.JLabel(); + jLabel7 = new javax.swing.JLabel(); + jLabel8 = new javax.swing.JLabel(); + jLabel9 = new javax.swing.JLabel(); + playerHandLabel = new javax.swing.JLabel(); + playerLibraryLabel = new javax.swing.JLabel(); + playerGraveLabel = new javax.swing.JLabel(); + jMenuBar1 = new javax.swing.JMenuBar(); + menuBar = new javax.swing.JMenu(); + + getContentPane().setLayout(null); + + setTitle(ForgeProps.getLocalized(LANG.PROGRAM_NAME)); + setFont(new java.awt.Font("Times New Roman", 0, 16)); + addWindowListener(new java.awt.event.WindowAdapter() { + @Override + public void windowClosing(java.awt.event.WindowEvent evt) { + exitForm(evt); + } + }); + + messageArea.setEditable(false); + messageArea.setFont(getFont()); + messageArea.setLineWrap(true); + messageArea.setWrapStyleWord(true); + jScrollPane1.setViewportView(messageArea); + + getContentPane().add(jScrollPane1); + jScrollPane1.setBounds(10, 20, 290, 100); + + jPanel1.setBorder(new javax.swing.border.EtchedBorder()); + cancelButton.setText("Cancel"); + cancelButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cancelButtonActionPerformed(evt); + } + }); + + jPanel1.add(cancelButton); + + okButton.setText("OK"); + okButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + okButtonActionPerformed(evt); + + if(AllZone.Phase.isNeedToNextPhase() == true) { + //for debugging: System.out.println("There better be no nextPhase in the stack."); + AllZone.Phase.setNeedToNextPhase(false); + AllZone.Phase.nextPhase(); + } + } + }); + + jPanel1.add(okButton); + + getContentPane().add(jPanel1); + jPanel1.setBounds(10, 130, 290, 40); + + jScrollPane2.setBorder(new javax.swing.border.EtchedBorder()); + stackPanel.setLayout(new java.awt.GridLayout(0, 1, 10, 10)); + + jScrollPane2.setViewportView(stackPanel); + + getContentPane().add(jScrollPane2); + jScrollPane2.setBounds(10, 260, 290, 210); + + jPanel2.setLayout(new java.awt.BorderLayout()); + + jPanel2.setBorder(new javax.swing.border.TitledBorder(new javax.swing.border.EtchedBorder(), "Combat")); + combatArea.setEditable(false); + combatArea.setFont(getFont()); + combatArea.setLineWrap(true); + combatArea.setWrapStyleWord(true); + jScrollPane3.setViewportView(combatArea); + + jPanel2.add(jScrollPane3, java.awt.BorderLayout.CENTER); + + getContentPane().add(jPanel2); + jPanel2.setBounds(10, 480, 290, 120); + + jPanel5.setLayout(new java.awt.BorderLayout()); + + jPanel5.setBorder(new javax.swing.border.EmptyBorder(new java.awt.Insets(1, 1, 1, 1))); + jPanel6.setLayout(new java.awt.GridLayout(5, 0, 10, 10)); + + oppLandPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT)); + + oppLandPanel.setBorder(new javax.swing.border.EtchedBorder()); + jPanel6.add(oppLandPanel); + + oppCreaturePanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT)); + + oppCreaturePanel.setBorder(new javax.swing.border.EtchedBorder()); + jPanel6.add(oppCreaturePanel); + + playerCreaturePanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT)); + + playerCreaturePanel.setBorder(new javax.swing.border.EtchedBorder()); + jPanel6.add(playerCreaturePanel); + + playerLandPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT)); + + playerLandPanel.setBorder(new javax.swing.border.EtchedBorder()); + jPanel6.add(playerLandPanel); + + playerHandPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT)); + + playerHandPanel.setBorder(new javax.swing.border.EtchedBorder()); + jPanel6.add(playerHandPanel); + + jScrollPane4.setViewportView(jPanel6); + + jPanel5.add(jScrollPane4, java.awt.BorderLayout.CENTER); + + getContentPane().add(jPanel5); + jPanel5.setBounds(320, 20, 460, 670); + + jPanel3.setLayout(new java.awt.BorderLayout()); + + jPanel3.setBorder(new javax.swing.border.TitledBorder(new javax.swing.border.EtchedBorder(), "Computer")); + oppLifeLabel.setFont(new java.awt.Font("MS Sans Serif", 0, 40)); + oppLifeLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + oppLifeLabel.setText("19"); + oppLifeLabel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jPanel3.add(oppLifeLabel, java.awt.BorderLayout.CENTER); + + getContentPane().add(jPanel3); + jPanel3.setBounds(210, 170, 90, 90); + + jPanel7.setLayout(new java.awt.BorderLayout()); + + jPanel7.setBorder(new javax.swing.border.TitledBorder(new javax.swing.border.EtchedBorder(), "Player")); + playerLifeLabel.setFont(new java.awt.Font("MS Sans Serif", 0, 40)); + playerLifeLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + playerLifeLabel.setText("19"); + playerLifeLabel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jPanel7.add(playerLifeLabel, java.awt.BorderLayout.CENTER); + + getContentPane().add(jPanel7); + jPanel7.setBounds(210, 600, 90, 90); + + cdPanel.setLayout(new java.awt.GridLayout(2, 1, 0, 5)); + + cdPanel.setBorder(new javax.swing.border.EtchedBorder()); + jPanel9.setLayout(new java.awt.GridLayout(5, 0, 0, 5)); + + cdLabel1.setFont(getFont()); + cdLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + cdLabel1.setText("jLabel3"); + jPanel9.add(cdLabel1); + + cdLabel2.setFont(getFont()); + cdLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + cdLabel2.setText("jLabel4"); + jPanel9.add(cdLabel2); + + cdLabel3.setFont(getFont()); + cdLabel3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + cdLabel3.setText("jLabel5"); + jPanel9.add(cdLabel3); + + cdLabel4.setFont(getFont()); + cdLabel4.setText("jLabel6"); + jPanel9.add(cdLabel4); + + cdLabel5.setFont(getFont()); + cdLabel5.setText("jLabel7"); + jPanel9.add(cdLabel5); + + cdPanel.add(jPanel9); + + jPanel10.setLayout(new java.awt.BorderLayout()); + + cdArea.setFont(getFont()); + cdArea.setLineWrap(true); + cdArea.setWrapStyleWord(true); + jScrollPane5.setViewportView(cdArea); + + jPanel10.add(jScrollPane5, java.awt.BorderLayout.CENTER); + + cdPanel.add(jPanel10); + + getContentPane().add(cdPanel); + cdPanel.setBounds(790, 20, 230, 300); + + picturePanel.setLayout(new java.awt.BorderLayout()); + + picturePanel.setBorder(new javax.swing.border.EtchedBorder()); + getContentPane().add(picturePanel); + picturePanel.setBounds(790, 350, 230, 300); + + jLabel1.setFont(new java.awt.Font("MS Sans Serif", 0, 18)); + jLabel1.setText("Library:"); + getContentPane().add(jLabel1); + jLabel1.setBounds(60, 200, 70, 20); + + jLabel2.setFont(new java.awt.Font("MS Sans Serif", 0, 18)); + jLabel2.setText("Hand:"); + getContentPane().add(jLabel2); + jLabel2.setBounds(60, 170, 60, 20); + + jLabel3.setFont(new java.awt.Font("MS Sans Serif", 0, 18)); + jLabel3.setText("Grave:"); + getContentPane().add(jLabel3); + jLabel3.setBounds(60, 230, 70, 20); + + oppHandLabel.setFont(new java.awt.Font("MS Sans Serif", 0, 18)); + oppHandLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); + oppHandLabel.setText("7"); + oppHandLabel.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + getContentPane().add(oppHandLabel); + oppHandLabel.setBounds(90, 170, 60, 20); + + oppLibraryLabel.setFont(new java.awt.Font("MS Sans Serif", 0, 18)); + oppLibraryLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); + oppLibraryLabel.setText("60"); + oppLibraryLabel.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + getContentPane().add(oppLibraryLabel); + oppLibraryLabel.setBounds(90, 200, 60, 20); + + oppGraveLabel.setFont(new java.awt.Font("MS Sans Serif", 0, 18)); + oppGraveLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); + oppGraveLabel.setText("200"); + oppGraveLabel.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + getContentPane().add(oppGraveLabel); + oppGraveLabel.setBounds(90, 230, 60, 20); + + jLabel7.setFont(new java.awt.Font("MS Sans Serif", 0, 18)); + jLabel7.setText("Hand:"); + getContentPane().add(jLabel7); + jLabel7.setBounds(60, 610, 60, 20); + + jLabel8.setFont(new java.awt.Font("MS Sans Serif", 0, 18)); + jLabel8.setText("Library:"); + getContentPane().add(jLabel8); + jLabel8.setBounds(60, 640, 60, 20); + + jLabel9.setFont(new java.awt.Font("MS Sans Serif", 0, 18)); + jLabel9.setText("Grave:"); + getContentPane().add(jLabel9); + jLabel9.setBounds(60, 670, 60, 20); + + playerHandLabel.setFont(new java.awt.Font("MS Sans Serif", 0, 18)); + playerHandLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); + playerHandLabel.setText("6"); + playerHandLabel.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + getContentPane().add(playerHandLabel); + playerHandLabel.setBounds(90, 610, 60, 20); + + playerLibraryLabel.setFont(new java.awt.Font("MS Sans Serif", 0, 18)); + playerLibraryLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); + playerLibraryLabel.setText("54"); + playerLibraryLabel.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + getContentPane().add(playerLibraryLabel); + playerLibraryLabel.setBounds(90, 640, 60, 20); + + playerGraveLabel.setFont(new java.awt.Font("MS Sans Serif", 0, 18)); + playerGraveLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); + playerGraveLabel.setText("0"); + playerGraveLabel.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + getContentPane().add(playerGraveLabel); + playerGraveLabel.setBounds(90, 670, 60, 20); + + menuBar.setText("Menu"); + jMenuBar1.add(menuBar); + + setJMenuBar(jMenuBar1); + + pack(); + }//GEN-END:initComponents + + private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cancelButtonActionPerformed + {//GEN-HEADEREND:event_cancelButtonActionPerformed + inputControl.selectButtonCancel(); + }//GEN-LAST:event_cancelButtonActionPerformed + + private void okButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_okButtonActionPerformed + {//GEN-HEADEREND:event_okButtonActionPerformed + inputControl.selectButtonOK(); + }//GEN-LAST:event_okButtonActionPerformed + + /** Exit the Application */ + private void exitForm(java.awt.event.WindowEvent evt)//GEN-FIRST:event_exitForm + { + dispose(); + Constant.Runtime.WinLose.addLose(); + new Gui_WinLose(); + }//GEN-LAST:event_exitForm + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton cancelButton; + private javax.swing.JTextArea cdArea; + private javax.swing.JLabel cdLabel1; + private javax.swing.JLabel cdLabel2; + private javax.swing.JLabel cdLabel3; + private javax.swing.JLabel cdLabel4; + private javax.swing.JLabel cdLabel5; + public javax.swing.JPanel cdPanel; + private javax.swing.JTextArea combatArea; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JLabel jLabel9; + private javax.swing.JMenuBar jMenuBar1; + @SuppressWarnings("unused") + // jMenuBar2 + private javax.swing.JMenuBar jMenuBar2; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel10; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel3; + private javax.swing.JPanel jPanel5; + private javax.swing.JPanel jPanel6; + private javax.swing.JPanel jPanel7; + private javax.swing.JPanel jPanel9; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JScrollPane jScrollPane3; + private javax.swing.JScrollPane jScrollPane4; + private javax.swing.JScrollPane jScrollPane5; + private javax.swing.JMenu menuBar; + private javax.swing.JTextArea messageArea; + private javax.swing.JButton okButton; + private javax.swing.JPanel oppCreaturePanel; + private javax.swing.JLabel oppGraveLabel; + private javax.swing.JLabel oppHandLabel; + private javax.swing.JPanel oppLandPanel; + private javax.swing.JLabel oppLibraryLabel; + private javax.swing.JLabel oppLifeLabel; + private javax.swing.JPanel picturePanel; + private javax.swing.JPanel playerCreaturePanel; + private javax.swing.JLabel playerGraveLabel; + private javax.swing.JLabel playerHandLabel; + private javax.swing.JPanel playerHandPanel; + private javax.swing.JPanel playerLandPanel; + private javax.swing.JLabel playerLibraryLabel; + private javax.swing.JLabel playerLifeLabel; + private javax.swing.JPanel stackPanel; + // End of variables declaration//GEN-END:variables + +} diff --git a/src/GuiDisplay3.java b/src/GuiDisplay3.java new file mode 100644 index 00000000000..e547ee7990a --- /dev/null +++ b/src/GuiDisplay3.java @@ -0,0 +1,1273 @@ + +import static org.jdesktop.swingx.MultiSplitLayout.*; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.beans.XMLDecoder; +import java.beans.XMLEncoder; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Observable; +import java.util.Observer; + +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JTextArea; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingConstants; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import org.jdesktop.swingx.MultiSplitPane; +import org.jdesktop.swingx.MultiSplitLayout.Node; + +import forge.error.ErrorViewer; +import forge.gui.ForgeAction; +import forge.gui.ListChooser; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + +public class GuiDisplay3 extends JFrame implements Display, NewConstants, NewConstants.GUI.GuiDisplay, NewConstants.LANG.GuiDisplay { + private static final long serialVersionUID = 4519302185194841060L; + + private GuiInput inputControl; + + Font statFont = new Font("MS Sans Serif", Font.PLAIN, 12); + Font lifeFont = new Font("MS Sans Serif", Font.PLAIN, 40); + Font checkboxFont = new Font("MS Sans Serif", Font.PLAIN, 9); + + /* + public Color c1 = new Color(112,112,112); + public Color c2 = new Color(50,50,50); + public Color c3 = new Color(204,204,204); + */ + + public static Color c1 = new Color(204, 204, 204); + public static Color c2 = new Color(204, 204, 204); + + private Action HUMAN_GRAVEYARD_ACTION; + private Action HUMAN_REMOVED_ACTION; + private Action HUMAN_FLASHBACK_ACTION; + private Action COMPUTER_GRAVEYARD_ACTION; + private Action COMPUTER_REMOVED_ACTION; + private Action CONCEDE_ACTION; + + public GuiDisplay3() { + setupActions(); + initComponents(); + + addObservers(); + addListeners(); + addMenu(); + inputControl = new GuiInput(); + } + + @Override + public void setVisible(boolean visible) { + if(visible) { + //causes an error if put in the constructor, causes some random null pointer exception + AllZone.InputControl.updateObservers(); + + //Use both so that when "un"maximizing, the frame isn't tiny + setSize(1024, 740); + System.out.println(getExtendedState()); + setExtendedState(Frame.MAXIMIZED_BOTH); + System.out.println(getExtendedState()); + } + super.setVisible(visible); + } + + public void assignDamage(Card attacker, CardList blockers, int damage) { + new Gui_MultipleBlockers3(attacker, blockers, damage, this); + } + + private void setupActions() { + HUMAN_GRAVEYARD_ACTION = new ZoneAction(AllZone.Human_Graveyard, HUMAN_GRAVEYARD); + HUMAN_REMOVED_ACTION = new ZoneAction(AllZone.Human_Removed, HUMAN_REMOVED); + HUMAN_FLASHBACK_ACTION = new ZoneAction(AllZone.Human_Removed, HUMAN_FLASHBACK) { + + private static final long serialVersionUID = 8120331222693706164L; + + @Override + protected Card[] getCards() { + return CardFactoryUtil.getFlashbackCards(Constant.Player.Human).toArray(); + } + + @Override + protected void doAction(Card c) { + SpellAbility[] sa = c.getSpellAbility(); + if(sa[1].canPlay()) AllZone.GameAction.playSpellAbility(sa[1]); + } + }; + COMPUTER_GRAVEYARD_ACTION = new ZoneAction(AllZone.Computer_Graveyard, COMPUTER_GRAVEYARD); + COMPUTER_REMOVED_ACTION = new ZoneAction(AllZone.Computer_Removed, COMPUTER_REMOVED); + CONCEDE_ACTION = new ConcedeAction(); + } + + private void addMenu() { + Object[] obj = { + HUMAN_GRAVEYARD_ACTION, HUMAN_REMOVED_ACTION, HUMAN_FLASHBACK_ACTION, COMPUTER_GRAVEYARD_ACTION, + COMPUTER_REMOVED_ACTION, GuiDisplay3.eotCheckboxForMenu, new JSeparator(), + ErrorViewer.ALL_THREADS_ACTION, new JSeparator(), CONCEDE_ACTION}; + + JMenu gameMenu = new JMenu(ForgeProps.getLocalized(MENU_BAR.MENU.TITLE)); + for(Object o:obj) { + if(o instanceof ForgeAction) gameMenu.add(((ForgeAction) o).setupButton(new JMenuItem())); + else if(o instanceof Action) gameMenu.add((Action) o); + else if(o instanceof Component) gameMenu.add((Component) o); + else throw new AssertionError(); + } + + JMenuBar menuBar = new JMenuBar(); + menuBar.add(gameMenu); + menuBar.add(new MenuItem_HowToPlay()); + this.setJMenuBar(menuBar); + }//addMenu() + + public MyButton getButtonOK() { + MyButton ok = new MyButton() { + public void select() { + inputControl.selectButtonOK(); + } + + public boolean isSelectable() { + return okButton.isEnabled(); + } + + public void setSelectable(boolean b) { + okButton.setEnabled(b); + } + + public String getText() { + return okButton.getText(); + } + + public void setText(String text) { + okButton.setText(text); + } + + public void reset() { + okButton.setText("OK"); + } + }; + + return ok; + }//getButtonOK() + + public MyButton getButtonCancel() { + MyButton cancel = new MyButton() { + public void select() { + inputControl.selectButtonCancel(); + } + + public boolean isSelectable() { + return cancelButton.isEnabled(); + } + + public void setSelectable(boolean b) { + cancelButton.setEnabled(b); + } + + public String getText() { + return cancelButton.getText(); + } + + public void setText(String text) { + cancelButton.setText(text); + } + + public void reset() { + cancelButton.setText("Cancel"); + } + }; + return cancel; + }//getButtonCancel() + + public void showCombat(String message) { + combatArea.setText(message); + } + + public void showMessage(String s) { + messageArea.setText(s); + } + + //returned Object could be null + public T getChoiceOptional(String message, T[] choices) { + ListChooser c = new ListChooser(message, 0, 1, choices); + final JList list = c.getJList(); + if(choices[0] instanceof Card) { + list.addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent ev) { + if(list.getSelectedValue() instanceof Card) updateCardDetail((Card) list.getSelectedValue()); + } + }); + } + if(!c.show()) return null; + + return c.getSelectedValue(); + }//getChoiceOptional() + + // returned Object will never be null + public T getChoice(String message, T[] choices) { + ListChooser c = new ListChooser(message, 1, choices); + final JList list = c.getJList(); + if(choices[0] instanceof Card) { + list.addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent ev) { + if(list.getSelectedValue() instanceof Card) updateCardDetail((Card) list.getSelectedValue()); + } + }); + } + c.show(); + return c.getSelectedValue(); + }//getChoice() + + private void addListeners() { + //mouse Card Detail + playerHandPanel.addMouseMotionListener(GuiDisplayUtil.getCardDetailMouse(this)); + playerLandPanel.addMouseMotionListener(GuiDisplayUtil.getCardDetailMouse(this)); + playerCreaturePanel.addMouseMotionListener(GuiDisplayUtil.getCardDetailMouse(this)); + + oppLandPanel.addMouseMotionListener(GuiDisplayUtil.getCardDetailMouse(this)); + oppCreaturePanel.addMouseMotionListener(GuiDisplayUtil.getCardDetailMouse(this)); + + + //opponent life mouse listener + oppLifeLabel.addMouseListener(new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent e) { + inputControl.selectPlayer(Constant.Player.Computer); + } + }); + + //self life mouse listener + playerLifeLabel.addMouseListener(new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent e) { + inputControl.selectPlayer(Constant.Player.Human); + } + }); + + //self play (land) ---- Mouse + playerLandPanel.addMouseListener(new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent e) { + Object o = playerLandPanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) { + CardPanel cardPanel = (CardPanel) o; + + if(cardPanel.getCard().isTapped() + && (inputControl.input instanceof Input_PayManaCost || inputControl.input instanceof Input_PayManaCost_Ability)) { + while(cardPanel.connectedCard != null) { + cardPanel = cardPanel.connectedCard; + if(cardPanel.getCard().isUntapped()) { + break; + } + } + } + + inputControl.selectCard(cardPanel.getCard(), AllZone.Human_Play); + } + } + }); + //self play (no land) ---- Mouse + playerCreaturePanel.addMouseListener(new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent e) { + Object o = playerCreaturePanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) { + CardPanel cardPanel = (CardPanel) o; + + CardList att = new CardList(AllZone.Combat.getAttackers()); + + if((cardPanel.getCard().isTapped() || cardPanel.getCard().hasSickness() || ((cardPanel.getCard().getKeyword().contains("Vigilance")) && att.contains(cardPanel.getCard()))) + && (inputControl.input instanceof Input_Attack)) { + while(cardPanel.connectedCard != null) { + cardPanel = cardPanel.connectedCard; + if(cardPanel.getCard().isUntapped() && !cardPanel.getCard().hasSickness()) { + break; + } + } + } + + inputControl.selectCard(cardPanel.getCard(), AllZone.Human_Play); + } + } + }); + //self hand ---- Mouse + playerHandPanel.addMouseListener(new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent e) { + Object o = playerHandPanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) { + CardPanel cardPanel = (CardPanel) o; + inputControl.selectCard(cardPanel.getCard(), AllZone.Human_Hand); + okButton.requestFocusInWindow(); + } + } + }); + + //***************************************************************** + //computer + + //computer play (land) ---- Mouse + oppLandPanel.addMouseListener(new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent e) { + Object o = oppLandPanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) { + CardPanel cardPanel = (CardPanel) o; + inputControl.selectCard(cardPanel.getCard(), AllZone.Computer_Play); + } + } + }); + + //computer play (no land) ---- Mouse + oppCreaturePanel.addMouseListener(new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent e) { + Object o = oppCreaturePanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) { + CardPanel cardPanel = (CardPanel) o; + inputControl.selectCard(cardPanel.getCard(), AllZone.Computer_Play); + } + } + }); + + + }//addListener() + + public void updateCardDetail(Card c) { +// if(! c.isToken()) +// System.out.println(c +" " +c.getSpellAbility()[0].canPlay() +" " +c.getSpellAbility()[0].getManaCost()); + + if(c == null) return; + + cdLabel1.setText(""); + cdLabel2.setText(""); + cdLabel3.setText(""); + cdLabel4.setText(""); + cdLabel5.setText(""); + cdLabel6.setText(""); + cdArea.setText(""); + + if(!c.isFaceDown()) { + if(c.isLand()) cdLabel1.setText(c.getName()); + else cdLabel1.setText(c.getName() + " - " + c.getManaCost()); + } else cdLabel1.setText("Morph"); + + cdLabel2.setText(GuiDisplayUtil.formatCardType(c)); + + if(c.isFaceDown()) cdLabel2.setText("Creature"); + + if(c.isCreature()) { + String stats = "" + c.getNetAttack() + " / " + c.getNetDefense(); + cdLabel3.setText(stats); + } + + if(c.isCreature()) cdLabel4.setText("Damage: " + c.getDamage() + " Assigned Damage: " + + c.getAssignedDamage()); + + if(c.isPlaneswalker()) cdLabel4.setText("Assigned Damage: " + c.getAssignedDamage()); + + String uniqueID = c.getUniqueNumber() + " "; + cdLabel5.setText("Card ID " + uniqueID); + + //if (c.getCounters(Counters.SPORE) != 0) + // cdLabel6.setText("Spore counters: " + c.getCounters(Counters.SPORE)); + + String tokenText = ""; + if(c.isToken()) tokenText = tokenText + "Token\r\n"; + + String counterText = "\r\n"; + + if(c.getCounters(Counters.AGE) != 0) counterText = counterText + "Age counters: " + + c.getCounters(Counters.AGE) + "\r\n"; + if(c.getCounters(Counters.BLAZE) != 0) counterText = counterText + "Blaze counters: " + + c.getCounters(Counters.BLAZE) + "\r\n"; + if(c.getCounters(Counters.CHARGE) != 0) counterText = counterText + "Charge counters: " + + c.getCounters(Counters.CHARGE) + "\r\n"; + if(c.getCounters(Counters.DIVINITY) != 0) counterText = counterText + "Divinity counters: " + + c.getCounters(Counters.DIVINITY) + "\r\n"; + if(c.getCounters(Counters.FADE) != 0) counterText = counterText + "Fade counters: " + + c.getCounters(Counters.FADE) + "\r\n"; + if(c.getCounters(Counters.HOOFPRINT) != 0) counterText = counterText + "Hoofprint counters: " + + c.getCounters(Counters.HOOFPRINT) + "\r\n"; + if(c.getCounters(Counters.ICE) != 0) counterText = counterText + "Ice counters: " + + c.getCounters(Counters.ICE) + "\r\n"; + if(c.getCounters(Counters.LOYALTY) != 0) counterText = counterText + "Loyalty counters: " + + c.getCounters(Counters.LOYALTY) + "\r\n"; + if(c.getCounters(Counters.MANA) != 0) counterText = counterText + "Mana counters: " + + c.getCounters(Counters.MANA) + "\r\n"; + if(c.getCounters(Counters.P0M1) != 0) counterText = counterText + "0/-1 counters: " + + c.getCounters(Counters.P0M1) + "\r\n"; + if(c.getNetPTCounters() != 0) { //+1/+1 and -1/-1 counters should cancel each other out: + if(c.getNetPTCounters() > 0) counterText = counterText + "+1/+1 counters: " + c.getNetPTCounters() + + "\r\n"; + else { + int m1m1Counters = -1 * c.getNetPTCounters(); + counterText = counterText + "-1/-1 counters: " + m1m1Counters + "\r\n"; + } + } + /*if (c.getCounters(Counters.P1P1) != 0) + counterText = counterText + "+1/+1 counters: " + c.getCounters(Counters.P1P1) + "\r\n"; + if (c.getCounters(Counters.M1M1) != 0) + counterText = counterText + "-1/-1 counters: " + c.getCounters(Counters.M1M1) + "\r\n"; + */ + if(c.getCounters(Counters.QUEST) != 0) + counterText = counterText + "Quest counters: " + c.getCounters(Counters.QUEST) + "\r\n"; + if(c.getCounters(Counters.SPORE) != 0) counterText = counterText + "Spore counters: " + + c.getCounters(Counters.SPORE) + "\r\n"; + + String chosenTypeText = ""; + if(c.getChosenType() != "") chosenTypeText = "(chosen type: " + c.getChosenType() + ")"; + + String equippingText = ""; + if(c.getEquipping().size() > 0) equippingText = "=Equipping " + c.getEquipping().get(0) + "="; + + + String equippedByText = ""; + if(c.getEquippedBy().size() > 0) { + equippedByText = "=Equipped by " + c.getEquippedBy().get(0); + for(int i = 1; i < c.getEquippedBy().size(); i++) { + equippedByText += ", " + c.getEquippedBy().get(i); + } + equippedByText += "="; + } + + String enchantingText = ""; + if(c.getEnchanting().size() > 0) { + enchantingText = "*Enchanting " + c.getEnchanting().get(0) + "*"; + } + + String enchantedByText = ""; + if(c.getEnchantedBy().size() > 0) { + enchantedByText = "*Enchanted by " + c.getEnchantedBy().get(0); + for(int i = 1; i < c.getEnchantedBy().size(); i++) { + enchantedByText += ", " + c.getEnchantedBy().get(i); + } + enchantedByText += "*"; + } + + if(!c.isFaceDown()) this.cdArea.setText(tokenText + c.getText() + counterText + chosenTypeText + + equippingText + equippedByText + enchantingText + enchantedByText); + else this.cdArea.setText(tokenText + counterText); + + cdPanel.setBorder(GuiDisplayUtil.getBorder(c)); + + //picture + picturePanel.removeAll(); + JPanel pic = GuiDisplayUtil.getPicture(c); + pic.setSize(300, 300); + picturePanel.add(pic); + picturePanel.revalidate(); + }//updateCardDetail() + + private void addObservers() { + //Human Hand, Graveyard, and Library totals + {//make sure to not interfer with anything below, since this is a very long method + Observer o = new Observer() { + public void update(Observable a, Object b) { + playerHandValue.setText("" + AllZone.Human_Hand.getCards().length); + playerGraveValue.setText("" + AllZone.Human_Graveyard.getCards().length); + playerLibraryValue.setText("" + AllZone.Human_Library.getCards().length); + playerFBValue.setText("" + CardFactoryUtil.getFlashbackCards(Constant.Player.Human).size()); + playerRemovedValue.setText("" + AllZone.Human_Removed.getCards().length); + + } + }; + AllZone.Human_Hand.addObserver(o); + AllZone.Human_Graveyard.addObserver(o); + AllZone.Human_Library.addObserver(o); + } + + //opponent Hand, Graveyard, and Library totals + {//make sure to not interfer with anything below, since this is a very long method + Observer o = new Observer() { + public void update(Observable a, Object b) { + oppHandValue.setText("" + AllZone.Computer_Hand.getCards().length); + oppGraveValue.setText("" + AllZone.Computer_Graveyard.getCards().length); + oppLibraryValue.setText("" + AllZone.Computer_Library.getCards().length); + oppRemovedValue.setText("" + AllZone.Computer_Removed.getCards().length); + } + }; + AllZone.Computer_Hand.addObserver(o); + AllZone.Computer_Graveyard.addObserver(o); + AllZone.Computer_Library.addObserver(o); + } + + + //opponent life + oppLifeLabel.setText("" + AllZone.Computer_Life.getLife()); + AllZone.Computer_Life.addObserver(new Observer() { + public void update(Observable a, Object b) { + int life = AllZone.Computer_Life.getLife(); + oppLifeLabel.setText("" + life); + } + }); + AllZone.Computer_Life.updateObservers(); + + //player life + playerLifeLabel.setText("" + AllZone.Human_Life.getLife()); + AllZone.Human_Life.addObserver(new Observer() { + public void update(Observable a, Object b) { + int life = AllZone.Human_Life.getLife(); + playerLifeLabel.setText("" + life); + } + }); + AllZone.Human_Life.updateObservers(); + + //stack + AllZone.Stack.addObserver(new Observer() { + public void update(Observable a, Object b) { + stackPanel.removeAll(); + MagicStack stack = AllZone.Stack; + int count = 1; + JLabel label; + + for(int i = stack.size() - 1; 0 <= i; i--) { + label = new JLabel("" + (count++) + ". " + stack.peek(i).getStackDescription()); + + + //update card detail + final CardPanel cardPanel = new CardPanel(stack.peek(i).getSourceCard()); + cardPanel.setLayout(new BorderLayout()); + cardPanel.add(label); + cardPanel.addMouseMotionListener(new MouseMotionAdapter() { + + @Override + public void mouseMoved(MouseEvent me) { + GuiDisplay3.this.updateCardDetail(cardPanel.getCard()); + }//mouseMoved + }); + + stackPanel.add(cardPanel); + } + + stackPanel.revalidate(); + stackPanel.repaint(); + + okButton.requestFocusInWindow(); + + } + }); + AllZone.Stack.updateObservers(); + //END, stack + + + //self hand + AllZone.Human_Hand.addObserver(new Observer() { + public void update(Observable a, Object b) { + PlayerZone pZone = (PlayerZone) a; + JPanel p = playerHandPanel; + p.removeAll(); + + Card c[] = pZone.getCards(); + JPanel panel; + for(int i = 0; i < c.length; i++) { + panel = GuiDisplayUtil.getCardPanel(c[i]); + p.add(panel); + } + + p.setBackground(c2); + p.revalidate(); + p.repaint(); + } + }); + AllZone.Human_Hand.updateObservers(); + //END, self hand + + //self play (land) + AllZone.Human_Play.addObserver(new Observer() { + public void update(Observable a, Object b) { + //PlayerZone pZone = (PlayerZone) a; //unused + JPanel p = playerLandPanel; + p.removeAll(); + + GuiDisplayUtil.setupLandPanel(p, AllZone.Human_Play.getCards()); + p.setBackground(c2); + p.revalidate(); + p.repaint(); + } + }); + AllZone.Human_Play.updateObservers(); + //END - self play (only land) + + + //self play (no land) + AllZone.Human_Play.addObserver(new Observer() { + public void update(Observable a, Object b) { + //PlayerZone pZone = (PlayerZone) a; //unused + JPanel p = playerCreaturePanel; + p.removeAll(); + + GuiDisplayUtil.setupNoLandPanel(p, AllZone.Human_Play.getCards()); + p.setBackground(c2); + p.revalidate(); + p.repaint(); + } + }); + AllZone.Human_Play.updateObservers(); + //END - self play (no land) + + + //computer play (no land) + AllZone.Computer_Play.addObserver(new Observer() { + public void update(Observable a, Object b) { + //PlayerZone pZone = (PlayerZone) a; //unused + JPanel p = oppCreaturePanel; + p.removeAll(); + + GuiDisplayUtil.setupNoLandPanel(p, AllZone.Computer_Play.getCards()); + + p.setBackground(c2); + p.revalidate(); + p.repaint(); + } + }); + AllZone.Computer_Play.updateObservers(); + //END - computer play (no land) + + //computer play (land) + AllZone.Computer_Play.addObserver(new Observer() { + public void update(Observable a, Object b) { + //PlayerZone pZone = (PlayerZone) a; //unused + JPanel p = oppLandPanel; + p.removeAll(); + + GuiDisplayUtil.setupLandPanel(p, AllZone.Computer_Play.getCards()); + p.setBackground(c2); + p.revalidate(); + p.repaint(); + } + }); + AllZone.Computer_Play.updateObservers(); + //END - computer play (only land) + + }//addObservers() + + private void initComponents() { + //Preparing the Frame + setTitle(ForgeProps.getProperty(LANG.PROGRAM_NAME)); + setFont(new Font("Times New Roman", 0, 16)); + getContentPane().setLayout(new BorderLayout()); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent evt) { + concede(); + } + + @Override + public void windowClosed(WindowEvent e) { + File f = ForgeProps.getFile(LAYOUT); + Node layout = pane.getMultiSplitLayout().getModel(); + try { + XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(f))); + encoder.writeObject(layout); + encoder.close(); + } catch(IOException ex) { + ex.printStackTrace(); + } + } + }); + + //making the multi split pane + Node model; + File f = ForgeProps.getFile(LAYOUT); + try { + XMLDecoder decoder = new XMLDecoder(new BufferedInputStream(new FileInputStream(f))); + model = (Node) decoder.readObject(); + decoder.close(); + pane.getMultiSplitLayout().setModel(model); + //pane.getMultiSplitLayout().setFloatingDividers(false); + } catch(Exception ex) { + model = parseModel(""// + + "(ROW "// + + "(COLUMN"// + + " (LEAF weight=0.2 name=info)"// + + " (LEAF weight=0.2 name=compy)"// + + " (LEAF weight=0.2 name=stack)"// + + " (LEAF weight=0.2 name=combat)"// + + " (LEAF weight=0.2 name=human)) "// + + "(COLUMN weight=1"// + + " (LEAF weight=0.2 name=compyLand)"// + + " (LEAF weight=0.2 name=compyPlay)"// + + " (LEAF weight=0.2 name=humanPlay)"// + + " (LEAF weight=0.2 name=humanLand)"// + + " (LEAF weight=0.2 name=humanHand)) "// + + "(COLUMN"// + + " (LEAF weight=0.5 name=detail)"// + + " (LEAF weight=0.5 name=picture)))"); + pane.setModel(model); + } + pane.getMultiSplitLayout().setFloatingDividers(false); + getContentPane().add(pane); + + //adding the individual parts + initMsgYesNo(pane); + initOpp(pane); + initStackCombat(pane); + initPlayer(pane); + initZones(pane); + initCardPicture(pane); + } + + private void initMsgYesNo(JPanel pane) { +// messageArea.setBorder(BorderFactory.createEtchedBorder()); + messageArea.setEditable(false); + messageArea.setFont(getFont()); + messageArea.setLineWrap(true); + messageArea.setWrapStyleWord(true); + + cancelButton.setText("Cancel"); + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + cancelButtonActionPerformed(evt); + okButton.requestFocusInWindow(); + } + }); + okButton.setText("OK"); + okButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + okButtonActionPerformed(evt); + + if(AllZone.Phase.isNeedToNextPhase() == true) { + //for debugging: System.out.println("There better be no nextPhase in the stack."); + AllZone.Phase.setNeedToNextPhase(false); + AllZone.Phase.nextPhase(); + } + okButton.requestFocusInWindow(); + } + }); + okButton.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent arg0) { + // TODO make triggers on escape + int code = arg0.getKeyCode(); + if(code == KeyEvent.VK_ESCAPE) { + cancelButton.doClick(); + } else if(code == KeyEvent.VK_ENTER) { + //same as space + okButton.doClick(); + } + } + }); + + okButton.requestFocusInWindow(); + + //if(okButton.isEnabled()) + //okButton.doClick(); + JPanel yesNoPanel = new JPanel(new FlowLayout()); + yesNoPanel.setBackground(c1); + yesNoPanel.setBorder(new EtchedBorder()); + yesNoPanel.add(cancelButton); + yesNoPanel.add(okButton); + + JPanel panel = new JPanel(new BorderLayout()); + JScrollPane scroll = new JScrollPane(messageArea); + scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + panel.add(scroll); + panel.add(yesNoPanel, BorderLayout.SOUTH); + pane.add(new ExternalPanel(panel), "info"); + } + + private void initOpp(JPanel pane) { + oppLifeLabel.setFont(lifeFont); + oppLifeLabel.setHorizontalAlignment(SwingConstants.CENTER); + + JLabel oppLibraryLabel = new JLabel(ForgeProps.getLocalized(COMPUTER_LIBRARY.TITLE), + SwingConstants.TRAILING); + oppLibraryLabel.setFont(statFont); + + JLabel oppHandLabel = new JLabel(ForgeProps.getLocalized(COMPUTER_HAND.TITLE), SwingConstants.TRAILING); + oppHandLabel.setFont(statFont); + + //JLabel oppGraveLabel = new JLabel("Grave:", SwingConstants.TRAILING); + JButton oppGraveButton = new JButton(COMPUTER_GRAVEYARD_ACTION); + oppGraveButton.setText((String) COMPUTER_GRAVEYARD_ACTION.getValue("buttonText")); + oppGraveButton.setMargin(new Insets(0, 0, 0, 0)); + oppGraveButton.setHorizontalAlignment(SwingConstants.TRAILING); + oppGraveButton.setFont(statFont); + + + JPanel gravePanel = new JPanel(new BorderLayout()); + gravePanel.add(oppGraveButton, BorderLayout.EAST); + + JButton oppRemovedButton = new JButton(COMPUTER_REMOVED_ACTION); + oppRemovedButton.setText((String) COMPUTER_REMOVED_ACTION.getValue("buttonText")); + oppRemovedButton.setMargin(new Insets(0, 0, 0, 0)); + //removedButton.setHorizontalAlignment(SwingConstants.TRAILING); + oppRemovedButton.setFont(statFont); + + + oppHandValue.setFont(statFont); + oppHandValue.setHorizontalAlignment(SwingConstants.LEADING); + + oppLibraryValue.setFont(statFont); + oppLibraryValue.setHorizontalAlignment(SwingConstants.LEADING); + + oppGraveValue.setFont(statFont); + oppGraveValue.setHorizontalAlignment(SwingConstants.LEADING); + + oppRemovedValue.setFont(statFont); + oppRemovedValue.setHorizontalAlignment(SwingConstants.LEADING); + + JPanel oppNumbersPanel = new JPanel(new GridLayout(0, 2, 3, 1)); + oppNumbersPanel.add(oppHandLabel); + oppNumbersPanel.add(oppHandValue); + oppNumbersPanel.add(oppRemovedButton); + oppNumbersPanel.add(oppRemovedValue); + oppNumbersPanel.add(oppLibraryLabel); + oppNumbersPanel.add(oppLibraryValue); + oppNumbersPanel.add(gravePanel); + oppNumbersPanel.add(oppGraveValue); + oppNumbersPanel.setBackground(c1); + + JPanel oppPanel = new JPanel(); + oppPanel.setBackground(c1); + oppPanel.setBorder(new TitledBorder(new EtchedBorder(), ForgeProps.getLocalized(COMPUTER_TITLE))); + oppPanel.setLayout(new BorderLayout()); + oppPanel.add(oppNumbersPanel, BorderLayout.WEST); + oppPanel.add(oppLifeLabel, BorderLayout.EAST); + pane.add(new ExternalPanel(oppPanel), "compy"); + } + + private void initStackCombat(JPanel pane) { + stackPanel.setLayout(new GridLayout(0, 1, 10, 10)); + JScrollPane stackPane = new JScrollPane(stackPanel); + stackPane.setBorder(new EtchedBorder()); + pane.add(new ExternalPanel(stackPane), "stack"); + + combatArea.setEditable(false); + combatArea.setFont(getFont()); + combatArea.setLineWrap(true); + combatArea.setWrapStyleWord(true); + combatArea.setBackground(c1); + + JScrollPane combatPane = new JScrollPane(combatArea); + combatPane.setBackground(c1); + + combatPane.setBorder(new TitledBorder(new EtchedBorder(), ForgeProps.getLocalized(COMBAT))); + pane.add(new ExternalPanel(combatPane), "combat"); + } + + private void initPlayer(JPanel pane) { + int fontSize = 12; + playerLifeLabel.setFont(lifeFont); + playerLifeLabel.setHorizontalAlignment(SwingConstants.CENTER); + + + JLabel playerLibraryLabel = new JLabel(ForgeProps.getLocalized(HUMAN_LIBRARY.TITLE), + SwingConstants.TRAILING); + playerLibraryLabel.setFont(statFont); + + JLabel playerHandLabel = new JLabel(ForgeProps.getLocalized(HUMAN_HAND.TITLE), SwingConstants.TRAILING); + playerHandLabel.setFont(statFont); + + //JLabel playerGraveLabel = new JLabel("Grave:", SwingConstants.TRAILING); + JButton playerGraveButton = new JButton(HUMAN_GRAVEYARD_ACTION); + playerGraveButton.setText((String) HUMAN_GRAVEYARD_ACTION.getValue("buttonText")); + playerGraveButton.setMargin(new Insets(0, 0, 0, 0)); + playerGraveButton.setHorizontalAlignment(SwingConstants.TRAILING); + playerGraveButton.setFont(statFont); + + + JButton playerFlashBackButton = new JButton(HUMAN_FLASHBACK_ACTION); + playerFlashBackButton.setText((String) HUMAN_FLASHBACK_ACTION.getValue("buttonText")); + playerFlashBackButton.setMargin(new Insets(0, 0, 0, 0)); + playerFlashBackButton.setHorizontalAlignment(SwingConstants.TRAILING); + playerFlashBackButton.setFont(statFont); + + + JPanel gravePanel = new JPanel(new BorderLayout()); + gravePanel.add(playerGraveButton, BorderLayout.EAST); + + JPanel playerFBPanel = new JPanel(new BorderLayout()); + playerFBPanel.add(playerFlashBackButton, BorderLayout.EAST); + + JButton playerRemovedButton = new JButton(HUMAN_REMOVED_ACTION); + playerRemovedButton.setText((String) HUMAN_REMOVED_ACTION.getValue("buttonText")); + playerRemovedButton.setMargin(new Insets(0, 0, 0, 0)); + //removedButton.setHorizontalAlignment(SwingConstants.TRAILING); + playerRemovedButton.setFont(statFont); + + + playerHandValue.setFont(statFont); + playerHandValue.setHorizontalAlignment(SwingConstants.LEADING); + + playerLibraryValue.setFont(statFont); + playerLibraryValue.setHorizontalAlignment(SwingConstants.LEADING); + + playerGraveValue.setFont(statFont); + playerGraveValue.setHorizontalAlignment(SwingConstants.LEADING); + + playerFBValue.setFont(statFont); + playerGraveValue.setHorizontalAlignment(SwingConstants.LEADING); + + playerRemovedValue.setFont(new Font("MS Sans Serif", 0, fontSize)); + playerRemovedValue.setHorizontalAlignment(SwingConstants.LEADING); + + JPanel playerNumbersPanel = new JPanel(new GridLayout(0, 2, 5, 1)); + playerNumbersPanel.add(playerHandLabel); + playerNumbersPanel.add(playerHandValue); + playerNumbersPanel.add(playerRemovedButton); + playerNumbersPanel.add(playerRemovedValue); + playerNumbersPanel.add(playerLibraryLabel); + playerNumbersPanel.add(playerLibraryValue); + playerNumbersPanel.add(gravePanel); + playerNumbersPanel.add(playerGraveValue); + playerNumbersPanel.add(playerFBPanel); + playerNumbersPanel.add(playerFBValue); + playerNumbersPanel.setBackground(c1); + + JPanel playerPanel = new JPanel(); + playerPanel.setBackground(c1); + playerPanel.setBorder(new TitledBorder(new EtchedBorder(), ForgeProps.getLocalized(HUMAN_TITLE))); + playerPanel.setLayout(new BorderLayout()); + playerPanel.add(playerNumbersPanel, BorderLayout.WEST); + playerPanel.add(playerLifeLabel, BorderLayout.EAST); + pane.add(new ExternalPanel(playerPanel), "human"); + } + + private void initZones(JPanel pane) { + JPanel[] zones = {oppLandPanel, oppCreaturePanel, playerCreaturePanel, playerLandPanel, playerHandPanel}; + String[] names = {"compyLand", "compyPlay", "humanPlay", "humanLand", "humanHand"}; + for(int i = 0; i < names.length; i++) { + zones[i].setLayout(null); + zones[i].setBorder(BorderFactory.createEtchedBorder()); + Dimension d = zones[i].getPreferredSize(); + d.height = 100; + zones[i].setPreferredSize(d); + pane.add(new ExternalPanel(new JScrollPane(zones[i])), names[i]); + } + playerHandPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); + } + + private void initCardPicture(JPanel pane) { + cdLabel1.setFont(getFont()); + cdLabel1.setHorizontalAlignment(SwingConstants.CENTER); + cdLabel1.setText("jLabel3"); + + cdLabel2.setFont(getFont()); + cdLabel2.setHorizontalAlignment(SwingConstants.CENTER); + cdLabel2.setText("jLabel4"); + + cdLabel3.setFont(getFont()); + cdLabel3.setHorizontalAlignment(SwingConstants.CENTER); +//~ cdLabel3.setText("jLabel5"); + + cdLabel4.setFont(getFont()); +//~ cdLabel4.setText("jLabel6"); + + cdLabel5.setFont(getFont()); +//~ cdLabel5.setText("jLabel7"); + + cdLabel6.setFont(getFont()); +//~ cdLabel6.setText("jLabel8"); + + JPanel cdLabels = new JPanel(new GridLayout(6, 0, 0, 5)); + cdLabels.add(cdLabel1); + cdLabels.add(cdLabel2); + cdLabels.add(cdLabel3); + cdLabels.add(cdLabel4); + cdLabels.add(cdLabel6); + cdLabels.add(cdLabel5); + //cdLabels.setBackground(c1); + + //StyledEditorKit se = new StyledEditorKit(); + + //cdArea.setEditorKit(new StyledEditorKit()); + cdArea.setFont(getFont()); + cdArea.setLineWrap(true); + cdArea.setWrapStyleWord(true); + + JScrollPane cdPane = new JScrollPane(cdArea); + + cdPanel.setLayout(new GridLayout(2, 1, 0, 5)); + cdPanel.setBorder(new EtchedBorder()); + cdPanel.add(cdLabels); + cdPanel.add(cdPane); + pane.add(new ExternalPanel(cdPanel), "detail"); + + //~ picturePanel.setBorder(new EtchedBorder()); + + picturePanel.setLayout(new BoxLayout(picturePanel, BoxLayout.Y_AXIS)); + picturePanel.setBackground(c1); + pane.add(new ExternalPanel(picturePanel), "picture"); + } + + private void cancelButtonActionPerformed(ActionEvent evt) { + inputControl.selectButtonCancel(); + } + + private void okButtonActionPerformed(ActionEvent evt) { + inputControl.selectButtonOK(); + } + + /** + * Exit the Application + */ + private void concede() { + dispose(); + Constant.Runtime.WinLose.addLose(); + new Gui_WinLose(); + } + + public boolean stopEOT() { + return eotCheckboxForMenu.isSelected(); + } + + public static JCheckBoxMenuItem eotCheckboxForMenu = new JCheckBoxMenuItem("Stop at End of Turn", false); + + MultiSplitPane pane = new MultiSplitPane(); + JButton cancelButton = new JButton(); + JButton okButton = new JButton(); + JTextArea messageArea = new JTextArea(1, 10); + JTextArea cdArea = new JTextArea(4, 12); + //JEditorPane cdArea = new JEditorPane(); + JTextArea combatArea = new JTextArea(); + JPanel stackPanel = new JPanel(); + JPanel oppLandPanel = new JPanel(); + JPanel oppCreaturePanel = new JPanel(); + JPanel playerCreaturePanel = new JPanel(); + JPanel playerLandPanel = new JPanel(); + //JPanel playerLandPanel = new ImageJPanel("forest.jpg"); + //JPanel playerLandPanel = new BackgroundPanel("bg1.jpg"); + JPanel playerHandPanel = new JPanel(); + //JPanel playerHandPanel = new BackgroundPanel("bg2.jpg"); + JPanel cdPanel = new JPanel(); + //JPanel picturePanel = new JPanel(); + JPanel picturePanel = new JPanel(); + JLabel oppLifeLabel = new JLabel(); + JLabel playerLifeLabel = new JLabel(); + JLabel cdLabel1 = new JLabel(); + JLabel cdLabel2 = new JLabel(); + JLabel cdLabel3 = new JLabel(); + JLabel cdLabel4 = new JLabel(); + JLabel cdLabel5 = new JLabel(); + JLabel cdLabel6 = new JLabel(); + JLabel oppHandValue = new JLabel(); + JLabel oppLibraryValue = new JLabel(); + JLabel oppGraveValue = new JLabel(); + JLabel oppRemovedValue = new JLabel(); + JLabel playerHandValue = new JLabel(); + JLabel playerLibraryValue = new JLabel(); + JLabel playerGraveValue = new JLabel(); + JLabel playerFBValue = new JLabel(); + JLabel playerRemovedValue = new JLabel(); + + private class ZoneAction extends ForgeAction { + private static final long serialVersionUID = -5822976087772388839L; + private PlayerZone zone; + private String title; + + public ZoneAction(PlayerZone zone, String property) { + super(property); + title = ForgeProps.getLocalized(property + "/title"); + this.zone = zone; + } + + public void actionPerformed(ActionEvent e) { + Card[] c = getCards(); + + if(AllZone.NameChanger.shouldChangeCardName()) c = AllZone.NameChanger.changeCard(c); + + if(c.length == 0) AllZone.Display.getChoiceOptional(title, new String[] {"no cards"}); + else { + Card choice = AllZone.Display.getChoiceOptional(title, c); + if(choice != null) doAction(choice); + } + } + /* + protected PlayerZone getZone() { + return zone; + } + */ + protected Card[] getCards() { + return zone.getCards(); + } + + protected void doAction(Card c) {} + } + + private class ConcedeAction extends ForgeAction { + + private static final long serialVersionUID = -6976695235601916762L; + + public ConcedeAction() { + super(CONCEDE); + } + + public void actionPerformed(ActionEvent e) { + concede(); + } + } +} + +//very hacky + + +class Gui_MultipleBlockers3 extends JFrame { + private static final long serialVersionUID = 7622818310877381045L; + + private int assignDamage; + private Card att; + private GuiDisplay3 guiDisplay; + + private BorderLayout borderLayout1 = new BorderLayout(); + private JPanel mainPanel = new JPanel(); + private JScrollPane jScrollPane1 = new JScrollPane(); + private JLabel numberLabel = new JLabel(); + private JPanel jPanel3 = new JPanel(); + private BorderLayout borderLayout3 = new BorderLayout(); + private JPanel creaturePanel = new JPanel(); + + + public static void main(String[] args) { + CardList list = new CardList(); + list.add(AllZone.CardFactory.getCard("Elvish Piper", "")); + list.add(AllZone.CardFactory.getCard("Lantern Kami", "")); + list.add(AllZone.CardFactory.getCard("Frostling", "")); + list.add(AllZone.CardFactory.getCard("Frostling", "")); + + for(int i = 0; i < 2; i++) + new Gui_MultipleBlockers3(null, list, i + 1, null); + } + + Gui_MultipleBlockers3(Card attacker, CardList creatureList, int damage, GuiDisplay3 display) { + this(); + assignDamage = damage; + updateDamageLabel();//update user message about assigning damage + guiDisplay = display; + att = attacker; + + for(int i = 0; i < creatureList.size(); i++) + creaturePanel.add(GuiDisplayUtil.getCardPanel(creatureList.get(i))); + + + JDialog dialog = new JDialog(this, true); + dialog.setTitle("Multiple Blockers"); + dialog.setContentPane(mainPanel); + dialog.setSize(470, 260); + dialog.setVisible(true); + } + + public Gui_MultipleBlockers3() { + try { + jbInit(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } +// setSize(470, 280); +// show(); + } + + private void jbInit() throws Exception { + this.getContentPane().setLayout(borderLayout1); + this.setTitle("Multiple Blockers"); + mainPanel.setLayout(null); + numberLabel.setHorizontalAlignment(SwingConstants.CENTER); + numberLabel.setHorizontalTextPosition(SwingConstants.CENTER); + numberLabel.setText("Assign"); + numberLabel.setBounds(new Rectangle(52, 30, 343, 24)); + jPanel3.setLayout(borderLayout3); + jPanel3.setBounds(new Rectangle(26, 75, 399, 114)); + creaturePanel.addMouseListener(new java.awt.event.MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + creaturePanel_mousePressed(e); + } + }); + creaturePanel.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { + @Override + public void mouseMoved(MouseEvent e) { + creaturePanel_mouseMoved(e); + } + }); + mainPanel.add(jPanel3, null); + jPanel3.add(jScrollPane1, BorderLayout.CENTER); + mainPanel.add(numberLabel, null); + jScrollPane1.getViewport().add(creaturePanel, null); + this.getContentPane().add(mainPanel, BorderLayout.CENTER); + } + + void okButton_actionPerformed(ActionEvent e) { + dispose(); + } + + void creaturePanel_mousePressed(MouseEvent e) { + Object o = creaturePanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) { + CardPanel cardPanel = (CardPanel) o; + Card c = cardPanel.getCard(); + //c.setAssignedDamage(c.getAssignedDamage() + 1); + CardList cl = new CardList(); + cl.add(att); + AllZone.GameAction.setAssignedDamage(c, cl, c.getAssignedDamage() + 1); + + if(guiDisplay != null) guiDisplay.updateCardDetail(c); + } + //reduce damage, show new user message, exit if necessary + assignDamage--; + updateDamageLabel(); + if(assignDamage == 0) dispose(); + }//creaturePanel_mousePressed() + + void updateDamageLabel() { + numberLabel.setText("Assign " + assignDamage + " damage - click on card to assign damage"); + } + + void creaturePanel_mouseMoved(MouseEvent e) { + Object o = creaturePanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) { + CardPanel cardPanel = (CardPanel) o; + Card c = cardPanel.getCard(); + + if(guiDisplay != null) guiDisplay.updateCardDetail(c); + } + } +} diff --git a/src/GuiDisplayUtil.java b/src/GuiDisplayUtil.java new file mode 100644 index 00000000000..5c77b0fa633 --- /dev/null +++ b/src/GuiDisplayUtil.java @@ -0,0 +1,894 @@ +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.Point; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; +import java.awt.event.MouseMotionListener; +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.border.Border; + +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + + +public class GuiDisplayUtil implements NewConstants { + public static JPanel getCardPanel(Card c) { + return getCardPanel(c, c.getName()); + } + + public static JPanel getCardPanel(Card c, String name) { + JPanel panel = new CardPanel(c); + panel.setBorder(getBorder(c)); + Image cardImage = ImageCache.getImage(c); + + if(cardImage != null) { + + panel.setLayout(new GridLayout(1, 1)); + JLabel imageLabel = new JLabel(); + + + if(c.isBasicLand()) { + String basicLandSuffix = ""; + if(c.getRandomPicture() != 0) { + basicLandSuffix = Integer.toString(c.getRandomPicture()); + name += basicLandSuffix; + } + } else if(c.isFaceDown()) name = "Morph"; + + if(c.isTapped()) { + cardImage = ImageUtil.getTappedImage(cardImage, name); + } + imageLabel.setIcon(new ImageIcon(cardImage)); + panel.add(imageLabel); + } else { + + panel.setLayout(new GridLayout(4, 1)); + + if(c.isFaceDown()) name = "Morph"; + + panel.add(new JLabel(name + " " + c.getManaCost())); + panel.add(new JLabel(formatCardType(c))); + + JPanel p1 = new JPanel(); + panel.add(p1); + JLabel tapLabel = new JLabel(); + p1.add(tapLabel); + + if(c.isTapped()) { + if(!c.isCreature()) { + panel.setLayout(new GridLayout(3, 1)); + } + + p1.setBackground(Color.white); + tapLabel.setText("Tapped"); + } + String stats = c.getNetAttack() + " / " + c.getNetDefense(); + + if(c.isCreature()) panel.add(new JLabel(stats)); + } + + return panel; + }//getCardPanel(Card c, String name) + + public static Border getBorder(Card card) { + Color color; + if(card.isArtifact()) color = Color.gray; + else if(CardUtil.getColor(card).equals(Constant.Color.Black) || card.getName().equals("Swamp") + || card.getName().equals("Bog")) color = Color.black; + else if(CardUtil.getColor(card).equals(Constant.Color.Green) || card.getName().equals("Forest") + || card.getName().equals("Grass")) color = new Color(0, 220, 39); + else if(CardUtil.getColor(card).equals(Constant.Color.White) || card.getName().equals("Plains") + || card.getName().equals("White Sand")) color = Color.white; + else if(CardUtil.getColor(card).equals(Constant.Color.Red) || card.getName().equals("Mountain") + || card.getName().equals("Rock")) color = Color.red; + else if(CardUtil.getColor(card).equals(Constant.Color.Blue) || card.getName().equals("Island") + || card.getName().equals("Underwater")) color = Color.blue; + else color = Color.black; + + if(CardUtil.getColors(card).size() != 1) { + color = Color.orange; + } + + if(!card.isArtifact()) { + int r = color.getRed(); + int g = color.getGreen(); + int b = color.getBlue(); + + int shade = 10; + + r -= shade; + g -= shade; + b -= shade; + + r = Math.max(0, r); + g = Math.max(0, g); + b = Math.max(0, b); + + color = new Color(r, g, b); + } + //~ + + return BorderFactory.createLineBorder(color, 2); + } + + public static MouseMotionListener getCardDetailMouse(final GuiDisplay3 visual) { + return new MouseMotionAdapter() { + @Override + public void mouseMoved(MouseEvent me) { + JPanel panel = (JPanel) me.getSource(); + Object o = panel.getComponentAt(me.getPoint()); + + if((o != null) && (o instanceof CardPanel)) { + CardPanel cardPanel = (CardPanel) o; + visual.updateCardDetail(cardPanel.getCard()); + } + }//mouseMoved + }; + } + + public static MouseMotionListener getCardDetailMouse(final GuiDisplay2 visual) { + return new MouseMotionAdapter() { + @Override + public void mouseMoved(MouseEvent me) { + JPanel panel = (JPanel) me.getSource(); + Object o = panel.getComponentAt(me.getPoint()); + + if((o != null) && (o instanceof CardPanel)) { + CardPanel cardPanel = (CardPanel) o; + visual.updateCardDetail(cardPanel.getCard()); + } + }//mouseMoved + }; + } + + + public static String formatCardType(Card card) { + + ArrayList list = card.getType(); + String returnString = ""; + String s; + + for(int i = 0; i < list.size(); i++) { + s = list.get(i).toString(); + if(s.equals("Creature") || s.equals("Land")) { + s += " - "; + } else s += " "; + + returnString += s; + } + + return returnString; + } + + public static JPanel getPicture(Card c) { + if(AllZone.NameChanger.shouldChangeCardName()) return new JPanel(); + + + String suffix = ".jpg"; + String filename = ""; + if(!c.isFaceDown()) { + String basicLandSuffix = ""; + if(c.isBasicLand()) { + if(c.getRandomPicture() != 0) basicLandSuffix = Integer.toString(c.getRandomPicture()); + } + + filename = cleanString(c.getImageName()) + basicLandSuffix + suffix; + } else filename = "morph" + suffix; + File file = new File(ForgeProps.getFile(IMAGE_BASE), filename); + + //try current directory + if(!file.exists()) { + filename = cleanString(c.getName()) + suffix; + file = new File(filename); + } + + + if(file.exists()) { + return new PicturePanel(file); + } else { + JPanel p = new JPanel(); + + JTextArea text = new JTextArea("\r\n\r\n" + filename, 10, 15); + Font f = text.getFont(); + f = f.deriveFont(f.getSize() + 2.0f); + text.setFont(f); + text.setBackground(p.getBackground()); + + p.add(text); + + if(c.isToken()) return new JPanel(); + + return p; + }//else + }//getPicture() + + public static String cleanString(String in) { + StringBuffer out = new StringBuffer(); + char c; + for(int i = 0; i < in.length(); i++) { + c = in.charAt(i); + if(c == ' ' || c == '-') out.append('_'); + else if(Character.isLetterOrDigit(c)) { + out.append(c); + } + } + return out.toString().toLowerCase(); + } + + public static void setupNoLandPanel(JPanel j, Card c[]) { + ArrayList a = new ArrayList(); + /* + for(int i = 0; i < c.length; i++) + if(c[i].isCreature() || c[i].isGlobalEnchantment() || c[i].isArtifact() || c[i].isPlaneswalker()) + a.add(c[i]); + */ + + /* + + //creatures or planeswalkers + for(int i = 0; i < c.length; i++) + //!artifact because of Memnarch turning planeswalkers into artifacts. + if (c[i].isCreature() || (c[i].isPlaneswalker() && !c[i].isArtifact())) + a.add(c[i]); + //(non-creature, non-enchantment,non-land) artifacts + for(int i = 0; i < c.length; i++) + if (c[i].isArtifact() && !c[i].isCreature() && !c[i].isLand() && !c[i].isGlobalEnchantment() ) + a.add(c[i]); + //(non-creature) enchantments + for(int i = 0; i < c.length; i++) + if (c[i].isGlobalEnchantment() && !c[i].isCreature()) + a.add(c[i]); + + */ + + for(int i = 0; i < c.length; i++) { + a.add(c[i]); + } + + setupNoLandPermPanel(j, a, true); + } + + public static void setupLandPanel(JPanel j, Card c[]) { + ArrayList a = new ArrayList(); + for(int i = 0; i < c.length; i++) + if((!(c[i].isCreature() || c[i].isEnchantment() || c[i].isArtifact() || c[i].isPlaneswalker()) || (c[i].isLand() + && c[i].isArtifact() && !c[i].isCreature() && !c[i].isEnchantment())) + && !AllZone.GameAction.isAttachee(c[i]) || (c[i].getName().startsWith("Mox") && !c[i].getName().equals("Mox Diamond")) ) + a.add(c[i]); + + setupPanel(j, a, true); + } + + /* + private static void setupPanel(JPanel p, ArrayList list) { + setupPanel(p, list, false); + } + */ + + //list holds Card objects + //puts local enchanments in the right order + //adds "<<" to local enchanments names + private static void setupPanel(JPanel p, ArrayList list, boolean stack) { + + int maxY = 0; + int maxX = 0; + //remove all local enchantments + + Card c; + /* + for(int i = 0; i < list.size(); i++) + { + c = (Card)list.get(i); + if(c.isLocalEnchantment()) + list.remove(i); + } + + //add local enchantments to the permanents + //put local enchantments "next to" the permanent they are enchanting + //the inner for loop is backward so permanents with more than one local enchantments are in the right order + Card ca[]; + for(int i = 0; i < list.size(); i++) + { + c = (Card)list.get(i); + if(c.hasAttachedCards()) + { + ca = c.getAttachedCards(); + for(int inner = ca.length - 1; 0 <= inner; inner--) + list.add(i + 1, ca[inner]); + } + } + */ + + if(stack) { + // add all Cards in list to the GUI, add arrows to Local Enchantments + + ArrayList manaPool = getCard(list, "Mana Pool"); + ArrayList enchantedLands = getEnchantedLands(list); + ArrayList basicBlues = getBasics(list, Constant.Color.Blue); + ArrayList basicReds = getBasics(list, Constant.Color.Red); + ArrayList basicBlacks = getBasics(list, Constant.Color.Black); + ArrayList basicGreens = getBasics(list, Constant.Color.Green); + ArrayList basicWhites = getBasics(list, Constant.Color.White); + ArrayList badlands = getNonBasicLand(list, "Badlands"); + ArrayList bayou = getNonBasicLand(list, "Bayou"); + ArrayList plateau = getNonBasicLand(list, "Plateau"); + ArrayList scrubland = getNonBasicLand(list, "Scrubland"); + ArrayList savannah = getNonBasicLand(list, "Savannah"); + ArrayList taiga = getNonBasicLand(list, "Taiga"); + ArrayList tropicalIsland = getNonBasicLand(list, "Tropical Island"); + ArrayList tundra = getNonBasicLand(list, "Tundra"); + ArrayList undergroundSea = getNonBasicLand(list, "Underground Sea"); + ArrayList volcanicIsland = getNonBasicLand(list, "Volcanic Island"); + + ArrayList nonBasics = getNonBasics(list); + + ArrayList moxEmerald = getMoxen(list, "Mox Emerald"); + ArrayList moxJet = getMoxen(list, "Mox Jet"); + ArrayList moxPearl = getMoxen(list, "Mox Pearl"); + ArrayList moxRuby = getMoxen(list, "Mox Ruby"); + ArrayList moxSapphire = getMoxen(list, "Mox Sapphire"); + //ArrayList moxDiamond = getMoxen(list, "Mox Diamond"); + + list = new ArrayList(); + list.addAll(manaPool); + list.addAll(enchantedLands); + list.addAll(basicBlues); + list.addAll(basicReds); + list.addAll(basicBlacks); + list.addAll(basicGreens); + list.addAll(basicWhites); + list.addAll(badlands); + list.addAll(bayou); + list.addAll(plateau); + list.addAll(scrubland); + list.addAll(savannah); + list.addAll(taiga); + list.addAll(tropicalIsland); + list.addAll(tundra); + list.addAll(undergroundSea); + list.addAll(volcanicIsland); + + list.addAll(nonBasics); + + list.addAll(moxEmerald); + list.addAll(moxJet); + list.addAll(moxPearl); + list.addAll(moxRuby); + list.addAll(moxSapphire); + //list.addAll(moxDiamond); + + + int atInStack = 0; + + int marginX = 5; + int marginY = 5; + + int x = marginX; + + int cardOffset = 10; + + String color = ""; + ArrayList cards = new ArrayList(); + + ArrayList connectedCards = new ArrayList(); + + boolean nextEnchanted = false; + Card prevCard = null; + int nextXIfNotStacked = 0; + for(int i = 0; i < list.size(); i++) { + JPanel addPanel; + c = list.get(i); + + addPanel = getCardPanel(c); + + + boolean startANewStack = false; + + if(!isStackable(c)) { + startANewStack = true; + } else { + String newColor = c.getName(); //CardUtil.getColor(c); + + if(!newColor.equals(color)) { + startANewStack = true; + color = newColor; + } + } + + if(i == 0) { + startANewStack = false; + } + + + if(!startANewStack && atInStack == 4) { + startANewStack = true; + } + + + if(c.isAura() && c.isEnchanting() && !nextEnchanted) startANewStack = false; + else if(c.isAura() && c.isEnchanting()) { + startANewStack = true; + nextEnchanted = false; + } + + if(c.isLand() && c.isEnchanted()) { + startANewStack = false; + nextEnchanted = true; + } + + + //very hacky, but this is to ensure enchantment stacking occurs correctly when a land is enchanted, and there are more lands of that same name + + else if((prevCard != null && c.isLand() && prevCard.isLand() && prevCard.isEnchanted() && prevCard.getName().equals( + c.getName()))) startANewStack = true; + else if(prevCard != null && c.isLand() && prevCard.isLand() + && !prevCard.getName().equals(c.getName())) startANewStack = true; + + /* + if (c.getName().equals("Squirrel Nest")) { + startANewStack = true; + System.out.println("startANewStack: " + startANewStack); + } + */ + if(c.isAura() && c.isEnchanting() && prevCard != null && prevCard.getName().equals("Mana Pool")) + startANewStack = true; + + + if(startANewStack) { + setupConnectedCards(connectedCards); + connectedCards.clear(); + + // Fixed distance if last was a stack, looks a bit nicer + if(atInStack > 1) { + x += Math.max(addPanel.getPreferredSize().width, addPanel.getPreferredSize().height) + + marginX; + } else { + x = nextXIfNotStacked; + } + + atInStack = 0; + } else { + if(i != 0) { + x += cardOffset; + } + } + + nextXIfNotStacked = x + marginX + addPanel.getPreferredSize().width; + + int xLoc = x; + + int yLoc = marginY; + yLoc += atInStack * cardOffset; + + addPanel.setLocation(new Point(xLoc, yLoc)); + addPanel.setSize(addPanel.getPreferredSize()); + + + cards.add(addPanel); + + connectedCards.add((CardPanel) addPanel); + + atInStack++; + prevCard = c; + } + + setupConnectedCards(connectedCards); + connectedCards.clear(); + + + for(int i = cards.size() - 1; i >= 0; i--) { + JPanel card = cards.get(i); + //maxX = Math.max(maxX, card.getLocation().x + card.getSize().width + marginX); + maxY = Math.max(maxY, card.getLocation().y + card.getSize().height + marginY); + p.add(card); + } + + maxX = nextXIfNotStacked; + + //System.out.println("x:" + maxX + ", y:" + maxY); + if(maxX > 0 && maxY > 0) { //p.getSize().width || maxY > p.getSize().height) { +// p.setSize(new Dimension(maxX, maxY)); + p.setPreferredSize(new Dimension(maxX, maxY)); + } + + } else { + //add all Cards in list to the GUI, add arrows to Local Enchantments + JPanel addPanel; + for(int i = 0; i < list.size(); i++) { + c = list.get(i); + /*if(c.isLocalEnchantment()) + addPanel = getCardPanel(c, "<< " +c.getName()); + else + addPanel = getCardPanel(c); + */ + addPanel = getCardPanel(c); + + p.add(addPanel); + } + } + }//setupPanel() + + @SuppressWarnings("unchecked") + private static void setupNoLandPermPanel(JPanel p, ArrayList list, boolean stack) { + + int maxY = 0; + int maxX = 0; + + Card c; + + if(stack) { + // add all Cards in list to the GUI, add arrows to Local Enchantments + + ArrayList planeswalkers = getPlaneswalkers(list); + ArrayList equippedEnchantedCreatures = getEquippedEnchantedCreatures(list); //this will also fetch the equipment and/or enchantment + ArrayList nonTokenCreatures = getNonTokenCreatures(list); + ArrayList tokenCreatures = getTokenCreatures(list); + + //sort tokenCreatures by name (TODO: fix the warning message somehow) + Collections.sort(tokenCreatures, new Comparator() { + public int compare(Object o1, Object o2) { + Card c1 = (Card) o1; + Card c2 = (Card) o2; + return c1.getName().compareTo(c2.getName()); + } + }); + + ArrayList artifacts = getNonCreatureArtifacts(list); + ArrayList enchantments = getGlobalEnchantments(list); + //ArrayList nonBasics = getNonBasics(list); + + + list = new ArrayList(); + list.addAll(planeswalkers); + list.addAll(equippedEnchantedCreatures); + list.addAll(nonTokenCreatures); + list.addAll(tokenCreatures); + list.addAll(artifacts); + list.addAll(enchantments); + + + int atInStack = 0; + + int marginX = 5; + int marginY = 5; + + int x = marginX; + + int cardOffset = 10; + + String color = ""; + ArrayList cards = new ArrayList(); + + ArrayList connectedCards = new ArrayList(); + + + boolean nextEquippedEnchanted = false; + int nextXIfNotStacked = 0; + Card prevCard = null; + for(int i = 0; i < list.size(); i++) { + JPanel addPanel; + c = list.get(i); + addPanel = getCardPanel(c); + + boolean startANewStack = false; + + if(!isStackable(c)) { + startANewStack = true; + } else { + String newColor = c.getName(); //CardUtil.getColor(c); + + if(!newColor.equals(color)) { + startANewStack = true; + color = newColor; + } + } + + + if(i == 0) { + startANewStack = false; + } + + if(!startANewStack && atInStack == 4) { + startANewStack = true; + } + + + if((c.isEquipment() || c.isAura()) && (c.isEquipping() || c.isEnchanting()) + && !nextEquippedEnchanted) startANewStack = false; + else if((c.isEquipment() || c.isAura()) && (c.isEquipping() || c.isEnchanting())) { + startANewStack = true; + nextEquippedEnchanted = false; + } + + if(c.isCreature() && (c.isEquipped() || c.isEnchanted())) { + startANewStack = false; + nextEquippedEnchanted = true; + } + //very hacky, but this is to ensure equipment stacking occurs correctly when a token is equipped/enchanted, and there are more tokens of that same name + else if((prevCard != null && c.isCreature() && prevCard.isCreature() + && (prevCard.isEquipped() || prevCard.isEnchanted()) && prevCard.getName().equals( + c.getName()))) startANewStack = true; + else if(prevCard != null && c.isCreature() && prevCard.isCreature() + && !prevCard.getName().equals(c.getName())) startANewStack = true; + + if( ( (c.isAura() && c.isEnchanting()) || (c.isEquipment() && c.isEquipping()) ) && prevCard != null && prevCard.isPlaneswalker()) + startANewStack = true; + + if(startANewStack) { + setupConnectedCards(connectedCards); + connectedCards.clear(); + + // Fixed distance if last was a stack, looks a bit nicer + if(atInStack > 1) { + x += Math.max(addPanel.getPreferredSize().width, addPanel.getPreferredSize().height) + + marginX; + } else { + x = nextXIfNotStacked; + } + + atInStack = 0; + } else { + if(i != 0) { + x += cardOffset; + } + } + + nextXIfNotStacked = x + marginX + addPanel.getPreferredSize().width; + + int xLoc = x; + + int yLoc = marginY; + yLoc += atInStack * cardOffset; + + addPanel.setLocation(new Point(xLoc, yLoc)); + addPanel.setSize(addPanel.getPreferredSize()); + + + cards.add(addPanel); + + connectedCards.add((CardPanel) addPanel); + + atInStack++; + prevCard = c; + } + + setupConnectedCards(connectedCards); + connectedCards.clear(); + + + for(int i = cards.size() - 1; i >= 0; i--) { + JPanel card = cards.get(i); + //maxX = Math.max(maxX, card.getLocation().x + card.getSize().width + marginX); + maxY = Math.max(maxY, card.getLocation().y + card.getSize().height + marginY); + p.add(card); + } + + maxX = nextXIfNotStacked; + + if(maxX > 0 && maxY > 0) { //p.getSize().width || maxY > p.getSize().height) { + p.setPreferredSize(new Dimension(maxX, maxY)); + } + + } else { + JPanel addPanel; + for(int i = 0; i < list.size(); i++) { + c = list.get(i); + addPanel = getCardPanel(c); + + p.add(addPanel); + } + } + }//setupPanel() + + public static ArrayList getPlaneswalkers(ArrayList cards) { + ArrayList ret = new ArrayList(); + for(Card c:cards) { + if(c.isPlaneswalker() && !c.isArtifact()) ret.add(c); + } + return ret; + } + + public static ArrayList getEquippedEnchantedCreatures(ArrayList cards) { + ArrayList ret = new ArrayList(); + for(Card c:cards) { + if(c.isCreature() && (c.isEquipped() || c.isEnchanted())) { + if(c.isEquipped()) ret.addAll(c.getEquippedBy()); + if(c.isEnchanted()) ret.addAll(c.getEnchantedBy()); + + ret.add(c); + } + + } + return ret; + } + + + public static ArrayList getNonTokenCreatures(ArrayList cards) { + ArrayList ret = new ArrayList(); + for(Card c:cards) { + if(c.isCreature() && !c.isToken() && !c.isEquipped() && !c.isEnchanted()) ret.add(c); + } + return ret; + } + + public static ArrayList getTokenCreatures(ArrayList cards) { + ArrayList ret = new ArrayList(); + for(Card c:cards) { + if(c.isCreature() && c.isToken() && !c.isEquipped() && !c.isEnchanted()) ret.add(c); + } + return ret; + } + + public static ArrayList getTokenCreatures(ArrayList cards, String tokenName) { + ArrayList ret = new ArrayList(); + for(Card c:cards) { + String name = c.getName(); + if(c.isCreature() && c.isToken() && name.equals(tokenName)) ret.add(c); + } + return ret; + } + + public static ArrayList getMoxen(ArrayList cards, String moxName) { + ArrayList ret = new ArrayList(); + for(Card c:cards) { + String name = c.getName(); + if(name.equals(moxName)) ret.add(c); + } + return ret; + } + + public static ArrayList getNonCreatureArtifacts(ArrayList cards) { + ArrayList ret = new ArrayList(); + for(Card c:cards) { + String name = c.getName(); + if(c.isArtifact() && !c.isCreature() && !c.isLand() && !c.isGlobalEnchantment() + && !(c.isEquipment() && c.isEquipping()) && !name.equals("Mox Emerald") + && !name.equals("Mox Jet") && !name.equals("Mox Pearl") && !name.equals("Mox Ruby") + && !name.equals("Mox Sapphire")) ret.add(c); + } + return ret; + } + + public static ArrayList getGlobalEnchantments(ArrayList cards) { + ArrayList ret = new ArrayList(); + for(Card c:cards) { + if(c.isGlobalEnchantment() && !c.isCreature()) ret.add(c); + } + return ret; + } + + public static ArrayList getCard(ArrayList cards, String name) { + ArrayList ret = new ArrayList(); + for(Card c:cards) { + if(c.getName().equals(name)) ret.add(c); + } + return ret; + } + + public static ArrayList getEnchantedLands(ArrayList cards) { + ArrayList ret = new ArrayList(); + for(Card c:cards) { + if(c.isLand() && c.isEnchanted()) { + ret.addAll(c.getEnchantedBy()); + ret.add(c); + } + + } + return ret; + } + + + public static ArrayList getBasics(ArrayList cards, String color) { + ArrayList ret = new ArrayList(); + + for(Card c:cards) { + String name = c.getName(); + + if(c.isEnchanted()) ;//do nothing + + else if(name.equals("Swamp") || name.equals("Bog")) { + if(color == Constant.Color.Black) { + ret.add(c); + } + } else if(name.equals("Forest") || name.equals("Grass")) { + if(color == Constant.Color.Green) { + ret.add(c); + } + + } else if(name.equals("Plains") || name.equals("White Sand")) { + if(color == Constant.Color.White) { + ret.add(c); + } + + } else if(name.equals("Mountain") || name.equals("Rock")) { + if(color == Constant.Color.Red) { + ret.add(c); + } + + } else if(name.equals("Island") || name.equals("Underwater")) { + if(color == Constant.Color.Blue) { + ret.add(c); + } + } + } + + return ret; + } + + public static ArrayList getNonBasics(ArrayList cards) { + ArrayList ret = new ArrayList(); + + for(Card c:cards) { + if(!c.isLand() && !c.getName().startsWith("Mox") && !c.getName().equals("Mana Pool")) { + ret.add(c); + } else { + String name = c.getName(); + if(c.isEnchanted() || name.equals("Swamp") || name.equals("Bog") || name.equals("Forest") + || name.equals("Grass") || name.equals("Plains") || name.equals("White Sand") + || name.equals("Mountain") || name.equals("Rock") || name.equals("Island") + || name.equals("Underwater") || name.equals("Badlands") || name.equals("Bayou") + || name.equals("Plateau") || name.equals("Scrubland") || name.equals("Savannah") + || name.equals("Taiga") || name.equals("Tropical Island") || name.equals("Tundra") + || name.equals("Underground Sea") || name.equals("Volcanic Island") + || name.startsWith("Mox") || name.equals("Mana Pool")) { + // do nothing. + } else { + ret.add(c); + } + } + } + + return ret; + } + + public static ArrayList getNonBasicLand(ArrayList cards, String landName) { + ArrayList ret = new ArrayList(); + + for(Card c:cards) + if(c.getName().equals(landName)) ret.add(c); + + return ret; + } + + public static boolean isStackable(Card c) { + + /*String name = c.getName(); + if( name.equals("Swamp") || name.equals("Bog") || + name.equals("Forest") || name.equals("Grass") || + name.equals("Plains") || name.equals("White Sand") || + name.equals("Mountain") || name.equals("Rock") || + name.equals("Island") || name.equals("Underwater")) { + return true; + } + */ + if(c.isLand() || (c.getName().startsWith("Mox") && !c.getName().equals("Mox Diamond") )|| (c.isLand() && c.isEnchanted()) + || (c.isAura() && c.isEnchanting()) || (c.isToken() && CardFactoryUtil.multipleControlled(c)) + || (c.isCreature() && (c.isEquipped() || c.isEnchanted())) || (c.isEquipment() && c.isEquipping()) + || (c.isEnchantment())) return true; + + return false; + } + + //~ + public static void setupConnectedCards(ArrayList connectedCards) { + for(int i = connectedCards.size() - 1; i > 0; i--) { + //System.out.println("We should have a stack"); + CardPanel cp = connectedCards.get(i); + cp.connectedCard = connectedCards.get(i - 1); + } + } + //~ +} diff --git a/src/GuiInput.java b/src/GuiInput.java new file mode 100644 index 00000000000..773192a9798 --- /dev/null +++ b/src/GuiInput.java @@ -0,0 +1,38 @@ +import java.util.*; + +public class GuiInput extends MyObservable implements Observer +{ + Input input; + + public GuiInput() + { + AllZone.InputControl.addObserver(this); + AllZone.Stack.addObserver(this); + AllZone.Phase.addObserver(this); + } + public void update(Observable observable, Object obj) + { + Input tmp = AllZone.InputControl.getInput(); + if(tmp != null){ + setInput(tmp); + } + } + private void setInput(Input in) + { + input = in; + input.showMessage(); + } + + public void showMessage() + { + //if (input instanceof Input_PayManaCost) + input.showMessage(); + } + public void selectButtonOK() {input.selectButtonOK();} + public void selectButtonCancel(){input.selectButtonCancel();} + + public void selectPlayer(String player) {input.selectPlayer(player);} + public void selectCard(Card card, PlayerZone zone) {input.selectCard(card, zone);} + + public String toString(){return input.toString();} +} \ No newline at end of file diff --git a/src/Gui_BoosterDraft.java b/src/Gui_BoosterDraft.java new file mode 100644 index 00000000000..e6d4cc558c7 --- /dev/null +++ b/src/Gui_BoosterDraft.java @@ -0,0 +1,594 @@ +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; + +import forge.error.ErrorViewer; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + + +public class Gui_BoosterDraft extends JFrame implements CardDetail, NewConstants, NewConstants.LANG.Gui_BoosterDraft { + private static final long serialVersionUID = -6055633915602448260L; + + private BoosterDraft boosterDraft; + + private final boolean limitedDeckEditor = true; + + private TableModel allCardModel; + private TableModel deckModel; + + private JScrollPane jScrollPane1 = new JScrollPane(); + private JScrollPane jScrollPane2 = new JScrollPane(); + @SuppressWarnings("unused") + // border1 + private Border border1; + private TitledBorder titledBorder1; + @SuppressWarnings("unused") + // border2 + private Border border2; + private TitledBorder titledBorder2; + private JPanel cardDetailPanel = new JPanel(); + private Border border3; + private TitledBorder titledBorder3; + private JPanel picturePanel = new JPanel(); + private JLabel statsLabel = new JLabel(); + private JTable allCardTable = new JTable(); + private JTable deckTable = new JTable(); + private JScrollPane jScrollPane3 = new JScrollPane(); + private JPanel jPanel3 = new JPanel(); + private JLabel cdLabel4 = new JLabel(); + private JLabel cdLabel1 = new JLabel(); + private JLabel cdLabel2 = new JLabel(); + private JLabel cdLabel3 = new JLabel(); + private GridLayout gridLayout1 = new GridLayout(); + private JLabel cdLabel5 = new JLabel(); + private JTextArea cdTextArea = new JTextArea(); + private BorderLayout borderLayout1 = new BorderLayout(); + private JLabel statsLabel2 = new JLabel(); + private JButton jButton1 = new JButton(); + + public static void main(String[] args) { + Constant.Runtime.GameType[0] = Constant.GameType.Draft; + Constant.Runtime.HumanDeck[0] = new Deck(Constant.GameType.Sealed); + + Gui_BoosterDraft g = new Gui_BoosterDraft(); + g.showGui(new BoosterDraftTest()); + } + + + public void showGui(BoosterDraft in_boosterDraft) { + boosterDraft = in_boosterDraft; + + setup(); + showChoices(boosterDraft.nextChoice()); + + allCardModel.sort(1, true); + deckModel.sort(1, true); + + setVisible(true); + } + + private void addListeners() { + this.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent ev) { + int n = JOptionPane.showConfirmDialog(null, ForgeProps.getLocalized(CLOSE_MESSAGE), "", + JOptionPane.YES_NO_OPTION); + if(n == JOptionPane.YES_OPTION) { + dispose(); + new Gui_NewGame(); + } + }//windowClosing() + }); + }//addListeners() + + private void setup() { + addListeners(); +// setupMenu(); + + //construct allCardTable, get all cards + allCardModel = new TableModel(new CardList(), this); + allCardModel.addListeners(allCardTable); + allCardTable.setModel(allCardModel); + + + //construct deckModel + deckModel = new TableModel(this); + deckModel.addListeners(deckTable); + deckTable.setModel(deckModel); + + //add cards to GUI from deck +// refreshGui(); + + allCardTable.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0) jButton1_actionPerformed(null); + } + });//MouseListener + + + //get stats from deck + deckModel.addTableModelListener(new TableModelListener() { + public void tableChanged(TableModelEvent ev) { + CardList deck = deckModel.getCards(); + statsLabel.setText(getStats(deck)); + } + }); + + + //get stats from all cards + allCardModel.addTableModelListener(new TableModelListener() { + public void tableChanged(TableModelEvent ev) { + CardList deck = allCardModel.getCards(); + statsLabel2.setText(getStats(deck)); + } + }); + + //Use both so that when "un"maximizing, the frame isn't tiny + setSize(1024, 740); + setExtendedState(Frame.MAXIMIZED_BOTH); + }//setupAndDisplay() + + private String getStats(CardList deck) { + int total = deck.size(); + int creature = deck.getType("Creature").size(); + int land = deck.getType("Land").size(); + + String show = "Total - " + total + ", Creatures - " + creature + ", Land - " + land; + String[] color = Constant.Color.Colors; + for(int i = 0; i < 5; i++) + show += ", " + color[i] + " - " + CardListUtil.getColor(deck, color[i]).size(); + + return show; + }//getStats() + + public Gui_BoosterDraft() { + try { + jbInit(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + } + + public void updateCardDetail(Card c) { + CardDetailUtil.updateCardDetail(c, cdTextArea, cardDetailPanel, picturePanel, new JLabel[] { + cdLabel1, cdLabel2, cdLabel3, cdLabel4, cdLabel5}); + } + + private void jbInit() throws Exception { + border1 = new EtchedBorder(EtchedBorder.RAISED, Color.white, new Color(148, 145, 140)); + titledBorder1 = new TitledBorder(BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)), + "Previous Picked Cards"); + border2 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder2 = new TitledBorder(BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)), + "Choose one card"); + border3 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder3 = new TitledBorder(border3, "Card Detail"); + this.getContentPane().setLayout(null); + jScrollPane1.setBorder(titledBorder2); + jScrollPane1.setBounds(new Rectangle(19, 28, 661, 344)); + jScrollPane2.setBorder(titledBorder1); + jScrollPane2.setBounds(new Rectangle(19, 478, 661, 184)); + cardDetailPanel.setBorder(titledBorder3); + cardDetailPanel.setBounds(new Rectangle(693, 23, 239, 323)); + cardDetailPanel.setLayout(null); + picturePanel.setBorder(BorderFactory.createEtchedBorder()); + picturePanel.setBounds(new Rectangle(698, 362, 226, 301)); + picturePanel.setLayout(borderLayout1); + statsLabel.setFont(new java.awt.Font("Dialog", 0, 16)); + statsLabel.setText("Total - 0, Creatures - 0 Land - 0"); + statsLabel.setBounds(new Rectangle(19, 665, 665, 31)); + this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + this.setTitle("Booster Draft"); + jScrollPane3.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPane3.setBounds(new Rectangle(6, 168, 225, 143)); + jPanel3.setBounds(new Rectangle(7, 21, 224, 141)); + jPanel3.setLayout(gridLayout1); + cdLabel4.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel4.setHorizontalAlignment(SwingConstants.LEFT); + cdLabel1.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel1.setHorizontalAlignment(SwingConstants.CENTER); + cdLabel2.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel2.setHorizontalAlignment(SwingConstants.CENTER); + cdLabel3.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel3.setHorizontalAlignment(SwingConstants.CENTER); + gridLayout1.setColumns(1); + gridLayout1.setRows(0); + cdLabel5.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel5.setHorizontalAlignment(SwingConstants.LEFT); + cdTextArea.setFont(new java.awt.Font("Dialog", 0, 12)); + cdTextArea.setLineWrap(true); + cdTextArea.setWrapStyleWord(true); + statsLabel2.setBounds(new Rectangle(19, 378, 665, 31)); + statsLabel2.setText("Total - 0, Creatures - 0 Land - 0"); + statsLabel2.setFont(new java.awt.Font("Dialog", 0, 16)); + jButton1.setBounds(new Rectangle(238, 418, 147, 44)); + jButton1.setFont(new java.awt.Font("Dialog", 0, 16)); + jButton1.setText("Choose Card"); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + jButton1_actionPerformed(e); + } + }); + this.getContentPane().add(cardDetailPanel, null); + cardDetailPanel.add(jScrollPane3, null); + jScrollPane3.getViewport().add(cdTextArea, null); + cardDetailPanel.add(jPanel3, null); + jPanel3.add(cdLabel1, null); + jPanel3.add(cdLabel2, null); + jPanel3.add(cdLabel3, null); + jPanel3.add(cdLabel4, null); + this.getContentPane().add(picturePanel, null); + this.getContentPane().add(jScrollPane1, null); + this.getContentPane().add(statsLabel2, null); + this.getContentPane().add(statsLabel, null); + this.getContentPane().add(jScrollPane2, null); + this.getContentPane().add(jButton1, null); + jScrollPane2.getViewport().add(deckTable, null); + jScrollPane1.getViewport().add(allCardTable, null); + jPanel3.add(cdLabel5, null); + } + + void addButton_actionPerformed(ActionEvent e) { + int n = allCardTable.getSelectedRow(); + if(n != -1) { + setTitle("Deck Editor - " + Constant.Runtime.HumanDeck[0].getName() + " - changed"); + + Card c = allCardModel.rowToCard(n); + deckModel.addCard(c); + deckModel.resort(); + + if(limitedDeckEditor) { + allCardModel.removeCard(c); + } + + //3 conditions" 0 cards left, select the same row, select next row + int size = allCardModel.getRowCount(); + if(size != 0) { + if(size == n) n--; + allCardTable.addRowSelectionInterval(n, n); + } + }//if(valid row) + }//addButton_actionPerformed + + void removeButton_actionPerformed(ActionEvent e) { + int n = deckTable.getSelectedRow(); + if(n != -1) { + setTitle("Deck Editor - " + Constant.Runtime.HumanDeck[0].getName() + " - changed"); + + Card c = deckModel.rowToCard(n); + deckModel.removeCard(c); + + if(limitedDeckEditor) { + allCardModel.addCard(c); + allCardModel.resort(); + } + + //3 conditions" 0 cards left, select the same row, select next row + int size = deckModel.getRowCount(); + if(size != 0) { + if(size == n) n--; + deckTable.addRowSelectionInterval(n, n); + } + }//if(valid row) + }//removeButton_actionPerformed + + //if true, don't do anything else + private boolean checkSaveDeck() { + //a crappy way of checking if the deck has been saved + if(getTitle().endsWith("changed")) { + + int n = JOptionPane.showConfirmDialog(null, ForgeProps.getLocalized(SAVE_MESSAGE), + ForgeProps.getLocalized(SAVE_TITLE), JOptionPane.YES_NO_CANCEL_OPTION); + if(n == JOptionPane.CANCEL_OPTION) return true; + else if(n == JOptionPane.YES_OPTION) saveItem_actionPerformed(); + } + return false; + }//checkSaveDeck() + + private void newItem_actionPerformed() { + if(checkSaveDeck()) return; + + setTitle("Deck Editor"); + + Deck deck = Constant.Runtime.HumanDeck[0]; + while(deck.countMain() != 0) + deck.addSideboard(deck.removeMain(0)); + + refreshGui(); + }//newItem_actionPerformed + + private void closeItem_actionPerformed() { + //check if saved, show dialog "yes, "no" + checkSaveDeck(); + dispose(); + } + + private void stats_actionPerformed(CardList list) { + + } + + private void saveAsItem_actionPerformed() {}//saveItem_actionPerformed() + + private void saveItem_actionPerformed() {} + + private void openItem_actionPerformed() {}//openItem_actionPerformed() + + public void deleteItem_actionPerformed() {} + + public void renameItem_actionPerformed() { + String newName = ""; + while(newName.equals("")) { + newName = JOptionPane.showInputDialog(null, ForgeProps.getLocalized(RENAME_MESSAGE), + ForgeProps.getLocalized(RENAME_TITLE), JOptionPane.QUESTION_MESSAGE); + if(newName == null) break; + } + + //when the user selects "Cancel" + if(newName != null) { + //String oldName = Constant.Runtime.HumanDeck[0].getName(); //unused + + Constant.Runtime.HumanDeck[0].setName(newName); + setTitle("Deck Editor - " + newName + " - changed"); + } + } + + @SuppressWarnings("unused") + // setupMenu + private void setupMenu() { + //final boolean[] isSaved = new boolean[1]; // unused + + JMenuItem newItem = new JMenuItem("New"); + JMenuItem openItem = new JMenuItem("Open"); + JMenuItem saveItem = new JMenuItem("Save"); + JMenuItem saveAsItem = new JMenuItem("Save As"); + JMenuItem renameItem = new JMenuItem("Rename"); + JMenuItem deleteItem = new JMenuItem("Delete"); + JMenuItem statsPoolItem = new JMenuItem("Statistics - Card Pool"); + JMenuItem statsDeckItem = new JMenuItem("Statistics - Deck"); + JMenuItem closeItem = new JMenuItem("Close"); + + newItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + newItem_actionPerformed(); + } + }); + openItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + openItem_actionPerformed(); + } + }); + saveItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + saveItem_actionPerformed(); + } + }); + saveAsItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + saveAsItem_actionPerformed(); + } + }); + renameItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + renameItem_actionPerformed(); + } + }); + deleteItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + deleteItem_actionPerformed(); + } + }); + statsPoolItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + stats_actionPerformed(allCardModel.getCards()); + } + }); + statsDeckItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + stats_actionPerformed(deckModel.getCards()); + } + }); + closeItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + closeItem_actionPerformed(); + } + }); + + JMenu fileMenu = new JMenu("Deck Actions"); + fileMenu.add(newItem); + fileMenu.add(openItem); + fileMenu.add(saveItem); + fileMenu.add(saveAsItem); + + fileMenu.addSeparator(); + fileMenu.add(renameItem); + fileMenu.add(deleteItem); +// fileMenu.add(statsPoolItem); +// fileMenu.add(statsDeckItem); + fileMenu.addSeparator(); + fileMenu.add(closeItem); + + JMenuBar menuBar = new JMenuBar(); + menuBar.add(fileMenu); + + this.setJMenuBar(menuBar); + }/*setupMenu(); */ + + //refresh Gui from deck, Gui shows the cards in the deck + private void refreshGui() { + Deck deck = Constant.Runtime.HumanDeck[0]; + if(deck == null) //this is just a patch, i know + deck = new Deck(Constant.Runtime.GameType[0]); + + allCardModel.clear(); + deckModel.clear(); + + Card c; + ReadBoosterPack pack = new ReadBoosterPack(); + for(int i = 0; i < deck.countMain(); i++) { + c = AllZone.CardFactory.getCard(deck.getMain(i), Constant.Player.Human); + + //add rarity to card if this is a sealed card pool + if(!Constant.Runtime.GameType[0].equals(Constant.GameType.Constructed)) + c.setRarity(pack.getRarity(c.getName()));; + + deckModel.addCard(c); + }//for + + if(deck.isSealed() || deck.isRegular()) { + //add sideboard to GUI + for(int i = 0; i < deck.countSideboard(); i++) { + c = AllZone.CardFactory.getCard(deck.getSideboard(i), Constant.Player.Human); + c.setRarity(pack.getRarity(c.getName())); + allCardModel.addCard(c); + } + } else { + CardList all = AllZone.CardFactory.getAllCards(); + for(int i = 0; i < all.size(); i++) + allCardModel.addCard(all.get(i)); + } + + allCardModel.resort(); + deckModel.resort(); + }//refreshGui() + + //updates Constant.Runtime.HumanDeck[0] from the cards shown in the GUI + @SuppressWarnings("unused") + // refreshDeck + private void refreshDeck() { + //make new Deck + Deck deck = new Deck(Constant.Runtime.GameType[0]); + deck.setName(Constant.Runtime.HumanDeck[0].getName()); + Constant.Runtime.HumanDeck[0] = deck; + + //update Deck with cards shown in GUI + CardList list = deckModel.getCards(); + for(int i = 0; i < list.size(); i++) + deck.addMain(list.get(i).getName()); + + if(deck.isSealed()) { + //add sideboard to deck + list = allCardModel.getCards(); + for(int i = 0; i < list.size(); i++) + deck.addSideboard(list.get(i).getName()); + } + }/* refreshDeck() */ + + void jButton1_actionPerformed(ActionEvent e) { + //pick card + int n = allCardTable.getSelectedRow(); + if(n == -1) //is valid selection? + return; + + Card c = allCardModel.rowToCard(n); + + deckModel.addCard(c); + deckModel.resort(); + + //get next booster pack + boosterDraft.setChoice(c); + if(boosterDraft.hasNextChoice()) { + showChoices(boosterDraft.nextChoice()); + } else { + //quit + saveDraft(); + dispose(); + } + }/*OK Button*/ + + private void showChoices(CardList list) { + allCardModel.clear(); + + ReadBoosterPack pack = new ReadBoosterPack(); + Card c; + for(int i = 0; i < list.size(); i++) { + c = list.get(i); + c.setRarity(pack.getRarity(c.getName())); + allCardModel.addCard(c); + } + allCardModel.resort(); + allCardTable.setRowSelectionInterval(0, 0); + + }//showChoices() + + private Deck getPlayersDeck() { + Deck deck = new Deck(Constant.GameType.Draft); + Constant.Runtime.HumanDeck[0] = deck; + + //add sideboard to deck + CardList list = deckModel.getCards(); + for(int i = 0; i < list.size(); i++) + deck.addSideboard(list.get(i).getName()); + + + for(int i = 0; i < 40; i++) { + deck.addSideboard("Forest"); + deck.addSideboard("Mountain"); + deck.addSideboard("Swamp"); + deck.addSideboard("Island"); + deck.addSideboard("Plains"); + } + + return deck; + }//getPlayersDeck() + + private void saveDraft() { + String s = ""; + while(s == null || s.length() == 0) { + s = JOptionPane.showInputDialog(null, ForgeProps.getLocalized(SAVE_DRAFT_MESSAGE), + ForgeProps.getLocalized(SAVE_DRAFT_TITLE), JOptionPane.QUESTION_MESSAGE); + } + //TODO: check if overwriting the same name, and let the user delete old drafts + + //construct computer's decks + //save draft + Deck[] computer = boosterDraft.getDecks(); + + Deck human = getPlayersDeck(); + human.setName(s); + + Deck[] all = { + human, computer[0], computer[1], computer[2], computer[3], computer[4], computer[5], computer[6]}; + + DeckIO deckIO = new DeckIO(ForgeProps.getFile(BOOSTER_DECKS)); + deckIO.writeBoosterDeck(all); + + //write file + deckIO.close(); + + //close and open next screen + dispose(); + new Gui_NewGame(); + }/*saveDraft()*/ +} \ No newline at end of file diff --git a/src/Gui_DeckEditor.java b/src/Gui_DeckEditor.java new file mode 100644 index 00000000000..5fb66c5309f --- /dev/null +++ b/src/Gui_DeckEditor.java @@ -0,0 +1,722 @@ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; +import java.awt.GridLayout; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; + +import forge.error.ErrorViewer; + + +//import java.util.*; //unused + +public class Gui_DeckEditor extends JFrame implements CardDetail, DeckDisplay +{ + private static final long serialVersionUID = 130339644136746796L; + + Gui_DeckEditor_Menu customMenu; + + private ImageIcon upIcon = Constant.IO.upIcon; + private ImageIcon downIcon = Constant.IO.downIcon; + + private TableModel topModel; + private TableModel bottomModel; + + private JScrollPane jScrollPane1 = new JScrollPane(); + private JScrollPane jScrollPane2 = new JScrollPane(); + private JButton removeButton = new JButton(); + @SuppressWarnings("unused") // border1 + private Border border1; + private TitledBorder titledBorder1; + private Border border2; + private TitledBorder titledBorder2; + private JButton addButton = new JButton(); + private JPanel cardDetailPanel = new JPanel(); + private Border border3; + private TitledBorder titledBorder3; + private JPanel picturePanel = new JPanel(); + private JLabel statsLabel = new JLabel(); + private JTable topTable = new JTable(); + private JTable bottomTable = new JTable(); + private JScrollPane jScrollPane3 = new JScrollPane(); + private JPanel jPanel3 = new JPanel(); + private JLabel cdLabel4 = new JLabel(); + private JLabel cdLabel1 = new JLabel(); + private JLabel cdLabel2 = new JLabel(); + private JLabel cdLabel3 = new JLabel(); + private GridLayout gridLayout1 = new GridLayout(); + private JLabel cdLabel5 = new JLabel(); + private JTextArea cdTextArea = new JTextArea(); + private BorderLayout borderLayout1 = new BorderLayout(); + private JLabel statsLabel2 = new JLabel(); + private JLabel jLabel1 = new JLabel(); + + private JCheckBox whiteCheckBox = new JCheckBox("W", true); + private JCheckBox blueCheckBox = new JCheckBox("U", true); + private JCheckBox blackCheckBox = new JCheckBox("B", true); + private JCheckBox redCheckBox = new JCheckBox("R", true); + private JCheckBox greenCheckBox = new JCheckBox("G", true); + private JCheckBox colorlessCheckBox = new JCheckBox("C", true); + + private JCheckBox landCheckBox = new JCheckBox("Land", true); + private JCheckBox creatureCheckBox = new JCheckBox("Creature", true); + private JCheckBox sorceryCheckBox = new JCheckBox("Sorcery", true); + private JCheckBox instantCheckBox = new JCheckBox("Instant", true); + private JCheckBox planeswalkerCheckBox = new JCheckBox("Planeswalker", true); + private JCheckBox artifactCheckBox = new JCheckBox("Artifact", true); + private JCheckBox enchantmentCheckBox = new JCheckBox("Enchant", true); + + private CardList top; + private CardList bottom; + + public static void main(String[] args) + { + + } + + @Override + public void setTitle(String message) { + super.setTitle(message); + } + + public void updateDisplay(CardList top, CardList bottom) { + + this.top = top; + this.bottom = bottom; + + topModel.clear(); + bottomModel.clear(); + + if (AllZone.NameChanger.shouldChangeCardName()) { + top = new CardList(AllZone.NameChanger.changeCard(top.toArray())); + bottom = new CardList(AllZone.NameChanger.changeCard(bottom + .toArray())); + } + + Card c; + String cardName; + ReadBoosterPack pack = new ReadBoosterPack(); + + // update top + for (int i = 0; i < top.size(); i++) { + c = top.get(i); + + // add rarity to card if this is a sealed card pool + + cardName = AllZone.NameChanger.getOriginalName(c.getName()); + if (!pack.getRarity(cardName).equals("error")) { + c.setRarity(pack.getRarity(cardName)); + } + + boolean filteredOut = filterByColor(c); + + if (!filteredOut) { + filteredOut = filterByType(c); + } + + if (!filteredOut) { + topModel.addCard(c); + } + }// for + + // update bottom + for (int i = 0; i < bottom.size(); i++) { + c = bottom.get(i); + + // add rarity to card if this is a sealed card pool + if (!customMenu.getGameType().equals(Constant.GameType.Constructed)) + c.setRarity(pack.getRarity(c.getName())); + + bottomModel.addCard(c); + }// for + + topModel.resort(); + bottomModel.resort(); + }// updateDisplay + + public void updateDisplay() { + //updateDisplay(this.top, this.bottom); + + topModel.clear(); + + if (AllZone.NameChanger.shouldChangeCardName()) { + top = new CardList(AllZone.NameChanger.changeCard(top.toArray())); + bottom = new CardList(AllZone.NameChanger.changeCard(bottom + .toArray())); + } + + Card c; + String cardName; + ReadBoosterPack pack = new ReadBoosterPack(); + + // update top + for (int i = 0; i < top.size(); i++) { + c = top.get(i); + + // add rarity to card if this is a sealed card pool + + cardName = AllZone.NameChanger.getOriginalName(c.getName()); + if (!pack.getRarity(cardName).equals("error")) { + c.setRarity(pack.getRarity(cardName)); + } + + boolean filteredOut = filterByColor(c); + + if (!filteredOut) { + filteredOut = filterByType(c); + } + + if (!filteredOut) { + topModel.addCard(c); + } + }// for + + topModel.resort(); + } + + private boolean filterByColor(Card c) { + boolean filterOut = false; + + if (!whiteCheckBox.isSelected()) { + if (CardUtil.getColors(c).contains(Constant.Color.White)) { + filterOut = true; + } + } + + if (!blueCheckBox.isSelected()) { + if (CardUtil.getColors(c).contains(Constant.Color.Blue)) { + filterOut = true; + } + } + + if (!blackCheckBox.isSelected()) { + if (CardUtil.getColors(c).contains(Constant.Color.Black)) { + filterOut = true; + } + } + + if (!redCheckBox.isSelected()) { + if (CardUtil.getColors(c).contains(Constant.Color.Red)) { + filterOut = true; + } + } + + if (!greenCheckBox.isSelected()) { + if (CardUtil.getColors(c).contains(Constant.Color.Green)) { + filterOut = true; + } + } + + if (!colorlessCheckBox.isSelected()) { + if (CardUtil.getColors(c).contains(Constant.Color.Colorless)) { + filterOut = true; + } + } + + return filterOut; + } + + private boolean filterByType(Card c) { + boolean filterOut = false; + + if (!landCheckBox.isSelected() && c.isLand()) { + filterOut = true; + } + + if (!creatureCheckBox.isSelected() && c.isCreature()) { + filterOut = true; + } + + if (!sorceryCheckBox.isSelected() && c.isSorcery()) { + filterOut = true; + } + + if (!instantCheckBox.isSelected() && c.isInstant()) { + filterOut = true; + } + + if (!planeswalkerCheckBox.isSelected() && c.isPlaneswalker()) { + filterOut = true; + } + + if (!artifactCheckBox.isSelected() && c.isArtifact()) { + filterOut = true; + } + + if (!enchantmentCheckBox.isSelected() && c.isEnchantment()) { + filterOut = true; + } + + return filterOut; + } + + //top shows available card pool + //if constructed, top shows all cards + //if sealed, top shows 5 booster packs + //if draft, top shows cards that were chosen + + public TableModel getTopTableModel() + { + return topModel; + } + + public CardList getTop() {return topModel.getCards();} + + //bottom shows cards that the user has chosen for his library + public CardList getBottom() {return bottomModel.getCards();} + + public void show(final Command exitCommand) + { + final Command exit = new Command() + { + private static final long serialVersionUID = 5210924838133689758L; + + public void execute() + { + Gui_DeckEditor.this.dispose(); + exitCommand.execute(); + } + }; + + customMenu = new Gui_DeckEditor_Menu(this, exit); + this.setJMenuBar(customMenu); + + + //do not change this!!!! + this.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent ev) { + customMenu.close(); + } + }); + + + setup(); + + //show cards, makes this user friendly + customMenu.newConstructed(); + + topModel.sort(1, true); + bottomModel.sort(1, true); + }//show(Command) + + private void addListeners() + { + + }//addListeners() + + private void setup() + { + addListeners(); + + //construct topTable, get all cards + topModel = new TableModel(new CardList(), (CardDetail)this); + topModel.addListeners(topTable); + + topTable.setModel(topModel); + topModel.resizeCols(topTable); + + //construct bottomModel + bottomModel = new TableModel((CardDetail)this); + bottomModel.addListeners(bottomTable); + + bottomTable.setModel(bottomModel); + topModel.resizeCols(bottomTable); + + //get stats from deck + bottomModel.addTableModelListener(new TableModelListener() + { + public void tableChanged(TableModelEvent ev) + { + CardList deck = bottomModel.getCards(); + statsLabel.setText(getStats(deck)); + } + }); + + + //get stats from all cards + topModel.addTableModelListener(new TableModelListener() { + public void tableChanged(TableModelEvent ev) { + CardList deck = topModel.getCards(); + statsLabel2.setText(getStats(deck)); + } + }); + + setSize(1024, 768); + + //TODO use this as soon the deck editor has resizable GUI +// //Use both so that when "un"maximizing, the frame isn't tiny +// setSize(1024, 740); +// setExtendedState(Frame.MAXIMIZED_BOTH); + }//setupAndDisplay() + + private String getStats(CardList deck) { + int total = deck.size(); + int creature = deck.getType("Creature").size(); + int land = deck.getType("Land").size(); + + String show = "Total - " + total + ", Creatures - " + creature + ", Land - " + land; + String[] color = Constant.Color.Colors; + for(int i = 0; i < 5; i++) + show += ", " + color[i] + " - " + CardListUtil.getColor(deck, color[i]).size(); + + return show; + }//getStats() + + public Gui_DeckEditor() { + try { + jbInit(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + } + + public void updateCardDetail(Card c) { + //change card name if needed + c = AllZone.CardFactory.copyCard(c); + if(AllZone.NameChanger.shouldChangeCardName()) c = AllZone.NameChanger.changeCard(c); + + CardDetailUtil.updateCardDetail(c, cdTextArea, cardDetailPanel, picturePanel, new JLabel[] { + cdLabel1, cdLabel2, cdLabel3, cdLabel4, cdLabel5}); + } + + private void jbInit() throws Exception { + border1 = new EtchedBorder(EtchedBorder.RAISED, Color.white, new Color(148, 145, 140)); + titledBorder1 = new TitledBorder(BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)), + "All Cards"); + border2 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder2 = new TitledBorder(border2, "Deck"); + border3 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder3 = new TitledBorder(border3, "Card Detail"); + this.getContentPane().setLayout(null); + jScrollPane1.setBorder(titledBorder1); + jScrollPane1.setBounds(new Rectangle(19, 28, 726, 346)); + jScrollPane2.getViewport().setBackground(new Color(204, 204, 204)); + jScrollPane2.setBorder(titledBorder2); + jScrollPane2.setBounds(new Rectangle(19, 458, 726, 218)); + removeButton.setBounds(new Rectangle(180, 403, 146, 49)); + removeButton.setIcon(upIcon); + removeButton.setFont(new java.awt.Font("Dialog", 0, 13)); + removeButton.setText("Remove Card"); + removeButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + removeButton_actionPerformed(e); + } + }); + addButton.setText("Add Card"); + addButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + addButton_actionPerformed(e); + } + }); + addButton.setIcon(downIcon); + addButton.setFont(new java.awt.Font("Dialog", 0, 13)); + addButton.setBounds(new Rectangle(23, 403, 146, 49)); + + /** + * Type filtering + */ + Font f = new Font("Tahoma", Font.PLAIN, 10); + landCheckBox.setBounds(340, 400, 48, 20); + landCheckBox.setFont(f); + landCheckBox.setOpaque(false); + landCheckBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + creatureCheckBox.setBounds(385, 400, 65, 20); + creatureCheckBox.setFont(f); + creatureCheckBox.setOpaque(false); + creatureCheckBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + sorceryCheckBox.setBounds(447, 400, 62, 20); + sorceryCheckBox.setFont(f); + sorceryCheckBox.setOpaque(false); + sorceryCheckBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + instantCheckBox.setBounds(505, 400, 60, 20); + instantCheckBox.setFont(f); + instantCheckBox.setOpaque(false); + instantCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + planeswalkerCheckBox.setBounds(558, 400, 85, 20); + planeswalkerCheckBox.setFont(f); + planeswalkerCheckBox.setOpaque(false); + planeswalkerCheckBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + artifactCheckBox.setBounds(638, 400, 58, 20); + artifactCheckBox.setFont(f); + artifactCheckBox.setOpaque(false); + artifactCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + enchantmentCheckBox.setBounds(692, 400, 80, 20); + enchantmentCheckBox.setFont(f); + enchantmentCheckBox.setOpaque(false); + enchantmentCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + + /** + * Color filtering + */ + whiteCheckBox.setBounds(340, 430, 40, 20); + whiteCheckBox.setOpaque(false); + whiteCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + blueCheckBox.setBounds(380, 430, 40, 20); + blueCheckBox.setOpaque(false); + blueCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + blackCheckBox.setBounds(420, 430, 40, 20); + blackCheckBox.setOpaque(false); + blackCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + redCheckBox.setBounds(460, 430, 40, 20); + redCheckBox.setOpaque(false); + redCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + greenCheckBox.setBounds(500, 430, 40, 20); + greenCheckBox.setOpaque(false); + greenCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + colorlessCheckBox.setBounds(540, 430, 40, 20); + colorlessCheckBox.setOpaque(false); + colorlessCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + + /** + * Other + */ + cardDetailPanel.setBorder(titledBorder3); + cardDetailPanel.setBounds(new Rectangle(765, 23, 239, 323)); + cardDetailPanel.setLayout(null); + picturePanel.setBorder(BorderFactory.createEtchedBorder()); + picturePanel.setBounds(new Rectangle(772, 362, 226, 301)); + picturePanel.setLayout(borderLayout1); + statsLabel.setFont(new java.awt.Font("Dialog", 0, 14)); + statsLabel.setText("Total - 0, Creatures - 0 Land - 0"); + statsLabel.setBounds(new Rectangle(19, 672, 720, 31)); + //Do not lower statsLabel any lower, we want this to be visible at 1024 x 768 screen size + this.setTitle("Deck Editor"); + jScrollPane3.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPane3.setBounds(new Rectangle(6, 168, 225, 143)); + jPanel3.setBounds(new Rectangle(7, 21, 224, 141)); + jPanel3.setLayout(gridLayout1); + cdLabel4.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel4.setHorizontalAlignment(SwingConstants.LEFT); + cdLabel1.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel1.setHorizontalAlignment(SwingConstants.CENTER); + cdLabel2.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel2.setHorizontalAlignment(SwingConstants.CENTER); + cdLabel3.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel3.setHorizontalAlignment(SwingConstants.CENTER); + gridLayout1.setColumns(1); + gridLayout1.setRows(0); + cdLabel5.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel5.setHorizontalAlignment(SwingConstants.LEFT); + cdTextArea.setFont(new java.awt.Font("Dialog", 0, 12)); + cdTextArea.setLineWrap(true); + cdTextArea.setWrapStyleWord(true); + statsLabel2.setBounds(new Rectangle(19, 371, 720, 31)); + statsLabel2.setText("Total - 0, Creatures - 0 Land - 0"); + statsLabel2.setFont(new java.awt.Font("Dialog", 0, 14)); + jLabel1.setText("Click on the column name (like name or color) to sort the cards"); + jLabel1.setBounds(new Rectangle(20, 9, 400, 19)); + this.getContentPane().add(cardDetailPanel, null); + cardDetailPanel.add(jScrollPane3, null); + jScrollPane3.getViewport().add(cdTextArea, null); + cardDetailPanel.add(jPanel3, null); + jPanel3.add(cdLabel1, null); + jPanel3.add(cdLabel2, null); + jPanel3.add(cdLabel3, null); + jPanel3.add(cdLabel4, null); + this.getContentPane().add(picturePanel, null); + this.getContentPane().add(jScrollPane1, null); + this.getContentPane().add(jScrollPane2, null); + this.getContentPane().add(addButton, null); + this.getContentPane().add(removeButton, null); + this.getContentPane().add(statsLabel2, null); + this.getContentPane().add(statsLabel, null); + this.getContentPane().add(jLabel1, null); + jScrollPane2.getViewport().add(bottomTable, null); + jScrollPane1.getViewport().add(topTable, null); + jPanel3.add(cdLabel5, null); + + this.getContentPane().add(landCheckBox, null); + this.getContentPane().add(creatureCheckBox, null); + this.getContentPane().add(sorceryCheckBox, null); + this.getContentPane().add(instantCheckBox, null); + this.getContentPane().add(planeswalkerCheckBox, null); + this.getContentPane().add(artifactCheckBox, null); + this.getContentPane().add(enchantmentCheckBox, null); + + this.getContentPane().add(whiteCheckBox, null); + this.getContentPane().add(blueCheckBox, null); + this.getContentPane().add(blackCheckBox, null); + this.getContentPane().add(redCheckBox, null); + this.getContentPane().add(greenCheckBox, null); + this.getContentPane().add(colorlessCheckBox, null); + } + + void addButton_actionPerformed(ActionEvent e) { + setTitle("Deck Editor : " + customMenu.getDeckName() + " : unsaved"); + + int n = topTable.getSelectedRow(); + if(n != -1) { + Card c = topModel.rowToCard(n); + bottomModel.addCard(c); + bottomModel.resort(); + + if(!Constant.GameType.Constructed.equals(customMenu.getGameType())) { + topModel.removeCard(c); + } + + //3 conditions" 0 cards left, select the same row, select next row + int size = topModel.getRowCount(); + if(size != 0) { + if(size == n) n--; + topTable.addRowSelectionInterval(n, n); + } + }//if(valid row) + }//addButton_actionPerformed + + void removeButton_actionPerformed(ActionEvent e) { + setTitle("Deck Editor : " + customMenu.getDeckName() + " : unsaved"); + + int n = bottomTable.getSelectedRow(); + if(n != -1) { + Card c = bottomModel.rowToCard(n); + bottomModel.removeCard(c); + + if(!Constant.GameType.Constructed.equals(customMenu.getGameType())) { + topModel.addCard(c); + topModel.resort(); + } + + //3 conditions" 0 cards left, select the same row, select next row + int size = bottomModel.getRowCount(); + if(size != 0) { + if(size == n) n--; + bottomTable.addRowSelectionInterval(n, n); + } + }//if(valid row) + }//removeButton_actionPerformed + + @SuppressWarnings("unused") + // stats_actionPerformed + private void stats_actionPerformed(CardList list) { + + } + + //refresh Gui from deck, Gui shows the cards in the deck + @SuppressWarnings("unused") // refreshGui +private void refreshGui() + { + Deck deck = Constant.Runtime.HumanDeck[0]; + if(deck == null) //this is just a patch, i know + deck = new Deck(Constant.Runtime.GameType[0]); + + topModel.clear(); + bottomModel.clear(); + + Card c; + ReadBoosterPack pack = new ReadBoosterPack(); + for(int i = 0; i < deck.countMain(); i++) + { + c = AllZone.CardFactory.getCard(deck.getMain(i), Constant.Player.Human); + + //add rarity to card if this is a sealed card pool + if(Constant.Runtime.GameType[0].equals(Constant.GameType.Sealed)) + c.setRarity(pack.getRarity(c.getName())); + + bottomModel.addCard(c); + }//for + + if(deck.isSealed() || deck.isDraft()) + { + //add sideboard to GUI + for(int i = 0; i < deck.countSideboard(); i++) + { + c = AllZone.CardFactory.getCard(deck.getSideboard(i), Constant.Player.Human); + c.setRarity(pack.getRarity(c.getName())); + topModel.addCard(c); + } + } + else + { + CardList all = AllZone.CardFactory.getAllCards(); + for(int i = 0; i < all.size(); i++) + topModel.addCard(all.get(i)); + } + + topModel.resort(); + bottomModel.resort(); + }////refreshGui() +} \ No newline at end of file diff --git a/src/Gui_DeckEditor_Menu.java b/src/Gui_DeckEditor_Menu.java new file mode 100644 index 00000000000..2df0c821835 --- /dev/null +++ b/src/Gui_DeckEditor_Menu.java @@ -0,0 +1,1059 @@ +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; + +import javax.swing.JFileChooser; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import javax.swing.filechooser.FileFilter; + +import forge.error.ErrorViewer; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + +interface DeckDisplay +{ + public void updateDisplay(CardList top, CardList bottom); + + //top shows available card pool + //if constructed, top shows all cards + //if sealed, top shows 5 booster packs + //if draft, top shows cards that were chosen + public CardList getTop(); + + //bottom shows cards that the user has chosen for his library + public CardList getBottom(); + + public void setTitle(String message); +} + +public class Gui_DeckEditor_Menu extends JMenuBar implements NewConstants { + private static final long serialVersionUID = -4037993759604768755L; + + //used by importConstructed() and exportConstructected() + private static File previousDirectory = null; + + + private final boolean debugPrint = false; + + private final DeckIO deckIO = new DeckIO(ForgeProps.getFile(DECKS)); + private final DeckIO boosterDeckIO = new DeckIO(ForgeProps.getFile(BOOSTER_DECKS)); + + private boolean isDeckSaved; + private String currentDeckName; + private String currentGameType; + + private JMenuItem newDraftItem; + private DeckDisplay deckDisplay; + + private Command exitCommand; + + public Gui_DeckEditor_Menu(DeckDisplay in_display, Command exit) { + deckDisplay = in_display; + exitCommand = exit; + + //this is added just to make save() and saveAs() work ok + //when first started up, just a silly patch + currentGameType = Constant.GameType.Constructed; + setDeckData("", false); + + setupMenu(); + setupSortMenu(); + } + + private void setupSortMenu() { + JMenuItem name = new JMenuItem("Card Name"); + JMenuItem cost = new JMenuItem("Cost"); + JMenuItem color = new JMenuItem("Color"); + JMenuItem type = new JMenuItem("Type"); + JMenuItem stats = new JMenuItem("Power/Toughness"); + JMenuItem rarity = new JMenuItem("Rarity"); + JMenuItem newFirst = new JMenuItem("Newer Cards First"); + + JMenu menu = new JMenu("Sort By"); + menu.add(name); + menu.add(cost); + menu.add(color); + menu.add(type); + menu.add(stats); + menu.add(rarity); + menu.add(newFirst); + + this.add(menu); + + //add listeners + + + name.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + //index 1 sorts by card name - for more info see TableSorter + // 0 1 2 3 4 5 6 + //private String column[] = {"Qty", "Name", "Cost", "Color", "Type", "Stats", "Rarity"}; + Gui_DeckEditor g = (Gui_DeckEditor) deckDisplay; + g.getTopTableModel().sort(1, true); + } + }); + + cost.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + // 0 1 2 3 4 5 6 + //private String column[] = {"Qty", "Name", "Cost", "Color", "Type", "Stats", "Rarity"}; + Gui_DeckEditor g = (Gui_DeckEditor) deckDisplay; + + //sort by type, color, cost + g.getTopTableModel().sort(4, true); + g.getTopTableModel().sort(3, true); + g.getTopTableModel().sort(2, true); + } + }); + + color.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + // 0 1 2 3 4 5 6 + //private String column[] = {"Qty", "Name", "Cost", "Color", "Type", "Stats", "Rarity"}; + Gui_DeckEditor g = (Gui_DeckEditor) deckDisplay; + + //sort by type, cost, color + g.getTopTableModel().sort(4, true); + g.getTopTableModel().sort(2, true); + g.getTopTableModel().sort(3, true); + } + }); + + type.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + // 0 1 2 3 4 5 6 + //private String column[] = {"Qty", "Name", "Cost", "Color", "Type", "Stats", "Rarity"}; + Gui_DeckEditor g = (Gui_DeckEditor) deckDisplay; + + //sort by cost, color, type + g.getTopTableModel().sort(2, true); + g.getTopTableModel().sort(3, true); + g.getTopTableModel().sort(4, true); + } + }); + + stats.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + // 0 1 2 3 4 5 6 + //private String column[] = {"Qty", "Name", "Cost", "Color", "Type", "Stats", "Rarity"}; + Gui_DeckEditor g = (Gui_DeckEditor) deckDisplay; + + g.getTopTableModel().sort(4, true); + g.getTopTableModel().sort(2, true); + g.getTopTableModel().sort(3, true); + g.getTopTableModel().sort(5, true); + } + }); + + rarity.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + // 0 1 2 3 4 5 6 + //private String column[] = {"Qty", "Name", "Cost", "Color", "Type", "Stats", "Rarity"}; + Gui_DeckEditor g = (Gui_DeckEditor) deckDisplay; + + //sort by cost, type, color, rarity + g.getTopTableModel().sort(2, true); + g.getTopTableModel().sort(4, true); + g.getTopTableModel().sort(3, true); + g.getTopTableModel().sort(6, true); + } + }); + + newFirst.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + // 0 1 2 3 4 5 6 + //private String column[] = {"Qty", "Name", "Cost", "Color", "Type", "Stats", "Rarity"}; + Gui_DeckEditor g = (Gui_DeckEditor) deckDisplay; + + g.getTopTableModel().sort(7, true); + } + }); + + }//setupSortMenu() + + public void newConstructed() { + if(debugPrint) System.out.println("New Constructed"); + +// if(! isDeckSaved) +// save(); + + currentGameType = Constant.GameType.Constructed; + setDeckData("", false); + + deckDisplay.updateDisplay(AllZone.CardFactory.getAllCards(), new CardList()); + }//new constructed + + private void newRandomConstructed() { + if(debugPrint) System.out.println("Random Constructed"); + +// if(! isDeckSaved) +// save(); + + currentGameType = Constant.GameType.Constructed; + setDeckData("", false); + + CardList all = AllZone.CardFactory.getAllCards(); + all.shuffle(); + CardList random = new CardList(); + + for(int i = 0; i < (15 * 5); i++) + random.add(all.remove(0)); + + random.add(AllZone.CardFactory.getCard("Forest", Constant.Player.Human)); + random.add(AllZone.CardFactory.getCard("Island", Constant.Player.Human)); + random.add(AllZone.CardFactory.getCard("Plains", Constant.Player.Human)); + random.add(AllZone.CardFactory.getCard("Mountain", Constant.Player.Human)); + random.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Human)); + + random.add(AllZone.CardFactory.getCard("Terramorphic Expanse", Constant.Player.Human)); + + + deckDisplay.updateDisplay(random, new CardList()); + }//new sealed + + + private void newGenerateConstructed() { + if(debugPrint) System.out.println("Generate Constructed"); + +// if(! isDeckSaved) +// save(); + + currentGameType = Constant.GameType.Constructed; + setDeckData("", false); + + GenerateConstructedDeck gen = new GenerateConstructedDeck(); + + deckDisplay.updateDisplay(AllZone.CardFactory.getAllCards(), gen.generateDeck()); + }//new sealed + + + private void newSealed() { + if(debugPrint) System.out.println("New Sealed"); + +// if(! isDeckSaved) +// save(); + + currentGameType = Constant.GameType.Sealed; + setDeckData("", false); + + deckDisplay.updateDisplay(new ReadBoosterPack().getBoosterPack5(), new CardList()); + }//new sealed + + private void newDraft() { + if(debugPrint) System.out.println("New Draft"); + +// if(! isDeckSaved) +// save(); + + currentGameType = Constant.GameType.Draft; + + //move all cards from deck main and sideboard to CardList + Deck deck = boosterDeckIO.readBoosterDeck(currentDeckName)[0]; + setDeckData("", false); + + CardList top = new CardList(); + + for(int i = 0; i < deck.countMain(); i++) + top.add(AllZone.CardFactory.getCard(deck.getMain(i), Constant.Player.Human)); + + for(int i = 0; i < deck.countSideboard(); i++) + top.add(AllZone.CardFactory.getCard(deck.getSideboard(i), Constant.Player.Human)); + + deckDisplay.updateDisplay(top, new CardList()); + }//new draft + + private FileFilter getFileFilter() { + FileFilter filter = new FileFilter() { + @Override + public boolean accept(File f) { + return f.getName().endsWith(".deck") || f.isDirectory(); + } + + @Override + public String getDescription() { + return "Deck File .deck"; + } + }; + + return filter; + }//getFileFilter() + + private File getImportFilename() { + JFileChooser chooser = new JFileChooser(previousDirectory); + + chooser.addChoosableFileFilter(getFileFilter()); + int returnVal = chooser.showOpenDialog(null); + + if(returnVal == JFileChooser.APPROVE_OPTION) { + File file = chooser.getSelectedFile(); + previousDirectory = file.getParentFile(); + return file; + } + + + return null; + + }//openFileDialog() + + private void showDeck(Deck deck) { + String gameType = deck.getDeckType(); + + if(gameType.equals(Constant.GameType.Constructed)) showConstructedDeck(deck); + + if(gameType.equals(Constant.GameType.Draft)) showDraftDeck(deck); + + if(gameType.equals(Constant.GameType.Sealed)) showSealedDeck(deck); + }//showDeck() + + private void importDeck() { + File file = getImportFilename(); + + if(file == null) return; + + Object check = null; + + try { + ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); + check = in.readObject(); + + in.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : importDeck() error, " + ex); + } + + Deck deck = null; + + //is Draft deck? + if(check instanceof Deck[]) { + Deck[] draftDeck = (Deck[]) check; + + currentGameType = Constant.GameType.Draft; + boosterDeckIO.writeBoosterDeck(draftDeck); + + //enable the new draft deck menu option + newDraftItem.setEnabled(true); + deck = draftDeck[0]; + } else //Sealed or Constructed + { + deck = (Deck) check; + currentGameType = deck.getDeckType(); + deckIO.writeDeck(deck); + + //disable the new draft deck menu option + newDraftItem.setEnabled(false); + } + + //update gui + showDeck(deck); + + }//importDeck() + + private void exportDeck() { + File filename = getExportFilename(); + + if(filename == null) return; + + //write is an Object variable because you might just + //write one Deck object or + //many Deck objects if it is a draft deck + Deck deck = getDeck(); + Object write = deck; + + deck.setName(filename.getName()); + + //export Draft decks, this is a little hacky + //a Draft deck holds 8 decks, [0] is the player's deck + //and the other 7 are the computer's deck + if(currentGameType.equals(Constant.GameType.Draft)) { + //read all draft decks + Deck d[] = boosterDeckIO.readBoosterDeck(currentDeckName); + + //replace your deck + d[0] = deck; + write = d; + } + + try { + ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename)); + out.writeObject(write); + out.flush(); + out.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : exportDeck() error, " + ex); + } + + exportDeckText(deck, filename.getAbsolutePath()); + + }//exportDeck() + + @SuppressWarnings("unchecked") + // TableSorter type saftey + private void exportDeckText(Deck aDeck, String filename) { + //convert Deck into CardList + CardList all = new CardList(); + for(int i = 0; i < aDeck.countMain(); i++) { + String cardName = aDeck.getMain(i); + Card c = AllZone.CardFactory.getCard(cardName, ""); + + all.add(c); + } + + //sort by card name + all.sort(new TableSorter(all, 1, true)); + + //remove all copies of cards + //make a singleton + CardList noCopies = new CardList(); + for(int i = 0; i < all.size(); i++) { + Card c = all.get(i); + + if(!noCopies.containsName(c.getName())) noCopies.add(c); + } + + + String text = ""; + String newLine = "\r\n"; + int count = 0; + + text = all.size() + " Total Cards" + newLine + newLine; + + //creatures + text += all.getType("Creature").size() + " Creatures" + newLine; + text += "-------------" + newLine; + + for(int i = 0; i < noCopies.size(); i++) { + Card c = noCopies.get(i); + if(c.isCreature()) { + count = all.getName(c.getName()).size(); + text += count + "x " + c.getName() + newLine; + } + } + + //count spells, arg! this is tough + CardListFilter cf = new CardListFilter() { + public boolean addCard(Card c) { + return !(c.isCreature() || c.isLand()); + } + };//CardListFilter + count = all.filter(cf).size(); + + //spells + text += newLine + count + " Spells" + newLine; + text += "----------" + newLine; + + for(int i = 0; i < noCopies.size(); i++) { + Card c = noCopies.get(i); + if(!(c.isCreature() || c.isLand())) { + count = all.getName(c.getName()).size(); + text += count + "x " + c.getName() + newLine; + } + } + + //land + text += newLine + all.getType("Land").size() + " Land" + newLine; + text += "--------" + newLine; + + for(int i = 0; i < noCopies.size(); i++) { + Card c = noCopies.get(i); + if(c.isLand()) { + count = all.getName(c.getName()).size(); + text += count + "x " + c.getName() + newLine; + } + } + + //remove ".deck" extension + int cut = filename.indexOf("."); + filename = filename.substring(0, cut); + + try { + FileWriter writer = new FileWriter(filename + ".txt"); + writer.write(text); + + writer.flush(); + writer.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : exportDeckText() error, " + ex.getMessage() + " : " + + ex.getStackTrace()); + } + }//exportDeckText() + + + private File getExportFilename() { + //Object o = null; // unused + + JFileChooser save = new JFileChooser(previousDirectory); + + save.setDialogTitle("Export Deck Filename"); + save.setDialogType(JFileChooser.SAVE_DIALOG); + save.addChoosableFileFilter(getFileFilter()); + save.setSelectedFile(new File(currentDeckName + ".deck")); + + int returnVal = save.showSaveDialog(null); + + if(returnVal == JFileChooser.APPROVE_OPTION) { + File file = save.getSelectedFile(); + String check = file.getAbsolutePath(); + + previousDirectory = file.getParentFile(); + + if(check.endsWith(".deck")) return file; + else return new File(check + ".deck"); + } + + return null; + }//getExportFilename() + + + private void openConstructed() { + if(debugPrint) System.out.println("Open Constructed"); + +// if(! isDeckSaved) +// save(); + + String name = getUserInput_OpenDeck(Constant.GameType.Constructed); + + if(name.equals("")) return; + + //must be AFTER get user input, since user could cancel + currentGameType = Constant.GameType.Constructed; + newDraftItem.setEnabled(false); + + Deck deck = deckIO.readDeck(name); + showConstructedDeck(deck); + }//open constructed + + private void showConstructedDeck(Deck deck) { + setDeckData(deck.getName(), true); + + CardList main = new CardList(); + for(int i = 0; i < deck.countMain(); i++) + main.add(AllZone.CardFactory.getCard(deck.getMain(i), Constant.Player.Human)); + + deckDisplay.updateDisplay(AllZone.CardFactory.getAllCards(), main); + }//showConstructedDeck() + + private void openSealed() { + if(debugPrint) System.out.println("Open Sealed"); + +// if(! isDeckSaved) +// save(); + + String name = getUserInput_OpenDeck(Constant.GameType.Sealed); + + if(name.equals("")) return; + + //must be AFTER get user input, since user could cancel + currentGameType = Constant.GameType.Sealed; + newDraftItem.setEnabled(false); + + Deck deck = deckIO.readDeck(name); + showSealedDeck(deck); + }//open sealed + + private void showSealedDeck(Deck deck) { + setDeckData(deck.getName(), true); + + CardList top = new CardList(); + for(int i = 0; i < deck.countSideboard(); i++) + top.add(AllZone.CardFactory.getCard(deck.getSideboard(i), Constant.Player.Human)); + + CardList bottom = new CardList(); + for(int i = 0; i < deck.countMain(); i++) + bottom.add(AllZone.CardFactory.getCard(deck.getMain(i), Constant.Player.Human)); + + deckDisplay.updateDisplay(top, bottom); + }//showSealedDeck() + + private void openDraft() { + if(debugPrint) System.out.println("Open Draft"); + + String name = getUserInput_OpenDeck(Constant.GameType.Draft); + + if(name.equals("")) return; + + //must be AFTER get user input, since user could cancel + currentGameType = Constant.GameType.Draft; + newDraftItem.setEnabled(true); + + Deck deck = boosterDeckIO.readBoosterDeck(name)[0]; + showDraftDeck(deck); + }//open draft + + private void showDraftDeck(Deck deck) { + setDeckData(deck.getName(), true); + + CardList top = new CardList(); + for(int i = 0; i < deck.countSideboard(); i++) + top.add(AllZone.CardFactory.getCard(deck.getSideboard(i), Constant.Player.Human)); + + CardList bottom = new CardList(); + for(int i = 0; i < deck.countMain(); i++) + bottom.add(AllZone.CardFactory.getCard(deck.getMain(i), Constant.Player.Human)); + + deckDisplay.updateDisplay(top, bottom); + }//showDraftDeck() + + private void save() { + if(debugPrint) System.out.println("Save"); + + if(currentDeckName.equals("")) saveAs(); + else if(currentGameType.equals(Constant.GameType.Draft)) { + setDeckData(currentDeckName, true); + //write booster deck + Deck[] all = boosterDeckIO.readBoosterDeck(currentDeckName); + all[0] = getDeck(); + boosterDeckIO.writeBoosterDeck(all); + } else//constructed or sealed + { + setDeckData(currentDeckName, true); + deckIO.deleteDeck(currentDeckName); + deckIO.writeDeck(getDeck()); + } + }//save + + private void saveAs() { + if(debugPrint) System.out.println("Save As"); + + String name = getUserInput_GetDeckName(); + + if(name.equals("")) return; + else if(currentGameType.equals(Constant.GameType.Draft)) { + //MUST copy array + Deck[] read = boosterDeckIO.readBoosterDeck(currentDeckName); + Deck[] all = new Deck[read.length]; + + System.arraycopy(read, 0, all, 0, read.length); + + setDeckData(name, true); + + all[0] = getDeck(); + boosterDeckIO.writeBoosterDeck(all); + } else//constructed and sealed + { + setDeckData(name, true); + deckIO.writeDeck(getDeck()); + } + }//save as + + private void delete() { + if(debugPrint) System.out.println("Delete"); + + if(currentGameType.equals("") || currentDeckName.equals("")) return; + + int n = JOptionPane.showConfirmDialog(null, "Do you want to delete this deck " + currentDeckName + " ?", + "Delete", JOptionPane.YES_NO_OPTION); + if(n == JOptionPane.NO_OPTION) return; + + if(currentGameType.equals(Constant.GameType.Draft)) boosterDeckIO.deleteBoosterDeck(currentDeckName); + else deckIO.deleteDeck(currentDeckName); + + setDeckData("", true); + deckDisplay.updateDisplay(new CardList(), new CardList()); + }//delete + + public void close() { + if(debugPrint) System.out.println("Close"); + +// if(! isDeckSaved) +// save(); + + deckIO.close(); + boosterDeckIO.close(); + exitCommand.execute(); + }//close + + private void setDeckData(String deckName, boolean in_isDeckSaved) { + currentDeckName = deckName; + isDeckSaved = in_isDeckSaved; + + deckDisplay.setTitle("Deck Editor : " + currentDeckName); + } + + public String getDeckName() { + return currentDeckName; + } + + public String getGameType() { + return currentGameType; + } + + public boolean isDeckSaved() { + return isDeckSaved; + } + + private String getUserInput_GetDeckName() { + Object o = JOptionPane.showInputDialog(null, "Save As", "Deck Name", JOptionPane.OK_CANCEL_OPTION); + + if(o == null) return ""; + + String deckName = cleanString(o.toString()); + + boolean isUniqueName; + if(currentGameType.equals(Constant.GameType.Draft)) isUniqueName = deckIO.isUniqueDraft(deckName); + else isUniqueName = deckIO.isUnique(deckName); + + if((!isUniqueName) || deckName.equals("")) { + JOptionPane.showMessageDialog(null, "Please pick another deck name, a deck currently has that name."); + return getUserInput_GetDeckName(); + } + + return deckName; + }//getUserInput_GetDeckName() + + //only accepts numbers, letters or dashes up to 10 characters in length + private String cleanString(String in) { + String out = ""; + char[] c = in.toCharArray(); + + for(int i = 0; i < c.length && i < 20; i++) + if(Character.isLetterOrDigit(c[i]) || c[i] == '-') out += c[i]; + + return out; + } + + + private String getUserInput_OpenDeck(String deckType) { + ArrayList choices = getDeckNames(deckType); + if(choices.size() == 0) { + JOptionPane.showMessageDialog(null, "No decks found", "Open Deck", JOptionPane.PLAIN_MESSAGE); + return ""; + } + Object o = JOptionPane.showInputDialog(null, "Deck Name", "Open Deck", JOptionPane.OK_CANCEL_OPTION, null, + choices.toArray(), choices.toArray()[0]); + + if(o == null) return ""; + + return o.toString(); + }//getUserInput_OpenDeck() + + + private ArrayList getDeckNames(String deckType) { + ArrayList list = new ArrayList(); + + //only get decks according to the Gui_NewGame screen option + if(deckType.equals(Constant.GameType.Draft)) { + Iterator it = boosterDeckIO.getBoosterDecks().keySet().iterator(); + + while(it.hasNext()) + list.add(it.next().toString()); + } else { + Deck[] d = deckIO.getDecks(); + for(int i = 0; i < d.length; i++) + if(deckType.equals(d[i].getDeckType())) list.add(d[i].toString()); + } + + Collections.sort(list); + return list; + }//getDecks() + + private Deck getDeck() { + Deck deck = new Deck(currentGameType); + deck.setName(currentDeckName); + CardList list; + String cardName; + + //always move "bottom" to main + list = deckDisplay.getBottom(); + for(int i = 0; i < list.size(); i++) { + cardName = list.get(i).getName(); + deck.addMain(AllZone.NameChanger.getOriginalName(cardName)); + } + + //if sealed or draft, move "top" to sideboard + if(!currentGameType.equals(Constant.GameType.Constructed)) { + list = deckDisplay.getTop(); + for(int i = 0; i < list.size(); i++) { + cardName = list.get(i).getName(); + deck.addSideboard(AllZone.NameChanger.getOriginalName(cardName)); + } + } + return deck; + }//getDeck() + + private void setupMenu() { + JMenuItem newConstructed = new JMenuItem("New Deck - Constructed"); + + JMenuItem newSealed = new JMenuItem("New Deck - Sealed"); + JMenuItem newDraft = new JMenuItem("New Deck - Draft"); + + JMenuItem newRandomConstructed = new JMenuItem("New Deck - Generate Random Constructed Cardpool"); + JMenuItem newGenerateConstructed = new JMenuItem("New Deck - Generate Constructed Deck"); + + + JMenuItem importDeck = new JMenuItem("Import Deck"); + JMenuItem exportDeck = new JMenuItem("Export Deck"); + + + JMenuItem openConstructed = new JMenuItem("Open Deck - Constructed"); + JMenuItem openSealed = new JMenuItem("Open Deck - Sealed"); + JMenuItem openDraft = new JMenuItem("Open Deck - Draft"); + + newDraftItem = newDraft; + newDraftItem.setEnabled(false); + + JMenuItem save = new JMenuItem("Save"); + JMenuItem saveAs = new JMenuItem("Save As"); + JMenuItem delete = new JMenuItem("Delete"); + JMenuItem close = new JMenuItem("Close"); + + JMenu fileMenu = new JMenu("Deck Actions"); + fileMenu.add(newConstructed); + + fileMenu.add(newSealed); + fileMenu.add(newDraft); + fileMenu.addSeparator(); + + fileMenu.add(openConstructed); + fileMenu.add(openSealed); + fileMenu.add(openDraft); + fileMenu.addSeparator(); + + fileMenu.add(importDeck); + fileMenu.add(exportDeck); + fileMenu.addSeparator(); + + fileMenu.add(newRandomConstructed); + fileMenu.add(newGenerateConstructed); + fileMenu.addSeparator(); + + fileMenu.add(save); + fileMenu.add(saveAs); + fileMenu.add(delete); + fileMenu.addSeparator(); + + fileMenu.add(close); + + this.add(fileMenu); + + //add listeners + exportDeck.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + exportDeck(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : exportDeck() error - " + ex); + } + } + }); + + + importDeck.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + importDeck(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : importDeck() error - " + ex); + } + } + }); + + + newConstructed.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + newConstructed(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : newConstructed() error - " + ex); + } + } + }); + + + newRandomConstructed.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + newRandomConstructed(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : newRandomConstructed() error - " + ex); + } + } + }); + + + newGenerateConstructed.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + newGenerateConstructed(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : newRandomConstructed() error - " + ex); + } + } + }); + + + newSealed.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + newSealed(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : newSealed() error - " + ex); + } + } + }); + + newDraft.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + newDraft(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : newDraft() error - " + ex); + } + } + }); + + openConstructed.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + openConstructed(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : openConstructed() error - " + ex); + } + } + }); + + openSealed.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + openSealed(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : openSealed() error - " + ex); + } + } + }); + + openDraft.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + openDraft(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : openDraft() error - " + ex); + } + } + }); + + save.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + save(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : save() error - " + ex); + } + } + }); + + saveAs.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + saveAs(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : saveAs() error - " + ex); + } + } + }); + + delete.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + delete(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : delete() error - " + ex); + } + } + }); + + close.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + close(); + } + }); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_DeckEditor_Menu : close() error - " + ex); + } + } + }); + }//setupMenu() +} \ No newline at end of file diff --git a/src/Gui_DownloadPictures.java b/src/Gui_DownloadPictures.java new file mode 100644 index 00000000000..be457ef2d78 --- /dev/null +++ b/src/Gui_DownloadPictures.java @@ -0,0 +1,314 @@ + +import static java.lang.Integer.*; +import static javax.swing.JOptionPane.*; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.URL; +import java.util.ArrayList; +import java.util.StringTokenizer; + +import javax.swing.AbstractButton; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; +import javax.swing.DefaultBoundedRangeModel; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.JRadioButton; +import javax.swing.JTextField; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import forge.error.ErrorViewer; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + + +public class Gui_DownloadPictures extends DefaultBoundedRangeModel implements Runnable, NewConstants, NewConstants.LANG.Gui_DownloadPictures { + + private static final long serialVersionUID = -7890794857949935256L; + + public static void main(String[] args) { + startDownload(null); + } + + public static final Proxy.Type[] types = Proxy.Type.values(); + + //proxy + private int type; + private JTextField addr, port; + + //progress + private Card[] cards; + private int card; + private boolean cancel; + private JProgressBar bar; + + private JOptionPane dlg; + private JButton close; + + private Gui_DownloadPictures(Card[] c) { + this.cards = c; + addr = new JTextField(ForgeProps.getLocalized(PROXY_ADDRESS)); + port = new JTextField(ForgeProps.getLocalized(PROXY_PORT)); + bar = new JProgressBar(this); + + JPanel p0 = new JPanel(); + p0.setLayout(new BoxLayout(p0, BoxLayout.Y_AXIS)); + + //Proxy Choice + ButtonGroup bg = new ButtonGroup(); + String[] labels = { + ForgeProps.getLocalized(NO_PROXY), ForgeProps.getLocalized(HTTP_PROXY), + ForgeProps.getLocalized(SOCKS_PROXY)}; + for(int i = 0; i < types.length; i++) { + JRadioButton rb = new JRadioButton(labels[i]); + rb.addChangeListener(new ProxyHandler(i)); + bg.add(rb); + p0.add(rb); + if(i == 0) rb.setSelected(true); + } + + //Proxy config + p0.add(addr); + p0.add(port); +// JTextField[] tfs = {addr, port}; +// String[] labels = {"Address", "Port"}; +// for(int i = 0; i < labels.length; i++) { +// JPanel p1 = new JPanel(new BorderLayout()); +// p0.add(p1); +//// p1.add(new JLabel(labels[i]), WEST); +// p1.add(tfs[i]); +// } + + //Start + final JButton b = new JButton(ForgeProps.getLocalized(BUTTONS.START)); + b.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + new Thread(Gui_DownloadPictures.this).start(); + b.setEnabled(false); + } + }); +// p0.add(b); + + p0.add(Box.createVerticalStrut(5)); + + //Progress + p0.add(bar); + bar.setStringPainted(true); + bar.setString(ForgeProps.getLocalized(BAR_BEFORE_START)); + Dimension d = bar.getPreferredSize(); + d.width = 300; + bar.setPreferredSize(d); + + //JOptionPane + Object[] options = {b, close = new JButton(ForgeProps.getLocalized(BUTTONS.CANCEL))}; + dlg = new JOptionPane(p0, DEFAULT_OPTION, PLAIN_MESSAGE, null, options, options[1]); + } + + @Override + public int getMinimum() { + return 0; + } + + @Override + public int getValue() { + return card; + } + + @Override + public int getExtent() { + return 0; + } + + @Override + public int getMaximum() { + return cards == null? 0:cards.length; + } + + private void update(int card) { + this.card = card; + fireStateChanged(); + bar.setString(String.format(ForgeProps.getLocalized(card == cards.length? BAR_CLOSE:BAR_WAIT), this.card, + cards.length)); + System.out.println(card + "/" + cards.length); + } + + public JDialog getDlg(JFrame frame) { + final JDialog dlg = this.dlg.createDialog(frame, ForgeProps.getLocalized(TITLE)); + close.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + dlg.setVisible(false); + } + }); + return dlg; + } + + public void setCancel(boolean cancel) { + this.cancel = cancel; + } + + + public void run() { + BufferedInputStream in; + BufferedOutputStream out; + + File base = ForgeProps.getFile(IMAGE_BASE); + + Proxy p = null; + if(type == 0) p = Proxy.NO_PROXY; + else try { + p = new Proxy(types[type], new InetSocketAddress(addr.getText(), parseInt(port.getText()))); + } catch(Exception ex) { + ErrorViewer.showError(ex, ForgeProps.getLocalized(ERRORS.PROXY_CONNECT), addr.getText(), + port.getText()); +// throw new RuntimeException("Gui_DownloadPictures : error 1 - " +ex); + return; + } + + if(p != null) { + byte[] buf = new byte[1024]; + int len; + System.out.println("basedir: " + base); + for(update(0); card < cards.length && !cancel; update(card + 1)) { + try { + String url = cards[card].url; + File f = new File(base, cards[card].name); + + in = new BufferedInputStream(new URL(url).openConnection(p).getInputStream()); + out = new BufferedOutputStream(new FileOutputStream(f)); + + while((len = in.read(buf)) != -1) { + //user cancelled + if(cancel) { + in.close(); + out.flush(); + out.close(); + + //delete what was written so far + f.delete(); + + return; + }//if - cancel + + out.write(buf, 0, len); + }//while - read and write file + + in.close(); + out.flush(); + out.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex, ForgeProps.getLocalized(ERRORS.OTHER), cards[card].name, + cards[card].url); +// throw new RuntimeException("Gui_DownloadPictures : error 1 - " +ex); + break; + } + }//for + } + close.setText(ForgeProps.getLocalized(BUTTONS.CLOSE)); + }//run + + public static void startDownload(JFrame frame) { + final Card[] card = getNeededCards(); + + if(card.length == 0) { + JOptionPane.showMessageDialog(frame, ForgeProps.getLocalized(NO_MORE)); + return; + } + + Gui_DownloadPictures download = new Gui_DownloadPictures(card); + JDialog dlg = download.getDlg(frame); + dlg.setVisible(true); + dlg.dispose(); + download.setCancel(true); + }//startDownload() + + private static Card[] getNeededCards() { + //read all card names and urls + Card[] card = readFile(); + ArrayList list = new ArrayList(); + File file; + + File base = ForgeProps.getFile(IMAGE_BASE); + + //check to see which cards we already have + for(int i = 0; i < card.length; i++) { + file = new File(base, card[i].name); + if(!file.exists()) list.add(card[i]); + } + //return all card names and urls that are needed + Card[] out = new Card[list.size()]; + list.toArray(out); + +// for(int i = 0; i < out.length; i++) +// System.out.println(out[i].name +" " +out[i].url); + return out; + }//getNeededCards() + + private static Card[] readFile() { + try { + BufferedReader in = new BufferedReader(new FileReader(ForgeProps.getFile(CARD_PICTURES))); + String line; + ArrayList list = new ArrayList(); + StringTokenizer tok; + + line = in.readLine(); + while(line != null && (!line.equals(""))) { + tok = new StringTokenizer(line); + list.add(new Card(tok.nextToken(), tok.nextToken())); + + line = in.readLine(); + } + + Card[] out = new Card[list.size()]; + list.toArray(out); + return out; + + } catch(Exception ex) { + ErrorViewer.showError(ex, "Gui_DownloadPictures: readFile() error"); + throw new RuntimeException("Gui_DownloadPictures : readFile() error"); + } + }//readFile() + + private class ProxyHandler implements ChangeListener { + private int type; + + public ProxyHandler(int type) { + this.type = type; + } + + public void stateChanged(ChangeEvent e) { + if(((AbstractButton) e.getSource()).isSelected()) { + Gui_DownloadPictures.this.type = type; + addr.setEnabled(type != 0); + port.setEnabled(type != 0); + } + } + } + + private static class Card { + final public String name; + final public String url; + + Card(String cardName, String cardURL) { + name = cardName; + url = cardURL; + } + }//Card +} diff --git a/src/Gui_MultipleBlockers.java b/src/Gui_MultipleBlockers.java new file mode 100644 index 00000000000..e8faa91a0d1 --- /dev/null +++ b/src/Gui_MultipleBlockers.java @@ -0,0 +1,131 @@ +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +public class Gui_MultipleBlockers extends JFrame +{ + private static final long serialVersionUID = -3585314684734680978L; + + private int assignDamage; + private Card att; + private GuiDisplay2 guiDisplay; + + private BorderLayout borderLayout1 = new BorderLayout(); + private JPanel mainPanel = new JPanel(); + private JScrollPane jScrollPane1 = new JScrollPane(); + private JLabel numberLabel = new JLabel(); + private JPanel jPanel3 = new JPanel(); + private BorderLayout borderLayout3 = new BorderLayout(); + private JPanel creaturePanel = new JPanel(); + + public static void main(String[] args) + { + CardList list = new CardList(); + list.add(AllZone.CardFactory.getCard("Elvish Piper", "")); + list.add(AllZone.CardFactory.getCard("Lantern Kami", "")); + list.add(AllZone.CardFactory.getCard("Frostling", "")); + list.add(AllZone.CardFactory.getCard("Frostling", "")); + + + for(int i = 0; i < 2; i++) + new Gui_MultipleBlockers(list.get(i),list, i+1, null); + } + + @SuppressWarnings("deprecation") // dialog.show is deprecated + public Gui_MultipleBlockers(Card attacker, CardList creatureList, int damage, GuiDisplay2 display) + { + this(); + assignDamage = damage; + updateDamageLabel();//update user message about assigning damage + guiDisplay = display; + att = attacker; + + for(int i = 0; i < creatureList.size(); i++) + creaturePanel.add(GuiDisplayUtil.getCardPanel(creatureList.get(i))); + + JDialog dialog = new JDialog(this, true); + dialog.setTitle("Multiple Blockers"); + dialog.setContentPane(mainPanel); + dialog.setSize(470, 260); + dialog.show(); + } + public Gui_MultipleBlockers() { + try { + jbInit(); + } + catch(Exception e) { + e.printStackTrace(); + } +// setSize(470, 280); +// show(); + } + private void jbInit() throws Exception { + this.getContentPane().setLayout(borderLayout1); + this.setTitle("Multiple Blockers"); + mainPanel.setLayout(null); + numberLabel.setHorizontalAlignment(SwingConstants.CENTER); + numberLabel.setHorizontalTextPosition(SwingConstants.CENTER); + numberLabel.setText("Assign"); + numberLabel.setBounds(new Rectangle(52, 30, 343, 24)); + jPanel3.setLayout(borderLayout3); + jPanel3.setBounds(new Rectangle(26, 75, 399, 114)); + creaturePanel.addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(MouseEvent e) { + creaturePanel_mousePressed(e); + } + }); + creaturePanel.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { + public void mouseMoved(MouseEvent e) { + creaturePanel_mouseMoved(e); + } + }); + mainPanel.add(jPanel3, null); + jPanel3.add(jScrollPane1, BorderLayout.CENTER); + mainPanel.add(numberLabel, null); + jScrollPane1.getViewport().add(creaturePanel, null); + this.getContentPane().add(mainPanel, BorderLayout.CENTER); + } + + void okButton_actionPerformed(ActionEvent e) { + dispose(); + } + + void creaturePanel_mousePressed(MouseEvent e) { + Object o = creaturePanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) + { + CardPanel cardPanel = (CardPanel)o; + Card c = cardPanel.getCard(); + + CardList cl = new CardList(); + cl.add(att); + AllZone.GameAction.setAssignedDamage(c, cl, c.getAssignedDamage() + 1); + //c.setAssignedDamage(c.getAssignedDamage() + 1); + + if(guiDisplay != null) + guiDisplay.updateCardDetail(c); + } + //reduce damage, show new user message, exit if necessary + assignDamage--; + updateDamageLabel(); + if(assignDamage == 0) + dispose(); + }//creaturePanel_mousePressed() + void updateDamageLabel() + { + numberLabel.setText("Assign " +assignDamage +" damage - click on card to assign damage"); + } + + void creaturePanel_mouseMoved(MouseEvent e) + { + Object o = creaturePanel.getComponentAt(e.getPoint()); + if(o instanceof CardPanel) + { + CardPanel cardPanel = (CardPanel)o; + Card c = cardPanel.getCard(); + + if(guiDisplay != null) + guiDisplay.updateCardDetail(c); + } + } +} \ No newline at end of file diff --git a/src/Gui_NewGame.java b/src/Gui_NewGame.java new file mode 100644 index 00000000000..2a2453f99b6 --- /dev/null +++ b/src/Gui_NewGame.java @@ -0,0 +1,670 @@ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextArea; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; + +import forge.error.ErrorViewer; +import forge.error.ExceptionHandler; +import forge.gui.ListChooser; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; +import forge.properties.NewConstants.LANG.Gui_NewGame.MENU_BAR.MENU; +import forge.properties.NewConstants.LANG.Gui_NewGame.MENU_BAR.OPTIONS; + + +public class Gui_NewGame extends JFrame implements NewConstants, NewConstants.LANG.Gui_NewGame { + private static final long serialVersionUID = -2437047615019135648L; + + private final DeckIO deckIO = new DeckIO(ForgeProps.getFile(DECKS)); + private final DeckIO boosterDeckIO = new DeckIO(ForgeProps.getFile(BOOSTER_DECKS)); + private ArrayList allDecks; + private static Gui_DeckEditor editor; + + private JLabel titleLabel = new JLabel(); + private JLabel jLabel2 = new JLabel(); + private JLabel jLabel3 = new JLabel(); + private JComboBox humanComboBox = new JComboBox(); + private JComboBox computerComboBox = new JComboBox(); + private JButton deckEditorButton = new JButton(); + private JButton startButton = new JButton(); + private ButtonGroup buttonGroup1 = new ButtonGroup(); + private JRadioButton sealedRadioButton = new JRadioButton(); + private JRadioButton singleRadioButton = new JRadioButton(); + private JPanel jPanel2 = new JPanel(); + private Border border1; + private TitledBorder titledBorder1; + private JRadioButton draftRadioButton = new JRadioButton(); + private JPanel jPanel1 = new JPanel(); + private Border border2; + @SuppressWarnings("unused") + // titledBorder2 + private TitledBorder titledBorder2; + private static JCheckBox newGuiCheckBox = new JCheckBox("", true); + private static JCheckBox smoothLandCheckBox = new JCheckBox("", true); + + // GenerateConstructedDeck.get2Colors() and GenerateSealedDeck.get2Colors() + // use these two variables + public static JCheckBoxMenuItem removeSmallCreatures = new JCheckBoxMenuItem( + ForgeProps.getLocalized(MENU_BAR.OPTIONS.GENERATE.REMOVE_SMALL)); + public static JCheckBoxMenuItem removeArtifacts = new JCheckBoxMenuItem( + ForgeProps.getLocalized(MENU_BAR.OPTIONS.GENERATE.REMOVE_ARTIFACTS)); + + private JButton questButton = new JButton(); + + private Action LOOK_AND_FEEL_ACTION = new LookAndFeelAction(this); + private Action DOWNLOAD_ACTION = new DownloadAction(); + private Action CARD_SIZES_ACTION = new CardSizesAction(); + private Action ABOUT_ACTION = new AboutAction(); + + public static void main(String[] args) { + ExceptionHandler.registerErrorHandling(); + try { + Object[] o = UIManager.getInstalledLookAndFeels(); + if(o.length > 3) { + final Color background = new Color(204, 204, 204); + + String[] properties = { + "Panel.background", "Panel.background", "JPanel.background", "Button.background", + "RadioButton.background", "MenuBar.background", "Menu.background", "JMenu.background", + "ComboBox.background", "MenuItem.background", "JCheckBoxMenuItem.background", + "Dialog.background", "OptionPane.background", "ScrollBar.background"}; + for(int i = 0; i < properties.length; i++) { + //UIManager.put(properties, background); + UIManager.put(properties[i], background); + } + } + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + + + try { + + Constant.Runtime.GameType[0] = Constant.GameType.Constructed; + AllZone.Computer = new ComputerAI_Input(new ComputerAI_General()); + + new Gui_NewGame(); + + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + } + + public Gui_NewGame() { + AllZone.QuestData = null; + allDecks = getDecks(); + Constant.Runtime.WinLose.reset(); + + if(Constant.Runtime.width[0] == 0) Constant.Runtime.width[0] = 70; + + if(Constant.Runtime.height[0] == 0) Constant.Runtime.height[0] = 98; + + + try { + jbInit(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + + if(Constant.Runtime.GameType[0].equals(Constant.GameType.Constructed)) { + singleRadioButton.setSelected(true); + updateDeckComboBoxes(); + } + if(Constant.Runtime.GameType[0].equals(Constant.GameType.Sealed)) { + sealedRadioButton.setSelected(true); + updateDeckComboBoxes(); + } + if(Constant.Runtime.GameType[0].equals(Constant.GameType.Draft)) { + draftRadioButton.setSelected(true); + draftRadioButton_actionPerformed(null); + } + + addListeners(); + + Dimension screen = getToolkit().getScreenSize(); + Rectangle bounds = getBounds(); + bounds.width = 460; + bounds.height = 560; + bounds.x = (screen.width - bounds.width) / 2; + bounds.y = (screen.height - bounds.height) / 2; + setBounds(bounds); + + setTitle(ForgeProps.getLocalized(LANG.PROGRAM_NAME)); + setupMenu(); + setVisible(true); + + }// init() + + private void setupMenu() { + Action[] actions = { + LOOK_AND_FEEL_ACTION, DOWNLOAD_ACTION, CARD_SIZES_ACTION, ErrorViewer.ALL_THREADS_ACTION, + ABOUT_ACTION}; + JMenu menu = new JMenu(ForgeProps.getLocalized(MENU.TITLE)); + for(Action a:actions) + menu.add(a); + + // new stuff + JMenu generatedDeck = new JMenu(ForgeProps.getLocalized(MENU_BAR.OPTIONS.GENERATE.TITLE)); + generatedDeck.add(removeSmallCreatures); + generatedDeck.add(removeArtifacts); + JMenu optionsMenu = new JMenu(ForgeProps.getLocalized(OPTIONS.TITLE)); + optionsMenu.add(generatedDeck); + + JMenuBar bar = new JMenuBar(); + bar.add(menu); + bar.add(optionsMenu); + bar.add(new MenuItem_HowToPlay()); + + setJMenuBar(bar); + } + + + // returns, ArrayList of Deck objects + private ArrayList getDecks() { + ArrayList list = new ArrayList(); + Deck[] deck = deckIO.getDecks(); + for(int i = 0; i < deck.length; i++) + list.add(deck[i]); + + Collections.sort(list, new DeckSort()); + return list; + } + + private void addListeners() { + this.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent ev) { + System.exit(0); + } + }); + + questButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + // close this windows + // can't use this.dispose() because "this" object is an + // ActionListener + Gui_NewGame.this.dispose(); + + new Gui_QuestOptions(); + } + }); + }// addListeners() + + @SuppressWarnings("unused") + // setupSealed + private void setupSealed() { + Deck deck = new Deck(Constant.GameType.Sealed); + + ReadBoosterPack booster = new ReadBoosterPack(); + CardList pack = booster.getBoosterPack5(); + + for(int i = 0; i < pack.size(); i++) + deck.addSideboard(pack.get(i).getName()); + + Constant.Runtime.HumanDeck[0] = deck; + } + + private void jbInit() throws Exception { + border1 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder1 = new TitledBorder(border1, "Game Type"); + border2 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder2 = new TitledBorder(border2, "Library"); + titleLabel.setBounds(new Rectangle(155, 8, 171, 57)); + titleLabel.setText("New Game"); + titleLabel.setFont(new java.awt.Font("Dialog", 0, 26)); + this.getContentPane().setLayout(null); + jLabel2.setText("Your Deck"); + jLabel2.setBounds(new Rectangle(9, 12, 85, 27)); + jLabel3.setText("Opponent"); + jLabel3.setBounds(new Rectangle(9, 45, 85, 27)); + humanComboBox.setBounds(new Rectangle(75, 14, 197, 23)); + humanComboBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + humanComboBox_actionPerformed(e); + } + }); + computerComboBox.setBounds(new Rectangle(75, 47, 197, 23)); + deckEditorButton.setBounds(new Rectangle(278, 24, 124, 36)); + deckEditorButton.setToolTipText(""); + deckEditorButton.setText("Deck Editor"); + deckEditorButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + deckEditorButton_actionPerformed(e); + } + }); + startButton.setBounds(new Rectangle(159, 375, 139, 54)); + startButton.setFont(new java.awt.Font("Dialog", 0, 18)); + startButton.setHorizontalTextPosition(SwingConstants.LEADING); + startButton.setText("Start Game"); + startButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + startButton_actionPerformed(e); + } + }); + sealedRadioButton.setToolTipText(""); + sealedRadioButton.setText("Sealed Deck (Medium) - Create your deck from 75 available cards"); + sealedRadioButton.setBounds(new Rectangle(14, 51, 406, 28)); + sealedRadioButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + sealedRadioButton_actionPerformed(e); + } + }); + singleRadioButton.setText("Constructed (Easy) - Use all of the cards to defeat the computer"); + singleRadioButton.setBounds(new Rectangle(14, 17, 403, 31)); + singleRadioButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + singleRadioButton_actionPerformed(e); + } + }); + jPanel2.setBorder(titledBorder1); + jPanel2.setBounds(new Rectangle(10, 71, 425, 120)); + jPanel2.setLayout(null); + draftRadioButton.setToolTipText(""); + draftRadioButton.setText("Booster Draft (Hard) - Pick cards 1 at a time to create your deck"); + draftRadioButton.setBounds(new Rectangle(14, 82, 399, 25)); + draftRadioButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + draftRadioButton_actionPerformed(e); + } + }); + jPanel1.setBorder(BorderFactory.createEtchedBorder()); + jPanel1.setBounds(new Rectangle(10, 209, 425, 150)); + jPanel1.setLayout(null); + newGuiCheckBox.setText("Resizable Game Area"); + newGuiCheckBox.setBounds(new Rectangle(159, 305, 164, 25)); + //newGuiCheckBox.setSelected(true); + smoothLandCheckBox.setText("Stack AI land"); + smoothLandCheckBox.setBounds(new Rectangle(159, 330, 165, 25)); + //smoothLandCheckBox.setSelected(true); + + questButton.setBounds(new Rectangle(137, 435, 187, 53)); + questButton.setFont(new java.awt.Font("Dialog", 0, 18)); + questButton.setText("Quest Mode"); + + this.getContentPane().add(titleLabel, null); + jPanel1.add(computerComboBox, null); + jPanel1.add(humanComboBox, null); + jPanel1.add(jLabel2, null); + jPanel1.add(jLabel3, null); + jPanel1.add(deckEditorButton, null); + this.getContentPane().add(startButton, null); + this.getContentPane().add(newGuiCheckBox, null); + this.getContentPane().add(smoothLandCheckBox, null); + this.getContentPane().add(questButton, null); + this.getContentPane().add(jPanel2, null); + jPanel2.add(singleRadioButton, null); + jPanel2.add(sealedRadioButton, null); + jPanel2.add(draftRadioButton, null); + this.getContentPane().add(jPanel1, null); + buttonGroup1.add(singleRadioButton); + buttonGroup1.add(sealedRadioButton); + buttonGroup1.add(draftRadioButton); + } + + void deckEditorButton_actionPerformed(ActionEvent e) { + if(editor == null) { + editor = new Gui_DeckEditor(); + + { + { + Command exit = new Command() { + private static final long serialVersionUID = -9133358399503226853L; + + public void execute() { + new Gui_NewGame(); + } + }; + editor.show(exit); + editor.setVisible(true); + }//run() + } + }//if + + editor.setVisible(true); + dispose(); + } + + Deck getRandomDeck(Deck[] d) { + //get a random number between 0 and d.length + int i = (int) (Math.random() * d.length); + + return d[i]; + } + + void startButton_actionPerformed(ActionEvent e) { + if(humanComboBox.getSelectedItem() == null || computerComboBox.getSelectedItem() == null) return; + + String human = humanComboBox.getSelectedItem().toString(); + + String computer = null; + if(computerComboBox.getSelectedItem() != null) computer = computerComboBox.getSelectedItem().toString(); + + if(draftRadioButton.isSelected()) { + if(human.equals("New Draft")) { + dispose(); + Gui_BoosterDraft draft = new Gui_BoosterDraft(); + draft.showGui(new BoosterDraft_1()); + return; + } else//load old draft + { + Deck[] deck = boosterDeckIO.readBoosterDeck(human); + int index = Integer.parseInt(computer); + + Constant.Runtime.HumanDeck[0] = deck[0]; + Constant.Runtime.ComputerDeck[0] = deck[index]; + + if(Constant.Runtime.ComputerDeck[0] == null) throw new RuntimeException( + "Gui_NewGame : startButton() error - computer deck is null"); + }// else - load old draft + }// if + else { + // non-draft decks + String format = Constant.Runtime.GameType[0]; + boolean sealed = Constant.GameType.Sealed.equals(format); + boolean constructed = Constant.GameType.Constructed.equals(format); + + boolean humanGenerate = human.equals("Generate Deck"); + boolean humanGenerateMulti3 = human.equals("Generate 3-Color Deck"); + boolean humanGenerateMulti5 = human.equals("Generate 5-Color Gold Deck"); + boolean humanRandom = human.equals("Random"); + if(humanGenerate) { + if(constructed) Constant.Runtime.HumanDeck[0] = generateConstructedDeck(); + else if(sealed) Constant.Runtime.HumanDeck[0] = generateSealedDeck(); + } + else if (humanGenerateMulti3) { + if(constructed) Constant.Runtime.HumanDeck[0] = generateConstructed3ColorDeck(); + } + else if (humanGenerateMulti5) { + if(constructed) Constant.Runtime.HumanDeck[0] = generateConstructed5ColorDeck(); + } + else if(humanRandom) { + Constant.Runtime.HumanDeck[0] = getRandomDeck(getDecks(format)); + JOptionPane.showMessageDialog(null, String.format("You are using deck: %s", + Constant.Runtime.HumanDeck[0].getName()), "Deck Name", JOptionPane.INFORMATION_MESSAGE); + } + else { + Constant.Runtime.HumanDeck[0] = deckIO.readDeck(human); + } + + + boolean computerGenerate = computer.equals("Generate Deck"); + boolean computerGenerateMulti3 = computer.equals("Generate 3-Color Deck"); + boolean computerGenerateMulti5 = computer.equals("Generate 5-Color Gold Deck"); + + boolean computerRandom = computer.equals("Random"); + if(computerGenerate) { + if(constructed) Constant.Runtime.ComputerDeck[0] = generateConstructedDeck(); + else if(sealed) Constant.Runtime.ComputerDeck[0] = generateSealedDeck(); + } + else if (computerGenerateMulti3) { + if(constructed) Constant.Runtime.ComputerDeck[0] = generateConstructed3ColorDeck(); + } + else if (computerGenerateMulti5) { + if(constructed) Constant.Runtime.ComputerDeck[0] = generateConstructed5ColorDeck(); + } + else if(computerRandom) { + Constant.Runtime.ComputerDeck[0] = getRandomDeck(getDecks(format)); + JOptionPane.showMessageDialog(null, String.format("The computer is using deck: %s", + Constant.Runtime.ComputerDeck[0].getName()), "Deck Name", JOptionPane.INFORMATION_MESSAGE); + } else { + Constant.Runtime.ComputerDeck[0] = deckIO.readDeck(computer); + } + }// else + + //DO NOT CHANGE THIS ORDER, GuiDisplay needs to be created before cards are added + + if(newGuiCheckBox.isSelected()) AllZone.Display = new GuiDisplay3(); + else AllZone.Display = new GuiDisplay2(); + + if(smoothLandCheckBox.isSelected()) Constant.Runtime.smooth[0] = true; + else Constant.Runtime.smooth[0] = false; + + AllZone.GameAction.newGame(Constant.Runtime.HumanDeck[0], Constant.Runtime.ComputerDeck[0]); + AllZone.Display.setVisible(true); + + dispose(); + }//startButton_actionPerformed() + + private Deck generateSealedDeck() { + GenerateSealedDeck gen = new GenerateSealedDeck(); + CardList name = gen.generateDeck(); + Deck deck = new Deck(Constant.GameType.Sealed); + + for(int i = 0; i < 40; i++) + deck.addMain(name.get(i).getName()); + return deck; + } + + + private Deck generateConstructedDeck() { + GenerateConstructedDeck gen = new GenerateConstructedDeck(); + CardList name = gen.generateDeck(); + Deck deck = new Deck(Constant.GameType.Constructed); + + for(int i = 0; i < 60; i++) + deck.addMain(name.get(i).getName()); + return deck; + } + + private Deck generateConstructed3ColorDeck() { + GenerateConstructedMultiColorDeck gen = new GenerateConstructedMultiColorDeck(); + CardList name = gen.generate3ColorDeck(); + Deck deck = new Deck(Constant.GameType.Constructed); + + for(int i = 0; i < 60; i++) + deck.addMain(name.get(i).getName()); + return deck; + } + + private Deck generateConstructed5ColorDeck() { + GenerateConstructedMultiColorDeck gen = new GenerateConstructedMultiColorDeck(); + CardList name = gen.generate5ColorDeck(); + Deck deck = new Deck(Constant.GameType.Constructed); + + for(int i = 0; i < 60; i++) + deck.addMain(name.get(i).getName()); + return deck; + } + + void singleRadioButton_actionPerformed(ActionEvent e) { + Constant.Runtime.GameType[0] = Constant.GameType.Constructed; + updateDeckComboBoxes(); + } + + void sealedRadioButton_actionPerformed(ActionEvent e) { + Constant.Runtime.GameType[0] = Constant.GameType.Sealed; + updateDeckComboBoxes(); + } + + private void updateDeckComboBoxes() { + humanComboBox.removeAllItems(); + computerComboBox.removeAllItems(); + + if(Constant.GameType.Sealed.equals(Constant.Runtime.GameType[0]) + || Constant.GameType.Constructed.equals(Constant.Runtime.GameType[0])) { + humanComboBox.addItem("Generate Deck"); + computerComboBox.addItem("Generate Deck"); + + humanComboBox.addItem("Generate 3-Color Deck"); + computerComboBox.addItem("Generate 3-Color Deck"); + + humanComboBox.addItem("Generate 5-Color Gold Deck"); + computerComboBox.addItem("Generate 5-Color Gold Deck"); + + humanComboBox.addItem("Random"); + computerComboBox.addItem("Random"); + } + + Deck d; + for(int i = 0; i < allDecks.size(); i++) { + d = allDecks.get(i); + if(d.getDeckType().equals(Constant.Runtime.GameType[0])) { + humanComboBox.addItem(d.getName()); + computerComboBox.addItem(d.getName()); + } + }//for + + //not sure if the code below is useful or not + //this will select the deck that you previously used + + //if(Constant.Runtime.HumanDeck[0] != null) + // humanComboBox.setSelectedItem(Constant.Runtime.HumanDeck[0].getName()); + + }/*updateComboBoxes()*/ + + Deck[] getDecks(String gameType) { + ArrayList list = new ArrayList(); + + Deck d; + for(int i = 0; i < allDecks.size(); i++) { + d = allDecks.get(i); + if(d.getDeckType().equals(gameType)) list.add(d); + }//for + + //convert ArrayList to Deck[] + Deck[] out = new Deck[list.size()]; + list.toArray(out); + + return out; + }//getDecks() + + void draftRadioButton_actionPerformed(ActionEvent e) { + Constant.Runtime.GameType[0] = Constant.GameType.Draft; + humanComboBox.removeAllItems(); + computerComboBox.removeAllItems(); + + humanComboBox.addItem("New Draft"); + Object[] key = boosterDeckIO.getBoosterDecks().keySet().toArray(); + Arrays.sort(key); + for(int i = 0; i < key.length; i++) + humanComboBox.addItem(key[i]); + + for(int i = 0; i < 7; i++) + computerComboBox.addItem("" + (i + 1)); + } + + void humanComboBox_actionPerformed(ActionEvent e) { + + }/* draftRadioButton_actionPerformed() */ + + public static class LookAndFeelAction extends AbstractAction { + + private static final long serialVersionUID = -4447498333866711215L; + private Component c; + + public LookAndFeelAction(Component c) { + super(ForgeProps.getLocalized(MENU_BAR.MENU.LF)); + this.c = c; + } + + public void actionPerformed(ActionEvent e) { + LookAndFeelInfo[] info = UIManager.getInstalledLookAndFeels(); + String[] keys = new String[info.length]; + for(int i = 0; i < info.length; i++) + keys[i] = info[i].getName(); + ListChooser ch = new ListChooser("Choose one", 0, 1, keys); + if(ch.show()) try { + int index = ch.getSelectedIndex(); + if(index == -1) return; + UIManager.setLookAndFeel(info[index].getClassName()); + SwingUtilities.updateComponentTreeUI(c); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + } + } + + public static class DownloadAction extends AbstractAction { + + private static final long serialVersionUID = 6564425021778307101L; + + public DownloadAction() { + super(ForgeProps.getLocalized(MENU_BAR.MENU.DOWNLOAD)); + } + + public void actionPerformed(ActionEvent e) { + Gui_DownloadPictures.startDownload(null); + } + } + + public static class CardSizesAction extends AbstractAction { + + private static final long serialVersionUID = -2900235618450319571L; + private String[] keys = {"Tiny", "Small", "Medium", "Large"}; + private int[] widths = {42, 63, 70, 93}; + private int[] heights = {59, 88, 98, 130}; + + public CardSizesAction() { + super(ForgeProps.getLocalized(MENU_BAR.MENU.CARD_SIZES)); + } + + public void actionPerformed(ActionEvent e) { + ListChooser ch = new ListChooser("Choose one", "Choose a new card size", 0, 1, keys); + if(ch.show()) try { + int index = ch.getSelectedIndex(); + if(index == -1) return; + Constant.Runtime.width[0] = widths[index]; + Constant.Runtime.height[0] = heights[index]; + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + } + } + + public static class AboutAction extends AbstractAction { + + private static final long serialVersionUID = 5492173304463396871L; + + public AboutAction() { + super(ForgeProps.getLocalized(MENU_BAR.MENU.ABOUT)); + } + + public void actionPerformed(ActionEvent e) { + JTextArea area = new JTextArea(8, 25); + Font f = new Font(area.getFont().getName(), Font.PLAIN, 13); + area.setFont(f); + + area.setText("I enjoyed programming this project. I'm glad other people also enjoy my program. MTG Forge has turned out to be very successful.\n\nmtgrares@yahoo.com\nhttp://mtgrares.blogspot.com\n\nWritten by: Forge"); + + area.setWrapStyleWord(true); + area.setLineWrap(true); + area.setEditable(false); + + JPanel p = new JPanel(); + area.setBackground(p.getBackground()); + + JOptionPane.showMessageDialog(null, area, "About", JOptionPane.INFORMATION_MESSAGE); + } + } +} \ No newline at end of file diff --git a/src/Gui_Quest.java b/src/Gui_Quest.java new file mode 100644 index 00000000000..5954a3d1ab6 --- /dev/null +++ b/src/Gui_Quest.java @@ -0,0 +1,241 @@ +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.ArrayList; +import java.util.Collections; + +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; + + +//presumes AllZone.QuestData is not null +//AllZone.QuestData should be set by Gui_QuestOptions +public class Gui_Quest extends JFrame { + private static final long serialVersionUID = -6432089669283627896L; + + private QuestData questData; + + private JLabel jLabel1 = new JLabel(); + private JLabel difficultlyLabel = new JLabel(); + private JLabel winLostLabel = new JLabel(); + private JLabel rankLabel = new JLabel(); + @SuppressWarnings("unused") + // border1 + private Border border1; + private TitledBorder titledBorder1; + private JButton deckEditorButton = new JButton(); + private JPanel jPanel2 = new JPanel(); + private JButton playGameButton = new JButton(); + private JRadioButton oppTwoRadio = new JRadioButton(); + private JRadioButton oppOneRadio = new JRadioButton(); + private JRadioButton oppThreeRadio = new JRadioButton(); + private JLabel jLabel5 = new JLabel(); + private JComboBox deckComboBox = new JComboBox(); + private ButtonGroup oppGroup = new ButtonGroup(); + private static JCheckBox smoothLandCheckBox = new JCheckBox("", true); + private static JCheckBox resizeCheckbox = new JCheckBox("", true); + + public static void main(String[] args) { + new Gui_Quest(); + } + + public Gui_Quest() { + try { + jbInit(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + + questData = AllZone.QuestData; + setup(); + + setVisible(true); + } + + private void setup() { + //center window on the screen + Dimension screen = this.getToolkit().getScreenSize(); + setBounds(screen.width / 4, 50, //position + 500, 500); //size + + //if user closes this window, go back to "Quest Options" screen + this.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent ev) { + Gui_Quest.this.dispose(); + new Gui_QuestOptions(); + } + }); + + //set labels + difficultlyLabel.setText(questData.getDifficulty()); + rankLabel.setText(questData.getRank()); + + String s = questData.getWin() + " wins / " + questData.getLost() + " losses"; + winLostLabel.setText(s); + + String[] op = questData.getOpponents(); + oppOneRadio.setText(op[0]); + oppTwoRadio.setText(op[1]); + oppThreeRadio.setText(op[2]); + + + //get deck names as Strings + ArrayList list = questData.getDeckNames(); + Collections.sort(list); + for(int i = 0; i < list.size(); i++) + deckComboBox.addItem(list.get(i)); + + if(Constant.Runtime.HumanDeck[0] != null) + deckComboBox.setSelectedItem(Constant.Runtime.HumanDeck[0].getName()); + }//setup() + + private void jbInit() throws Exception { + border1 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder1 = new TitledBorder(BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)), + "Choices"); + jLabel1.setFont(new java.awt.Font("Dialog", 0, 25)); + jLabel1.setHorizontalAlignment(SwingConstants.CENTER); + jLabel1.setText("Quest Mode"); + jLabel1.setBounds(new Rectangle(1, 7, 453, 45)); + this.setResizable(false); + this.setTitle("Quest Mode"); + this.getContentPane().setLayout(null); + difficultlyLabel.setText("Medium"); + difficultlyLabel.setBounds(new Rectangle(1, 52, 453, 41)); + difficultlyLabel.setFont(new java.awt.Font("Dialog", 0, 25)); + difficultlyLabel.setHorizontalAlignment(SwingConstants.CENTER); + winLostLabel.setText("23 wins / 10 loses"); + winLostLabel.setBounds(new Rectangle(1, 130, 453, 43)); + winLostLabel.setFont(new java.awt.Font("Dialog", 0, 25)); + winLostLabel.setHorizontalAlignment(SwingConstants.CENTER); + winLostLabel.setHorizontalTextPosition(SwingConstants.CENTER); + rankLabel.setText("Card Flopper"); + rankLabel.setBounds(new Rectangle(1, 93, 453, 37)); + rankLabel.setFont(new java.awt.Font("Dialog", 0, 25)); + rankLabel.setHorizontalAlignment(SwingConstants.CENTER); + deckEditorButton.setBounds(new Rectangle(291, 123, 142, 38)); + deckEditorButton.setFont(new java.awt.Font("Dialog", 0, 18)); + deckEditorButton.setText("Deck Editor"); + deckEditorButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + deckEditorButton_actionPerformed(e); + } + }); + jPanel2.setBorder(titledBorder1); + jPanel2.setBounds(new Rectangle(39, 173, 441, 173)); + jPanel2.setLayout(null); + playGameButton.setBounds(new Rectangle(150, 418, 161, 37)); + playGameButton.setFont(new java.awt.Font("Dialog", 0, 18)); + playGameButton.setText("Play Game"); + playGameButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + playGameButton_actionPerformed(e); + } + }); + oppTwoRadio.setText("Bob"); + oppTwoRadio.setBounds(new Rectangle(15, 50, 397, 41)); + oppOneRadio.setSelected(true); + oppOneRadio.setText("Sam"); + oppOneRadio.setBounds(new Rectangle(15, 18, 392, 33)); + oppThreeRadio.setText("Generated Deck"); + oppThreeRadio.setBounds(new Rectangle(15, 91, 406, 25)); + jLabel5.setText("Your Deck:"); + jLabel5.setBounds(new Rectangle(15, 126, 125, 29)); + deckComboBox.setBounds(new Rectangle(98, 127, 185, 29)); + smoothLandCheckBox.setText("Stack AI land"); + smoothLandCheckBox.setBounds(new Rectangle(154, 385, 153, 21)); + //smoothLandCheckBox.setSelected(true); + resizeCheckbox.setText("Resizable Game Area"); + resizeCheckbox.setBounds(new Rectangle(154, 354, 156, 24)); + //resizeCheckbox.setSelected(true); + this.getContentPane().add(rankLabel, null); + this.getContentPane().add(jLabel1, null); + this.getContentPane().add(difficultlyLabel, null); + this.getContentPane().add(winLostLabel, null); + jPanel2.add(jLabel5, null); + jPanel2.add(deckComboBox, null); + jPanel2.add(oppOneRadio, null); + jPanel2.add(oppTwoRadio, null); + jPanel2.add(oppThreeRadio, null); + jPanel2.add(deckEditorButton, null); + this.getContentPane().add(playGameButton, null); + this.getContentPane().add(smoothLandCheckBox, null); + this.getContentPane().add(resizeCheckbox, null); + this.getContentPane().add(jPanel2, null); + oppGroup.add(oppOneRadio); + oppGroup.add(oppTwoRadio); + oppGroup.add(oppThreeRadio); + } + + void deckEditorButton_actionPerformed(ActionEvent e) { + Command exit = new Command() { + private static final long serialVersionUID = -5110231879441074581L; + + public void execute() { + //saves all deck data + QuestData.saveData(AllZone.QuestData); + + new Gui_Quest(); + } + }; + + Gui_Quest_DeckEditor g = new Gui_Quest_DeckEditor(); + + g.show(exit); + g.setVisible(true); + + this.dispose(); + }//deck editor button + + void playGameButton_actionPerformed(ActionEvent e) { + Object check = deckComboBox.getSelectedItem(); + if(check == null || getOpponent().equals("")) return; + + Deck human = questData.getDeck(check.toString()); + Deck computer = questData.ai_getDeck(getOpponent()); + + Constant.Runtime.HumanDeck[0] = human; + Constant.Runtime.ComputerDeck[0] = computer; + + //smoothLandCheckBox.isSelected() - for the AI + + //DO NOT CHANGE THIS ORDER, GuiDisplay needs to be created before cards are added + if(resizeCheckbox.isSelected()) AllZone.Display = new GuiDisplay3(); + else AllZone.Display = new GuiDisplay2(); + + if(smoothLandCheckBox.isSelected()) Constant.Runtime.smooth[0] = true; + else Constant.Runtime.smooth[0] = false; + + AllZone.GameAction.newGame(human, computer); + AllZone.Display.setVisible(true); + //end - you can change stuff after this + + //close this window + dispose(); + + }//play game button + + String getOpponent() { + if(oppOneRadio.isSelected()) return oppOneRadio.getText(); + + else if(oppTwoRadio.isSelected()) return oppTwoRadio.getText(); + + else if(oppThreeRadio.isSelected()) return oppThreeRadio.getText(); + + return ""; + } +} \ No newline at end of file diff --git a/src/Gui_QuestOptions.java b/src/Gui_QuestOptions.java new file mode 100644 index 00000000000..eeb9ea62f3b --- /dev/null +++ b/src/Gui_QuestOptions.java @@ -0,0 +1,207 @@ +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.ArrayList; + +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextArea; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; + + +public class Gui_QuestOptions extends JFrame { + private static final long serialVersionUID = 2018518804206822235L; + + private QuestData questData = new QuestData(); + + private JLabel jLabel1 = new JLabel(); + private JButton continueQuestButton = new JButton(); + private JPanel jPanel1 = new JPanel(); + @SuppressWarnings("unused") + // border1 + private Border border1; + private TitledBorder titledBorder1; + private JPanel jPanel2 = new JPanel(); + private GridLayout gridLayout1 = new GridLayout(); + private JRadioButton easyRadio = new JRadioButton(); + private JRadioButton hardRadio = new JRadioButton(); + private JRadioButton mediumRadio = new JRadioButton(); + private JRadioButton veryHardRadio = new JRadioButton(); + private JButton newQuestButton = new JButton(); + private JTextArea jTextArea1 = new JTextArea(); + private ButtonGroup buttonGroup1 = new ButtonGroup(); + private JPanel jPanel3 = new JPanel(); + private Border border2; + private TitledBorder titledBorder2; + + public static void main(String[] args) { + new Gui_QuestOptions(); + } + + public Gui_QuestOptions() { + try { + jbInit(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + + setup(); + setupRadioButtonText(); + + setVisible(true); + } + + private void setup() { + //make the text look correct on the screen + jTextArea1.setBackground(getBackground()); + + //center window on the screen + Dimension screen = this.getToolkit().getScreenSize(); + setBounds(screen.width / 4, 50, //position + 420, 490); //size + + //if user closes this window, go back to "New Game" screen + this.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent ev) { + Gui_QuestOptions.this.dispose(); + new Gui_NewGame(); + } + }); + + //is there any saved data? + if(!questData.hasSaveFile()) continueQuestButton.setEnabled(false); + }//setup() + + //show total number of games for each difficulty + private void setupRadioButtonText() { + String[] diff = questData.getDifficutlyChoices(); + JRadioButton[] b = {easyRadio, mediumRadio, hardRadio, veryHardRadio}; + + for(int i = 0; i < diff.length; i++) { + b[i].setText(diff[i] + " - " + questData.getTotalNumberOfGames(diff[i])); + } + + }//setupRadioButtonText() + + private void jbInit() throws Exception { + border1 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder1 = new TitledBorder(BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)), + "Quest Length"); + border2 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder2 = new TitledBorder(border2, "Continue"); + jLabel1.setFont(new java.awt.Font("Dialog", 0, 25)); + jLabel1.setHorizontalAlignment(SwingConstants.CENTER); + jLabel1.setText("Quest Options"); + jLabel1.setBounds(new Rectangle(104, 0, 213, 63)); + this.setTitle("Quest Options"); + this.getContentPane().setLayout(null); + continueQuestButton.setBounds(new Rectangle(70, 23, 159, 35)); + continueQuestButton.setFont(new java.awt.Font("Dialog", 0, 18)); + continueQuestButton.setText("Continue Quest"); + continueQuestButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + continueQuestButton_actionPerformed(e); + } + }); + jPanel1.setBorder(titledBorder1); + jPanel1.setBounds(new Rectangle(67, 63, 303, 259)); + jPanel1.setLayout(null); + jPanel2.setBounds(new Rectangle(12, 27, 271, 101)); + jPanel2.setLayout(gridLayout1); + gridLayout1.setColumns(1); + gridLayout1.setRows(4); + easyRadio.setText("Easy - 50 games"); + hardRadio.setText("Hard - 200 games"); + mediumRadio.setText("Medium - 100 games"); + veryHardRadio.setText("Very Hard - 300 games"); + newQuestButton.setBounds(new Rectangle(78, 206, 145, 38)); + newQuestButton.setFont(new java.awt.Font("Dialog", 0, 18)); + newQuestButton.setText("New Quest"); + newQuestButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + newQuestButton_actionPerformed(e); + } + }); + jTextArea1.setEnabled(false); + jTextArea1.setFont(new java.awt.Font("Dialog", 0, 14)); + jTextArea1.setDisabledTextColor(Color.black); + jTextArea1.setEditable(false); + jTextArea1.setText("Note: Starting a new quest will delete your current quest data"); + jTextArea1.setLineWrap(true); + jTextArea1.setWrapStyleWord(true); + jTextArea1.setBounds(new Rectangle(13, 141, 274, 50)); + jPanel3.setBorder(titledBorder2); + jPanel3.setBounds(new Rectangle(68, 338, 289, 86)); + jPanel3.setLayout(null); + jPanel2.add(easyRadio, null); + jPanel2.add(mediumRadio, null); + jPanel2.add(hardRadio, null); + jPanel2.add(veryHardRadio, null); + jPanel1.add(newQuestButton, null); + jPanel1.add(jTextArea1, null); + this.getContentPane().add(jPanel1, null); + this.getContentPane().add(jPanel3, null); + jPanel3.add(continueQuestButton, null); + this.getContentPane().add(jLabel1, null); + jPanel1.add(jPanel2, null); + buttonGroup1.add(easyRadio); + buttonGroup1.add(mediumRadio); + buttonGroup1.add(hardRadio); + buttonGroup1.add(veryHardRadio); + } + + void continueQuestButton_actionPerformed(ActionEvent e) { + //set global variable + AllZone.QuestData = QuestData.loadData(); + dispose(); + new Gui_Quest(); + } + + void newQuestButton_actionPerformed(ActionEvent e) { + String difficulty = ""; + + if(easyRadio.isSelected()) difficulty = questData.EASY; + + else if(mediumRadio.isSelected()) difficulty = questData.MEDIUM; + + else if(hardRadio.isSelected()) difficulty = questData.HARD; + + else if(veryHardRadio.isSelected()) difficulty = questData.VERY_HARD; + + else //user didn't select a difficulty + return; + + //give the user a few cards to build a deck + questData.newGame(difficulty); + + copyAIDecks(questData, QuestData.loadData()); + QuestData.saveData(questData); + + questData.readAIQuestDeckFiles(); + + //set global variable + AllZone.QuestData = questData; + + dispose(); + new Gui_Quest(); + } + + //copy AI decks from old to newData + void copyAIDecks(QuestData newData, QuestData old) { + ArrayList a = old.ai_getDeckNames(); + for(int i = 0; i < a.size(); i++) + newData.ai_addDeck(old.ai_getDeck(a.get(i).toString())); + } +} \ No newline at end of file diff --git a/src/Gui_Quest_DeckEditor.java b/src/Gui_Quest_DeckEditor.java new file mode 100644 index 00000000000..fcdccf1268e --- /dev/null +++ b/src/Gui_Quest_DeckEditor.java @@ -0,0 +1,744 @@ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; +import java.awt.GridLayout; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.ArrayList; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; + +import forge.error.ErrorViewer; + + +public class Gui_Quest_DeckEditor extends JFrame implements CardDetail, DeckDisplay { + private static final long serialVersionUID = 152061168634545L; + + Gui_Quest_DeckEditor_Menu customMenu; + + private ImageIcon upIcon = Constant.IO.upIcon; + private ImageIcon downIcon = Constant.IO.downIcon; + + public TableModel topModel; + public TableModel bottomModel; + + private JScrollPane jScrollPane1 = new JScrollPane(); + private JScrollPane jScrollPane2 = new JScrollPane(); + private JButton removeButton = new JButton(); + @SuppressWarnings("unused") + // border1 + private Border border1; + private TitledBorder titledBorder1; + private Border border2; + private TitledBorder titledBorder2; + private JButton addButton = new JButton(); + private JPanel cardDetailPanel = new JPanel(); + private Border border3; + private TitledBorder titledBorder3; + private JPanel picturePanel = new JPanel(); + private JLabel statsLabel = new JLabel(); + private JTable topTable = new JTable(); + private JTable bottomTable = new JTable(); + private JScrollPane jScrollPane3 = new JScrollPane(); + private JPanel jPanel3 = new JPanel(); + private JLabel cdLabel4 = new JLabel(); + private JLabel cdLabel1 = new JLabel(); + private JLabel cdLabel2 = new JLabel(); + private JLabel cdLabel3 = new JLabel(); + private GridLayout gridLayout1 = new GridLayout(); + private JLabel cdLabel5 = new JLabel(); + private JTextArea cdTextArea = new JTextArea(); + private BorderLayout borderLayout1 = new BorderLayout(); + private JLabel statsLabel2 = new JLabel(); + private JLabel jLabel1 = new JLabel(); + + private JCheckBox whiteCheckBox = new JCheckBox("W", true); + private JCheckBox blueCheckBox = new JCheckBox("U", true); + private JCheckBox blackCheckBox = new JCheckBox("B", true); + private JCheckBox redCheckBox = new JCheckBox("R", true); + private JCheckBox greenCheckBox = new JCheckBox("G", true); + private JCheckBox colorlessCheckBox = new JCheckBox("C", true); + + private JCheckBox landCheckBox = new JCheckBox("Land", true); + private JCheckBox creatureCheckBox = new JCheckBox("Creature", true); + private JCheckBox sorceryCheckBox = new JCheckBox("Sorcery", true); + private JCheckBox instantCheckBox = new JCheckBox("Instant", true); + private JCheckBox planeswalkerCheckBox = new JCheckBox("Planeswalker", true); + private JCheckBox artifactCheckBox = new JCheckBox("Artifact", true); + private JCheckBox enchantmentCheckBox = new JCheckBox("Enchant", true); + + private CardList top; + private CardList bottom; + + public static void main(String[] args) { + + } + + @Override + public void setTitle(String message) { + super.setTitle(message); + } + + public void updateDisplay(CardList top, CardList bottom) { + + this.top = top; + this.bottom = bottom; + + topModel.clear(); + bottomModel.clear(); + + if (AllZone.NameChanger.shouldChangeCardName()) { + top = new CardList(AllZone.NameChanger.changeCard(top.toArray())); + bottom = new CardList(AllZone.NameChanger.changeCard(bottom + .toArray())); + } + + Card c; + String cardName; + QuestData_BoosterPack pack = new QuestData_BoosterPack(); + + ArrayList addedList = AllZone.QuestData.getAddedCards(); + + + //update top + for(int i = 0; i < top.size(); i++) { + c = top.get(i); + + cardName = c.getName(); + c.setRarity(pack.getRarity(cardName)); + + if(addedList.contains(cardName)) c.setRarity("new"); + + + topModel.addCard(c); + }//for + + //update bottom + for(int i = 0; i < bottom.size(); i++) { + c = bottom.get(i); + + + c.setRarity(pack.getRarity(c.getName()));; + + bottomModel.addCard(c); + }//for + + topModel.resort(); + bottomModel.resort(); + }//updateDisplay + + public void updateDisplay() { + //updateDisplay(this.top, this.bottom); + + topModel.clear(); + + if (AllZone.NameChanger.shouldChangeCardName()) { + top = new CardList(AllZone.NameChanger.changeCard(top.toArray())); + bottom = new CardList(AllZone.NameChanger.changeCard(bottom + .toArray())); + } + + Card c; + String cardName; + ReadBoosterPack pack = new ReadBoosterPack(); + + // update top + for (int i = 0; i < top.size(); i++) { + c = top.get(i); + + // add rarity to card if this is a sealed card pool + + cardName = AllZone.NameChanger.getOriginalName(c.getName()); + if (!pack.getRarity(cardName).equals("error")) { + c.setRarity(pack.getRarity(cardName)); + } + + boolean filteredOut = filterByColor(c); + + if (!filteredOut) { + filteredOut = filterByType(c); + } + + if (!filteredOut) { + topModel.addCard(c); + } + }// for + + topModel.resort(); + } + + private boolean filterByColor(Card c) { + boolean filterOut = false; + + if (!whiteCheckBox.isSelected()) { + if (CardUtil.getColors(c).contains(Constant.Color.White)) { + filterOut = true; + } + } + + if (!blueCheckBox.isSelected()) { + if (CardUtil.getColors(c).contains(Constant.Color.Blue)) { + filterOut = true; + } + } + + if (!blackCheckBox.isSelected()) { + if (CardUtil.getColors(c).contains(Constant.Color.Black)) { + filterOut = true; + } + } + + if (!redCheckBox.isSelected()) { + if (CardUtil.getColors(c).contains(Constant.Color.Red)) { + filterOut = true; + } + } + + if (!greenCheckBox.isSelected()) { + if (CardUtil.getColors(c).contains(Constant.Color.Green)) { + filterOut = true; + } + } + + if (!colorlessCheckBox.isSelected()) { + if (CardUtil.getColors(c).contains(Constant.Color.Colorless)) { + filterOut = true; + } + } + + return filterOut; + } + + private boolean filterByType(Card c) { + boolean filterOut = false; + + if (!landCheckBox.isSelected() && c.isLand()) { + filterOut = true; + } + + if (!creatureCheckBox.isSelected() && c.isCreature()) { + filterOut = true; + } + + if (!sorceryCheckBox.isSelected() && c.isSorcery()) { + filterOut = true; + } + + if (!instantCheckBox.isSelected() && c.isInstant()) { + filterOut = true; + } + + if (!planeswalkerCheckBox.isSelected() && c.isPlaneswalker()) { + filterOut = true; + } + + if (!artifactCheckBox.isSelected() && c.isArtifact()) { + filterOut = true; + } + + if (!enchantmentCheckBox.isSelected() && c.isEnchantment()) { + filterOut = true; + } + + return filterOut; + } + + public TableModel getTopTableModel() { + return topModel; + } + + + //top shows available card pool + public CardList getTop() { + return topModel.getCards(); + } + + //bottom shows cards that the user has chosen for his library + public CardList getBottom() { + return bottomModel.getCards(); + } + + + public void show(final Command exitCommand) { + final Command exit = new Command() { + private static final long serialVersionUID = -7428793574300520612L; + + public void execute() { + Gui_Quest_DeckEditor.this.dispose(); + exitCommand.execute(); + } + }; + + //do not change this!!!! + this.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent ev) { + customMenu.close(); + } + }); + + + setup(); + + customMenu = new Gui_Quest_DeckEditor_Menu(this, exit); + this.setJMenuBar(customMenu); + + + QuestData questData = AllZone.QuestData; + Deck deck = null; + + //open deck that the player used if QuestData has it + if(Constant.Runtime.HumanDeck[0] != null + && questData.getDeckNames().contains(Constant.Runtime.HumanDeck[0].getName())) { + deck = questData.getDeck(Constant.Runtime.HumanDeck[0].getName()); + } else { + deck = new Deck(Constant.GameType.Sealed); + deck.setName(""); + } + + //tell Gui_Quest_DeckEditor the name of the deck + customMenu.setHumanPlayer(deck.getName()); + + + //convert Deck main into CardList to show on the screen + //convert Deck main into CardList to show on the screen + CardList bottom = new CardList(); + for(int i = 0; i < deck.countMain(); i++) + { + bottom.add(AllZone.CardFactory.getCard(deck.getMain(i), "")); + } + + + ArrayList list = AllZone.QuestData.getCardpool(); + CardList cardpool = Gui_Quest_DeckEditor_Menu.covertToCardList(list); + + //remove bottom cards that are in the deck from the card pool + for(int i = 0; i < bottom.size(); i++) + { + if(cardpool.containsName(bottom.get(i).getName())) + cardpool.remove(bottom.get(i).getName()); + } + + //show cards, makes this user friendly, lol, well may, ha + updateDisplay(cardpool, bottom); + + //this affects the card pool + topModel.sort(4, true);//sort by type + topModel.sort(3, true);//then sort by color + + bottomModel.sort(1, true); + }//show(Command) + + private void addListeners() + { + + }//addListeners() + + public void setup() { + addListeners(); + + //construct topTable, get all cards + topModel = new TableModel(new CardList(), this); + topModel.addListeners(topTable); + topTable.setModel(topModel); + topModel.resizeCols(topTable); + + //construct bottomModel + bottomModel = new TableModel(this); + bottomModel.addListeners(bottomTable); + bottomTable.setModel(bottomModel); + bottomModel.resizeCols(bottomTable); + + //get stats from deck + bottomModel.addTableModelListener(new TableModelListener() { + public void tableChanged(TableModelEvent ev) { + CardList deck = bottomModel.getCards(); + statsLabel.setText(getStats(deck)); + } + }); + + + //get stats from all cards + topModel.addTableModelListener(new TableModelListener() { + public void tableChanged(TableModelEvent ev) { + CardList deck = topModel.getCards(); + statsLabel2.setText(getStats(deck)); + } + }); + + setSize(1024, 768); + //TODO use this as soon the deck editor has resizable GUI +// //Use both so that when "un"maximizing, the frame isn't tiny +// setSize(1024, 740); +// setExtendedState(Frame.MAXIMIZED_BOTH); + }//setupAndDisplay() + + private String getStats(CardList deck) { + int total = deck.size(); + int creature = deck.getType("Creature").size(); + int land = deck.getType("Land").size(); + + String show = "Total - " + total + ", Creatures - " + creature + ", Land - " + land; + String[] color = Constant.Color.Colors; + for(int i = 0; i < 5; i++) + show += ", " + color[i] + " - " + CardListUtil.getColor(deck, color[i]).size(); + + return show; + }//getStats() + + public Gui_Quest_DeckEditor() { + try { + jbInit(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + } + + public void updateCardDetail(Card c) { + //change card name if needed + c = AllZone.CardFactory.copyCard(c); + if(AllZone.NameChanger.shouldChangeCardName()) c = AllZone.NameChanger.changeCard(c); + + CardDetailUtil.updateCardDetail(c, cdTextArea, cardDetailPanel, picturePanel, new JLabel[] { + cdLabel1, cdLabel2, cdLabel3, cdLabel4, cdLabel5}); + } + + private void jbInit() throws Exception { + border1 = new EtchedBorder(EtchedBorder.RAISED, Color.white, new Color(148, 145, 140)); + titledBorder1 = new TitledBorder(BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)), + "All Cards"); + border2 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder2 = new TitledBorder(border2, "Deck"); + border3 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder3 = new TitledBorder(border3, "Card Detail"); + this.getContentPane().setLayout(null); + jScrollPane1.setBorder(titledBorder1); + jScrollPane1.setBounds(new Rectangle(19, 28, 726, 346)); + jScrollPane2.getViewport().setBackground(new Color(204, 204, 204)); + jScrollPane2.setBorder(titledBorder2); + jScrollPane2.setBounds(new Rectangle(19, 458, 726, 218)); + removeButton.setBounds(new Rectangle(180, 403, 146, 49)); + removeButton.setIcon(upIcon); + removeButton.setFont(new java.awt.Font("Dialog", 0, 13)); + removeButton.setText("Remove Card"); + removeButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + removeButton_actionPerformed(e); + } + }); + addButton.setText("Add Card"); + addButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + addButton_actionPerformed(e); + } + }); + addButton.setIcon(downIcon); + addButton.setFont(new java.awt.Font("Dialog", 0, 13)); + addButton.setBounds(new Rectangle(23, 403, 146, 49)); + + /** + * Type filtering + */ + Font f = new Font("Tahoma", Font.PLAIN, 10); + landCheckBox.setBounds(340, 400, 48, 20); + landCheckBox.setFont(f); + landCheckBox.setOpaque(false); + landCheckBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + creatureCheckBox.setBounds(385, 400, 65, 20); + creatureCheckBox.setFont(f); + creatureCheckBox.setOpaque(false); + creatureCheckBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + sorceryCheckBox.setBounds(447, 400, 62, 20); + sorceryCheckBox.setFont(f); + sorceryCheckBox.setOpaque(false); + sorceryCheckBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + instantCheckBox.setBounds(505, 400, 60, 20); + instantCheckBox.setFont(f); + instantCheckBox.setOpaque(false); + instantCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + planeswalkerCheckBox.setBounds(558, 400, 85, 20); + planeswalkerCheckBox.setFont(f); + planeswalkerCheckBox.setOpaque(false); + planeswalkerCheckBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + artifactCheckBox.setBounds(638, 400, 58, 20); + artifactCheckBox.setFont(f); + artifactCheckBox.setOpaque(false); + artifactCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + enchantmentCheckBox.setBounds(692, 400, 80, 20); + enchantmentCheckBox.setFont(f); + enchantmentCheckBox.setOpaque(false); + enchantmentCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + + /** + * Color filtering + */ + whiteCheckBox.setBounds(340, 430, 40, 20); + whiteCheckBox.setOpaque(false); + whiteCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + blueCheckBox.setBounds(380, 430, 40, 20); + blueCheckBox.setOpaque(false); + blueCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + blackCheckBox.setBounds(420, 430, 40, 20); + blackCheckBox.setOpaque(false); + blackCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + redCheckBox.setBounds(460, 430, 40, 20); + redCheckBox.setOpaque(false); + redCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + greenCheckBox.setBounds(500, 430, 40, 20); + greenCheckBox.setOpaque(false); + greenCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + colorlessCheckBox.setBounds(540, 430, 40, 20); + colorlessCheckBox.setOpaque(false); + colorlessCheckBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + updateDisplay(); + } + }); + + /** + * Other + */ + + cardDetailPanel.setBorder(titledBorder3); + cardDetailPanel.setBounds(new Rectangle(765, 23, 239, 323)); + cardDetailPanel.setLayout(null); + picturePanel.setBorder(BorderFactory.createEtchedBorder()); + picturePanel.setBounds(new Rectangle(772, 362, 226, 301)); + picturePanel.setLayout(borderLayout1); + statsLabel.setFont(new java.awt.Font("Dialog", 0, 14)); + statsLabel.setText("Total - 0, Creatures - 0 Land - 0"); + statsLabel.setBounds(new Rectangle(19, 672, 720, 31)); + //Do not lower statsLabel any lower, we want this to be visible at 1024 x 768 screen size + this.setTitle("Deck Editor"); + jScrollPane3.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPane3.setBounds(new Rectangle(6, 168, 225, 143)); + jPanel3.setBounds(new Rectangle(7, 21, 224, 141)); + jPanel3.setLayout(gridLayout1); + cdLabel4.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel4.setHorizontalAlignment(SwingConstants.LEFT); + cdLabel1.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel1.setHorizontalAlignment(SwingConstants.CENTER); + cdLabel2.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel2.setHorizontalAlignment(SwingConstants.CENTER); + cdLabel3.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel3.setHorizontalAlignment(SwingConstants.CENTER); + gridLayout1.setColumns(1); + gridLayout1.setRows(0); + cdLabel5.setFont(new java.awt.Font("Dialog", 0, 14)); + cdLabel5.setHorizontalAlignment(SwingConstants.LEFT); + cdTextArea.setFont(new java.awt.Font("Dialog", 0, 12)); + cdTextArea.setLineWrap(true); + cdTextArea.setWrapStyleWord(true); + statsLabel2.setBounds(new Rectangle(19, 371, 720, 31)); + statsLabel2.setText("Total - 0, Creatures - 0 Land - 0"); + statsLabel2.setFont(new java.awt.Font("Dialog", 0, 14)); + jLabel1.setText("Click on the column name (like name or color) to sort the cards"); + jLabel1.setBounds(new Rectangle(20, 9, 400, 19)); + this.getContentPane().add(cardDetailPanel, null); + cardDetailPanel.add(jScrollPane3, null); + jScrollPane3.getViewport().add(cdTextArea, null); + cardDetailPanel.add(jPanel3, null); + jPanel3.add(cdLabel1, null); + jPanel3.add(cdLabel2, null); + jPanel3.add(cdLabel3, null); + jPanel3.add(cdLabel4, null); + this.getContentPane().add(picturePanel, null); + this.getContentPane().add(jScrollPane1, null); + this.getContentPane().add(jScrollPane2, null); + this.getContentPane().add(addButton, null); + this.getContentPane().add(removeButton, null); + this.getContentPane().add(statsLabel2, null); + this.getContentPane().add(statsLabel, null); + this.getContentPane().add(jLabel1, null); + jScrollPane2.getViewport().add(bottomTable, null); + jScrollPane1.getViewport().add(topTable, null); + jPanel3.add(cdLabel5, null); + + this.getContentPane().add(landCheckBox, null); + this.getContentPane().add(creatureCheckBox, null); + this.getContentPane().add(sorceryCheckBox, null); + this.getContentPane().add(instantCheckBox, null); + this.getContentPane().add(planeswalkerCheckBox, null); + this.getContentPane().add(artifactCheckBox, null); + this.getContentPane().add(enchantmentCheckBox, null); + + this.getContentPane().add(whiteCheckBox, null); + this.getContentPane().add(blueCheckBox, null); + this.getContentPane().add(blackCheckBox, null); + this.getContentPane().add(redCheckBox, null); + this.getContentPane().add(greenCheckBox, null); + this.getContentPane().add(colorlessCheckBox, null); + } + + void addButton_actionPerformed(ActionEvent e) { + setTitle("Deck Editor : " + customMenu.getDeckName() + " : unsaved"); + + int n = topTable.getSelectedRow(); + if(n != -1) { + Card c = topModel.rowToCard(n); + bottomModel.addCard(c); + bottomModel.resort(); + + if(!Constant.GameType.Constructed.equals(customMenu.getGameType())) { + topModel.removeCard(c); + } + + //3 conditions" 0 cards left, select the same row, select next row + int size = topModel.getRowCount(); + if(size != 0) { + if(size == n) n--; + topTable.addRowSelectionInterval(n, n); + } + }//if(valid row) + }//addButton_actionPerformed + + void removeButton_actionPerformed(ActionEvent e) { + setTitle("Deck Editor : " + customMenu.getDeckName() + " : unsaved"); + + int n = bottomTable.getSelectedRow(); + if(n != -1) { + Card c = bottomModel.rowToCard(n); + bottomModel.removeCard(c); + + if(!Constant.GameType.Constructed.equals(customMenu.getGameType())) { + topModel.addCard(c); + topModel.resort(); + } + + //3 conditions" 0 cards left, select the same row, select next row + int size = bottomModel.getRowCount(); + if(size != 0) { + if(size == n) n--; + bottomTable.addRowSelectionInterval(n, n); + } + }//if(valid row) + }//removeButton_actionPerformed + + @SuppressWarnings("unused") + // stats_actionPerformed + private void stats_actionPerformed(CardList list) { + + } + + //refresh Gui from deck, Gui shows the cards in the deck + @SuppressWarnings("unused") // refreshGui +private void refreshGui() + { + Deck deck = Constant.Runtime.HumanDeck[0]; + if(deck == null) //this is just a patch, i know + deck = new Deck(Constant.Runtime.GameType[0]); + + topModel.clear(); + bottomModel.clear(); + + Card c; + ReadBoosterPack pack = new ReadBoosterPack(); + for(int i = 0; i < deck.countMain(); i++) + { + c = AllZone.CardFactory.getCard(deck.getMain(i), Constant.Player.Human); + + c.setRarity(pack.getRarity(c.getName())); + + + bottomModel.addCard(c); + }//for + + if(deck.isSealed() || deck.isDraft()) + { + //add sideboard to GUI + for(int i = 0; i < deck.countSideboard(); i++) + { + c = AllZone.CardFactory.getCard(deck.getSideboard(i), Constant.Player.Human); + c.setRarity(pack.getRarity(c.getName())); + topModel.addCard(c); + } + } + else + { + CardList all = AllZone.CardFactory.getAllCards(); + for(int i = 0; i < all.size(); i++) + topModel.addCard(all.get(i)); + } + + topModel.resort(); + bottomModel.resort(); + }////refreshGui() + +} \ No newline at end of file diff --git a/src/Gui_Quest_DeckEditor_Menu.java b/src/Gui_Quest_DeckEditor_Menu.java new file mode 100644 index 00000000000..c65f7c07a46 --- /dev/null +++ b/src/Gui_Quest_DeckEditor_Menu.java @@ -0,0 +1,761 @@ +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.Collections; + +import javax.swing.JFileChooser; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.filechooser.FileFilter; + + +//presumes AllZone.QuestData is not null +public class Gui_Quest_DeckEditor_Menu extends JMenuBar { + private static final long serialVersionUID = -4052319220021158574L; + + //this should be false in the public version + //if true, the Quest Deck editor will let you edit the computer's decks + private final boolean canEditComputerDecks; + + private final String deckEditorName = "Deck Editor"; + + //used for import and export, try to made the gui user friendly + private static File previousDirectory = null; + + private Command exitCommand; + private QuestData questData; + private Deck currentDeck; + + //the class DeckDisplay is in the file "Gui_DeckEditor_Menu.java" + private DeckDisplay deckDisplay; + + + public Gui_Quest_DeckEditor_Menu(DeckDisplay d, Command exit) { + //is a file named "edit" in this directory + //lame but it works, I don't like 2 versions of MTG Forge floating around + //one that lets you edit the AI decks and one that doesn't + File f = new File("edit"); + if(f.exists()) canEditComputerDecks = true; + else canEditComputerDecks = false; + + deckDisplay = d; + d.setTitle(deckEditorName); + + questData = AllZone.QuestData; + + exitCommand = exit; + + setupMenu(); + + if(canEditComputerDecks) setupComputerMenu(); + } + + + private void addImportExport(JMenu menu, final boolean isHumanMenu) { + JMenuItem import2 = new JMenuItem("Import"); + JMenuItem export = new JMenuItem("Export"); + + import2.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + importDeck(isHumanMenu); + } + });//import + + export.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + exportDeck(); + } + });//export + + menu.add(import2); + menu.add(export); + + }//addImportExport() + + private void exportDeck() { + File filename = getExportFilename(); + + if(filename == null) return; + + //write is an Object variable because you might just + //write one Deck object + Deck deck = convertCardListToDeck(deckDisplay.getBottom());; + Object write = deck; + + deck.setName(filename.getName()); + + + try { + ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename)); + out.writeObject(write); + out.flush(); + out.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_Quest_DeckEditor_Menu : exportDeck() error, " + ex); + } + + exportDeckText(getExportDeckText(deck), filename.getAbsolutePath()); + + }//exportDeck() + + @SuppressWarnings("unchecked") + // TableSorter type safety + private String getExportDeckText(Deck aDeck) { + //convert Deck into CardList + CardList all = new CardList(); + for(int i = 0; i < aDeck.countMain(); i++) { + String cardName = aDeck.getMain(i); + Card c = AllZone.CardFactory.getCard(cardName, ""); + + all.add(c); + } + + //sort by card name + all.sort(new TableSorter(all, 1, true)); + + //remove all copies of cards + //make a singleton + CardList noCopies = new CardList(); + for(int i = 0; i < all.size(); i++) { + Card c = all.get(i); + + if(!noCopies.containsName(c.getName())) noCopies.add(c); + } + + + String text = ""; + String newLine = "\r\n"; + int count = 0; + + text = all.size() + " Total Cards" + newLine + newLine; + + //creatures + text += all.getType("Creature").size() + " Creatures" + newLine; + text += "-------------" + newLine; + + for(int i = 0; i < noCopies.size(); i++) { + Card c = noCopies.get(i); + if(c.isCreature()) { + count = all.getName(c.getName()).size(); + text += count + "x " + c.getName() + newLine; + } + } + + //count spells, arg! this is tough + CardListFilter cf = new CardListFilter() { + public boolean addCard(Card c) { + return !(c.isCreature() || c.isLand()); + } + };//CardListFilter + count = all.filter(cf).size(); + + //spells + text += newLine + count + " Spells" + newLine; + text += "----------" + newLine; + + for(int i = 0; i < noCopies.size(); i++) { + Card c = noCopies.get(i); + if(!(c.isCreature() || c.isLand())) { + count = all.getName(c.getName()).size(); + text += count + "x " + c.getName() + newLine; + } + } + + //land + text += newLine + all.getType("Land").size() + " Land" + newLine; + text += "--------" + newLine; + + for(int i = 0; i < noCopies.size(); i++) { + Card c = noCopies.get(i); + if(c.isLand()) { + count = all.getName(c.getName()).size(); + text += count + "x " + c.getName() + newLine; + } + } + + text += newLine; + + return text; + }//getExportDeckText + + private void exportDeckText(String deckText, String filename) { + + //remove ".deck" extension + int cut = filename.indexOf("."); + filename = filename.substring(0, cut); + + try { + FileWriter writer = new FileWriter(filename + ".txt"); + writer.write(deckText); + + writer.flush(); + writer.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_Quest_DeckEditor_Menu : exportDeckText() error, " + ex.getMessage() + + " : " + ex.getStackTrace()); + } + }//exportDeckText() + + + private FileFilter getFileFilter() { + FileFilter filter = new FileFilter() { + @Override + public boolean accept(File f) { + return f.getName().endsWith(".deck") || f.isDirectory(); + } + + @Override + public String getDescription() { + return "Deck File .deck"; + } + }; + + return filter; + }//getFileFilter() + + private File getExportFilename() { + //Object o = null; // unused + + JFileChooser save = new JFileChooser(previousDirectory); + + save.setDialogTitle("Export Deck Filename"); + save.setDialogType(JFileChooser.SAVE_DIALOG); + save.addChoosableFileFilter(getFileFilter()); + save.setSelectedFile(new File(currentDeck.getName() + ".deck")); + + int returnVal = save.showSaveDialog(null); + + if(returnVal == JFileChooser.APPROVE_OPTION) { + File file = save.getSelectedFile(); + String check = file.getAbsolutePath(); + + previousDirectory = file.getParentFile(); + + if(check.endsWith(".deck")) return file; + else return new File(check + ".deck"); + } + + return null; + }//getExportFilename() + + private void importDeck(boolean isHumanDeck) { + File file = getImportFilename(); + + if(file == null) return; + + Object check = null; + + try { + ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); + check = in.readObject(); + + in.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Gui_Quest_DeckEditor_Menu : importDeck() error, " + ex); + } + + Deck deck = (Deck) check; + deckDisplay.setTitle(deckEditorName + " - " + deck.getName()); + + CardList cardpool; + + if(isHumanDeck) { + questData.addDeck(deck); + + //convert ArrayList of card names (Strings), into Card objects + cardpool = new CardList(); + ArrayList list = questData.getCardpool(); + + for(int i = 0; i < list.size(); i++) + cardpool.add(AllZone.CardFactory.getCard(list.get(i).toString(), "")); + } else { + questData.ai_addDeck(deck); + cardpool = AllZone.CardFactory.getAllCards(); + } + + //convert Deck main to CardList + CardList deckList = new CardList(); + for(int i = 0; i < deck.countMain(); i++) + deckList.add(AllZone.CardFactory.getCard(deck.getMain(i), "")); + + //update gui + deckDisplay.updateDisplay(cardpool, deckList); + + }//importDeck() + + + private File getImportFilename() { + JFileChooser chooser = new JFileChooser(previousDirectory); + + chooser.addChoosableFileFilter(getFileFilter()); + int returnVal = chooser.showOpenDialog(null); + + if(returnVal == JFileChooser.APPROVE_OPTION) { + File file = chooser.getSelectedFile(); + previousDirectory = file.getParentFile(); + return file; + } + + return null; + }//openFileDialog() + + //edit the AI decks + private void setupComputerMenu() { + JMenuItem open = new JMenuItem("Open"); + JMenuItem new2 = new JMenuItem("New"); + JMenuItem rename = new JMenuItem("Rename"); + JMenuItem save = new JMenuItem("Save"); + JMenuItem copy = new JMenuItem("Copy"); + JMenuItem delete = new JMenuItem("Delete"); + JMenuItem exit = new JMenuItem("Exit"); + + + JMenuItem viewAllDecks = new JMenuItem("View All Decks"); + + + //AI + viewAllDecks.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + ArrayList nameList = questData.ai_getDeckNames(); + Collections.sort(nameList); + + Deck deck; + String allText = ""; + + for(int i = 0; i < nameList.size(); i++) { + deck = questData.ai_getDeck(nameList.get(i).toString()); + allText += deck.getName() + "\r\n"; + allText += getExportDeckText(deck); + allText += "++++++++++++++++++++++++++++++++++++++++++++++++++++++ \r\n \r\n"; + } + + JTextArea area = new JTextArea(allText, 30, 30); + JOptionPane.showMessageDialog(null, new JScrollPane(area)); + + }//actionPerformed() + });//viewAllDecks + + //AI + open.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + String deckName = getUserInput_OpenDeck(questData.ai_getDeckNames()); + + //check if user selected "cancel" + if(deckName.equals("")) return; + + + setComputerPlayer(deckName); + + Deck d = questData.ai_getDeck(deckName); + CardList deck = new CardList(); + + for(int i = 0; i < d.countMain(); i++) + deck.add(AllZone.CardFactory.getCard(d.getMain(i), "")); + + CardList cardpool = AllZone.CardFactory.getAllCards(); + + deckDisplay.updateDisplay(cardpool, deck); + + } + });//open + + //AI + new2.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + deckDisplay.updateDisplay(AllZone.CardFactory.getAllCards(), new CardList()); + + setComputerPlayer(""); + } + });//new + + + //AI + rename.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + String name = getUserInput_GetDeckName(questData.ai_getDeckNames()); + + //check if user cancels + if(name.equals("")) return; + + //is the current deck already saved and in QuestData? + if(questData.ai_getDeckNames().contains(currentDeck.getName())) + questData.ai_removeDeck(currentDeck.getName());//remove old deck + + currentDeck.setName(name); + + Deck deck = convertCardListToDeck(deckDisplay.getBottom()); + deck.setName(name); + questData.ai_addDeck(deck); + + setComputerPlayer(name); + } + });//rename + + + //AI + save.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + String name = currentDeck.getName(); + + //check to see if name is set + if(name.equals("")) { + name = getUserInput_GetDeckName(questData.ai_getDeckNames()); + + //check if user cancels + if(name.equals("")) return; + } + + setComputerPlayer(name); + + Deck deck = convertCardListToDeck(deckDisplay.getBottom()); + deck.setName(name); + + questData.ai_addDeck(deck); + } + });//save + + + //AI + copy.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + String name = getUserInput_GetDeckName(questData.ai_getDeckNames()); + + //check if user cancels + if(name.equals("")) return; + + setComputerPlayer(name); + + Deck deck = convertCardListToDeck(deckDisplay.getBottom()); + deck.setName(name); + + questData.ai_addDeck(deck); + } + });//copy + + + //AI + delete.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + if(currentDeck.getName().equals("")) return; + + int check = JOptionPane.showConfirmDialog(null, "Do you really want to delete this deck?", + "Delete", JOptionPane.YES_NO_OPTION); + if(check == JOptionPane.NO_OPTION) return;//stop here + + questData.ai_removeDeck(currentDeck.getName()); + + //show card pool + CardList cardpool = AllZone.CardFactory.getAllCards(); + deckDisplay.updateDisplay(cardpool, new CardList()); + + setComputerPlayer(""); + } + });//delete + + + //AI + exit.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + Gui_Quest_DeckEditor_Menu.this.close(); + } + }); + + JMenu deckMenu = new JMenu("AI Deck"); + deckMenu.add(open); + deckMenu.add(rename); + deckMenu.add(new2); + deckMenu.add(save); + deckMenu.add(copy); + + deckMenu.addSeparator(); + addImportExport(deckMenu, false); + + deckMenu.add(viewAllDecks); + + deckMenu.addSeparator(); + deckMenu.add(delete); + deckMenu.addSeparator(); + deckMenu.add(exit); + + this.add(deckMenu); + + }//setupComputerMenu() + + private void openHumanDeck(String deckName) { + setHumanPlayer(deckName); + + CardList cardpool = covertToCardList(questData.getCardpool()); + + //covert Deck main to CardList + Deck d = questData.getDeck(deckName); + CardList deck = new CardList(); + + for(int i = 0; i < d.countMain(); i++) { + deck.add(AllZone.CardFactory.getCard(d.getMain(i), "")); + + //remove any cards that are in the deck from the card pool + cardpool.remove(d.getMain(i)); + } + + deckDisplay.updateDisplay(cardpool, deck); + + }//openHumanDeck + + + //the usual menu options that will be used + private void setupMenu() { + JMenuItem open = new JMenuItem("Open"); + JMenuItem new2 = new JMenuItem("New"); + JMenuItem rename = new JMenuItem("Rename"); + JMenuItem save = new JMenuItem("Save"); + JMenuItem copy = new JMenuItem("Copy"); + JMenuItem delete = new JMenuItem("Delete"); + JMenuItem exit = new JMenuItem("Exit"); + + //human + open.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + String deckName = getUserInput_OpenDeck(questData.getDeckNames()); + + //check if user selected "cancel" + if(deckName.equals("")) return; + + openHumanDeck(deckName); + } + });//open + + //human + new2.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + CardList cardpool = covertToCardList(questData.getCardpool()); + deckDisplay.updateDisplay(cardpool, new CardList()); + + setHumanPlayer(""); + } + });//new + + + //human + rename.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + String name = getUserInput_GetDeckName(questData.getDeckNames()); + + //check if user cancels + if(name.equals("")) return; + + //is the current deck already saved and in QuestData? + if(questData.getDeckNames().contains(currentDeck.getName())) + questData.removeDeck(currentDeck.getName());//remove old deck + + currentDeck.setName(name); + + Deck deck = convertCardListToDeck(deckDisplay.getBottom()); + deck.setName(name); + questData.addDeck(deck); + + setHumanPlayer(name); + } + });//rename + + + //human + save.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + String name = currentDeck.getName(); + + //check to see if name is set + if(name.equals("")) { + name = getUserInput_GetDeckName(questData.getDeckNames()); + + //check if user cancels + if(name.equals("")) return; + } + + setHumanPlayer(name); + + Deck deck = convertCardListToDeck(deckDisplay.getBottom()); + deck.setName(name); + + questData.addDeck(deck); + } + });//save + + + //human + copy.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + String name = getUserInput_GetDeckName(questData.getDeckNames()); + + //check if user cancels + if(name.equals("")) return; + + setHumanPlayer(name); + + Deck deck = convertCardListToDeck(deckDisplay.getBottom()); + deck.setName(name); + + questData.addDeck(deck); + } + });//copy + + + //human + delete.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + if(currentDeck.getName().equals("")) return; + + int check = JOptionPane.showConfirmDialog(null, "Do you really want to delete this deck?", + "Delete", JOptionPane.YES_NO_OPTION); + if(check == JOptionPane.NO_OPTION) return;//stop here + + questData.removeDeck(currentDeck.getName()); + + //show card pool + CardList cardpool = covertToCardList(questData.getCardpool()); + deckDisplay.updateDisplay(cardpool, new CardList()); + + setHumanPlayer(""); + } + });//delete + + + //human + exit.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + Gui_Quest_DeckEditor_Menu.this.close(); + } + }); + + JMenu deckMenu = new JMenu("Deck"); + deckMenu.add(open); + deckMenu.add(new2); + deckMenu.add(rename); + deckMenu.add(save); + deckMenu.add(copy); + + deckMenu.addSeparator(); + addImportExport(deckMenu, true); + + deckMenu.addSeparator(); + deckMenu.add(delete); + deckMenu.addSeparator(); + deckMenu.add(exit); + + this.add(deckMenu); + + }//setupMenu() + + private Deck convertCardListToDeck(CardList list) { + //put CardList into Deck main + Deck deck = new Deck(Constant.GameType.Sealed); + + for(int i = 0; i < list.size(); i++) + deck.addMain(list.get(i).getName()); + + return deck; + } + + //needs to be public because Gui_Quest_DeckEditor.show(Command) uses it + public void setHumanPlayer(String deckName) { + //the gui uses this, Gui_Quest_DeckEditor + currentDeck = new Deck(Constant.GameType.Sealed); + currentDeck.setName(deckName); + + deckDisplay.setTitle(deckEditorName + " - " + deckName); + } + + private void setComputerPlayer(String deckName) { + //the gui uses this, Gui_Quest_DeckEditor + currentDeck = new Deck(Constant.GameType.Constructed); + currentDeck.setName(deckName); + + deckDisplay.setTitle(deckEditorName + " - " + deckName); + } + + //only accepts numbers, letters or dashes up to 20 characters in length + private String cleanString(String in) { + String out = ""; + char[] c = in.toCharArray(); + + for(int i = 0; i < c.length && i < 20; i++) + if(Character.isLetterOrDigit(c[i]) || c[i] == '-' || c[i] == '_' || c[i] == ' ') out += c[i]; + + return out; + } + + //if user cancels, returns "" + private String getUserInput_GetDeckName(ArrayList nameList) { + Object o = JOptionPane.showInputDialog(null, "", "Deck Name", JOptionPane.OK_CANCEL_OPTION); + + if(o == null) return ""; + + String deckName = cleanString(o.toString()); + + if(nameList.contains(deckName) || deckName.equals("")) { + JOptionPane.showMessageDialog(null, "Please pick another deck name, a deck currently has that name."); + return getUserInput_GetDeckName(nameList); + } + + return deckName; + }//getUserInput_GetDeckName() + + + //if user cancels, it will return "" + private String getUserInput_OpenDeck(ArrayList deckNameList) { + ArrayList choices = deckNameList; + if(choices.size() == 0) { + JOptionPane.showMessageDialog(null, "No decks found", "Open Deck", JOptionPane.PLAIN_MESSAGE); + return ""; + } + + Object o = JOptionPane.showInputDialog(null, "Deck Name", "Open Deck", JOptionPane.OK_CANCEL_OPTION, null, + choices.toArray(), choices.toArray()[0]); + + if(o == null) return ""; + + return o.toString(); + }//getUserInput_OpenDeck() + + //used by Gui_Quest_DeckEditor + public void close() { + exitCommand.execute(); + } + + //used by Gui_Quest_DeckEditor + public String getDeckName() { + return currentDeck.getName(); + } + + //used by Gui_Quest_DeckEditor + public String getGameType() { + return currentDeck.getDeckType(); + } + + + //returns CardList of Card objects, + //argument ArrayList holds String card names + public static CardList covertToCardList(ArrayList list) { + CardList c = new CardList(); + Card card; + for(int i = 0; i < list.size(); i++) { + card = AllZone.CardFactory.getCard(list.get(i).toString(), ""); + c.add(card); + } + + return c; + } + +} \ No newline at end of file diff --git a/src/Gui_SealedDeck.java b/src/Gui_SealedDeck.java new file mode 100644 index 00000000000..3961f1fd7ff --- /dev/null +++ b/src/Gui_SealedDeck.java @@ -0,0 +1,61 @@ + + + + +import java.awt.FlowLayout; +import java.awt.Rectangle; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import forge.error.ErrorViewer; + + +public class Gui_SealedDeck extends JFrame { + private static final long serialVersionUID = -5073942967852403230L; + private JLabel jLabel1 = new JLabel(); + private JPanel jPanel1 = new JPanel(); + private JButton jButton3 = new JButton(); + private JButton jButton2 = new JButton(); + private FlowLayout flowLayout1 = new FlowLayout(); + private JComboBox boosterComboBox = new JComboBox(); + private JLabel jLabel5 = new JLabel(); + private JLabel jLabel4 = new JLabel(); + private JComboBox setComboBox = new JComboBox(); + + public Gui_SealedDeck() { + try { + jbInit(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + } + + private void jbInit() throws Exception { + jLabel1.setBounds(new Rectangle(118, 14, 220, 69)); + jLabel1.setText("Sealed Deck"); + jLabel1.setFont(new java.awt.Font("Dialog", 0, 26)); + this.getContentPane().setLayout(null); + jPanel1.setBounds(new Rectangle(89, 230, 237, 43)); + jPanel1.setLayout(flowLayout1); + jButton3.setText("Next ->"); + jButton2.setText("<- Back"); + boosterComboBox.setBounds(new Rectangle(240, 173, 51, 23)); + jLabel5.setText("Booster Packs Per Person"); + jLabel5.setBounds(new Rectangle(89, 173, 164, 21)); + jLabel4.setText("Set"); + jLabel4.setBounds(new Rectangle(89, 121, 30, 15)); + setComboBox.setBounds(new Rectangle(136, 115, 161, 23)); + jPanel1.add(jButton2, null); + jPanel1.add(jButton3, null); + this.getContentPane().add(jLabel1, null); + this.getContentPane().add(setComboBox, null); + this.getContentPane().add(jLabel4, null); + this.getContentPane().add(jLabel5, null); + this.getContentPane().add(boosterComboBox, null); + this.getContentPane().add(jPanel1, null); + } +} \ No newline at end of file diff --git a/src/Gui_SetEditor.java b/src/Gui_SetEditor.java new file mode 100644 index 00000000000..20e6109bac2 --- /dev/null +++ b/src/Gui_SetEditor.java @@ -0,0 +1,135 @@ +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Rectangle; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; + + +public class Gui_SetEditor extends JFrame { + private static final long serialVersionUID = 519896860030378941L; + + private JLabel jLabel1 = new JLabel(); + private JScrollPane jScrollPane1 = new JScrollPane(); + private JScrollPane jScrollPane2 = new JScrollPane(); + private JPanel jPanel1 = new JPanel(); + private Border border1; + private TitledBorder titledBorder1; + private JPanel jPanel2 = new JPanel(); + private JButton jButton1 = new JButton(); + private JButton jButton2 = new JButton(); + private JButton jButton3 = new JButton(); + private JList jList1 = new JList(); + private JList jList2 = new JList(); + private JPanel jPanel3 = new JPanel(); + private JButton jButton4 = new JButton(); + private JButton jButton5 = new JButton(); + private FlowLayout flowLayout1 = new FlowLayout(); + private JLabel jLabel2 = new JLabel(); + private JLabel jLabel3 = new JLabel(); + private JButton jButton6 = new JButton(); + private JButton jButton7 = new JButton(); + private JPanel jPanel4 = new JPanel(); + private Border border2; + private TitledBorder titledBorder2; + private JLabel jLabel5 = new JLabel(); + private JLabel jLabel6 = new JLabel(); + private JLabel jLabel4 = new JLabel(); + private JLabel jLabel7 = new JLabel(); + private JLabel jLabel8 = new JLabel(); + + public static void main(String[] args) { + Gui_SetEditor g = new Gui_SetEditor(); + g.setVisible(true); + } + + public Gui_SetEditor() { + try { + jbInit(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + } + + private void jbInit() throws Exception { + border1 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder1 = new TitledBorder(border1, "Card Detail"); + border2 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titledBorder2 = new TitledBorder(border2, "Set Statistics"); + jLabel1.setBounds(new Rectangle(299, 14, 137, 69)); + jLabel1.setText("Set Editor"); + jLabel1.setFont(new java.awt.Font("Dialog", 0, 26)); + this.getContentPane().setLayout(null); + jScrollPane1.setBounds(new Rectangle(13, 112, 181, 271)); + jScrollPane2.setBounds(new Rectangle(306, 112, 181, 271)); + jPanel1.setBorder(titledBorder1); + jPanel1.setBounds(new Rectangle(609, 28, 228, 291)); + jPanel2.setBorder(BorderFactory.createEtchedBorder()); + jPanel2.setBounds(new Rectangle(604, 343, 240, 321)); + jButton1.setBounds(new Rectangle(197, 161, 105, 32)); + jButton1.setText("Add ->"); + jButton2.setBounds(new Rectangle(197, 200, 105, 32)); + jButton2.setText("Add Note ->"); + jButton3.setText("<- Remove"); + jButton3.setBounds(new Rectangle(197, 286, 105, 32)); + jPanel3.setLayout(flowLayout1); + jPanel3.setBounds(new Rectangle(132, 514, 237, 43)); + jButton4.setText("Cancel"); + jButton5.setText("Save"); + jLabel2.setText("All Available Cards"); + jLabel2.setBounds(new Rectangle(51, 81, 133, 24)); + jLabel3.setHorizontalAlignment(SwingConstants.CENTER); + jLabel3.setText("Set"); + jLabel3.setBounds(new Rectangle(305, 82, 179, 22)); + jButton6.setBounds(new Rectangle(495, 119, 53, 54)); + jButton6.setToolTipText("Move a card up in the listing"); + jButton6.setText("Up"); + jButton7.setBounds(new Rectangle(494, 329, 56, 51)); + jButton7.setToolTipText("Move a card down in the listing"); + jButton7.setText("Down"); + jPanel4.setBorder(titledBorder2); + jPanel4.setBounds(new Rectangle(245, 400, 320, 96)); + jPanel4.setLayout(null); + jLabel5.setText("White - 10, Green - 10, Black - 10, Red - 10, Blue - 10"); + jLabel5.setBounds(new Rectangle(14, 19, 418, 23)); + jLabel6.setText("Artifact - 2, Land - 1, Multi-Colored - 0, Total - 100"); + jLabel6.setBounds(new Rectangle(14, 45, 418, 23)); + jLabel4.setText("Common - 70, Uncommon - 20, Rare - 10"); + jLabel4.setBounds(new Rectangle(14, 70, 418, 23)); + jLabel7.setText("Elvish Piper - R"); + jLabel7.setBounds(new Rectangle(497, 194, 101, 23)); + jLabel8.setText("Kodoma\'s Reach - C"); + jLabel8.setBounds(new Rectangle(494, 231, 127, 29)); + this.getContentPane().add(jLabel1, null); + this.getContentPane().add(jScrollPane2, null); + jScrollPane2.getViewport().add(jList1, null); + this.getContentPane().add(jScrollPane1, null); + jScrollPane1.getViewport().add(jList2, null); + this.getContentPane().add(jButton1, null); + this.getContentPane().add(jButton2, null); + this.getContentPane().add(jButton3, null); + jPanel3.add(jButton5, null); + jPanel3.add(jButton4, null); + this.getContentPane().add(jPanel4, null); + jPanel4.add(jLabel5, null); + jPanel4.add(jLabel6, null); + jPanel4.add(jLabel4, null); + this.getContentPane().add(jPanel3, null); + this.getContentPane().add(jLabel2, null); + this.getContentPane().add(jLabel3, null); + this.getContentPane().add(jButton6, null); + this.getContentPane().add(jButton7, null); + this.getContentPane().add(jPanel1, null); + this.getContentPane().add(jPanel2, null); + this.getContentPane().add(jLabel7, null); + this.getContentPane().add(jLabel8, null); + } +} \ No newline at end of file diff --git a/src/Gui_Welcome.java b/src/Gui_Welcome.java new file mode 100644 index 00000000000..e184414efc3 --- /dev/null +++ b/src/Gui_Welcome.java @@ -0,0 +1,59 @@ +import java.awt.Rectangle; +import java.awt.event.ActionEvent; + +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JRadioButton; + + +public class Gui_Welcome extends JFrame { + private static final long serialVersionUID = -7355345901761929563L; + + private JLabel jLabel1 = new JLabel(); + private JRadioButton jRadioButton1 = new JRadioButton(); + private JRadioButton jRadioButton2 = new JRadioButton(); + private JButton nextButton = new JButton(); + private ButtonGroup buttonGroup1 = new ButtonGroup(); + + public Gui_Welcome() { + try { + jbInit(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + setSize(399, 317); + setVisible(true); + } + + private void jbInit() throws Exception { + jLabel1.setFont(new java.awt.Font("Dialog", 0, 26)); + jLabel1.setText("Welcome"); + jLabel1.setBounds(new Rectangle(119, 8, 210, 69)); + this.getContentPane().setLayout(null); + jRadioButton1.setText("Single Game - Play against the Computer"); + jRadioButton1.setBounds(new Rectangle(26, 100, 343, 31)); + + jRadioButton2.setText("Sealed Deck - Create your deck from Booster Packs"); + jRadioButton2.setBounds(new Rectangle(26, 154, 329, 28)); + nextButton.setBounds(new Rectangle(146, 243, 86, 30)); + nextButton.setText("Next ->"); + nextButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + nextButton_actionPerformed(e); + } + }); + this.getContentPane().add(jLabel1, null); + this.getContentPane().add(nextButton, null); + this.getContentPane().add(jRadioButton2, null); + this.getContentPane().add(jRadioButton1, null); + buttonGroup1.add(jRadioButton1); + buttonGroup1.add(jRadioButton2); + } + + void nextButton_actionPerformed(ActionEvent e) { + + } + +} \ No newline at end of file diff --git a/src/Gui_WinLose.java b/src/Gui_WinLose.java new file mode 100644 index 00000000000..730e2b87706 --- /dev/null +++ b/src/Gui_WinLose.java @@ -0,0 +1,206 @@ +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.WindowEvent; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; + + +public class Gui_WinLose extends JFrame { + private static final long serialVersionUID = -5800412940994975483L; + + private JLabel titleLabel = new JLabel(); + private JButton continueButton = new JButton(); + private JButton restartButton = new JButton(); + private JButton quitButton = new JButton(); + private JLabel statsLabel = new JLabel(); + private JPanel jPanel2 = new JPanel(); + @SuppressWarnings("unused") + // titledBorder1 + private TitledBorder titledBorder1; + @SuppressWarnings("unused") + // border1 + private Border border1; + + public static void main(String[] args) { + Constant.Runtime.GameType[0] = Constant.GameType.Sealed; + + Constant.Runtime.WinLose.addWin(); + Constant.Runtime.WinLose.addLose(); + + + //setup limited deck + Deck deck = new Deck(Constant.GameType.Sealed); + CardList pack = new CardList(BoosterPack.getBoosterPack(1).toArray()); + + for(int i = 0; i < pack.size(); i++) + if((i % 2) == 0) deck.addSideboard(pack.get(i).getName()); + else deck.addMain(pack.get(i).getName()); + + Constant.Runtime.HumanDeck[0] = deck; + //end - setup limited deck + + new Gui_WinLose(); + } + + public Gui_WinLose() { + try { + jbInit(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + + setup(); + + Dimension screen = this.getToolkit().getScreenSize(); + setBounds(screen.width / 3, 100, //position + 215, 370); //size + setVisible(true); + } + + private void setup() { + WinLose winLose = Constant.Runtime.WinLose; + + //3 is the match length, 3 is the number of games + //disable buttons if match is up, or human player won 2 or lost 2 games already + if((winLose.countWinLose() == 3) || (winLose.getWin() == 2) || (winLose.getLose() == 2)) { +// editDeckButton.setEnabled(false); + continueButton.setEnabled(false); + } + + //show Wins and Loses + statsLabel.setText("Won: " + winLose.getWin() + ", Lost: " + winLose.getLose()); + + //show "You Won" or "You Lost" + if(winLose.didWinRecently()) titleLabel.setText("You Won"); + else titleLabel.setText("You Lost"); + + }//setup(); + + private void jbInit() throws Exception { + titledBorder1 = new TitledBorder(""); + border1 = BorderFactory.createEtchedBorder(Color.white, new Color(148, 145, 140)); + titleLabel.setFont(new java.awt.Font("Dialog", 0, 26)); + titleLabel.setHorizontalAlignment(SwingConstants.CENTER); + titleLabel.setText("You Won"); + titleLabel.setBounds(new Rectangle(-4, 0, 198, 60)); + this.getContentPane().setLayout(null); + continueButton.setBounds(new Rectangle(22, 21, 123, 30)); + continueButton.setText("Continue Match"); + continueButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + continueButton_actionPerformed(e); + } + }); + restartButton.setBounds(new Rectangle(22, 90, 123, 30)); + restartButton.setText("Restart Match"); + restartButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + restartButton_actionPerformed(e); + } + }); + quitButton.setBounds(new Rectangle(22, 158, 123, 30)); + quitButton.setText("Quit Match"); + quitButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + quitButton_actionPerformed(e); + } + }); + statsLabel.setFont(new java.awt.Font("Dialog", 0, 16)); + statsLabel.setHorizontalAlignment(SwingConstants.CENTER); + statsLabel.setText("Wins 2, Lost 1"); + statsLabel.setBounds(new Rectangle(12, 59, 170, 30)); + jPanel2.setBorder(BorderFactory.createLineBorder(Color.black)); + jPanel2.setBounds(new Rectangle(20, 104, 166, 217)); + jPanel2.setLayout(null); + this.addWindowListener(new java.awt.event.WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + this_windowClosing(e); + } + }); + this.getContentPane().add(statsLabel, null); + this.getContentPane().add(jPanel2, null); + jPanel2.add(continueButton, null); + jPanel2.add(quitButton, null); + jPanel2.add(restartButton, null); + this.getContentPane().add(titleLabel, null); + } + + void editDeckButton_actionPerformed(ActionEvent e) { + Command exit = new Command() { + private static final long serialVersionUID = 4735992294414389187L; + + public void execute() { + new Gui_WinLose(); + } + }; + Gui_DeckEditor editor = new Gui_DeckEditor(); + + editor.show(exit); + + dispose(); + }//editDeckButton_actionPerformed() + + void continueButton_actionPerformed(ActionEvent e) { + //open up "Game" screen +// AllZone.Computer_Play.reset();//sometimes computer has creature in play in the 2nd game of the match + AllZone.GameAction.newGame(Constant.Runtime.HumanDeck[0], Constant.Runtime.ComputerDeck[0]); + AllZone.Display.setVisible(true); + + dispose(); + } + + void restartButton_actionPerformed(ActionEvent e) { + Constant.Runtime.WinLose.reset(); + AllZone.GameAction.newGame(Constant.Runtime.HumanDeck[0], Constant.Runtime.ComputerDeck[0]); + AllZone.Display.setVisible(true); + + dispose(); + } + + void quitButton_actionPerformed(ActionEvent e) { + //are we on a quest? + if(AllZone.QuestData == null) new Gui_NewGame(); + else { + WinLose winLose = Constant.Runtime.WinLose; + QuestData quest = AllZone.QuestData; + + if(winLose.getWin() == 2) quest.addWin(); + else quest.addLost(); + + if(quest.shouldAddCards(winLose.didWinRecently())) { + quest.addCards(); + JOptionPane.showMessageDialog(null, "You have won new cards."); + } + + if(quest.shouldAddAdditionalCards(winLose.didWinRecently())) { + quest.addAdditionalCards(); + JOptionPane.showMessageDialog(null, "You have won a random rare."); + } + winLose.reset(); + + QuestData.saveData(quest); + new Gui_Quest(); + }//else - on quest + + dispose(); + + //clear Image caches, so the program doesn't get slower and slower + ImageUtil.rotatedCache.clear(); + ImageCache.cache.clear(); + } + + void this_windowClosing(WindowEvent e) { + quitButton_actionPerformed(null); + } +} \ No newline at end of file diff --git a/src/IO.java b/src/IO.java new file mode 100644 index 00000000000..15ca9004911 --- /dev/null +++ b/src/IO.java @@ -0,0 +1,93 @@ +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + + +public class IO { + private final File file; + + private Map map = new HashMap(); + + public IO(String filename) { + file = new File(filename); + try { + if(!file.exists()) { + file.createNewFile(); + writeMap(); + } + } catch(Exception ex) { + ErrorViewer.showError(ex, "IO : constructor error, bad filename - %s%n%s", filename, ex.getMessage()); + throw new RuntimeException(String.format("IO : constructor error, bad filename - %s%n%s", filename, + ex.getMessage()), ex); + } + } + + @SuppressWarnings("unchecked") + // Map has unchecked cast + private void readMap() { + try { + ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); + map = (Map) in.readObject(); + in.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("IO : readMap() error, " + ex.getMessage()); + } + } + + private void writeMap() { + try { + ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file)); + out.writeObject(map); + + out.flush(); + out.close(); + + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("IO : writeMap error, " + ex.getMessage()); + } + } + + public void writeObject(String key, Serializable ser) { + readMap(); + map.put(key, ser); + writeMap(); + } + + //may return null; + public Object readObject(String key) { + readMap(); + return map.get(key); + } + + public void deleteObject(String key) { + readMap(); + map.remove(key); + writeMap(); + } + + public ArrayList getKeyList() { + readMap(); + + ArrayList list = new ArrayList(); + Iterator it = map.keySet().iterator(); + while(it.hasNext()) + list.add(it.next()); // guessing that this is going to be a string. + return list; + } + + public String[] getKeyString() { + ArrayList list = getKeyList(); + String[] s = new String[list.size()]; + list.toArray(s); + return s; + } +} \ No newline at end of file diff --git a/src/ImageCache.java b/src/ImageCache.java new file mode 100644 index 00000000000..51cf2a7fbc0 --- /dev/null +++ b/src/ImageCache.java @@ -0,0 +1,127 @@ +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.io.File; +import java.util.HashMap; + +import javax.imageio.ImageIO; + +import forge.error.ErrorViewer; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + +/** + * For storing card images in a cache. + */ +public class ImageCache implements NewConstants { + + /** + * Card size. + */ + //protected static Rectangle cardSize = new Rectangle(93, 130); + //protected static Rectangle cardSize = new Rectangle(70, 98); + //public static Rectangle cardSize = new Rectangle(70,98); + public static Rectangle cardSize = new Rectangle(Constant.Runtime.width[0], + Constant.Runtime.height[0]); + + + /** + * Cache for storing images. + */ + public static HashMap cache = new HashMap(); + + //protected static HashMap cache = new HashMap(); + + //~ Image size was not getting updated if the user changed it between games... + public static void dumpCache() { + cardSize = new Rectangle(Constant.Runtime.width[0], Constant.Runtime.height[0]); + cache = new HashMap(); + } + + //~ + + + /** + * Load image from disk and then put it into the cache. If image has been loaded before then no loading is + * needed. + * + * @param card card to load image for + * @return {@link Image} + */ + final public static Image getImage(Card card) { + + /** + * Try to get from cache. + */ + String name = card.getImageName(); + if(card.isBasicLand()) { + if(card.getRandomPicture() != 0) name += Integer.toString(card.getRandomPicture()); + } else if(card.isFaceDown()) name = "Morph"; + if(cache.containsKey(name)) { + return cache.get(name); + } + + /** + * Load image. + */ + BufferedImage image = null; + Image resized = null; + + File imagePath = getImagePath(card); + if(imagePath == null) { + return null; + } + + try { + image = ImageIO.read(imagePath); + + resized = image.getScaledInstance(cardSize.width, cardSize.height, java.awt.Image.SCALE_SMOOTH); + } catch(Exception ex) { + ErrorViewer.showError(ex); + } + + /** + * Put to cache. + */ + cache.put(name, resized); + + return resized; + } + + /** + * Get path to image for specific card. + * + * @param c card to get path for + * @return String if image exists, else null + */ + final public static File getImagePath(Card c) { + if(AllZone.NameChanger.shouldChangeCardName()) { + return null; + } + + String suffix = ".jpg"; + String filename = ""; + if(!c.isFaceDown()) { + String basicLandSuffix = ""; + if(c.isBasicLand()) { + if(c.getRandomPicture() != 0) basicLandSuffix = Integer.toString(c.getRandomPicture()); + } + filename = GuiDisplayUtil.cleanString(c.getImageName()) + basicLandSuffix + suffix; + } else filename = "morph" + suffix; + File file = new File(ForgeProps.getFile(IMAGE_BASE), filename); + + /** + * try current directory + */ + if(!file.exists()) { + filename = GuiDisplayUtil.cleanString(c.getName()) + suffix; + file = new File(filename); + } + + if(file.exists()) { + return file; + } else { + return null; + } + } +} \ No newline at end of file diff --git a/src/ImageJPanel.java b/src/ImageJPanel.java new file mode 100644 index 00000000000..e4b66701a00 --- /dev/null +++ b/src/ImageJPanel.java @@ -0,0 +1,31 @@ +import java.awt.Graphics; +import java.awt.Image; + +import javax.swing.ImageIcon; +import javax.swing.JPanel; + +public class ImageJPanel extends JPanel +{ + private static final long serialVersionUID = 2908946871498362599L; + + private Image aImage = null; + + public ImageJPanel(String s) + { + init(s); + } + + private void init(String image) + { + + ImageIcon imageIcon = new ImageIcon("pics\\" + image); + aImage = imageIcon.getImage(); + + } + + public void paint(Graphics g) + { + super.paint(g); + g.drawImage(aImage, 0, 0, this); + } +} \ No newline at end of file diff --git a/src/ImageUtil.java b/src/ImageUtil.java new file mode 100644 index 00000000000..aa4fd3319e2 --- /dev/null +++ b/src/ImageUtil.java @@ -0,0 +1,98 @@ + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.util.HashMap; + +/** + * Class for working with images. + * + */ +public class ImageUtil +{ + + public static HashMap rotatedCache = new HashMap(); + + /** + * Rotates image and puts it into cache. + * If image has already been rotated before it is read from cache + * + * @param source image to rotate + * @return + */ + final public static Image getTappedImage(Image original, String name) + { + + if (rotatedCache.containsKey(name)) + { + return (Image) rotatedCache.get(name); + } + + + int width = original.getWidth(null); + int height = original.getHeight(null); + + if (width == -1 || height == -1) + { + return null; + } + + + + + BufferedImage source = new BufferedImage(height, height, BufferedImage.TYPE_INT_ARGB); + Graphics g = source.getGraphics(); + g.drawImage(original, 0, 0, null); + g.dispose(); + + + + BufferedImage target = new BufferedImage(height, width, BufferedImage.TYPE_INT_ARGB); + g = target.getGraphics(); + g.drawImage(rotateImage(source), 0, 0, null); + g.dispose(); + + rotatedCache.put(name, target); + + return target; + } + + /** + * Rotate image (90 degrees). + * + * @param source image to rotate + * @return rotated image + */ + final protected static BufferedImage rotateImage(BufferedImage source) + { + BufferedImage target = new BufferedImage(source.getHeight(), source.getWidth(), BufferedImage.TYPE_INT_ARGB); + + + + AffineTransform at = new AffineTransform(); + + /** + * Rotate 90 degrees around image center + */ + at.rotate(90.0 * Math.PI / 180.0, source.getWidth() / 2.0, source.getHeight() / 2.0); + + + //Draw from source (rotated) to target + Graphics2D g = (Graphics2D) target.getGraphics(); + g.drawImage(source, at, null); + g.dispose(); + + + //Code below is an alternate way to draw using straight Graphics2D - seems to be slower + + //Draw from source (rotated) to target +// Graphics2D g = (Graphics2D) target.getGraphics(); +// g.rotate(Math.PI / 2.0, source.getWidth() / 2.0, source.getHeight() / 2.0); +// g.drawImage(source, null, 0, 0); +// g.dispose(); + + return target; + } +} \ No newline at end of file diff --git a/src/Input.java b/src/Input.java new file mode 100644 index 00000000000..794f494f290 --- /dev/null +++ b/src/Input.java @@ -0,0 +1,39 @@ +public abstract class Input implements java.io.Serializable +{ + private static final long serialVersionUID = -6539552513871194081L; + + //showMessage() is always the first method called + public void showMessage() {AllZone.Display.showMessage("Blank Input");} + + public void selectCard(Card c, PlayerZone zone) {} + public void selectPlayer(String player) {} + public void selectButtonOK() {} + public void selectButtonCancel() {} + + //helper methods, since they are used alot + //to be used by anything in CardFactory like SetTargetInput + //NOT TO BE USED by Input_Main or any of the "regular" Inputs objects that are not set using AllZone.InputControl.setInput(Input) + final public void stop() + { + //clears a "temp" Input like Input_PayManaCost if there is one + AllZone.InputControl.resetInput(); + AllZone.InputControl.updateObservers(); + + if(AllZone.Phase.isNeedToNextPhase()==true){ + //for debugging: System.out.println("There better be no nextPhase in the stack."); + AllZone.Phase.setNeedToNextPhase(false); + AllZone.Phase.nextPhase(); + } + } + + final public void stopPayCost(SpellAbility sa) + { +// AllZone.InputControl.updateObservers(); + AllZone.GameAction.playSpellAbility(sa); + } + + //exits the "current" Input and sets the next Input + final public void stopSetNext(Input in) {stop(); AllZone.InputControl.setInput(in);} + + public String toString() {return "blank";}//returns the Input name like "EmptyStack" +} \ No newline at end of file diff --git a/src/InputControl.java b/src/InputControl.java new file mode 100644 index 00000000000..ba70dc539cf --- /dev/null +++ b/src/InputControl.java @@ -0,0 +1,247 @@ + import java.util.*; + + @SuppressWarnings("unused") // java.util.* + public class InputControl extends MyObservable implements java.io.Serializable + { + private static final long serialVersionUID = 3955194449319994301L; + + private Input input; + static int n = 0; + + public void setInput(Input in) + { + input = in; + updateObservers(); + } + public void resetInput() + { + input = null; + updateObservers(); + } + public Input getInput() + { + final String phase = AllZone.Phase.getPhase(); + final String player = AllZone.Phase.getActivePlayer(); + //System.out.println(n++ +" " +phase +" " +player); + + if(input != null) + return input; + + else if(AllZone.Stack.size() > 0) + { + input = new Input_StackNotEmpty(); + return input; + } + else if(player.equals(Constant.Player.Human)) + { + if(phase.equals(Constant.Phase.Untap)) + { + AllZone.Combat.reset(); + AllZone.Combat.setAttackingPlayer(Constant.Player.Human); + AllZone.Combat.setDefendingPlayer(Constant.Player.Computer); + + AllZone.pwCombat.reset(); + AllZone.pwCombat.setAttackingPlayer(Constant.Player.Human); + AllZone.pwCombat.setDefendingPlayer(Constant.Player.Computer); + + return new Input_Untap(); + } + //else if(phase.equals(Constant.Phase.Upkeep)) + //return new Input_Instant(Input_Instant.YES_NEXT_PHASE, "Upkeep Phase: Play Instants and Abilities"); + + else if(phase.equals(Constant.Phase.Draw)) + return new Input_Draw(); + + else if(phase.equals(Constant.Phase.Main1) || phase.equals(Constant.Phase.Main2)) + return new Input_Main(); + + else if(phase.equals(Constant.Phase.Combat_Before_Declare_Attackers_InstantAbility)) + { + if (ComputerUtil.getPossibleAttackers().size() > 0) + return new Input_Before_Attack_Instant(); + else + { + AllZone.Phase.setNeedToNextPhase(true); + return null; + } + } + + else if(phase.equals(Constant.Phase.Combat_Declare_Attackers)) + { + return new Input_Attack(); + } + + else if (phase.equals(Constant.Phase.Combat_Declare_Attackers_InstantAbility)) + { + if (! skipPhase()) + return new Input_Attack_Instant(); + else + { + AllZone.Phase.setNeedToNextPhase(true); + return null; + } + } + + //this is called twice per turn, only when its human's turn + //and then the 2nd time when its the computer's turn + else if(phase.equals(Constant.Phase.Combat_Declare_Blockers_InstantAbility)) + { + if(! skipPhase()) + return new Input_Block_Instant(); + else + { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(InputControl,phase.equals(Combat_Declare_Blockers_InstantAbility) = true"); + AllZone.Phase.setNeedToNextPhase(true); + //do not return getInput() here. There is now a check for null by this method's caller. + return null; + } + } + else if(phase.equals(Constant.Phase.Combat_FirstStrikeDamage)) + { + if(! skipPhase()) + return new Input_FirstStrikeDamage(); + else + { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(InputControl.getInput(),phase.equals(Combat_Damage)) = true"); + AllZone.Phase.setNeedToNextPhase(true); + //do not return getInput here. There is now a check for null by this method's caller. + //return getInput(); + return null; + } + } + else if(phase.equals(Constant.Phase.Combat_Damage)) + { + if(! skipPhase()) + return new Input_CombatDamage(); + else + { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(InputControl.getInput(),phase.equals(Combat_Damage)) = true"); + //System.out.println("stack size:" +AllZone.Stack.size()); + + AllZone.Phase.setNeedToNextPhase(true); + + //do not return getInput here. There is now a check for null by this method's caller. + //return getInput(); + return null; + } + } + else if(phase.equals(Constant.Phase.At_End_Of_Turn)) + { + AllZone.EndOfTurn.executeAt(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(InputControl.getInput(),phase.equals(At_End_Of_Turn)) = true"); + AllZone.Phase.setNeedToNextPhase(true); + //do not return getInput() here. There is now a check for null by this method's caller + //return getInput(); + return null; + } + else if(phase.equals(Constant.Phase.End_Of_Turn)) + { + if(AllZone.Display.stopEOT()) + return new Input_EOT(); + else + { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(InputControl.getInput(),phase.equals(End_Of_Turn)) = true"); + AllZone.Phase.setNeedToNextPhase(true); + //do not return getInput() here. There is now a check for null in this method's caller. + //return getInput(); + return null; + } + } + else if(phase.equals(Constant.Phase.Until_End_Of_Turn)) + { + AllZone.EndOfTurn.executeUntil(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(InputControl.getInput(),phase.equals(Until_End_Of_Turn)) = true"); + AllZone.Phase.setNeedToNextPhase(true); + //do not return getInput() here. There is now a check for null by this method's caller. + //return getInput(); + return null; + } + else if(phase.equals(Constant.Phase.Cleanup)) + return new Input_Cleanup(); + + //takes place during the computer's turn, like blocking etc... + else if(phase.equals(Constant.Phase.Combat_Declare_Blockers)) + { + if(! skipPhase()) + return new Input_Block(); + else + { + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(InputControl.getInput(),phase.equals(Combat_Declare_Blockers)) = true"); + AllZone.Phase.setNeedToNextPhase(true); + //do not return getInput here. There is now a check for null by this method's caller. + //return getInput(); + return null; + } + } + // else if(phase.equals(Constant.Phase.End_Of_Turn)) + // return new Input_Instant(Input_Instant.YES_NEXT_PHASE, "End of Computer's Turn: Play Instants and Abilities"); + + }//Human + else + { //computer + if(phase.equals(Constant.Phase.Untap)) + { + AllZone.Combat.reset(); + AllZone.Combat.setAttackingPlayer(Constant.Player.Computer); + AllZone.Combat.setDefendingPlayer(Constant.Player.Human); + + AllZone.pwCombat.reset(); + AllZone.pwCombat.setAttackingPlayer(Constant.Player.Computer); + AllZone.pwCombat.setDefendingPlayer(Constant.Player.Human); + + return new Input_Untap(); + } + else if(phase.equals(Constant.Phase.Draw)) + return new Computer_Draw(); + + else if(phase.equals(Constant.Phase.Cleanup)) + { + return new Computer_Cleanup(); + } + else + return AllZone.Computer; + }//Computer + + return new Input() + { + private static final long serialVersionUID = 7378891097354547936L; + + public void showMessage() + { + AllZone.Display.showMessage("InputControl : Error nothing found"); + throw new RuntimeException("InputControl : getInput() error, should not be here, phase " +phase +", player " +player); + } + }; + }//getInput() + private boolean skipPhase() + { + CardList check = new CardList(); + check.addAll(AllZone.Combat.getAttackers()); + check.addAll(AllZone.pwCombat.getAttackers()); + + CardList all = new CardList(); + all.addAll(AllZone.Computer_Play.getCards()); + all.addAll(AllZone.Human_Play.getCards()); + all = all.filter(new CardListFilter(){ + public boolean addCard(Card c) { + return c.isCreature() && c.getAssignedDamage() > 0; + } + + }); + + return check.size() == 0 && all.size() == 0; + } + }//InputControl diff --git a/src/InputUtil.java b/src/InputUtil.java new file mode 100644 index 00000000000..96efe2a7a2f --- /dev/null +++ b/src/InputUtil.java @@ -0,0 +1,30 @@ +//import java.util.*; //unused + +public class InputUtil +{ + //plays activated abilities and instants + static public void playInstantAbility(Card card, PlayerZone zone) + { + if(zone.is(Constant.Zone.Hand) || zone.is(Constant.Zone.Play, Constant.Player.Human)) + AllZone.GameAction.playCard(card); + } + + //plays activated abilities and any card including land, sorceries, and instants + static public void playAnyCard(Card card, PlayerZone zone) + { + if(zone.is(Constant.Zone.Hand, Constant.Player.Human) && + (card.isLand())) + { + AllZone.Human_Hand.remove(card); + AllZone.Human_Play.add(card); + } + else if(zone.is(Constant.Zone.Hand, Constant.Player.Human) && + card.getManaCost().equals("0"))//for Mox Ruby and the like + { + AllZone.Human_Hand.remove(card); + AllZone.Stack.add(card.getSpellAbility()[0]); + } + else if (zone.is(Constant.Zone.Hand, Constant.Player.Human) || zone.is(Constant.Zone.Play, Constant.Player.Human)) + AllZone.GameAction.playCard(card); + }//selectCard() +} \ No newline at end of file diff --git a/src/Input_Attack.java b/src/Input_Attack.java new file mode 100644 index 00000000000..2fa3fa9d7ff --- /dev/null +++ b/src/Input_Attack.java @@ -0,0 +1,83 @@ +public class Input_Attack extends Input +{ +private static final long serialVersionUID = 7849903731842214245L; + +public void showMessage() + { + ButtonUtil.enableOnlyOK(); + AllZone.Display.showMessage("Declare Attackers: Select creatures that you want to attack with"); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList creats = new CardList(play.getCards()); + creats = creats.getType("Creature"); + + for (int i = 0;i allBlocking = new ArrayList(); + + public void showMessage() + { + //for Castle Raptors, since it gets a bonus if untapped + for (String effect : AllZone.StateBasedEffects.getStateBasedMap().keySet() ) { + Command com = GameActionUtil.commands.get(effect); + com.execute(); + } + GameActionUtil.executeCardStateEffects(); + + + //could add "Reset Blockers" button + ButtonUtil.enableOnlyOK(); + + if(currentAttacker == null) + AllZone.Display.showMessage("To Block, click on your Opponents attacker first, then your blocker(s)"); + else + AllZone.Display.showMessage("Select a creature to block " +currentAttacker.getName() +" (" +currentAttacker.getUniqueNumber() +") "); + + CombatUtil.showCombat(); + } + public void selectButtonOK() + { + ButtonUtil.reset(); + if(AllZone.pwCombat.getAttackers().length == 0) + { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(Input_Cleanup.showMessage(), n<=7) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + else + { + AllZone.InputControl.setInput(new Input_Block_Planeswalker()); + } + } + public void selectCard(Card card, PlayerZone zone) + { + //is attacking? + if(CardUtil.toList(AllZone.Combat.getAttackers()).contains(card)) + { + currentAttacker = card; + } + else if(zone.is(Constant.Zone.Play, Constant.Player.Human) && + card.isCreature() && + card.isUntapped() && + CombatUtil.canBlock(currentAttacker, card)) + { + if(currentAttacker != null && (! allBlocking.contains(card))) + { + allBlocking.add(card); + AllZone.Combat.addBlocker(currentAttacker, card); + } + } + showMessage(); + }//selectCard() +} diff --git a/src/Input_Block_Instant.java b/src/Input_Block_Instant.java new file mode 100644 index 00000000000..470cf67e915 --- /dev/null +++ b/src/Input_Block_Instant.java @@ -0,0 +1,29 @@ +public class Input_Block_Instant extends Input +{ + private static final long serialVersionUID = 6024555691502280746L; + + public void showMessage() + { + //GameActionUtil.executeExaltedEffects(); + + AllZone.Combat.verifyCreaturesInPlay(); + CombatUtil.showCombat(); + + ButtonUtil.enableOnlyOK(); + AllZone.Display.showMessage("Declare Blockers: Play Instants and Abilities"); + } + public void selectButtonOK() + { + AllZone.Combat.setAssignedFirstStrikeDamage(); + AllZone.pwCombat.setAssignedFirstStrikeDamage(); + + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(Input_Block_Instant.selectButtonOK) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + public void selectCard(Card card, PlayerZone zone) + { + InputUtil.playInstantAbility(card, zone); + }//selectCard() +} \ No newline at end of file diff --git a/src/Input_Block_Planeswalker.java b/src/Input_Block_Planeswalker.java new file mode 100644 index 00000000000..22f5ad30aee --- /dev/null +++ b/src/Input_Block_Planeswalker.java @@ -0,0 +1,60 @@ +import java.util.*; + +public class Input_Block_Planeswalker extends Input +{ + private static final long serialVersionUID = 8504632360578751473L; + + private Card currentAttacker = null; + private ArrayList allBlocking = new ArrayList(); + + public void showMessage() + { + //for Castle Raptors, since it gets a bonus if untapped + for (String effect : AllZone.StateBasedEffects.getStateBasedMap().keySet() ) { + Command com = GameActionUtil.commands.get(effect); + com.execute(); + } + + GameActionUtil.executeCardStateEffects(); + + + //could add "Reset Blockers" button + ButtonUtil.enableOnlyOK(); + + if(currentAttacker == null) + AllZone.Display.showMessage("Planeswalker Combat\r\nTo Block, click on your Opponents attacker first , then your blocker(s)"); + else + AllZone.Display.showMessage("Select a creature to block " +currentAttacker.getName() +" (" +currentAttacker.getUniqueNumber() +") "); + + CombatUtil.showCombat(); + } + public void selectButtonOK() + { + ButtonUtil.reset(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(Input_Block_Planeswalker.selectButtonOK) = true; Note, this has not been tested, did it work?"); + AllZone.Phase.setNeedToNextPhase(true); + this.stop(); + } + public void selectCard(Card card, PlayerZone zone) + { + //is attacking? + if(CardUtil.toList(AllZone.pwCombat.getAttackers()).contains(card)) + { + currentAttacker = card; + } + else if(zone.is(Constant.Zone.Play, Constant.Player.Human) && + card.isCreature() && + card.isUntapped() && + CombatUtil.canBlock(currentAttacker, card)) + { + if(currentAttacker != null && (! allBlocking.contains(card))) + { + allBlocking.add(card); + AllZone.pwCombat.addBlocker(currentAttacker, card); + } + } + showMessage(); + }//selectCard() +} diff --git a/src/Input_Cleanup.java b/src/Input_Cleanup.java new file mode 100644 index 00000000000..f2c12465e49 --- /dev/null +++ b/src/Input_Cleanup.java @@ -0,0 +1,41 @@ +public class Input_Cleanup extends Input +{ + private static final long serialVersionUID = -4164275418971547948L; + + public void showMessage() + { + ButtonUtil.disableAll(); + int n = AllZone.Human_Hand.getCards().length; + + //MUST showMessage() before stop() or it will overwrite the next Input's message + AllZone.Display.showMessage("Cleanup Phase: You can only have a maximum of 7 cards, you currently have " +n +" cards in your hand - select a card to discard"); + + //goes to the next phase + if(n <= 7) + { + CombatUtil.removeAllDamage(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(Input_Cleanup.showMessage(), n<=7) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + } + public void selectCard(Card card, PlayerZone zone) + { + if(zone.is(Constant.Zone.Hand, Constant.Player.Human)) + { + AllZone.GameAction.discard(card); + showMessage(); + //We need a nextPhase here or else it will never get the needToNextPhase from showMessage() (because there isn't a nextPhsae() in the stack). + System.out.println("There better not be a nextPhase() on the stack!"); + if(AllZone.Phase != null) + { + if(AllZone.Phase.isNeedToNextPhase()) + { + AllZone.Phase.setNeedToNextPhase(false); + AllZone.Phase.nextPhase(); + } + } + } + }//selectCard() +} diff --git a/src/Input_CombatDamage.java b/src/Input_CombatDamage.java new file mode 100644 index 00000000000..35b90c56f90 --- /dev/null +++ b/src/Input_CombatDamage.java @@ -0,0 +1,241 @@ +import java.util.ArrayList; + +public class Input_CombatDamage extends Input +{ + private static final long serialVersionUID = -8549102582210309044L; + + public Input_CombatDamage() + { + AllZone.Combat.verifyCreaturesInPlay(); + AllZone.pwCombat.verifyCreaturesInPlay(); + + CombatUtil.showCombat(); + } + + public void showMessage() + { + ButtonUtil.enableOnlyOK(); + AllZone.Display.showMessage("Combat Damage is on the stack - Play Instants and Abilities"); + } + public void selectButtonOK() + { + damageCreatureAndPlayer(); + + AllZone.GameAction.checkStateEffects(); + + AllZone.Combat.reset(); + AllZone.Display.showCombat(""); + + //AllZone.Phase.nextPhase(); + //for debugging: + System.out.println("need to nextPhase(Input_CombatDamage.selectButtonOK) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + public void selectCard(Card card, PlayerZone zone) + { + InputUtil.playInstantAbility(card, zone); + }//selectCard() + @SuppressWarnings("unused") // playerDamage +private void playerDamage(PlayerLife p) + { + int n = p.getAssignedDamage(); + p.setAssignedDamage(0); + p.subtractLife(n); + } + + //moves assigned damage to damage for all creatures + //deals damage to player if needed + public void damageCreatureAndPlayer() + { + String player = AllZone.Combat.getDefendingPlayer(); + if (player.equals("")) //this is a really bad hack, to allow raging goblin to attack on turn 1 + player = Constant.Player.Computer; + PlayerLife life = AllZone.GameAction.getPlayerLife(player); + life.subtractLife(AllZone.Combat.getDefendingDamage()); + + //why??? + /* + life = AllZone.GameAction.getPlayerLife(AllZone.Combat.getAttackingPlayer()); + life.subtractLife(AllZone.Combat.getAttackingDamage()); + life.subtractLife(AllZone.pwCombat.getAttackingDamage()); + */ + + CardList unblocked = new CardList(AllZone.Combat.getUnblockedAttackers()); + for(int j = 0; j < unblocked.size(); j++) + { + //System.out.println("Unblocked Creature: " +unblocked.get(j).getName()); + if (!unblocked.getCard(j).hasFirstStrike() || + (unblocked.getCard(j).hasFirstStrike() && unblocked.getCard(j).hasDoubleStrike())) { + GameActionUtil.executePlayerCombatDamageEffects(unblocked.get(j)); + } + + } + //GameActionUtil.executePlayerCombatDmgOptionalEffects(unblocked.toArray()); + + CardList attackers = new CardList(AllZone.Combat.getAttackers()); + CardList blockers = new CardList(AllZone.Combat.getAllBlockers().toArray()); + + for (int i=0; i < attackers.size(); i++){ + + //this shouldn't trigger if creature has first strike, only if it also has double strike + if (!attackers.getCard(i).hasFirstStrike() || + (attackers.getCard(i).hasFirstStrike() && attackers.getCard(i).hasDoubleStrike())) + { + ArrayList list = attackers.getCard(i).getKeyword(); + + CardList defend = AllZone.Combat.getBlockers(attackers.getCard(i)); + //System.out.println("creatures blocking " + attackers.getCard(i).getName() + " : " +defend.size()); + + /* + //hack, don't get lifelink if a doublestriker kills his blocker with first strike damage + if (!attackers.getCard(i).hasDoubleStrike() || (defend.size()!=0 && attackers.getCard(i).hasDoubleStrike()) ) + { + for (int j=0; j < list.size(); j++) + { + if (list.get(j).equals("Lifelink")) + GameActionUtil.executeLifeLinkEffects(attackers.getCard(i)); + + } + } + */ + + if (!attackers.getCard(i).hasDoubleStrike() || + (attackers.getCard(i).hasDoubleStrike() && !AllZone.Combat.isBlocked(attackers.getCard(i)) ) || + (attackers.getCard(i).hasDoubleStrike() && AllZone.Combat.isBlocked(attackers.getCard(i)) && defend.size() != 0 ) ) + { + /* + //old stuff: lifelink triggers on multiple instances of the lifelink keyword + for (int j=0; j < list.size(); j++) + { + if (list.get(j).equals("Lifelink")) + GameActionUtil.executeLifeLinkEffects(attackers.getCard(i)); + } + */ + + if (list.contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(attackers.getCard(i)); + + for(int j=0; j < CardFactoryUtil.hasNumberEnchantments(attackers.getCard(i), "Guilty Conscience"); j++) + GameActionUtil.executeGuiltyConscienceEffects(attackers.getCard(i)); + } + + //not sure if this will work correctly with multiple blockers? + int defenderToughness = 0; + for (int k=0; k list = blockers.getCard(i).getKeyword(); + for (int j=0; j < list.size(); j++) + { + if (list.get(j).equals("Lifelink")) + GameActionUtil.executeLifeLinkEffects(blockers.getCard(i)); + } + + */ + } + + } + + //get all attackers and blockers + CardList check = new CardList(); + check.addAll(AllZone.Human_Play.getCards()); + check.addAll(AllZone.Computer_Play.getCards()); + + CardList all = check.getType("Creature"); + + if(AllZone.pwCombat.getPlaneswalker() != null) + all.add(AllZone.pwCombat.getPlaneswalker()); + + + CardList pwAttackers = new CardList(AllZone.pwCombat.getAttackers()); + CardList pwBlockers = new CardList(AllZone.pwCombat.getAllBlockers().toArray()); + + + for (int i=0; i < pwAttackers.size(); i++){ + //System.out.println("attacker #" + i + ": " + attackers.getCard(i).getName() +" " + attackers.getCard(i).getAttack()); + if ( (!pwAttackers.getCard(i).hasFirstStrike() || (pwAttackers.getCard(i).hasFirstStrike() && pwAttackers.getCard(i).hasDoubleStrike()) ) ) + { + if (pwAttackers.getCard(i).getKeyword().contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(pwAttackers.getCard(i)); + + for(int j=0; j < CardFactoryUtil.hasNumberEnchantments(pwAttackers.getCard(i), "Guilty Conscience"); j++) + GameActionUtil.executeGuiltyConscienceEffects(pwAttackers.getCard(i)); + + } + } + for (int i=0; i < pwBlockers.size(); i++){ + //System.out.println("blocker #" + i + ": " + blockers.getCard(i).getName() +" " + blockers.getCard(i).getAttack()); + if ( (!pwBlockers.getCard(i).hasFirstStrike() || + (pwBlockers.getCard(i).hasFirstStrike() && pwBlockers.getCard(i).hasDoubleStrike()) ) ) + { + if (pwBlockers.getCard(i).getKeyword().contains("Lifelink")) + GameActionUtil.executeLifeLinkEffects(pwBlockers.getCard(i)); + + for(int j=0; j < CardFactoryUtil.hasNumberEnchantments(pwBlockers.getCard(i), "Guilty Conscience"); j++) + GameActionUtil.executeGuiltyConscienceEffects(pwBlockers.getCard(i)); + + } + } + + //hacky stuff, hope it won't cause any bugs: + for (int i=0; i < pwAttackers.size(); i++){ + AllZone.pwCombat.removeFromCombat(pwAttackers.get(i)); + } + + for (int i=0; i < pwBlockers.size(); i++){ + AllZone.pwCombat.removeFromCombat(pwBlockers.get(i)); + } + + + + Card c; + for(int i = 0; i < all.size(); i++) + { + c = all.get(i); + //because this sets off Jackal Pup, and Filthly Cur damage ability + //and the stack says "Jack Pup causes 0 damage to the Computer" + if(c.getAssignedDamage() != 0) + { + //c.addDamage(c.getAssignedDamage()); + System.out.println("Calling addDamage for card " + c.getName()); + AllZone.GameAction.addDamage(c, c.getAssignedDamage()); + c.setAssignedDamage(0); + } + } + }//moveDamage() +} \ No newline at end of file diff --git a/src/Input_Draw.java b/src/Input_Draw.java new file mode 100644 index 00000000000..2cc1708d702 --- /dev/null +++ b/src/Input_Draw.java @@ -0,0 +1,99 @@ + import java.util.*; + + public class Input_Draw extends Input + { + private static final long serialVersionUID = -2341125041806280507L; + + public void showMessage() + { + if(AllZone.Phase.getActivePlayer().equals(Constant.Player.Computer)) + { + AllZone.GameAction.drawCard(Constant.Player.Computer); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(from Input_Draw on computer's draw) = true"); + AllZone.Phase.setNeedToNextPhase(true); + return; + } + + //check if human should skip their draw phase + CardList humanCards = new CardList(); + humanCards.addAll(AllZone.Human_Play.getCards()); + boolean humanSkipsDrawPhase = humanCards.containsName("Necropotence") || humanCards.containsName("Yawgmoth's Bargain"); + + if(AllZone.Phase.getPhase().equals(Constant.Phase.Draw) && humanSkipsDrawPhase){ + Input_Main.canPlayLand = true; + AllZone.Phase.setNeedToNextPhase(true); + + } + else{ //continue with draw phase + boolean drawCard = true; + if(0 < getDredge().size()) + { + String choices[] = {"Yes", "No"}; + Object o = AllZone.Display.getChoice("Do you want to dredge?", choices); + if(o.equals("Yes")) + { + drawCard = false; + Card c = (Card) AllZone.Display.getChoice("Select card to dredge", getDredge().toArray()); + + //might have to make this more sophisticated + //dredge library, put card in hand + AllZone.Human_Hand.add(c); + AllZone.Human_Graveyard.remove(c); + + for(int i = 0; i < getDredgeNumber(c); i++) + { + Card c2 = AllZone.Human_Library.get(0); + AllZone.Human_Library.remove(0); + AllZone.Human_Graveyard.add(c2); + } + } + }//if(0 < getDredge().size()) + + if(drawCard) + AllZone.GameAction.drawCard(Constant.Player.Human); + + if(AllZone.Phase.getPhase().equals(Constant.Phase.Draw)) + { + Input_Main.canPlayLand = true; + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(from Input_Draw on human's draw) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + else + stop(); + } + } //end necro check + + public ArrayList getDredge() + { + ArrayList dredge = new ArrayList(); + Card c[] = AllZone.Human_Graveyard.getCards(); + + for(int outer = 0; outer < c.length; outer++) + { + ArrayList a = c[outer].getKeyword(); + for(int i = 0; i < a.size(); i++) + if(a.get(i).toString().startsWith("Dredge")) + { + if(AllZone.Human_Library.size() >= getDredgeNumber(c[outer])) + dredge.add(c[outer]); + } + } + return dredge; + }//hasDredge() + public int getDredgeNumber(Card c) + { + ArrayList a = c.getKeyword(); + for(int i = 0; i < a.size(); i++) + if(a.get(i).toString().startsWith("Dredge")) + { + String s = a.get(i).toString(); + return Integer.parseInt("" +s.charAt(s.length() -1)); + } + + throw new RuntimeException("Input_Draw : getDredgeNumber() card doesn't have dredge - " +c.getName()); + }//getDredgeNumber() + } \ No newline at end of file diff --git a/src/Input_EOT.java b/src/Input_EOT.java new file mode 100644 index 00000000000..75892c28f55 --- /dev/null +++ b/src/Input_EOT.java @@ -0,0 +1,32 @@ +public class Input_EOT extends Input +{ + private static final long serialVersionUID = 5765929456837761648L; + + public void showMessage() + { + updateGUI(); + + ButtonUtil.enableOnlyOK(); + //String phase = AllZone.Phase.getPhase(); // unused + //String player = AllZone.Phase.getActivePlayer(); // unused + AllZone.Display.showMessage("Computer's End of Turn - Play Instants and Abilities"); + } + public void selectButtonOK() + { + updateGUI(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(Input_EOT.selectButtonOK) = true; note, this has not been tested, did it work?"); + AllZone.Phase.setNeedToNextPhase(true); + } + public void selectCard(Card card, PlayerZone zone) + { + InputUtil.playInstantAbility(card, zone); + }//selectCard() + private void updateGUI() + { + AllZone.Computer_Play.updateObservers(); + AllZone.Human_Play.updateObservers(); + AllZone.Human_Hand.updateObservers(); + } +} \ No newline at end of file diff --git a/src/Input_FirstStrikeDamage.java b/src/Input_FirstStrikeDamage.java new file mode 100644 index 00000000000..0db1553aafe --- /dev/null +++ b/src/Input_FirstStrikeDamage.java @@ -0,0 +1,189 @@ +import java.util.ArrayList; + +//import java.util.ArrayList; //unused + +public class Input_FirstStrikeDamage extends Input +{ + private static final long serialVersionUID = 6527794462455208533L; + + public Input_FirstStrikeDamage() + { + AllZone.Combat.verifyCreaturesInPlay(); + AllZone.pwCombat.verifyCreaturesInPlay(); + + CombatUtil.showCombat(); + } + + public void showMessage() + { + ButtonUtil.enableOnlyOK(); + AllZone.Display.showMessage("First Strike Combat Damage is on the stack - Play Instants and Abilities"); + } + public void selectButtonOK() + { + damageCreatureAndPlayer(); + + AllZone.GameAction.checkStateEffects(); + + //AllZone.Combat.reset(); + AllZone.Display.showCombat(""); + + //do normal combat damage now and then switch to next phase (combat damage dealt - play instants and abilities) + AllZone.Combat.setAssignedDamage(); + AllZone.pwCombat.setAssignedDamage(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(Input_Block_Instant.selectButtonOK) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + public void selectCard(Card card, PlayerZone zone) + { + InputUtil.playInstantAbility(card, zone); + }//selectCard() + @SuppressWarnings("unused") // playerDamage +private void playerDamage(PlayerLife p) + { + int n = p.getAssignedDamage(); + p.setAssignedDamage(0); + p.subtractLife(n); + } + + //moves assigned damage to damage for all creatures + //deals damage to player if needed + private void damageCreatureAndPlayer() + { + String player = AllZone.Combat.getDefendingPlayer(); + if (player.equals("")) //this is a really bad hack, to allow raging goblin to attack on turn 1 + player = Constant.Player.Computer; + PlayerLife life = AllZone.GameAction.getPlayerLife(player); + life.subtractLife(AllZone.Combat.getDefendingFirstStrikeDamage()); + + //What is this even for? doesn't look like it's used. + /* + life = AllZone.GameAction.getPlayerLife(AllZone.Combat.getAttackingPlayer()); + life.subtractLife(AllZone.Combat.getAttackingDamage()); + life.subtractLife(AllZone.pwCombat.getAttackingDamage()); + */ + CardList unblocked = new CardList(AllZone.Combat.getUnblockedFirstStrikeAttackers()); + for(int j = 0; j < unblocked.size(); j++) + { + //System.out.println("Unblocked Creature: " +unblocked.get(j).getName()); + GameActionUtil.executePlayerCombatDamageEffects(unblocked.get(j)); + + /*if (unblocked.get(j).getKeyword().contains("Lifelink")) + { + + } + */ + } + + CardList attackers = new CardList(AllZone.Combat.getAttackers()); + CardList blockers = new CardList(AllZone.Combat.getAllBlockers().toArray()); + + + for (int i=0; i < attackers.size(); i++){ + //System.out.println("attacker #" + i + ": " + attackers.getCard(i).getName() +" " + attackers.getCard(i).getAttack()); + + CardList defend = AllZone.Combat.getBlockers(attackers.getCard(i)); + ArrayList list = attackers.getCard(i).getKeyword(); + + + if ((attackers.getCard(i).hasFirstStrike() || attackers.getCard(i).hasDoubleStrike())) + { + if (attackers.getCard(i).getKeyword().contains("Lifelink")) + { + GameActionUtil.executeLifeLinkEffects(attackers.getCard(i)); + } + + for(int j=0; j < CardFactoryUtil.hasNumberEnchantments(attackers.getCard(i), "Guilty Conscience"); j++) + GameActionUtil.executeGuiltyConscienceEffects(attackers.getCard(i)); + /* + + //old stuff: gain life for each instance of lifelink + for (int j=0; j < list.size(); j++) + { + if (list.get(j).equals("Lifelink")) + GameActionUtil.executeLifeLinkEffects(attackers.getCard(i)); + + } + */ + } + + //not sure if this will work correctly with multiple blockers? + int defenderToughness = 0; + for (int k=0; k tappedLand = new ArrayList(); + private final SpellAbility spell; + + public Input_PayManaCost(SpellAbility sa) + { + originalManaCost = sa.getManaCost(); + originalCard = sa.getSourceCard(); + + spell = sa; + manaCost = new ManaCost(sa.getManaCost()); + } + private void resetManaCost() + { + manaCost = new ManaCost(originalManaCost); + } + public void selectCard(Card card, PlayerZone zone) + { + //this is a hack, to prevent lands being able to use mana to pay their own abilities from cards like + //Kher Keep, Pendelhaven, Blinkmoth Nexus, and Mikokoro, Center of the Sea, .... + /*if (originalCard.equals(card) && !card.getName().equals("Oboro, Palace in the Clouds"))*/ + if (originalCard.equals(card) && spell.isTapAbility()) + { + return; + //originalCard.tap(); + } + boolean canUse = false; + for (Ability_Mana am : card.getManaAbility()) + canUse |= am.canPlay(); + manaCost = Input_PayManaCostUtil.tapCard(card, manaCost); + showMessage(); + + if(manaCost.isPaid()) + done(); + } + private void done() + { + AllZone.ManaPool.paid(); + resetManaCost(); + + //if tap ability, tap card + if(spell.isTapAbility()) + originalCard.tap(); + + //this seems to remove a card if it is in the player's hand + //and trys to remove abilities, but no error messsage is generated + AllZone.Human_Hand.remove(originalCard); + + if (spell.getAfterPayMana() != null) + stopSetNext(spell.getAfterPayMana()); + else + { + AllZone.Stack.add(spell); + stopSetNext(new ComputerAI_StackNotEmpty()); + } + } + public void selectButtonCancel() + { + resetManaCost(); + AllZone.ManaPool.unpaid(); + AllZone.Human_Play.updateObservers();//DO NOT REMOVE THIS, otherwise the cards don't always tap + + stop(); + } + public void showMessage() + { + //if(manaCost.toString().equals("")) + + ButtonUtil.enableOnlyCancel(); + AllZone.Display.showMessage("Pay Mana Cost: " +manaCost.toString()); + } +} \ No newline at end of file diff --git a/src/Input_PayManaCostUtil.java b/src/Input_PayManaCostUtil.java new file mode 100644 index 00000000000..a9c43d63a59 --- /dev/null +++ b/src/Input_PayManaCostUtil.java @@ -0,0 +1,83 @@ +import java.util.*; + +public class Input_PayManaCostUtil +{ + //all mana abilities start with this and typical look like "tap: add G" + //mana abilities are Strings and are retreaved by calling card.getKeyword() + //taps any card that has mana ability, not just land + public static ManaCost tapCard(Card card, ManaCost manaCost) + { + if(card instanceof ManaPool) return ((ManaPool)card).subtractMana(manaCost); + ArrayList abilities = getManaAbilities(card); + + String cneeded=""; + for(String color : Constant.Color.Colors) + if(manaCost.isNeeded(color)) + cneeded+=getColor2(color); + Iterator it = abilities.iterator();//you can't remove unneded abilitie inside a for(am:abilities) loop :( + while(it.hasNext()) + { + Ability_Mana ma = it.next(); + if (!ma.canPlay()){ it.remove(); continue;} + if (cneeded.contains("1")) break; + boolean needed = false; + String[] canMake = ManaPool.getManaParts(ma); + for(String color : canMake) + if(cneeded.contains(color)) needed = true; + if (!needed) it.remove(); + } + if(abilities.isEmpty()) + return manaCost; + //String color; + Ability_Mana chosen = abilities.get(0); + if(1 < abilities.size()) + { + HashMap ability = new HashMap(); + for(Ability_Mana am : abilities) + ability.put(am.toString(), am); + chosen = (Ability_Mana) AllZone.Display.getChoice("Choose mana ability", abilities.toArray()); + } + { + AllZone.GameAction.playSpellAbility(chosen); + manaCost = AllZone.ManaPool.subtarctMana(manaCost, chosen); + AllZone.Human_Play.updateObservers();//DO NOT REMOVE THIS, otherwise the cards don't always tap (copied) + return manaCost; + } + } + public static ArrayList getManaAbilities(Card card) + {return card.getManaAbility();} + //color is like "G", returns "Green" + public static String getColor(String color) + { + Map m = new HashMap(); + m.put("G", Constant.Color.Green); + m.put("R", Constant.Color.Red); + m.put("U", Constant.Color.Blue); + m.put("B", Constant.Color.Black); + m.put("W", Constant.Color.White); + + Object o = m.get(color); + + if(o == null) + o = Constant.Color.Colorless; + + + return o.toString(); + } + + public static String getColor2(String color) + { + Map m = new HashMap(); + m.put(Constant.Color.Green, "G"); + m.put(Constant.Color.Red, "R"); + m.put(Constant.Color.Blue, "U"); + m.put(Constant.Color.Black, "B"); + m.put(Constant.Color.White, "W"); + m.put(Constant.Color.Colorless, "1"); + + Object o = m.get(color); + + return o.toString(); + } + +} diff --git a/src/Input_PayManaCost_Ability.java b/src/Input_PayManaCost_Ability.java new file mode 100644 index 00000000000..9c31f63c907 --- /dev/null +++ b/src/Input_PayManaCost_Ability.java @@ -0,0 +1,73 @@ +//import java.util.*; + +//if cost is paid, Command.execute() is called +public class Input_PayManaCost_Ability extends Input +{ + private static final long serialVersionUID = 3836655722696348713L; + + private String originalManaCost; + private ManaCost manaCost; + //private ArrayList tappedLand = new ArrayList(); + + private Command paidCommand; + private Command unpaidCommand; + @SuppressWarnings("unused") // isPaid + private boolean isPaid; + + //for Abilities that don't tap + public Input_PayManaCost_Ability(String manaCost, Command paid) + { + this(manaCost, paid, Command.Blank); + } + + //Command must set InputState, by calling AllZone.Input.selectState() + //or AllZone.Input.setState() with new InputState + public Input_PayManaCost_Ability(String manaCost_2, Command paidCommand_2, Command unpaidCommand_2) + { + originalManaCost = manaCost_2; + + manaCost = new ManaCost(originalManaCost); + paidCommand = paidCommand_2; + unpaidCommand = unpaidCommand_2; + } + public void resetManaCost() + { + manaCost = new ManaCost(originalManaCost); + } + public void selectCard(Card card, PlayerZone zone) + { + //tappedLand.add(card); + + //only tap card if the mana is needed + manaCost = Input_PayManaCostUtil.tapCard(card, manaCost); + showMessage(); + + if(manaCost.isPaid()) + { + resetManaCost(); + //(was) VERY IMPORTANT, otherwise land can be "magical" untapped + //tappedLand.clear(); + AllZone.ManaPool.paid(); + + //Command MUST BE AFTER, for Urborg Syphon-Mage - tap, mana, discard abilit + stopSetNext(new ComputerAI_StackNotEmpty()); + paidCommand.execute(); + } + + } + + public void selectButtonCancel() + { + resetManaCost(); + AllZone.ManaPool.unpaid(); + unpaidCommand.execute(); + stop(); + } + public void showMessage() + { + ButtonUtil.enableOnlyCancel(); + AllZone.Display.showMessage("Pay Mana Cost: \r\n" +manaCost.toString()); + } + + +} \ No newline at end of file diff --git a/src/Input_StackNotEmpty.java b/src/Input_StackNotEmpty.java new file mode 100644 index 00000000000..b9e4a5d4b5e --- /dev/null +++ b/src/Input_StackNotEmpty.java @@ -0,0 +1,72 @@ +public class Input_StackNotEmpty extends Input implements java.io.Serializable +{ + private static final long serialVersionUID = -3015125043127874730L; + + public void showMessage() + { + updateGUI(); + + ButtonUtil.enableOnlyOK(); + String phase = AllZone.Phase.getPhase(); + String player = AllZone.Phase.getActivePlayer(); + AllZone.Display.showMessage("Spells or Abilities on are on the Stack\nPhase: " +phase +", Player: " +player); + } + public void selectButtonOK() + { + updateGUI(); + + SpellAbility sa = AllZone.Stack.pop(); + Card c = sa.getSourceCard(); + + if (sa.getSourceCard().getKeyword().contains("Cantrip")) + AllZone.GameAction.drawCard(sa.getSourceCard().getController()); + + + final Card crd = c; + if (sa.isBuyBackAbility()) + { + c.addReplaceMoveToGraveyardCommand(new Command() { + private static final long serialVersionUID = -2559488318473330418L; + + public void execute() { + PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, crd.getController()); + AllZone.GameAction.moveTo(hand, crd); + } + }); + } + + sa.resolve(); + AllZone.GameAction.checkStateEffects(); + + //special consideration for "Beacon of Unrest" and other "Beacon" cards + if((c.isInstant() || c.isSorcery()) && + (! c.getName().startsWith("Beacon")) && + (! c.getName().startsWith("Pulse")) && + !AllZone.GameAction.isCardRemovedFromGame(c)) //hack to make flashback work + { + if (c.getReplaceMoveToGraveyard().size() == 0) + AllZone.GameAction.moveToGraveyard(c); + else + c.replaceMoveToGraveyard(); + } + + + //update all zones, something things arent' updated for some reason + AllZone.Human_Hand.updateObservers(); + AllZone.Human_Play.updateObservers(); + AllZone.Computer_Play.updateObservers(); + + if(AllZone.InputControl.getInput() == this) + AllZone.InputControl.resetInput(); + } + public void selectCard(Card card, PlayerZone zone) + { + InputUtil.playInstantAbility(card, zone); + }//selectCard() + private void updateGUI() + { + AllZone.Computer_Play.updateObservers(); + AllZone.Human_Play.updateObservers(); + AllZone.Human_Hand.updateObservers(); + } +} \ No newline at end of file diff --git a/src/Input_Untap.java b/src/Input_Untap.java new file mode 100644 index 00000000000..44e3c8dba91 --- /dev/null +++ b/src/Input_Untap.java @@ -0,0 +1,56 @@ +public class Input_Untap extends Input +{ + private static final long serialVersionUID = 3452595801560263386L; + + public void showMessage() + { + GameActionUtil.executeUpkeepEffects(); + + PlayerZone p = AllZone.getZone(Constant.Zone.Play, AllZone.Phase.getActivePlayer()); + Card[] c = p.getCards(); + + for(int i = 0; i < c.length; i++) + c[i].setSickness(false); + + if(isMarbleTitanInPlay()) + marbleUntap(); + else + regularUntap(); + + //otherwise land seems to stay tapped when it is really untapped + AllZone.Human_Play.updateObservers(); + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(Input_Untap) = true"); + AllZone.Phase.setNeedToNextPhase(true); + } + private void marbleUntap() + { + PlayerZone p = AllZone.getZone(Constant.Zone.Play, AllZone.Phase.getActivePlayer()); + Card[] c = p.getCards(); + + for(int i = 0; i < c.length; i++) + if(c[i].getNetAttack() < 3) + c[i].untap(); + } + private boolean isMarbleTitanInPlay() + { + CardList all = new CardList(); + all.addAll(AllZone.Human_Play.getCards()); + all.addAll(AllZone.Computer_Play.getCards()); + + all = all.getName("Marble Titan"); + return all.size() > 0; + } + private void regularUntap() + { + PlayerZone p = AllZone.getZone(Constant.Zone.Play, AllZone.Phase.getActivePlayer()); + Card[] c = p.getCards(); + + for(int i = 0; i < c.length; i++) + { + if(!c[i].getKeyword().contains("This card does not untap during your untap phase.")) + c[i].untap(); + } + }//regularUntap() +} \ No newline at end of file diff --git a/src/KeyListenerTest.java b/src/KeyListenerTest.java new file mode 100644 index 00000000000..e7eb3ad66ab --- /dev/null +++ b/src/KeyListenerTest.java @@ -0,0 +1,29 @@ +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +public class KeyListenerTest implements KeyListener +{ + +public void keyPressed(KeyEvent arg0) +{ + int code = arg0.getKeyCode(); + + if(code == KeyEvent.VK_ENTER) + { + //Do something here + System.out.println("You pressed enter"); + } + +} +public void keyReleased(KeyEvent arg0) +{ + // TODO Auto-generated method stub + +} +public void keyTyped(KeyEvent arg0) +{ + // TODO Auto-generated method stub + +} + +} \ No newline at end of file diff --git a/src/MagicStack.java b/src/MagicStack.java new file mode 100644 index 00000000000..01a6c8f6f56 --- /dev/null +++ b/src/MagicStack.java @@ -0,0 +1,61 @@ +import java.util.*; + +public class MagicStack extends MyObservable +{ + private ArrayList stack = new ArrayList(); + + public void reset() + { + stack.clear(); + this.updateObservers(); + } + + public void add(SpellAbility sp) + { + if(sp instanceof Ability_Mana) sp.resolve(); else + push(sp); + } + public int size() + { + return stack.size(); + } + public void push(SpellAbility sp) + { + stack.add(0, sp); + this.updateObservers(); + if(sp.isSpell()) + { + //put code for Standstill here + GameActionUtil.executePlayCardEffects(sp); + //attempt to counter human spell + if (sp.getSourceCard().getController().equals(Constant.Player.Human) && + CardFactoryUtil.isCounterable(sp.getSourceCard()) ) + ComputerAI_counterSpells.counter_Spell(sp); + } + } + public SpellAbility pop() + { + + SpellAbility sp = (SpellAbility) stack.remove(0); + this.updateObservers(); + return sp; + } + //index = 0 is the top, index = 1 is the next to top, etc... + public SpellAbility peek(int index) + { + return (SpellAbility) stack.get(index); + } + public SpellAbility peek() + { + return peek(0); + } + public ArrayList getSourceCards() + { + ArrayList a = new ArrayList(); + Iterator it = stack.iterator(); + while(it.hasNext()) + a.add(((SpellAbility)it.next()).getSourceCard()); + + return a; + } +} diff --git a/src/ManaCost.java b/src/ManaCost.java new file mode 100644 index 00000000000..409e435fe8f --- /dev/null +++ b/src/ManaCost.java @@ -0,0 +1,76 @@ +//import java.util.*; //unused + + +//this is just a wrapper for Mana_PayCost +//it was easier to change this than to update a bunch of stuff +class ManaCost +{ + private Mana_PayCost m; + + public ManaCost(String cost) + { + m = new Mana_PayCost(cost); + } + + public boolean isPaid() + { + return m.isPaid(); + } + public String toString() + { + return m.toString(); + } + + public void subtractMana(String color) + { + color = getShortManaString(color); + m.addMana(color); + } + + //convert "white" to "W" + //convert "colorless" to "1" for Mana_PartColorless + private String getShortManaString(String longManaString) + { + String s = longManaString; + if(s.equals(Constant.Color.White)) + return "W"; + if(s.equals(Constant.Color.Black)) + return "B"; + if(s.equals(Constant.Color.Blue)) + return "U"; + if(s.equals(Constant.Color.Green)) + return "G"; + if(s.equals(Constant.Color.Red)) + return "R"; + if(s.equals(Constant.Color.Colorless)) + return "1"; + else if((s.equals("G") || s.equals("U") || s.equals("W") || + s.equals("B") || s.equals("R") || s.equals("1"))) + return s; + + throw new RuntimeException("ManaCost : getShortManaString() invalid argument - " +longManaString); + }//getShortManaString() + + public boolean isNeeded(String color) + { + color = getShortManaString(color); + return m.isNeeded(color); + } + +/* + public int getColor(String color) + { + return (int)Math.abs(manaPool.getColor(color)); + } + public boolean isNeeded(String color) + { + int a = getColor(color); + int b = getColor(Constant.Color.Colorless); + + if(0 < a || 0 < b) + return true; + + return false; + } + */ +}//ManaCost diff --git a/src/ManaPool.java b/src/ManaPool.java new file mode 100644 index 00000000000..5870cfd1b1a --- /dev/null +++ b/src/ManaPool.java @@ -0,0 +1,320 @@ +import java.util.ArrayList; +import java.util.Arrays; + + +public class ManaPool extends Card +{ + private ArrayList used = new ArrayList(); + boolean[] spendAsCless ={true,true,true,true,true,true}; + boolean spendAll = true; + private int cIndex(String s) + { + //String c =(s.length()==1 ? s : Input_PayManaCostUtil.getColor2(s)); + if(s.length()!=1) throw new IllegalArgumentException(s + "isn't an indexable single character."); + if(!colors.contains(s)) return 0; + return colors.indexOf(s) + 1; + } + private String indexC(int index) + { + if (index == 0) return "1"; + return colors.charAt(index - 1) + ""; + } + private void updateKeywords() + { + extrinsicKeyword.clear(); + for(int val=0;val<6;val++) + for(int i=0; i < has[val]; i++) + extrinsicKeyword.add("ManaPool:" + indexC(val)); + } + private ArrayList extrinsicKeyword = new ArrayList(); + public ArrayList getExtrinsicKeyword() {return new ArrayList(extrinsicKeyword);} + public void setExtrinsicKeyword(ArrayList a) + { + extrinsicKeyword = new ArrayList(a); + Arrays.fill(has, 0); + for(String Manaword : extrinsicKeyword) + if (Manaword.startsWith("ManaPool:")) + { + String[] cost=Manaword.split(":"); + if (cost[1].length() == 1) has[cIndex(cost[1])]++; + } + this.updateObservers(); + } + public void addExtrinsicKeyword(String s) + { + if (s.startsWith("ManaPool:")) + { + extrinsicKeyword.add(s); + addMana(s.split(":")[1]); + } + } + public void removeExtrinsicKeyword(String s) + { + if (s.startsWith("ManaPool:")) + { + updateKeywords(); + extrinsicKeyword.remove(s); + subtractOne(s.split(":")[1]); + this.updateObservers(); + } + } + public int getExtrinsicKeywordSize() {updateKeywords(); return extrinsicKeyword.size(); } + + public ManaPool(String contents){this(); this.addMana(contents);} + public ManaPool() + { + super(); + setName("Mana Pool"); + addIntrinsicKeyword("Shroud"); + addIntrinsicKeyword("Indestructible"); + clear(); + } + public String getText() + { + empty = true; + String res="Mana available:\r\n"; + if(has[0]>0) {res+=Integer.toString(has[0]); empty = false;} + for(int j=0; j 0) {res+="("+Integer.toString(n)+")"; empty = false;} + } + if (empty) res+="None"; + return res; + } + + public final static String colors = "WUBRG"; + private boolean empty = false; + private int[] paid= new int[6]; + private int[] has = new int[6]; + + public static String oraclize(String manaCost){ + if(!manaCost.contains(" ")) return manaCost; + String[] parts = manaCost.split(" "); + String res=""; + for (String s : parts) + { + if (s.length()==2 && colors.contains(s.charAt(1) + "")) s=s.charAt(0)+"/"+s.charAt(1); + if (s.length()==3) s="(" + s + ")"; + if (s.equals("S")) s="(S)";//for if/when we implement snow mana + if (s.equals("X")) s="(X)";//X costs? + res +=s; + } + return res; + } + public ArrayList getColors() + { + ArrayList mana = new ArrayList(); + for(int i = 1; i <= 5; i++) + { + if (has[i]>0) + mana.add(Input_PayManaCostUtil.getColor(colors.charAt(i-1)+"")); + } + if(has[0]>0) mana.add(Constant.Color.Colorless); + return mana; + } + public void addMana(Ability_Mana am){addMana(!am.Mana().contains("X") ? am.Mana() : am.Mana().replaceAll("X", am.getX()+""));} + public void addMana(String mana){ + if (mana.length()<=1) {addOne(mana); return;} + String[] cost=mana.split(""); + String Colorless = ""; + int cless = 0; + for(String s : cost) + { + if(s.trim().equals("")) continue;//mana.split gave me a "" for some reason + if(colors.contains(s)) + { + has[colors.indexOf(s) + 1]++; + if (!Colorless.trim().equals("")) + { + try{ + cless+= Integer.parseInt(Colorless); + Colorless=""; + }catch(NumberFormatException ex) + { + throw new RuntimeException("Mana_Pool : Error, noncolor mana cost is not a number - " +Colorless); + } + } + } + else Colorless+=s; + } + has[0]+=cless; + } + public void addOne(String Mana) + { + if(Mana.trim().equals("")) return; + int cInt = cIndex(Mana); + if(cInt > 0) + has[cInt]++; + else try + { + has[cInt]+= Integer.parseInt(Mana); + } + catch(NumberFormatException ex) + { + throw new RuntimeException("Mana_Pool.AddOne : Error, noncolor mana cost is not a number - " + Mana); + } + } + + public static String[] getManaParts(Ability_Mana manaAbility){return getManaParts(manaAbility.Mana());}//wrapper + public static String[] getManaParts(String Mana_2)//turns "G G" -> {"G","G"}, "2 UG"->"{"2","U/G"}, "B W U R G" -> {"B","W","U","R","G"}, etc. + { + String Mana=Mana_2; + //if (Mana.isEmpty()) return null; + if (Mana.trim().equals("")) return null; + Mana=oraclize(Mana); + try + { + String[] Colorless = {Integer.parseInt(Mana)+""}; + return Colorless; + } + catch(NumberFormatException ex) {} + + ArrayList res= new ArrayList(); + int Colorless = 0; + String clessString = ""; + boolean parentheses=false; + String current=""; + + for(int i=0; i + "/" + + ")") + else if(parentheses){ + if(c!=')') {current+=c; continue;} + else { + parentheses=false; + res.add(current); + current=""; + continue; + } + } + String s = c+""; + if(colors.contains(s)) + { + res.add(s); + if(clessString.trim().equals("")) continue; + try + { + Colorless += Integer.parseInt(clessString); + } + catch(NumberFormatException ex) + { + throw new RuntimeException("Mana_Pool.getManaParts : Error, sum of noncolor mana parts is not a number - " + clessString); + } + clessString = ""; + } + else clessString+=s; + } + if(Colorless > 0) res.add(0, Colorless+""); + return res.toArray(new String[0]); + } + public ManaCost subtractMana(ManaCost m){ + spendAll = true; + String mana = oraclize(m.toString()); + if (empty || mana.equals(null)) return m; + if (mana.length()==1) + { + m=subtractOne(m,mana); + return m; + } + String[] cost=getManaParts(m.toString()+""); + for(String s : cost) + m=subtractOne(m, s); + return m; + } + public ManaCost subtarctMana(ManaCost m, Ability_Mana mability) + { + used.add(mability); + for(String c : getManaParts(mability)) + { + if(c.equals("")) continue; // some sort of glitch + subtractOne(m, c); + } + return m; + } + public void subtractOne(String Mana){subtractOne(new ManaCost(Mana),Mana);} + public ManaCost subtractOne(ManaCost manaCost, String Mana) + { + if(Mana.trim().equals("")||manaCost.toString().trim().equals("")) return manaCost; + if(cIndex(Mana) >0 ) + { + if(!manaCost.isNeeded(Mana) || has[cIndex(Mana)]==0) return manaCost; + manaCost.subtractMana(Input_PayManaCostUtil.getColor(Mana)); + has[cIndex(Mana)]--; + paid[cIndex(Mana)]++; + } + else + { + int cless; + try + { + cless = Integer.parseInt(Mana); + } + catch(NumberFormatException ex) + { + throw new RuntimeException("Mana_Pool.SubtractOne : Error, noncolor mana cost is not a number - " + Mana); + } + if (cless == 0) return manaCost; + if (cless == 1) + if(1<=has[0] && manaCost.isNeeded(Constant.Color.Colorless)){ + has[0]--; + paid[0]++; + manaCost.subtractMana(Constant.Color.Colorless); + return manaCost; + } + if(cless>totalMana()) {manaCost=subtractOne(manaCost,totalMana()+""); return manaCost;} + while(totalMana()>0 && cless>0 && !colors.contains(manaCost.toString().split(" ")[0]))// we're paying with colorless mana + { + if (has[0]>0){manaCost=subtractOne(manaCost,"1"); cless--; continue;} + String chosen; + String [] choices=getColors().toArray(new String[0]); + chosen=choices[0]; + if (getColors().size()> 1) + chosen = (String)AllZone.Display.getChoiceOptional("Choose mana to spend as colorless", choices); + if (chosen == null) {spendAll = false; return manaCost;} + manaCost=subtractOne(manaCost,Input_PayManaCostUtil.getColor2(chosen)); + cless--; + } + } + return manaCost; + } + + public int hasMana(String color){ + String s =(color.length()==1? color : Input_PayManaCostUtil.getColor2(color)); + Mana_Part.checkSingleMana(s); + return(has[cIndex(s)]); + } + public int totalMana(){ + int res = 0; + for (int n : has) + res += n; + return res; + } + public void clear(){ + used.clear(); + Arrays.fill(paid, 0); + Arrays.fill(has, 0); + } + public void paid(){ + used.clear(); + Arrays.fill(paid, 0); + } + public void unpaid(){ + if (!used.isEmpty()) + { + for (Ability_Mana am : used) + { + if (am.undoable()) + { + paid[cIndex(am.Mana())]--; + am.undo(); + } + } + + } + for(int i = 0; i < 6; i++) + has[i]+=paid[i]; + paid(); + } + +} \ No newline at end of file diff --git a/src/Mana_Part.java b/src/Mana_Part.java new file mode 100644 index 00000000000..9ef02e04da9 --- /dev/null +++ b/src/Mana_Part.java @@ -0,0 +1,17 @@ +public abstract class Mana_Part +{ + abstract public String toString(); + abstract public void reduce(String mana); + abstract public boolean isPaid(); + abstract public boolean isNeeded(String mana); + + public static void checkSingleMana(String m) + { + if (m.length() != 1) + throw new RuntimeException("Mana_Part : checkMana() error, argument mana is not of length 1, mana - " + m); + + if (!(m.equals("G") || m.equals("U") || m.equals("W") || + m.equals("B") || m.equals("R") || m.equals("1"))) + throw new RuntimeException("Mana_Part : checkMana() error, argument mana is invalid mana, mana - " + m); + } +} diff --git a/src/Mana_PartColor.java b/src/Mana_PartColor.java new file mode 100644 index 00000000000..b2c93fd46ba --- /dev/null +++ b/src/Mana_PartColor.java @@ -0,0 +1,44 @@ +public class Mana_PartColor extends Mana_Part +{ + private String manaCost; + + //String manaCostToPay is either "G" or "GW" NOT "3 G" + //ManaPartColor only needs 1 mana in order to be paid + //GW means it will accept either G or W like Selesnya Guildmage + public Mana_PartColor(String manaCostToPay) + { + char[] c = manaCostToPay.toCharArray(); + for(int i = 0; i < c.length; i++) { + if (i == 0 && c[i] == ' ') + ; + else + checkSingleMana("" +c[i]); + } + + manaCost = manaCostToPay; + } + public String toString() + { + return manaCost; + } + public boolean isNeeded(String mana) + { + //ManaPart method + checkSingleMana(mana); + + int index = manaCost.indexOf(mana); + return index != -1; + } + public void reduce(String mana) + { + //if mana is needed, then this mana cost is all paid up + if(! isNeeded(mana)) + throw new RuntimeException("Mana_PartColor : reduce() error, argument mana not needed, mana - " +mana +", toString() - " +toString()); + + manaCost = ""; + } + public boolean isPaid() + { + return manaCost.length() == 0; + } +} diff --git a/src/Mana_PartColorless.java b/src/Mana_PartColorless.java new file mode 100644 index 00000000000..003303a70be --- /dev/null +++ b/src/Mana_PartColorless.java @@ -0,0 +1,43 @@ +public class Mana_PartColorless extends Mana_Part { + private int manaNeeded; + + //String manaCostToPay is like "1", "4", but NO COLOR + public Mana_PartColorless(String manaCostToPay) { + try { + manaNeeded = Integer.parseInt(manaCostToPay); + } catch(NumberFormatException ex) { + ErrorViewer.showError(ex, "mana cost is not a number - %s", manaCostToPay); + throw new RuntimeException(String.format("mana cost is not a number - %s", manaCostToPay), ex); + } + } + + @Override + public String toString() { + if(isPaid()) return ""; + + return String.valueOf(manaNeeded); + } + + @Override + public boolean isNeeded(String mana) { + //ManaPart method + checkSingleMana(mana); + + return 0 < manaNeeded; + } + + @Override + public void reduce(String mana) { + //if mana is needed, then this mana cost is all paid up + if(!isNeeded(mana)) + throw new RuntimeException("Mana_PartColorless : reduce() error, argument mana not needed, mana - " + + mana + ", toString() - " + toString()); + + manaNeeded--; + } + + @Override + public boolean isPaid() { + return manaNeeded == 0; + } +} diff --git a/src/Mana_PartSplit.java b/src/Mana_PartSplit.java new file mode 100644 index 00000000000..fd3b4cdd66f --- /dev/null +++ b/src/Mana_PartSplit.java @@ -0,0 +1,75 @@ +//handles mana costs like 2/R or 2/B +//for cards like Flame Javelin (Shadowmoor) +public class Mana_PartSplit extends Mana_Part +{ + private Mana_Part manaPart; + private String originalCost; + + public Mana_PartSplit(String manaCost) + { + //is mana cost like "2/R" + if(manaCost.length() != 3) + throw new RuntimeException("Mana_PartSplit : constructor() error, bad mana cost parameter - " +manaCost); + + originalCost = manaCost; + } + + private boolean isFirstTime() + { + return manaPart == null; + } + private void setup(String manaToPay) + { + //get R out of "2/R" + String color = originalCost.substring(2, 3); + + //is manaToPay the one color we want or do we + //treat it like colorless? + //if originalCost is 2/R and is color W (treated like colorless) + //or R? if W use Mana_PartColorless, if R use Mana_PartColor + //does manaToPay contain color? + if(0 <= manaToPay.indexOf(color)) + { + manaPart = new Mana_PartColor(color); + } + else + { + //get 2 out of "2/R" + manaPart = new Mana_PartColorless(originalCost.substring(0, 1)); + } + }//setup() + + public void reduce(String mana) + { + if(isFirstTime()) + setup(mana); + + manaPart.reduce(mana); + } + public boolean isNeeded(String mana) + { + if(isFirstTime()) + { + //always true because any mana can pay the colorless part of 2/G + return true; + } + + return manaPart.isNeeded(mana); + }//isNeeded() + + public String toString() + { + if(isFirstTime()) + return originalCost; + + return manaPart.toString(); + } + + public boolean isPaid() + { + if(isFirstTime()) + return false; + + return manaPart.isPaid(); + } +} \ No newline at end of file diff --git a/src/Mana_PartTest.java b/src/Mana_PartTest.java new file mode 100644 index 00000000000..da900998d86 --- /dev/null +++ b/src/Mana_PartTest.java @@ -0,0 +1,479 @@ +public class Mana_PartTest +{ + static void testPayManaCost() + { + { + //test constructor + @SuppressWarnings("unused") + Mana_PayCost p = new Mana_PayCost("G"); + p = new Mana_PayCost("U"); + p = new Mana_PayCost("W"); + p = new Mana_PayCost("R"); + p = new Mana_PayCost("B"); + p = new Mana_PayCost("0"); + p = new Mana_PayCost("1"); + p = new Mana_PayCost("2"); + p = new Mana_PayCost("3"); + p = new Mana_PayCost("4"); + p = new Mana_PayCost("5"); + p = new Mana_PayCost("6"); + p = new Mana_PayCost("7"); + p = new Mana_PayCost("8"); + p = new Mana_PayCost("9"); + p = new Mana_PayCost("10"); + + p = new Mana_PayCost("GW"); + p = new Mana_PayCost("1 G"); + p = new Mana_PayCost("1 GW"); + p = new Mana_PayCost("GW GW"); + p = new Mana_PayCost("GW GW GW"); + p = new Mana_PayCost("GW GW GW GW"); + + p = new Mana_PayCost("G G"); + p = new Mana_PayCost("G G G"); + p = new Mana_PayCost("G G G"); + p = new Mana_PayCost("G G G G"); + + p = new Mana_PayCost("2 GW GW GW"); + p = new Mana_PayCost("3 G G G"); + p = new Mana_PayCost("12 GW GW GW"); + p = new Mana_PayCost("11 G G G"); + + p = new Mana_PayCost("2/U"); + p = new Mana_PayCost("2/B 2/B"); + p = new Mana_PayCost("2/G 2/G 2/G"); + p = new Mana_PayCost("2/R 2/R 2/R 2/R"); + p = new Mana_PayCost("2/W 2/B 2/U 2/R 2/G"); + } + + { + Mana_PayCost p = new Mana_PayCost("2/U"); + + check(0.3, p.isNeeded("G")); + check(0.4, p.isNeeded("U")); + check(0.5, p.isNeeded("B")); + check(0.6, p.isNeeded("W")); + check(0.7, p.isNeeded("R")); + check(0.8, p.isNeeded("1")); + + p.addMana("U"); + check(0.9, p.isPaid()); + + check(0.91, !p.isNeeded("R")); + } + + + { + Mana_PayCost p = new Mana_PayCost("G"); + check(1, p.isNeeded("G")); + + check(1.1, !p.isNeeded("U")); + check(1.2, !p.isNeeded("B")); + check(1.3, !p.isNeeded("W")); + check(1.4, !p.isNeeded("R")); + check(1.5, !p.isNeeded("1")); + + p.addMana("G"); + check(2, p.isPaid()); + + check(2.1, !p.isNeeded("G")); + + } + + { + Mana_PayCost p = new Mana_PayCost("1"); + + check(3, p.isNeeded("G")); + check(4, p.isNeeded("U")); + check(5, p.isNeeded("B")); + check(6, p.isNeeded("W")); + check(7, p.isNeeded("R")); + check(8, p.isNeeded("1")); + + p.addMana("B"); + check(9, p.isPaid()); + + check(9.1, !p.isNeeded("R")); + } + + { + Mana_PayCost p = new Mana_PayCost("GW"); + + check(10, p.isNeeded("G")); + check(13, p.isNeeded("W")); + + check(11, !p.isNeeded("U")); + check(12, !p.isNeeded("B")); + check(14, !p.isNeeded("R")); + check(15, !p.isNeeded("1")); + + p.addMana("W"); + check(16, p.isPaid()); + + check(17, !p.isNeeded("W")); + } + + + { + Mana_PayCost p = new Mana_PayCost("BR"); + + check(17.1, p.isNeeded("B")); + check(17.2, p.isNeeded("R")); + + check(17.3, !p.isNeeded("U")); + check(17.4, !p.isNeeded("W")); + check(17.5, !p.isNeeded("G")); + check(17.6, !p.isNeeded("1")); + + p.addMana("R"); + check(17.7, p.isPaid()); + + check(17.8, !p.isNeeded("R")); + } + + + { + Mana_PayCost p = new Mana_PayCost("1 G G"); + + p.addMana("G"); + + check(18.1, p.isNeeded("G")); + check(18.2, p.isNeeded("W")); + check(18.3, p.isNeeded("U")); + check(18.4, p.isNeeded("B")); + check(18.5, p.isNeeded("R")); + check(18.6, p.isNeeded("1")); + + p.addMana("1"); + p.addMana("G"); + + check(18.7, p.isPaid()); + + check(18.8, !p.isNeeded("W")); + } + + { + Mana_PayCost p = new Mana_PayCost("0"); + + check(19.1, !p.isNeeded("1")); + check(19.2, !p.isNeeded("G")); + check(19.3, !p.isNeeded("U")); + + check(19.4, p.isPaid()); + + check(19.5, !p.isNeeded("R")); + } + + { + Mana_PayCost p = new Mana_PayCost("G G"); + + check(20.1, !p.isNeeded("1")); + check(20.2, p.isNeeded("G")); + + check(20.3, !p.isNeeded("U")); + + p.addMana("G"); + p.addMana("G"); + + check(20.4, p.isPaid()); + + check(20.5, !p.isNeeded("B")); + } + + { + Mana_PayCost p = new Mana_PayCost("G G G"); + + check(21.1, !p.isNeeded("W")); + check(21.2, p.isNeeded("G")); + + check(21.3, !p.isNeeded("R")); + + p.addMana("G"); + p.addMana("G"); + p.addMana("G"); + + check(21.4, p.isPaid()); + + check(21.5, !p.isNeeded("U")); + } + + { + Mana_PayCost p = new Mana_PayCost("G G G G"); + + check(22.1, !p.isNeeded("W")); + check(22.2, p.isNeeded("G")); + + check(22.3, !p.isNeeded("R")); + + p.addMana("G"); + p.addMana("G"); + p.addMana("G"); + p.addMana("G"); + + check(22.4, p.isPaid()); + + check(22.5, !p.isNeeded("G")); + } + + { + Mana_PayCost p = new Mana_PayCost("GW"); + + check(23.1, p.isNeeded("W")); + check(23.2, p.isNeeded("G")); + check(23.3, !p.isNeeded("R")); + + p.addMana("G"); + + check(23.4, p.isPaid()); + + check(23.5, !p.isNeeded("G")); + } + + { + Mana_PayCost p = new Mana_PayCost("GW"); + + check(24.1, p.isNeeded("W")); + check(24.2, p.isNeeded("G")); + check(24.3, !p.isNeeded("U")); + + p.addMana("W"); + + check(24.4, p.isPaid()); + + check(24.5, !p.isNeeded("W")); + } + + { + Mana_PayCost p = new Mana_PayCost("3 GW GW"); + + check(25.1, p.isNeeded("W")); + check(25.2, p.isNeeded("G")); + check(25.3, p.isNeeded("U")); + + p.addMana("1"); + p.addMana("1"); + p.addMana("1"); + + check(25.4, p.isNeeded("W")); + check(25.5, p.isNeeded("G")); + check(25.6, !p.isNeeded("U")); + + p.addMana("G"); + p.addMana("W"); + + check(25.7, p.isPaid()); + + check(25.8, !p.isNeeded("W")); + check(25.9, !p.isNeeded("G")); + check(25.10, !p.isNeeded("1")); + check(25.11, !p.isNeeded("R")); + } + + { + Mana_PayCost p = new Mana_PayCost("4"); + + check(26.1, p.isNeeded("W")); + check(26.2, p.isNeeded("G")); + check(26.3, p.isNeeded("U")); + + p.addMana("1"); + p.addMana("1"); + p.addMana("1"); + p.addMana("1"); + + check(26.4, p.isPaid()); + } + + { + Mana_PayCost p = new Mana_PayCost("10"); + + p.addMana("G"); + p.addMana("W"); + p.addMana("R"); + p.addMana("U"); + p.addMana("B"); + + p.addMana("1"); + + p.addMana("W"); + p.addMana("R"); + p.addMana("U"); + p.addMana("B"); + + check(27, p.isPaid()); + } + + { + Mana_PayCost p = new Mana_PayCost("12 G GW"); + + for (int i = 0; i < 12; i++) + p.addMana("R"); + + p.addMana("G"); + p.addMana("W"); + + check(28, p.isPaid()); + } + + { + Mana_PayCost p = new Mana_PayCost("2 W B U R G"); + + for (int i = 0; i < 1; i++) + p.addMana("R"); + + for (int i = 0; i < 2; i++) + p.addMana("1"); + + for (int i = 0; i < 1; i++) + { + p.addMana("G"); + p.addMana("W"); + p.addMana("B"); + p.addMana("U"); + + } + check(29, p.isPaid()); + } + + { + Mana_PayCost p = new Mana_PayCost("W B U R G W"); + + p.addMana("R"); + p.addMana("G"); + p.addMana("B"); + p.addMana("U"); + + p.addMana("W"); + p.addMana("W"); + + check(30, p.isPaid()); + } + + { + Mana_PayCost p = new Mana_PayCost("W B U R G W B U R G"); + + for (int i = 0; i < 2; i++) + { + p.addMana("W"); + p.addMana("R"); + p.addMana("G"); + p.addMana("B"); + p.addMana("U"); + } + + check(31, p.isPaid()); + } + + { + Mana_PayCost p = new Mana_PayCost("2 W B U R G W B U R G G"); + + for (int i = 0; i < 2; i++) + { + p.addMana("W"); + p.addMana("R"); + p.addMana("G"); + p.addMana("B"); + p.addMana("U"); + } + + p.addMana("1"); + p.addMana("1"); + p.addMana("G"); + + check(32, p.isPaid()); + } + + { + Mana_PayCost p = new Mana_PayCost("1 B R"); + + p.addMana("B"); + p.addMana("1"); + p.addMana("R"); + + check(33, p.isPaid()); + } + + { + Mana_PayCost p = new Mana_PayCost("B R"); + + p.addMana("B"); + p.addMana("R"); + + check(34, p.isPaid()); + } + + + { + Mana_PayCost p = new Mana_PayCost("2/B 2/B 2/B"); + + check(35, p.isNeeded("G")); + + p.addMana("B"); + check(36, p.toString().equals("2/B 2/B")); + + p.addMana("B"); + check(37, p.toString().equals("2/B")); + + p.addMana("B"); + check(38, p.isPaid()); + } + + + { + Mana_PayCost p = new Mana_PayCost("2/G"); + + p.addMana("1"); + check(39, p.toString().equals("1")); + + p.addMana("W"); + check(40, p.isPaid()); + } + + { + Mana_PayCost p = new Mana_PayCost("2/R 2/R"); + + p.addMana("1"); + check(41, p.toString().equals("2/R 1")); + + p.addMana("W"); + check(42, p.toString().equals("2/R")); + } + + { + Mana_PayCost p = new Mana_PayCost("2/W 2/W"); + + for(int i = 0; i < 4; i++) + { + check(43, p.isPaid() == false); + p.addMana("1"); + } + + check(44, p.isPaid()); + } + + } //testPayManaCost() + + + static void check(double n, boolean b) + { + if (!b) + System.out.println("failed : " + n); + } + + public static void main(String[] args) + { + try + { + +// magic.core.ErrorReport.setThrowException(true); + + testPayManaCost(); + System.out.println("all tests passed"); + } + catch (Exception ex) + { + System.out.println("failed : exception " + ex); + ex.printStackTrace(); + } + } +} diff --git a/src/Mana_PayCost.java b/src/Mana_PayCost.java new file mode 100644 index 00000000000..142e08311ef --- /dev/null +++ b/src/Mana_PayCost.java @@ -0,0 +1,123 @@ +import java.util.*; + +public class Mana_PayCost +{ + //holds Mana_Part objects + //ManaPartColor is stored before ManaPartColorless + private ArrayList manaPart; + +//manaCost can be like "0", "3", "G", "GW", "10", "3 GW", "10 GW" + //or "split hybrid mana" like "2/G 2/G", "2/B 2/B 2/B" + //"GW" can be paid with either G or W + + //can barely handle Reaper King mana cost "2/W 2/U 2/B 2/R 2/G" + //to pay the colored costs for Reaper King you have to tap the colored + //mana in the order shown from right to left (wierd I know) + //note that when the cost is displayed it is backward "2/G 2/R 2/B 2/U 2/W" + //so you would have to tap W, then U, then B, then R, then G (order matters) + public Mana_PayCost(String manaCost) + { + manaPart = split(manaCost); + } + public boolean isNeeded(String mana) + { + Mana_Part m; + for(int i = 0; i < manaPart.size(); i++) + { + m = (Mana_Part)manaPart.get(i); + if(m.isNeeded(mana)) + return true; + } + return false; + } + public boolean isPaid() + { + Mana_Part m; + for(int i = 0; i < manaPart.size(); i++) + { + m = (Mana_Part)manaPart.get(i); + if(! m.isPaid()) + return false; + } + return true; + }//isPaid() + + public void addMana(String mana) + { + if(! isNeeded(mana)) + throw new RuntimeException("Mana_PayCost : addMana() error, mana not needed - " +mana); + + Mana_Part m; + for(int i = 0; i < manaPart.size(); i++) + { + m = (Mana_Part)manaPart.get(i); + if(m.isNeeded(mana)) + { + m.reduce(mana); + break; + } + }//for + } + public String toString() + { + String s = ""; + ArrayList list = new ArrayList(manaPart); + //need to reverse everything since the colored mana is stored first + Collections.reverse(list); + + for(int i = 0; i < list.size(); i++) + s = s +" " +list.get(i).toString(); + + return s.trim(); + } + + private ArrayList split(String cost) + { + ArrayList list = new ArrayList(); + + //handles costs like "3", "G", "GW", "10" + if(cost.length() == 1 || cost.length() == 2) + { + if(Character.isDigit(cost.charAt(0))) + list.add(new Mana_PartColorless(cost)); + else + list.add(new Mana_PartColor(cost)); + } + else//handles "3 GW", "10 GW", "1 G G", "G G" + { + //all costs that have a length greater than 2 have a space + StringTokenizer tok = new StringTokenizer(cost); + + while(tok.hasMoreTokens()) + list.add(getManaPart(tok.nextToken())); + + //ManaPartColorless needs to be added AFTER the colored mana + //in order for isNeeded() and addMana() to work correctly + Object o = list.get(0); + if(o instanceof Mana_PartColorless) + { + //move colorless cost to the end of the list + list.remove(0); + list.add(o); + } + }//else + + return list; + }//split() + + private Mana_Part getManaPart(String partCost) + { + if(partCost.length() == 3) + { + return new Mana_PartSplit(partCost); + } + else if(Character.isDigit(partCost.charAt(0))) + { + return new Mana_PartColorless(partCost); + } + else + { + return new Mana_PartColor(partCost); + } + } +} diff --git a/src/MenuItem_HowToPlay.java b/src/MenuItem_HowToPlay.java new file mode 100644 index 00000000000..8c0a7e478b8 --- /dev/null +++ b/src/MenuItem_HowToPlay.java @@ -0,0 +1,160 @@ + + + + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + +public class MenuItem_HowToPlay extends JMenuItem implements NewConstants.LANG.HowTo { + private static final long serialVersionUID = 5552000208438248428L; + + public MenuItem_HowToPlay() { + super(ForgeProps.getLocalized(TITLE)); + + this.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent a) { + String text = ForgeProps.getLocalized(MESSAGE); + + JTextArea area = new JTextArea(text, 25, 40); + area.setWrapStyleWord(true); + area.setLineWrap(true); + area.setEditable(false); + + area.setOpaque(false); + + JOptionPane.showMessageDialog(null, new JScrollPane(area), ForgeProps.getLocalized(TITLE), + JOptionPane.INFORMATION_MESSAGE); + } + }); + }//constructor + + @SuppressWarnings("unused") + private String getString() { + String newLine = "\r\n\r\n"; + StringBuffer s = new StringBuffer(); + + s.append("How to Play - (Revised: September 2009.)\r\n\r\n\r\n"); + + s.append("Introduction" + newLine); + s.append("1. This game is similar to many other trading card games. You start out with 20 life and your goal is to reduce your opponents life to zero by attacking with your creatures. The game will end when your life or the computer's life is reduced to zero. You play \"matches\" against the computer as a set of \"best two out of three\" games." + + newLine); + s.append("2. You use land to pay for spells. You can play one land a turn." + newLine); + s.append("3. Each land produces a different magical energy. This magical energy is shortened to one letter on cards." + + newLine); + s.append(" Forests make G\r\n"); + s.append(" Swamps make B\r\n"); + s.append(" Plains make W\r\n"); + s.append(" Islands make U\r\n"); + s.append(" Mountains make R" + newLine); + s.append("4. Each non-land card has a name and a cost. The cost looks like this \"2GG\" A cost like that would require two Forest lands and two other lands. The number 2 can be paid for by any land. A cost like \"R\", would require a Mountain land." + + newLine); + s.append("5. Creature cards stay in play and can attack on the turn AFTER they are played. A creature's attack and defense is shown like 2/4 meaning that the creature has an attack power of 2 and a defense of 4. If this creature receives 4 damage it is put into the graveyard." + + newLine); + s.append("6. When you attack with your creatures the computer has a chance to block with his creatures. When you attack you \"tap\" your creatures by turning them sideways. Your creatures will untap during your next turn. When you block, only untapped creatures can block. Usually a creature cannot attack and block during the same turn." + + newLine); + s.append("7. Sorcery and Instant cards have an effect on the game. After you play any card it goes on the stack to the left, click OK and the stack will clear. Sorcery cards can only be played during your turn and when the stack is empty. Instant cards can be played at any time and are more versatile." + + newLine); + s.append("8. If a card has a target, you get to choose that target. If the target is a player, click on that player's life points." + + newLine); + s.append("9. When you mulligan, the cards in your hand are shuffled into you deck and you are given 1 less card.\r\n\r\n\r\n"); + + s.append("Legendary Cards" + newLine); + s.append("Legendary cards are powerful cards that can be either creatures, enchantments, lands, artifacts or planeswalkers. These cards can only exist once in the battlefield, and if another copy of the legendary card is played, all copies of the card are destroyed and sent to the graveyard.\r\n\r\n\r\n"); + + s.append("Planeswalkers" + newLine); + s.append("There are 6 planeswalkers (Ajani Goldmane; Liliana Vess; Garruk Wildspeaker; Chandra Nalaar; Nicol Bolas; Elspeth, Knight-Errant) and they have specific rules for their special abilities." + + newLine); + s.append("You can only use one ability a turn. A planeswalker can be attacked, but you can also block with your creatures. For each 1 damage a planeswalker receives, you remove 1 counter. When a planeswalker doesn't have any counters, it goes to the graveyard.\r\n\r\n\r\n"); + + s.append("Hybrid Mana and Multicolored Cards" + newLine); + s.append("1. Hybrid Mana Cards are unique in their casting cost as seen in the card. Instead of seeing a single color per mana symbol, these cards have 2 colors per mana symbol indicating that the player has the choice of playing either of the two. There are also cases where numbers and colors are combined together in one mana symbol, which indicates that either colorless or colored mana can be paid for each symbol. Hybrid cards are treated as two colors and as such can be said to be multicolored." + + newLine); + s.append("2. Multicolored Cards are slightly different than hybrid mana cards, as they require two or more different colors of mana, which may or not be in a single mana symbol. An example would be a card like Lightning Helix which requires one red and one white mana to be played.\r\n\r\n\r\n"); + + s.append("Game Types" + newLine); + s.append("1. In Constructed Deck mode you can use any of the cards to make your deck. To make a constructed deck, from the Deck Editor select \"New Deck – Constructed\". A list of all the cards will be displayed." + + newLine); + s.append("2. In Sealed Deck mode you are given 75 cards and you have to make your deck from just those cards." + + newLine); + s.append("3. In Booster Draft mode you select 1 card at a time and then make your deck from just those cards. After you are done drafting you have to type in a filename, then go to the Deck Editor and from the menu select \"Open Deck - Draft\" and find the filename. This will allow you to construct your deck. You can then play against the other 7 computer opponents that were drafting with you." + + newLine); + s.append("4. In Quest Mode you start out with 275 cards, 200 are Basic Lands. As you complete matches in your quest you will win more cards. In easy mode you get more cards after every game, whether you win or lose. Your goal is to become world champion. Once you reach the end of your quest you can continue to play additional matches and win even more cards or you can start a new quest at anytime." + + newLine); + s.append("At the Quest Options screen you will be given a choice of four different difficulty levels. These difficulty levels control:" + + newLine); + s.append("1) the length of the quest in matches,\r\n"); + s.append("2) the hardness of the AI deck that you will face as an opponent,\r\n"); + s.append("3) the number of wins or loses needed to get more cards,\r\n"); + s.append("4) the number of wins needed to advance a player to the next rank.\r\n\r\n\r\n"); + + s.append("Quick Games" + newLine); + s.append("There may be occasions where you only have a few minutes to play a quick game or two. At the top of the New Game window you will see the three different game types with radio buttons. Click on the Constructed (Easy) button and it will become highlighted." + + newLine); + s.append("In the middle area of the New Game window you will see two menus, one labeled \"Your Deck\" and the other \"Opponent\". For a quick game you should select the \"Generate Deck\" or the \"Random\" option for both you and the computer." + + newLine); + s.append("1. The \"Generate Deck\" option creates a 2 color deck. This option randomly picks cards and sometimes your mana curve may be too high." + + newLine); + s.append("2. The \"Random\" option will randomly select one of the constructed decks that appear in the two deck menus. You either construct these decks in the Deck Editor or you imported a .deck file from the Deck Editor." + + newLine); + s.append("If you select the \"Random\" option and click on the \"Start Game\" button and the match fails to begin … well, this happens if you fail to have any constructed decks saved to your all-decks2 file. You should choose the \"Generate Deck\" option instead.\r\n\r\n\r\n"); + + s.append("Resizable Game Area & Stack AI Land" + newLine); + s.append("1. The \"Resizable Game Area\" check box should be set to on if your monitor will display more than 1024 x 768 pixels. The window containing the Battlefield and the informational displays will fill the entire screen." + + newLine); + s.append("2. The \"Stack AI Land\" option will make the computer a more difficult opponent to beat. The computer will draw non-land cards from it's library after it has drawn enough lands to cover the cost of it's spells. Set the check box to on for a stronger opponent and set the check box to off for a weaker opponent." + + newLine); + s.append("At times, you may notice that when you click the \"Start Game\" button that the match fails to begin. In this case you should turn the \"Stack AI Land\" option to off.\r\n\r\n\r\n"); + + s.append("Abilities" + newLine); + s.append("There are three kinds of abilities: Activated, Triggered, and Static." + newLine); + s.append("1. Activated abilities contain a colon that separates cost and effect, these can be played any time you could play an instant. An example is Elvish Piper's ability. That cost also contains the tap symbol. For creatures only, abilities containing the tap- or untap symbol can be played starting the turn after the creature came into play. Another common cost for an activated ability is sacrificing the card. You do that by putting it into your graveyard. Such abilities can only be played once." + + newLine); + s.append("2. Triggered abilities aren't played, they simply trigger when their condition occurs. An example is Angel of Mercy: You don't play the ability, but gain 3 life when it comes into play." + + newLine); + s.append("3. Static abilities are neither played, nor do they trigger. They still have an effect for as long as they are in play. An example is Glorious Anthem. There is no condition or cost, your creatures are just stronger.\r\n\r\n\r\n"); + + s.append("Keyword Abilities" + newLine); + s.append("1. Flying: Creatures with flying are harder to block. Only creatures with flying or reach can block other flyers." + + newLine); + s.append("2. Haste: Haste lets a creature attack or use any abilities immediately during this turn." + + newLine); + s.append("3. Fear: Creatures with fear can only be blocked by artifact or black creatures. Creatures with fear are harder to block." + + newLine); + s.append("4. Cycling: When you cycle a card you pay some cost like 2 and then you discard that card, and then draw a new card. Cycling helps make your deck more versatile." + + newLine); + s.append("5. Vigilance: This means that the creature will not tap when attacking. This creature can both attack and block during the same turn." + + newLine); + s.append("6. Trample: If you use 2/1 creature to block an attacking 3/4 creature with trample, you will still receive 2 damage because the 3/4 trampled over your 2/1 creature. Trample damage is calculated by (attack - blocker's defense), in this case 3-1 which is 2." + + newLine); + s.append("7. Deathtouch: When a creatures with deathtouch deals damage to a creature, that creature is destroyed." + + newLine); + s.append("8. Defender: Creatures with defender can not attack, they can only block another attacker." + + newLine); + s.append("9. First Strike and Double Strike: Creatures with first strike deals their combat damage first. Creatures with double strike deals their combat damage first, and then deals their combat damage a second time during the combat damage step." + + newLine); + s.append("10. Flash: You can play a creature with flash anytime that you can play an Instant." + newLine); + s.append("11. Landwalk: Allows your creature to attack without being blocked if your opponent controls the appropriate land type." + + newLine); + s.append("12. Lifelink: With lifeline you gain life equal to the amount of damage dealt." + newLine); + s.append("13. Protection: Can not be damaged, blocked or targeted by sources that match the protection type." + + newLine); + s.append("14. Reach: Creatures with reach can block flying creatures." + newLine); + s.append("15. Shroud: Permanents with shroud can not be targeted by abilities or spells." + newLine); + s.append("16. Regenerate: Regenerate is an ability that some creatures have which prevents them from being destroyed and put into the graveyard. When you regenerate a creature, it acts like a shield until end of turn." + + newLine); + s.append("17. Morph: A creature with morph can be played by usually paying 3 mana of any color and be treated as a 2/2 creature with no abilities rather than playing the creature's actual cost. This creature is placed face down in the battlefield and can be flipped face up anytime as long as you pay its morph cost which is indicated on the card. Once flipped face up the card is treated as the original card, the one that you would normally play with its original-full casting cost."); + + + return s.toString(); + } +}//MenuItem_HowToPlay + diff --git a/src/Move.java b/src/Move.java new file mode 100644 index 00000000000..ad017d4ec7f --- /dev/null +++ b/src/Move.java @@ -0,0 +1,39 @@ +public abstract class Move +{ + abstract public Move[] generateMoves(); + abstract public int getScore(); + + public Move bestMove = null; + public int bestScore = Integer.MIN_VALUE; + + public int min(Move move, int depth) + { + if(depth == 0) + return move.getScore(); + + Move v[] = move.generateMoves(); + int score = Integer.MAX_VALUE; + for(int i = 0; i < v.length; i++) + score = Math.min(score, max(v[i], depth-1, false)); + return score; + } + public int max(Move move, int depth, boolean first) + { + if(depth == 0) + return move.getScore(); + + Move v[] = move.generateMoves(); + int score = Integer.MIN_VALUE; + for(int i = 0; i < v.length; i++) + { + score = Math.max(score, min(v[i], depth-1)); + + if(first && bestScore < score) + { + bestScore = score; + bestMove = v[i]; + } + }//for + return score; + }//max() +} \ No newline at end of file diff --git a/src/MoveAttack.java b/src/MoveAttack.java new file mode 100644 index 00000000000..739cd8ef09a --- /dev/null +++ b/src/MoveAttack.java @@ -0,0 +1,190 @@ +import java.util.*; + +public class MoveAttack +{ + private MoveAttack bestMove = null; + private int bestScore = Integer.MIN_VALUE; + + private static Random random = new Random(); + + private static Card[] aCreature; + private static Card[] bCreature; + + @SuppressWarnings("unused") // aLife + private static int aLife; + private static int bLife; + + private SimpleCombat combat; + + private static ArrayList generate1List = new ArrayList(); + + //trying to find the move for A player + //Card[] a and Card[] b, are all untapped creatures that can attack or block + public MoveAttack(Card[] a, Card[] b, int alife, int blife) + { + aCreature = a; + bCreature = b; + aLife = alife; + bLife = blife; + } + private MoveAttack(SimpleCombat c) {setCombat(c);} + + //for internal use and testing purposes + public void setCombat(SimpleCombat c) {combat = c;} + + public SimpleCombat getCombat() {return combat;} + public CardList getAttackers() {return combat.getAttackers();} + public MoveAttack getBestMove() {return bestMove;} + //should be called with a depth of 3, ShouldAttack.findMove(3) + //depth 3 is randomly choosing which creatures to attack + //depth 2 is randomly choosing which creature will block + //depth 1 is the outcome after combat damage, to see which creatures are left + public MoveAttack[] generateMoves(int depth) + { + if(depth == 1-1) + return generate1(); + else if(depth == 2-1) + return generate2(); + else if(depth == 3-1) + return generate3(); + else + throw new RuntimeException("MoveAttack : generateMoves() invalid depth: " +depth); + } + //calls Combat.combatDamage() on all moves generates my generate2() + public MoveAttack[] generate1() + { + MoveAttack[] m = new MoveAttack[generate1List.size()]; + + for(int i = 0; i < generate1List.size(); i++) + m[i] = (MoveAttack) generate1List.get(i); + + for(int i = 0; i < m.length; i++) + m[i].combat.combatDamage(); + + return m; + } + //generate blockers + public MoveAttack[] generate2() + { + if(combat.getAttackers().isEmpty()) + { + MoveAttack[] a = {new MoveAttack(combat)}; + generate1List.add(a[0]); + return a; + } + + MoveAttack move[] = new MoveAttack[200]; + Card attacker; + Card blocker; + + for(int outer = 0; outer < move.length; outer++) + { + SimpleCombat battle = new SimpleCombat(combat.getAttackers()); + //not sure what "stop" should be, might need to change this + int stop = random.nextInt(combat.getAttackers().size() + 1); + CardList pool = new CardList(bCreature); + + for(int i = 0; i < stop && !pool.isEmpty(); i++) + { + attacker = CardUtil.getRandom(combat.getAttackers().toArray()); + blocker = CardUtil.getRandom(pool.toArray()); + + if(CombatUtil.canBlock(attacker, blocker)) + { + pool.remove(blocker); + battle.addBlocker(attacker, blocker); + } + } + move[outer] = new MoveAttack(battle); + + generate1List.add(move[outer]); + } + return move; + } + //generate attackers + public MoveAttack[] generate3() + { + MoveAttack move[] = new MoveAttack[200]; + + for(int outer = 0; outer < move.length; outer++) + { + SimpleCombat battle = new SimpleCombat(); + CardList pool = new CardList(aCreature); + int stop = random.nextInt(aCreature.length + 1); + + for(int i = 0; i < stop; i++) + { + battle.addAttacker(randomRemove(pool)); + } + move[outer] = new MoveAttack(battle); + } + return move; + } + public Card randomRemove(CardList c) + { + if(c.isEmpty()) + throw new RuntimeException("MoveAttack : randomRemove() argument is size 0"); + int n = random.nextInt(c.size()); + return c.remove(n); + } + public int getScore() + { + if(bLife <= totalAttack(combat.getUnblockedAttackers())) + return 10000; + + CardList[] destroy = combat.combatDamage(); + CardList aDestroy = destroy[0]; + CardList bDestroy = destroy[1]; +//System.out.println("destroyed " +aDestroy); + int score = 0; + score += totalAttack(combat.getUnblockedAttackers()); + score -= aDestroy.size() * 10;//do not trade creatures, ie. both creatures die + + score += bDestroy.size(); +//if(score == 2) +// System.out.println(combat.toString()); + return score; + } + private int totalAttack(CardList c) + { + int total = 0; + + for(int i = 0; i < c.size(); i++) + total += c.get(i).getNetAttack(); + + return total; + } + + + private int min(MoveAttack move, int depth) + { + if(depth == 0) + return move.getScore(); + + MoveAttack v[] = move.generateMoves(depth); + int score = Integer.MAX_VALUE; + for(int i = 0; i < v.length; i++) + score = Math.min(score, max(v[i], depth-1, false)); + return score; + } + public int max(MoveAttack move, int depth, boolean first) + { + if(depth == 0) + return move.getScore(); + + MoveAttack v[] = move.generateMoves(depth); + int score = Integer.MIN_VALUE; + for(int i = 0; i < v.length; i++) + { + score = Math.max(score, min(v[i], depth-1)); + + if(first && bestScore < score) + { + bestScore = score; + bestMove = v[i]; + } + }//for + return score; + }//max() + //does not implement multiple blockers +} \ No newline at end of file diff --git a/src/MyButton.java b/src/MyButton.java new file mode 100644 index 00000000000..6c4ca53cf64 --- /dev/null +++ b/src/MyButton.java @@ -0,0 +1,12 @@ +public interface MyButton +{ +// public MyButton(String buttonText, Command command) + public void select(); + public void setSelectable(boolean b); + public boolean isSelectable(); + + public String getText(); + public void setText(String text); + + public void reset(); //resets the text and calls setSelectable(false) +} \ No newline at end of file diff --git a/src/MyObservable.java b/src/MyObservable.java new file mode 100644 index 00000000000..05188dfa8da --- /dev/null +++ b/src/MyObservable.java @@ -0,0 +1,22 @@ +import java.util.Observable; + +public class MyObservable extends Observable +{ + public final void updateObservers() + { + + this.setChanged(); + this.notifyObservers(); + + if(AllZone.Phase != null){ + if(AllZone.Phase.isNeedToNextPhase()==true){ + if(AllZone.Phase.isNeedToNextPhaseInit() == true){ + AllZone.Phase.setNeedToNextPhase(false); + AllZone.Phase.nextPhase(); + } + } + } + + } +} + diff --git a/src/MyRandom.java b/src/MyRandom.java new file mode 100644 index 00000000000..e43d743c236 --- /dev/null +++ b/src/MyRandom.java @@ -0,0 +1,26 @@ +import java.util.*; + +public class MyRandom +{ + public static final Random random = new Random(); + + //if percent is like 50, the its like 50% of the time will be true + public static boolean percentTrue(int percent) + { + return percent > random.nextInt(100); + } + public static void shuffle(Object[] o) + { + for(int i = 0; i < o.length; i++) + { + swap(o, i, random.nextInt(o.length)); + swap(o, i, random.nextInt(o.length)); + } + } + private static void swap(Object o[], int index_1, int index_2) + { + Object hold = o[index_1]; + o[index_1] = o[index_2]; + o[index_2] = hold; + } +} \ No newline at end of file diff --git a/src/NameChanger.java b/src/NameChanger.java new file mode 100644 index 00000000000..8b4ddd2fc01 --- /dev/null +++ b/src/NameChanger.java @@ -0,0 +1,155 @@ +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.StringTokenizer; + +import forge.error.ErrorViewer; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + +public class NameChanger implements NewConstants { + private Map mutatedMap = new HashMap(); + private Map originalMap = new HashMap(); + + private boolean changeCardName; + + public NameChanger() { + readFile(); + setShouldChangeCardName(false); + } + + //should change card name? + public boolean shouldChangeCardName() { + return changeCardName; + } + + public void setShouldChangeCardName(boolean b) { + changeCardName = b; + } + + //returns an array of copies + public Card[] changeCard(Card c[]) { + for(int i = 0; i < c.length; i++) + changeCard(c[i]); + + return c; + } + + //changes card name, getText(), and all SpellAbility getStackDescription() and toString() + public Card changeCard(Card c) { + //change name + String newName = changeName(c.getName()); + c.setName(newName); + + //change text + String s; + s = c.getSpellText(); + c.setText(changeString(c, s)); + + //change all SpellAbilities + SpellAbility[] spell = c.getSpellAbility(); + for(int i = 0; i < spell.length; i++) { + s = spell[i].getStackDescription(); + spell[i].setStackDescription(changeString(c, s)); + + s = spell[i].toString(); + spell[i].setDescription(changeString(c, s)); + } + + return c; + }//getMutatedCard() + + public String changeString(Card c, String in) { + //String name = getOriginalName(c.getName()); // unused +// in = in.replaceAll(name, changeName(name)); + + return in; + } + + //always returns mutated (alias) for the card name + //if argument is a mutated name, it returns the same mutated name + public String changeName(String originalName) { + Object o = mutatedMap.get(originalName); + + if(o == null) return originalName; + + return o.toString(); + }//getMutatedName() + + //always returns the original cardname + //if argument is a original name, it returns the same original name + public String getOriginalName(String mutatedName) { + Object o = originalMap.get(mutatedName); + + if(o == null) return mutatedName; + + return o.toString(); + }//getOriginalName() + + private void readFile() { + try { + BufferedReader in = new BufferedReader(new FileReader(ForgeProps.getFile(NAME_MUTATOR))); + + String line = in.readLine(); + + //stop reading if end of file or blank line is read + while(line != null && (line.trim().length() != 0)) { + processLine(line.trim()); + + line = in.readLine(); + }//while + }//try + catch(Exception ex) { +//~ throw new RuntimeException("NameMutator : readFile() error, " +ex); + + + //~ (could be cleaner...) + try { + BufferedReader in = new BufferedReader(new FileReader(ForgeProps.getFile(NAME_MUTATOR))); + + String line; + + //stop reading if end of file or blank line is read + while((line = in.readLine()) != null && (line.trim().length() != 0)) { + processLine(line.trim()); + }//while + } catch(Exception ex2) { + // Show orig exception + ErrorViewer.showError(ex2); + throw new RuntimeException(String.format("NameMutator : readFile() error, %s", ex), ex); + } + //~ + } + }//readFile() + + //line is formated "original card name : alias card name" + private void processLine(String line) { + StringTokenizer tok = new StringTokenizer(line, ":"); + + if(tok.countTokens() != 2) + throw new RuntimeException( + "NameMutator : processLine() error, invalid line in file name-mutator.txt - " + line); + + String original = tok.nextToken().trim(); + String mutated = tok.nextToken().trim(); + + mutatedMap.put(original, mutated); + originalMap.put(mutated, original); + } + + @SuppressWarnings("unused") + // printMap + private void printMap(Map map) { + Iterator it = map.keySet().iterator(); + String key; + for(int i = 0; i < 5; i++) { + key = it.next().toString(); + System.out.println(key + " : " + map.get(key)); + } + } + + public static void main(String[] args) {}//main() +} \ No newline at end of file diff --git a/src/NewIO.java b/src/NewIO.java new file mode 100644 index 00000000000..3266a6d074f --- /dev/null +++ b/src/NewIO.java @@ -0,0 +1,114 @@ +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.io.WriteAbortedException; +import java.util.HashMap; + + +public class NewIO { + private HashMap map = new HashMap(); + private final File file; + + public NewIO(String filename) { + file = new File(filename); + if(!file.exists()) createBlankFile(); + } + + //would like one class to do all of the IO + //internally just a Map is used, and written to the hard drive + //WARNING - different parts of the program have to use different, unique keys + //the data is immediately written, nothing is cached or buffered + public void write(String key, Serializable data) { + readData(); + map.put(key, data); + + ObjectOutputStream out = getWriter(); + + try { + out.writeObject(map); + + out.flush(); + out.close(); + out = null; + } catch(IOException ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("IO : write() error - " + ex); + } + } + + public Object read(String key) { + readData(); + return map.get(key); + } + + public boolean containsKey(String key) { + return map.containsKey(key); + } + + private ObjectOutputStream getWriter() { + try { + return new ObjectOutputStream(new FileOutputStream(file)); + } catch(IOException ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("IO : getWriter() - error - " + ex); + } + } + + private ObjectInputStream getReader() { + try { + return new ObjectInputStream(new FileInputStream(file)); + } catch(IOException ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("IO : getReader() - error - " + ex); + } + }//getReader() + + @SuppressWarnings("unchecked") + // HashMap needs + private void readData() { + ObjectInputStream in = getReader(); + Object o; + try { + o = in.readObject(); + in.close(); + in = null; + } catch(WriteAbortedException ex) { + //deletes current file + //a new file will be constructed next time by the constructor + try { + in.close(); + in = null; + } catch(IOException ex2) {} + file.delete(); + ErrorViewer.showError(ex, "All old decks are lost, sorry - please restart"); + throw new RuntimeException( + "IO : readData() - WriterAbortedException - all old decks are lost, sorry - please restart"); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("IO : readData() - error - " + ex); + } + + if(o instanceof HashMap) map = (HashMap) o; + } + + private void createBlankFile() { + try { + if(file.exists()) file.delete(); + else file.createNewFile(); + + ObjectOutputStream out = getWriter(); + out.writeObject(map); + + out.flush(); + out.close(); + out = null; + } catch(IOException ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("IO : createBlankFile() - error - " + ex); + } + }//createBlankFile() +} diff --git a/src/NonScrollingJEditorPane.java b/src/NonScrollingJEditorPane.java new file mode 100644 index 00000000000..e73b6f254ea --- /dev/null +++ b/src/NonScrollingJEditorPane.java @@ -0,0 +1,20 @@ +import java.awt.Dimension; + +import javax.swing.JEditorPane; + +public class NonScrollingJEditorPane extends JEditorPane { + private static final long serialVersionUID = 5361467616843296999L; + + public NonScrollingJEditorPane() { + super(); + } + public boolean getScrollableTracksViewportWidth() { + return false; + } + public void setSize(Dimension d) { + if(d.width < getParent().getSize().width) { + d.width = getParent().getSize().width; + } + super.setSize(d); + } +} diff --git a/src/Phase.java b/src/Phase.java new file mode 100644 index 00000000000..595aeb78d08 --- /dev/null +++ b/src/Phase.java @@ -0,0 +1,181 @@ +import java.util.Observer; + +public class Phase extends MyObservable +{ + private int phaseIndex; + private int turn; + + private String phases[][] = + { + //human's turn + {Constant.Player.Human , Constant.Phase.Untap} , +// {Constant.Player.Human , Constant.Phase.Upkeep} , + {Constant.Player.Human , Constant.Phase.Draw} , + {Constant.Player.Human , Constant.Phase.Main1} , + {Constant.Player.Human , Constant.Phase.Combat_Declare_Attackers} , + {Constant.Player.Computer , Constant.Phase.Combat_Declare_Blockers} , + {Constant.Player.Human , Constant.Phase.Combat_Declare_Blockers_InstantAbility} , + {Constant.Player.Computer , Constant.Phase.Combat_Declare_Blockers_InstantAbility} , + {Constant.Player.Human , Constant.Phase.Combat_FirstStrikeDamage} , //TODO: need to allow computer to have priority (play instants and abilities). + {Constant.Player.Human , Constant.Phase.Combat_Damage} , + {Constant.Player.Human , Constant.Phase.Main2} , + {Constant.Player.Human , Constant.Phase.At_End_Of_Turn} , +// {Constant.Player.Computer , Constant.Phase.End_Of_Turn} , + {Constant.Player.Human , Constant.Phase.Until_End_Of_Turn} , + {Constant.Player.Human , Constant.Phase.Cleanup} , + + //computer's turn + {Constant.Player.Computer , Constant.Phase.Untap} , + {Constant.Player.Computer , Constant.Phase.Draw} , + {Constant.Player.Computer , Constant.Phase.Main1} , + {Constant.Player.Human , Constant.Phase.Combat_Before_Declare_Attackers_InstantAbility}, + {Constant.Player.Computer , Constant.Phase.Combat_Declare_Attackers} , + {Constant.Player.Human , Constant.Phase.Combat_Declare_Attackers_InstantAbility}, + {Constant.Player.Human , Constant.Phase.Combat_Declare_Blockers} , + {Constant.Player.Computer , Constant.Phase.Combat_Declare_Blockers_InstantAbility} , + {Constant.Player.Human , Constant.Phase.Combat_Declare_Blockers_InstantAbility} , + {Constant.Player.Human , Constant.Phase.Combat_FirstStrikeDamage} , //TODO: need to allow computer to have priority (play instants and abilities). + {Constant.Player.Human , Constant.Phase.Combat_Damage} , + {Constant.Player.Computer , Constant.Phase.Main2} , + {Constant.Player.Computer , Constant.Phase.At_End_Of_Turn} , + {Constant.Player.Human , Constant.Phase.End_Of_Turn} , + {Constant.Player.Computer , Constant.Phase.Until_End_Of_Turn} , + {Constant.Player.Computer , Constant.Phase.Cleanup} , + }; + + public Phase() + { + reset(); + } + public void reset() + { + turn = 1; + phaseIndex = 0; + this.updateObservers(); + } + public void setPhase(String phase, String player) + { + phaseIndex = findIndex(phase, player); + this.updateObservers(); + } + public void nextPhase() + { + + //System.out.println("current active Player: " + getActivePlayer()); + //experimental, add executeCardStateEffects() here: + for (String effect : AllZone.StateBasedEffects.getStateBasedMap().keySet() ) { + Command com = GameActionUtil.commands.get(effect); + com.execute(); + } + + GameActionUtil.executeCardStateEffects(); + + //for debugging: System.out.print("this phase - " +getActivePlayer() +" " +getPhase()+", next phase - "); + needToNextPhase = false; + + + if(getPhase().equals(Constant.Phase.Combat_Damage)){ + if(AllZone.Stack.size() != 0){ + return; + } + } + + if(getPhase().equals(Constant.Phase.Combat_Declare_Attackers_InstantAbility)) + System.out.println("HELLO"); + + //empty manapool: + //CardList cl = new CardList(AllZone.getZone(Constant.Zone.Play, Constant.Player.Human).getCards()); + //cl = cl.getName("Mana Pool"); + //if (cl.size() > 0) + //{ + // Card c = cl.get(0); + // c.setExtrinsicKeyword(new ArrayList()); + //} + + + AllZone.ManaPool.clear(); + + phaseIndex++; + if(phases.length <= phaseIndex) + phaseIndex = 0; + + if(getPhase().equals(Constant.Phase.Untap)) + turn++; + + //for debugging: System.out.println(getPhase()); + + //System.out.print(""); + this.updateObservers(); + if(AllZone.Phase != null){ + if(AllZone.Phase.isNeedToNextPhase()==true){ + AllZone.Phase.setNeedToNextPhase(false); + AllZone.Phase.nextPhase(); + } + } + } + public synchronized boolean is(String phase, String player) + { + return (getPhase().equals(phase) && getActivePlayer().equals(player)); + } + private int findIndex(String phase, String player) + { + for(int i = 0; i < phases.length; i++) + { + if(player.equals(phases[i][0]) && phase.equals(phases[i][1])) + return i; + } + throw new RuntimeException("Phase : findIndex() invalid argument, phase = " +phase +" player = " +player); + } + public String getActivePlayer() + { + //hack + return phases[phaseIndex][0]; + } + public String getPhase() + { + return phases[phaseIndex][1]; + } + public int getTurn() + { + return turn; + } + public void setTurn(int in_turn) + { + turn = in_turn; + } + public static void main(String args[]) + { + Phase phase = new Phase(); + for(int i = 0; i < phase.phases.length + 3; i++) + { + System.out.println(phase.getActivePlayer() +" " +phase.getPhase()); + phase.nextPhase(); + } + } + + public void addObserver(Observer o){ + super.deleteObservers(); + super.addObserver(o); + } + + boolean needToNextPhase = false; + public void setNeedToNextPhase(boolean needToNextPhase) { + this.needToNextPhase = needToNextPhase; + } + + public boolean isNeedToNextPhase(){ + return this.needToNextPhase; + } + + //This should only be true four times! that is for the initial nextPhases in MyObservable + int needToNextPhaseInit = 0; + public boolean isNeedToNextPhaseInit() { + needToNextPhaseInit++; + if(needToNextPhaseInit <=4){ + return true; + } + return false; +} + + +} \ No newline at end of file diff --git a/src/PhaseObserver.java b/src/PhaseObserver.java new file mode 100644 index 00000000000..1ab99c5f43f --- /dev/null +++ b/src/PhaseObserver.java @@ -0,0 +1,75 @@ +import java.util.*; + +public class PhaseObserver implements Observer +{ + private boolean canPlayLand; + + public PhaseObserver() + { + AllZone.Phase.addObserver(this); + } + + public boolean canPlayLand() {return canPlayLand;} + public void playedLand() {canPlayLand = false;} + + public void update(Observable o1, Object o2) + { + String player = AllZone.Phase.getActivePlayer(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + String phase = AllZone.Phase.getPhase(); + + + if(phase.equals(Constant.Phase.Main1)) + { + if(player.equals(Constant.Player.Human)) + canPlayLand = true; + + //untap all permanents + for(int i = 0; i < play.size(); i++) + { + play.get(i).untap(); + play.get(i).setSickness(false); + } + //TODO: computer needs to draw a card + if(AllZone.Phase.getTurn() > 1) + AllZone.GameAction.drawCard(player); + } + + else if(AllZone.Phase.is(Constant.Phase.Combat_Declare_Blockers, Constant.Player.Human) && + AllZone.Combat.getAttackers().length == 0) + { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(PhaseObserver.update,phase.is(Combat_Declare_Blockers & Human)) = true; Note, this has not been tested, did it work?"); + AllZone.Phase.setNeedToNextPhase(true); + } + else if(AllZone.Phase.is(Constant.Phase.Combat_Declare_Blockers_InstantAbility, Constant.Player.Human) && + AllZone.Combat.getAttackers().length == 0) + { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(PhaseObserver.update,phase.is(Combat_Declare_Blockers_InstantAbility & Human)) = true; Note, this has not been tested, did it work?"); + AllZone.Phase.setNeedToNextPhase(true); + } + else if(AllZone.Phase.is(Constant.Phase.Combat_Damage, Constant.Player.Human) && + AllZone.Combat.getAttackers().length == 0) + { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(PhaseObserver.update,phase.is(Combat_Damage & Human)) = true; Note, this has not been tested, did it work?"); + AllZone.Phase.setNeedToNextPhase(true); + } + else if(AllZone.Phase.is(Constant.Phase.Combat_Declare_Attackers, Constant.Player.Human) && + AllZone.Combat.getAttackers().length == 0) + { + if(PlayerZoneUtil.getCardType(AllZone.Human_Play, "Creature").size() == 0) + { + + //AllZone.Phase.nextPhase(); + //for debugging: System.out.println("need to nextPhase(PhaseObserver.update,phase.is(Combat_Declare_attackers & Human)) = true; Note, this has not been tested, did it work?"); + AllZone.Phase.setNeedToNextPhase(true); + } + } + + }//update() +} diff --git a/src/PicturePanel.java b/src/PicturePanel.java new file mode 100644 index 00000000000..30fe93d3939 --- /dev/null +++ b/src/PicturePanel.java @@ -0,0 +1,22 @@ + import java.io.File; + + import javax.swing.ImageIcon; + import javax.swing.JLabel; + import javax.swing.JPanel; + + import forge.error.ErrorViewer; + + + public class PicturePanel extends JPanel { + private static final long serialVersionUID = 2282867940272644768L; + + public PicturePanel(File f) { + if(!f.exists()) { + ErrorViewer.showError("PicturePanel : file does not exist - %s", f); + throw new RuntimeException("PicturePanel : file does not exist - " + f); + } + + ImageIcon i = new ImageIcon(f.getPath()); + this.add(new JLabel(i)); + } + } \ No newline at end of file diff --git a/src/PlayerLife.java b/src/PlayerLife.java new file mode 100644 index 00000000000..7bb581c08fd --- /dev/null +++ b/src/PlayerLife.java @@ -0,0 +1,32 @@ +public class PlayerLife extends MyObservable implements java.io.Serializable +{ + private static final long serialVersionUID = -1614695903669967202L; + + private int life; + private int assignedDamage;//from combat + + public void setAssignedDamage(int n) + {assignedDamage = n;} + public int getAssignedDamage() + {return assignedDamage;} + + public int getLife() + { + return life; + } + public void setLife(int life2) + { + life = life2; + this.updateObservers(); + } + public void addLife(int life2) + { + life += life2; + this.updateObservers(); + } + public void subtractLife(int life2) + { + life -= life2; + this.updateObservers(); + } +} \ No newline at end of file diff --git a/src/PlayerZone.java b/src/PlayerZone.java new file mode 100644 index 00000000000..cdca3091b08 --- /dev/null +++ b/src/PlayerZone.java @@ -0,0 +1,33 @@ +import java.util.*; + +//PlayerZone observers the cards that are added to its zone +abstract public class PlayerZone extends MyObservable implements IPlayerZone, Observer +{ + +} + +interface IPlayerZone +{ + public void setUpdate(boolean b); + public boolean getUpdate(); + + public int size(); + public void add(Object o); + public void add(Card c, int index); + + public Card get(int index); + public void remove(Object o); + public void remove(int index); + + public void setCards(Card c[]); + public Card[] getCards(); + + //removes all cards + public void reset(); + + public boolean is(String zone); + public boolean is(String zone, String player); + + public String getPlayer();//the Player that owns this zone + public String getZone();//returns the Zone's name like Graveyard +} \ No newline at end of file diff --git a/src/PlayerZoneUtil.java b/src/PlayerZoneUtil.java new file mode 100644 index 00000000000..1d27cd4a186 --- /dev/null +++ b/src/PlayerZoneUtil.java @@ -0,0 +1,65 @@ +import java.util.*; + +public class PlayerZoneUtil +{ + public static boolean containsCardType(PlayerZone zone, String cardType) + { + return (getCardType(zone, cardType).size() > 0); + } + + public static ArrayList getCardType(PlayerZone zone, String cardType) + { + Card c; + ArrayList list = new ArrayList(); + + for(int i = 0; i < zone.size(); i++) + { + c = zone.get(i); + if(c.getType().contains(cardType) /*|| c.getKeyword().contains("Changeling")*/ ) + list.add(c); + } + return list; + } + public static ArrayList getUntappedCreatures(PlayerZone zone) + { + ArrayList all = getCardType(zone, "Creature"); + ArrayList untapped = new ArrayList(); + + for(int i = 0; i < all.size(); i++) + if(((Card)all.get(i)).isUntapped()) + untapped.add(all.get(i)); + + return untapped; + } + static public boolean isCardInZone(PlayerZone pz, Card card) + { + if(card == null) + return false; + + Card c[] = pz.getCards(); + + for(int i = 0; i < c.length; i++) + if(c[i].equals(card)) + return true; + + return false; + } + static public ArrayList getCardsNamed(PlayerZone pz, final String name) + { + ArrayList sameName = new ArrayList(); + String s; + for(int i = 0; i < pz.size(); i++) + { + s = pz.get(i).getName(); + if(s.equals(name)) + sameName.add(pz.get(i)); + } + return sameName; + } + static public void moveToTop(PlayerZone pz, Card card) + { + pz.remove(card); + pz.add(card, 0); + } +} + diff --git a/src/PlayerZone_ComesIntoPlay.java b/src/PlayerZone_ComesIntoPlay.java new file mode 100644 index 00000000000..d7244b378b1 --- /dev/null +++ b/src/PlayerZone_ComesIntoPlay.java @@ -0,0 +1,150 @@ +import java.util.ArrayList; + +public class PlayerZone_ComesIntoPlay extends DefaultPlayerZone +{ + private static final long serialVersionUID = 5750837078903423978L; + + private boolean trigger = true; + private boolean leavesTrigger = true; + + public PlayerZone_ComesIntoPlay(String zone, String player) + { + super(zone, player); + } + + public void add(Object o) + { + if (o == null) + throw new RuntimeException( + "PlayerZone_ComesInto Play : add() object is null"); + + super.add(o); + + Card c = (Card) o; + if (trigger) + { + c.setSickness(true);// summoning sickness + c.comesIntoPlay(); + + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + + + if (c.isLand()) + { + //System.out.println("A land just came into play: " + c.getName()); + + CardList list = new CardList(play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.getKeyword().contains("Landfall"); + } + }); + + for (int i=0; i allyNamesList = new ArrayList(); + + for (int i=0;i 0 && (c.getType().contains("Creature") || c.getKeyword().contains("Changeling"))) || allyNamesList.contains(c.getName())) + { + CardList list = new CardList(play.getCards()); + list = list.filter(new CardListFilter() + { + public boolean addCard(Card c) { + return c.getType().contains("Ally") || c.getKeyword().contains("Changeling") || allyNamesList.contains(c.getName()); + } + }); + + for (Card var : list) + { + GameActionUtil.executeAllyEffects(var); + } + } + + + } + if (AllZone.StateBasedEffects.getCardToEffectsList().containsKey(c.getName())) + { + String[] effects = AllZone.StateBasedEffects.getCardToEffectsList().get(c.getName()); + for (String effect : effects) { + AllZone.StateBasedEffects.addStateBasedEffect(effect); + } + } + + + /* + for (String effect : AllZone.StateBasedEffects.getStateBasedMap().keySet() ) { + Command com = GameActionUtil.commands.get(effect); + com.execute(); + } + */ + + //System.out.println("Size: " + AllZone.StateBasedEffects.getStateBasedMap().size()); + } + + public void remove(Object o) + { + + super.remove(o); + + Card c = (Card) o; + if (leavesTrigger) + c.leavesPlay(); + + if (AllZone.StateBasedEffects.getCardToEffectsList().containsKey(c.getName())) + { + String[] effects = AllZone.StateBasedEffects.getCardToEffectsList().get(c.getName()); + String tempEffect = ""; + for (String effect : effects) { + tempEffect = effect; + AllZone.StateBasedEffects.removeStateBasedEffect(effect); + Command comm = GameActionUtil.commands.get(tempEffect); //this is to make sure cards reset correctly + comm.execute(); + } + + } + for (String effect : AllZone.StateBasedEffects.getStateBasedMap().keySet() ) { + Command com = GameActionUtil.commands.get(effect); + com.execute(); + } + + + } + + public void setTrigger(boolean b) + { + trigger = b; + } + + public void setLeavesTrigger(boolean b) + { + leavesTrigger = b; + } + + public void setTriggers(boolean b) + { + trigger = b; + leavesTrigger = b; + } +} diff --git a/src/PrintCardNames.java b/src/PrintCardNames.java new file mode 100644 index 00000000000..c3a2cfd1468 --- /dev/null +++ b/src/PrintCardNames.java @@ -0,0 +1,30 @@ +import java.util.*; + +import java.io.*; + +public class PrintCardNames +{ + public static void main(String[] args) throws IOException + { + FileWriter out = new FileWriter("c:\\all-card-names.txt"); + ArrayList list = getCardNames(); + + for(int i = 0; i < list.size(); i++) + out.write(list.get(i) +"\r\n"); + + out.flush(); + out.close(); + } + + static ArrayList getCardNames() + { + CardList c = AllZone.CardFactory.getAllCards(); + ArrayList list = new ArrayList(); + for(int i = 0; i < c.size(); i++) + list.add(c.get(i).getName()); +// list.add(c.get(i).getName() +"\t " +GuiDisplayUtil.cleanString(c.get(i).getName()) +".jpg"); + + Collections.sort(list); + return list; + } +} diff --git a/src/PrintCardPictures.java b/src/PrintCardPictures.java new file mode 100644 index 00000000000..31cabd25795 --- /dev/null +++ b/src/PrintCardPictures.java @@ -0,0 +1,38 @@ + + +import java.io.FileWriter; +import java.util.ArrayList; + +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + + +public class PrintCardPictures implements NewConstants { + public static void main(String[] args) throws Exception { + ReadCard read = new ReadCard(ForgeProps.getFile(CARDS)); + + //javax.swing.SwingUtilities.invokeAndWait(read); + read.run(); + + + ArrayList list = read.getCards(); + FileWriter out = new FileWriter("c:\\new-pictures.txt"); + + Card c; + String string; + + for(int i = 0; i < list.size(); i++) { + c = (Card) list.get(i); + string = GuiDisplayUtil.cleanString(c.getName()) + ".jpg"; + string = string + "\t http://mi.wizards.com/global/images/magic/general/" + string; + + System.out.println(string); + out.write(string + "\r\n"); + } + + out.flush(); + out.close(); + + }//main() +} \ No newline at end of file diff --git a/src/QuestData.java b/src/QuestData.java new file mode 100644 index 00000000000..7d9dc647707 --- /dev/null +++ b/src/QuestData.java @@ -0,0 +1,525 @@ + + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Random; + +import forge.error.ErrorViewer; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + + +class QuestData_State implements Serializable { + private static final long serialVersionUID = 7007940230351051937L; + + int rankIndex, win, lost; + String difficulty; + + ArrayList cardPool; + HashMap myDecks, aiDecks; +} + +//when you create QuestData and AFTER you copy the AI decks over +//you have to call one of these two methods below +//see Gui_QuestOptions for more details +// +//static readAIQuestDeckFiles(QuestData data, ArrayList aiDeckNames) +//OR non-static readAIQuestDeckFiles() +//which reads the files "questDecks-easy", "questDecks-medium","questDecks-hard", +public class QuestData implements NewConstants { + public final String EASY = "Easy"; + public final String MEDIUM = "Medium"; + public final String HARD = "Hard"; + public final String VERY_HARD = "Very Hard"; + + //easy, medium, hard, very hard + //easy gets a new booster pack after 1 wins + //medium gets a new booster pack after after 1 wins, etc... + //hard gets a new booster pack after after 2 wins, etc... + //very hard gets a new booster pack after after 2 wins, etc... + //these numbers are just guesses + private int[] addCardsArray = {1, 1, 2, 2}; + + //easy, medium, hard, very hard + //easy gets a new "rank" after 1 wins + //medium, gets a new "rank" after 2 wins + //these numbers are just guesses + private int[] rankChangeArray = {1, 2, 3, 4}; + + private int rankIndex; + private int win; + private int lost; + + private String difficulty; + + + private ArrayList easyAIDecks; + private ArrayList mediumAIDecks; + private ArrayList hardAIDecks; + + private HashMap myDecks = new HashMap(); + private HashMap aiDecks = new HashMap(); + + //holds String card names + private ArrayList cardPool = new ArrayList(); + private ArrayList newCardList = new ArrayList(); + + private QuestData_BoosterPack boosterPack = new QuestData_BoosterPack(); + + //used by shouldAddAdditionalCards() + private Random random = new Random(); + + //feel free to change this to something funnier + private String[] rankArray = { + "Level 0 - Confused Wizard", "Level 1 - Mana Mage", "Level 2 - Death by Megrim", + "Level 3 - Shattered the Competition", "Level 4 - Black Knighted", "Level 5 - Shockingly Good", + "Level 6 - Regressed into Timmy", "Level 7 - Loves Blue Control", "Level 8 - Immobilized by Fear", + "Level 9 - Lands = Friends", "Saltblasted for your talent", "Serra Angel is your girlfriend",}; + + /* + private String[] rankArray = + { + "Level 0 - Interested Newbie" , + "Level 1 - Card Flopper" , + "Level 2 - Friday Night Winner", + "Level 3 - Store Champion" , + "Level 4 - Card Crusher" , + "Level 5 - PTQ Player" , + "Level 6 - PTQ Winner" , + "Level 7 - Pro Wannabe" , + "Level 8 - Pro-Tour Winner" , + "Level 9 - Better Than Jon Finkel" , + "Level 10 - World Champion - You Win", + "Secret Level - Magic God" + }; + */ + + public QuestData() { + for(int i = 0; i < 40; i++) { + cardPool.add("Forest"); + cardPool.add("Mountain"); + cardPool.add("Swamp"); + cardPool.add("Island"); + cardPool.add("Plains"); + }//for + }//QuestData + + //adds cards to card pool and sets difficulty + @SuppressWarnings("unchecked") + public void newGame(String difficulty) { + setDifficulty(difficulty); + + int[][] totals = { {45, 20, 10}, //easy, 45 common, 20 uncommon, 10 rares + {40, 15, 10} //everything else + }; + + int n = 1; + if(difficulty.equals(EASY)) n = 0; + + ArrayList list = new ArrayList(); + list.addAll(boosterPack.getCommon(totals[n][0])); + list.addAll(boosterPack.getUncommon(totals[n][1])); + list.addAll(boosterPack.getRare(totals[n][2])); + + //because cardPool already has basic land added to it + cardPool.addAll(list); + } + + + public String[] getOpponents() { + int difficulty[][] = { + //if getWin() is < 5 return use easyAIDecks + //if getWin() is < 8 return mediumAIDecks + //else use hardAIDecks + {5, 8}, //easy difficulty + {5, 8}, //medium difficulty + {10, 20},//hard difficulty + {10, 20},//very hard difficulty + }; + + int index = convertDifficultyToIndex(getDifficulty()); + + if(getWin() < difficulty[index][0]) return getOpponents(easyAIDecks); + + if(getWin() < difficulty[index][1]) return getOpponents(mediumAIDecks); + + return getOpponents(hardAIDecks); + }//getOpponents() + + + static public void readAIQuestDeckFiles(QuestData data, ArrayList aiDeckNames) { + data.easyAIDecks = readFile(ForgeProps.getFile(QUEST.EASY), aiDeckNames); + data.mediumAIDecks = readFile(ForgeProps.getFile(QUEST.MEDIUM), aiDeckNames); + data.hardAIDecks = readFile(ForgeProps.getFile(QUEST.HARD), aiDeckNames); + + } + + public String[] getOpponents(ArrayList aiDeck) { + Collections.shuffle(aiDeck); + + return new String[] {aiDeck.get(0).toString(), aiDeck.get(1).toString(), aiDeck.get(2).toString()}; + + }//getOpponents() + + private static ArrayList readFile(File file, ArrayList aiDecks) { + ArrayList list = FileUtil.readFile(file); + + //remove any blank lines + ArrayList noBlankLines = new ArrayList(); + String s; + for(int i = 0; i < list.size(); i++) { + s = list.get(i).toString().trim(); + if(!s.equals("")) noBlankLines.add(s); + } + list = noBlankLines; + + if(list.size() < 3) + ErrorViewer.showError( + new Exception(), + "QuestData : readFile() error, file %s is too short, it must contain at least 3 ai decks names", + file); + + + for(int i = 0; i < list.size(); i++) + if(!aiDecks.contains(list.get(i).toString())) + ErrorViewer.showError(new Exception(), + "QuestData : readFile() error, file %s contains the invalid ai deck name: %s", file, + list.get(i)); + + + return list; + }//readFile() + + public void readAIQuestDeckFiles() { + readAIQuestDeckFiles(this, ai_getDeckNames()); + } + + @SuppressWarnings("unchecked") + static public QuestData loadData() { + try { + //read file "questData" + ObjectInputStream in = new ObjectInputStream(new FileInputStream(ForgeProps.getFile(QUEST.DATA))); + Object o = in.readObject(); + in.close(); + + QuestData_State state = (QuestData_State) o; + + QuestData data = new QuestData(); + + data.win = state.win; + data.lost = state.lost; + data.rankIndex = state.rankIndex; + data.difficulty = state.difficulty; + + data.cardPool = state.cardPool; + data.myDecks = state.myDecks; + data.aiDecks = state.aiDecks; + + readAIQuestDeckFiles(data, new ArrayList(data.aiDecks.keySet())); + + return data; + }//try + catch(Exception ex) { + ErrorViewer.showError(ex, "Error loading Quest Data"); + throw new RuntimeException(ex); + } + }//loadData() + + + //returns Strings of the card names + public ArrayList getCardpool() { + //make a copy so the internal ArrrayList cannot be changed externally + return new ArrayList(cardPool); + } + + //rename - removeDeck, addDeck + //copy - addDeck + + public void removeDeck(String deckName) { + myDecks.remove(deckName); + } + + public void ai_removeDeck(String deckName) { + aiDecks.remove(deckName); + } + + public void addDeck(Deck d) { + myDecks.put(d.getName(), d); + } + + public void ai_addDeck(Deck d) { + aiDecks.put(d.getName(), d); + } + + //this Deck object is a Constructed deck + //deck.getDeckType() is Constant.GameType.Sealed + //sealed since the card pool is the Deck sideboard + public Deck getDeck(String deckName) { + //have to always set the card pool aka the Deck sideboard + //because new cards may have been added to the card pool by addCards() + + //this sets the cards in Deck main + Deck d = getDeckFromMap(myDecks, deckName); + + //below is probably not needed + + //remove old cards from card pool + for(int i = 0; i < d.countSideboard(); i++) + d.removeSideboard(i); + + //add all cards to card pool + for(int i = 0; i < cardPool.size(); i++) + d.addSideboard(cardPool.get(i).toString()); + + return d; + } + + //this Deck object is a Constructed deck + //deck.getDeckType() is Constant.GameType.Constructed + //constructed because the computer can use any card + public Deck ai_getDeck(String deckName) { + return getDeckFromMap(aiDecks, deckName); + } + + + private Deck getDeckFromMap(Map map, String deckName) { + if(!map.containsKey(deckName)) + ErrorViewer.showError(new Exception(), + "QuestData : getDeckFromMap(String deckName) error, deck name not found - %s", deckName); + + return map.get(deckName); + } + + //returns human player decks + //returns ArrayList of String deck names + public ArrayList getDeckNames() { + return getDeckNames_String(myDecks); + }//getDecks() + + //returns AI computer decks + //returns ArrayList of String deck names + public ArrayList ai_getDeckNames() { + return getDeckNames_String(aiDecks); + } + + //returns ArrayList of Deck String names + private ArrayList getDeckNames_String(Map map) { + ArrayList out = new ArrayList(); + + Iterator it = map.keySet().iterator(); + while(it.hasNext()) + out.add(it.next().toString()); + + return out; + } + + //get new cards that were added to your card pool by addCards() + public ArrayList getAddedCards() { + return new ArrayList(newCardList); + } + + //adds 11 cards, to the current card pool + //(I chose 11 cards instead of 15 in order to make things more challenging) + @SuppressWarnings("unchecked") + public void addCards() { + int nCommon = 7; + int nUncommon = 3; + int nRare = 1; + + ArrayList newCards = new ArrayList(); + newCards.addAll(boosterPack.getCommon(nCommon)); + newCards.addAll(boosterPack.getUncommon(nUncommon)); + newCards.addAll(boosterPack.getRare(nRare)); + + + cardPool.addAll(newCards); + + //getAddedCards() uses newCardList + newCardList = newCards; + + }//addCards() + + public void addAdditionalCards() { + int nRare = 1; + + ArrayList newCards = new ArrayList(); + newCards.addAll(boosterPack.getRare(nRare)); + + cardPool.addAll(newCards); + //getAddedCards() uses newCardList + + + newCardList.addAll(newCards); + + } + + //gets all of the cards that are in the cardpool + public ArrayList getCards() { + //copy CardList in order to keep private variables private + //if we just return cardPool, it could be changed externally + return new ArrayList(cardPool); + } + + + public int getTotalNumberOfGames(String difficulty) { + //-2 because you start a level 1, and the last level is secret + int numberLevels = rankArray.length - 2; + int nMatches = rankChangeArray[convertDifficultyToIndex(difficulty)]; + + return numberLevels * nMatches; + } + + //this changes getRank() + public void addWin() { + win++; + + int n = convertDifficultyToIndex(); + + if(win % rankChangeArray[n] == 0) rankIndex++; + }//addWin() + + private int convertDifficultyToIndex() { + return convertDifficultyToIndex(getDifficulty()); + } + + private int convertDifficultyToIndex(String difficulty) { + String s = difficulty; + + if(s.equals(EASY)) return 0; + if(s.equals(MEDIUM)) return 1; + if(s.equals(HARD)) return 2; + + //VERY_HARD + return 3; + }//convertDifficultyToIndex() + + public void addLost() { + lost++; + } + + public int getWin() { + return win; + } + + public int getLost() { + return lost; + } + + //should be called first, because the difficultly won't change + public String getDifficulty() { + return difficulty; + } + + public void setDifficulty(String s) { + difficulty = s; + } + + public String[] getDifficutlyChoices() { + return new String[] {EASY, MEDIUM, HARD, VERY_HARD}; + } + + public String getRank() { + //is rankIndex too big? + if(rankIndex == rankArray.length) rankIndex--; + + return rankArray[rankIndex]; + } + + //add cards after a certain number of wins or loses + public boolean shouldAddCards(boolean didWin) { + int n = addCardsArray[convertDifficultyToIndex()]; + + if(didWin) return getWin() % n == 0; + else return getLost() % n == 0; + } + + public boolean shouldAddAdditionalCards(boolean didWin) { + if(didWin) return random.nextBoolean(); + else return false; + } + + + //opponentName is one of the Strings returned by getOpponents() + public Deck getOpponentDeck(String opponentName) { + return null; + } + + public boolean hasSaveFile() { + //File f = new File(this.saveFileName); // The static field QuestData.saveFileName should be accessed in a static way + // No warning is given for it below in getBackupFilename + return ForgeProps.getFile(QUEST.DATA).exists(); + } + + //returns somethings like "questData-10" + //find a new filename + @SuppressWarnings("unused") + static private File getBackupFilename() { + //I made this a long because maybe an int would overflow, but who knows + File original = ForgeProps.getFile(QUEST.DATA); + File parent = original.getParentFile(); + String name = original.getName(); + long n = 1; + + File f; + while((f = new File(parent, name + "-" + n)).exists()) + n++; + + return f; + }//getBackupFilename() + + static public void saveData(QuestData q) { + try { + /* + //rename previous file "questData" to something like questData-23 + //just in case there is an error when playing the game or saving + File file = new File(saveFileName); + if(file.exists()) + file.renameTo(getBackupFilename()); + */ + + //setup QuestData_State + QuestData_State state = new QuestData_State(); + state.win = q.win; + state.lost = q.lost; + state.difficulty = q.difficulty; + state.rankIndex = q.rankIndex; + + state.cardPool = q.cardPool; + state.myDecks = q.myDecks; + state.aiDecks = q.aiDecks; + + + //write object + ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(ForgeProps.getFile(QUEST.DATA))); + out.writeObject(state); + out.flush(); + out.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex, "Error saving Quest Data"); + throw new RuntimeException(ex); + } + }//saveData() + + public static void main(String[] args) { + QuestData q = new QuestData(); + for(int i = 0; i < 20; i++) + q.addCards(); + + for(int i = 0; i < 10; i++) { + QuestData.saveData(q); + QuestData.loadData(); + } + + System.exit(1); + } +} diff --git a/src/QuestData_BoosterPack.java b/src/QuestData_BoosterPack.java new file mode 100644 index 00000000000..836d2856bc3 --- /dev/null +++ b/src/QuestData_BoosterPack.java @@ -0,0 +1,281 @@ +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; + +import forge.error.ErrorViewer; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + +//balance the number of colors and creature/spells for +//new cards that are won in quest mode +public class QuestData_BoosterPack implements NewConstants { + final private String comment = "//"; + + private ArrayList commonCreature = new ArrayList(); + private ArrayList commonSpell = new ArrayList(); + + private ArrayList uncommonCreature = new ArrayList(); + private ArrayList uncommonSpell = new ArrayList(); + + private ArrayList rareCreature = new ArrayList(); + private ArrayList rareSpell = new ArrayList(); + + private Random random = new Random(); + + private String[] colors = { + "gold", Constant.Color.Colorless, Constant.Color.Black, Constant.Color.Blue, Constant.Color.Green, + Constant.Color.Red, Constant.Color.White, + + //repeat colors in order to make Colorless and gold not as popular + Constant.Color.Black, Constant.Color.Blue, Constant.Color.Green, Constant.Color.Red, + Constant.Color.White }; + + + //testing + private ArrayList colorTest = new ArrayList(); + + //prints statistics to make sure everything is working + public static void main(String[] args) { + QuestData_BoosterPack q = new QuestData_BoosterPack(); + + for(int i = 0; i < 100; i++) + q.print(q.getNewCards(6, 3, 1)); + + q.colorStats(); + }//main() + + //testing + //nCommon is the number of common cards + @SuppressWarnings("unchecked") + private ArrayList getNewCards(int nCommon, int nUncommon, int nRare) { + ArrayList out = new ArrayList(); + + out.addAll(getCommon(nCommon)); + out.addAll(getUncommon(nUncommon)); + out.addAll(getRare(nRare)); + + return out; + }//getNewCards() + + + //testing + @SuppressWarnings("unchecked") + private void print(ArrayList list) { + int nCreature = 0; + int nSpell = 0; + + Card c; + for(int i = 0; i < list.size(); i++) { + c = AllZone.CardFactory.getCard(list.get(i).toString(), ""); + + if(c.isCreature()) nCreature++; + else nSpell++; + + colorTest.add(getColor(c)); + }//for + System.out.println("creatures " + nCreature + " - non-creatures " + nSpell); + }//print() + + //testing + private void colorStats() { + String[] colors = { + "gold", Constant.Color.Colorless, Constant.Color.Black, Constant.Color.Blue, Constant.Color.Green, + Constant.Color.Red, Constant.Color.White}; + + for(int outer = 0; outer < colors.length; outer++) { + int n = 0; + + for(int z = 0; z < colorTest.size(); z++) { + if(colorTest.get(z).equals(colors[outer])) n++; + } + System.out.println(colors[outer] + " " + n); + } + }//colorStats() + + public QuestData_BoosterPack() { + setup(ForgeProps.getFile(QUEST.COMMON), commonCreature, commonSpell); + setup(ForgeProps.getFile(QUEST.UNCOMMON), uncommonCreature, uncommonSpell); + setup(ForgeProps.getFile(QUEST.RARE), rareCreature, rareSpell); + } + + private int getColorIndex(int n) { + return n % colors.length; + } + + //return a number that is a multiple of colors.length + //we want to loop all the way through the colors array + private int getLoopStop(int n) { + int stop = colors.length; + while(stop < n) + stop += colors.length; + + return stop; + } + + @SuppressWarnings("unchecked") + public ArrayList getCommon(int n) { + ArrayList bag = new ArrayList(); + String c; + int stop = getLoopStop(n); + + for(int i = 0; i < stop; i++) { + c = colors[getColorIndex(i)]; + + //creatures are more common than spells + bag.add(getColor(c, commonCreature)); + bag.add(getColor(c, commonCreature)); + bag.add(getColor(c, commonSpell)); + } + return getRandom(n, bag); + }//getCommon() + + + @SuppressWarnings("unchecked") + public ArrayList getUncommon(int n) { + ArrayList bag = new ArrayList(); + String c; + int stop = getLoopStop(n); + + for(int i = 0; i < stop; i++) { + c = colors[getColorIndex(i)]; + + //creatures are more common than spells + bag.add(getColor(c, uncommonCreature)); + bag.add(getColor(c, uncommonCreature)); + bag.add(getColor(c, uncommonSpell)); + } + return getRandom(n, bag); + }//getUncommon() + + public ArrayList getRare(int n) { + ArrayList bag = new ArrayList(); + String c; + int stop = getLoopStop(n); + + for(int i = 0; i < stop; i++) { + c = colors[getColorIndex(i)]; + + bag.add(getColor(c, rareCreature)); + bag.add(getColor(c, rareSpell)); + } + return getRandom(n, bag); + }//getRare() + + //returns String of the card name that matches the paramater "color" + @SuppressWarnings("unchecked") + private String getColor(String color, ArrayList list) { + Collections.shuffle(list, random); + + Card c; + String s; + for(int i = 0; i < list.size(); i++) { + s = list.get(i).toString(); + c = AllZone.CardFactory.getCard(s, ""); + if(getColor(c).equals(color)) return s; + } + //just get a random card + //this will happens if there are 0 gold cards + return list.get(0).toString(); + }//getColor() + + + @SuppressWarnings("unchecked") + private String getColor(Card c) { + String m = c.getManaCost(); + Set colors = new HashSet(); + + for(int i = 0; i < m.length(); i++) { + switch(m.charAt(i)) { + case ' ': + break; + case 'G': + colors.add(Constant.Color.Green); + break; + case 'W': + colors.add(Constant.Color.White); + break; + case 'B': + colors.add(Constant.Color.Black); + break; + case 'U': + colors.add(Constant.Color.Blue); + break; + case 'R': + colors.add(Constant.Color.Red); + break; + } + } + if(colors.isEmpty()) return Constant.Color.Colorless; + + if(1 < colors.size()) return "gold"; + + ArrayList list = new ArrayList(colors); + return list.get(0).toString(); + } + + private ArrayList getRandom(int n, ArrayList list) { + //must always shuffle since we are starting at 0 + Collections.shuffle(list, random); + + ArrayList out = new ArrayList(); + for(int i = 0; i < n; i++) + out.add(list.get(i)); + + return out; + } + + @SuppressWarnings("unchecked") + private void setup(File file, ArrayList creatureList, ArrayList spellList) { + ArrayList all = readFile(file); + + Card c; + String s; + for(int i = 0; i < all.size(); i++) { + s = all.get(i).toString(); + + c = AllZone.CardFactory.getCard(s, ""); + if(c.isCreature()) creatureList.add(s); + else spellList.add(s); + } + }//setup() + + @SuppressWarnings("unchecked") + private ArrayList readFile(File file) { + ArrayList cardList = new ArrayList(); + + BufferedReader in; + try { + in = new BufferedReader(new FileReader(file)); + String line = in.readLine(); + + //stop reading if end of file or blank line is read + while(line != null && (line.trim().length() != 0)) { + if(!line.startsWith(comment)) { + cardList.add(line.trim()); + } + + line = in.readLine(); + }//if + + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("QuestData_BoosterPack : readFile() error, " + ex); + } + + return cardList; + }//readFile() + + public String getRarity(String cardName) { + if(commonCreature.contains(cardName) || commonSpell.contains(cardName)) return "Common"; + else if(uncommonCreature.contains(cardName) || uncommonSpell.contains(cardName)) return "Uncommon"; + else if(rareCreature.contains(cardName) || rareSpell.contains(cardName)) return "Rare"; + else if(cardName.equals("Forest") || cardName.equals("Plains") || cardName.equals("Island") + || cardName.equals("Swamp") || cardName.equals("Mountain")) return "Land"; + else return "error"; + } +} \ No newline at end of file diff --git a/src/ReadBoosterPack.java b/src/ReadBoosterPack.java new file mode 100644 index 00000000000..4d196887c03 --- /dev/null +++ b/src/ReadBoosterPack.java @@ -0,0 +1,364 @@ + + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.ArrayList; + +import forge.error.ErrorViewer; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + + +public class ReadBoosterPack implements NewConstants { +// final private String commonFilename = Constant.IO.baseDir +"data/common.txt"; +// final private String uncommonFilename = Constant.IO.baseDir +"data/uncommon.txt"; +// final private String rareFilename = Constant.IO.baseDir +"data/rare.txt"; + + final private String comment = "//"; + + private CardList commonCreatureList; + private CardList commonNonCreatureList; + + private CardList commonList; + private CardList uncommonList; + private CardList rareList; + + + public static void main(String[] args) { + //testing + ReadBoosterPack r = new ReadBoosterPack(); + + + for(int i = 0; i < 1000; i++) { + r.getBoosterPack5(); + } + + System.exit(0); + }//main() + + /* + //average creature versus non-creature + + ReadBoosterPack r = new ReadBoosterPack(); + double n = 0; //total + int nCreature = 0; + int nSpell = 0; + + for(int i = 0; i < 1000; i++) + { + CardList list = r.getBoosterPack(); + + int c = list.getType("Creature").size(); + nCreature += c; + nSpell += (15 -c); + + n += 15; + } + System.out.println(nCreature / n +" - " +nSpell / n); + + System.exit(0); + */ + + public ReadBoosterPack() { + setup(); + } + + //returns "common", "uncommon", or "rare" + public String getRarity(String cardName) { + if(commonList.containsName(cardName)) return "Common"; + if(uncommonList.containsName(cardName)) return "Uncommon"; + if(rareList.containsName(cardName)) return "Rare"; + + ArrayList land = new ArrayList(); + land.add("Forest"); + land.add("Plains"); + land.add("Swamp"); + land.add("Mountain"); + land.add("Island"); + land.add("Terramorphic Expanse"); + if(land.contains(cardName)) return "Land"; + + return "error"; + } + + public CardList getBoosterPack5() { + CardList list = new CardList(); + for(int i = 0; i < 5; i++) + list.addAll(getBoosterPack().toArray()); + + for(int i = 0; i < 40; i++) { + list.add(AllZone.CardFactory.getCard("Forest", Constant.Player.Human)); + list.add(AllZone.CardFactory.getCard("Island", Constant.Player.Human)); + list.add(AllZone.CardFactory.getCard("Plains", Constant.Player.Human)); + list.add(AllZone.CardFactory.getCard("Mountain", Constant.Player.Human)); + list.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Human)); + } + + for(int i = 0; i < 4; i++) + list.add(AllZone.CardFactory.getCard("Terramorphic Expanse", Constant.Player.Human)); + + return list; + }//getBoosterPack5() + + public CardList getBoosterPack() { + CardList pack = new CardList(); + + pack.add(getRandomCard(rareList)); + + for(int i = 0; i < 3; i++) + pack.add(getRandomCard(uncommonList)); + + //11 commons, 7 creature 4 non-creature + CardList variety; + for(int i = 0; i < 7; i++) { + variety = getVariety(commonCreatureList); + pack.add(getRandomCard(variety)); + } + + for(int i = 0; i < 4; i++) { + variety = getVariety(commonNonCreatureList); + pack.add(getRandomCard(variety)); + } + + if(pack.size() != 15) + throw new RuntimeException("ReadBoosterPack : getBoosterPack() error, pack is not 15 card - " + + pack.size()); + + return pack; + } + + //return CardList of 5 or 6 cards, one for each color and maybe an artifact + private CardList getVariety(CardList in) { + CardList out = new CardList(); + + String color[] = Constant.Color.Colors; + Card check; + in.shuffle(); + + for(int i = 0; i < color.length; i++) { + check = findColor(in, color[i]); + if(check != null) out.add(check); + } + + return out; + }//getVariety() + + private Card findColor(CardList in, String color) { + for(int i = 0; i < in.size(); i++) + if(CardUtil.getColors(in.get(i)).contains(color)) return in.get(i); + + return null; + } + + + private Card getRandomCard(CardList list) { + for(int i = 0; i < 10; i++) + list.shuffle(); + + int index = MyRandom.random.nextInt(list.size()); + + Card c = AllZone.CardFactory.copyCard(list.get(index)); + c.setRarity("rare"); + return c; + }//getRandomCard() + + private void setup() { + commonList = readFile(ForgeProps.getFile(REGULAR.COMMON)); + uncommonList = readFile(ForgeProps.getFile(REGULAR.UNCOMMON)); + rareList = readFile(ForgeProps.getFile(REGULAR.RARE)); + + commonCreatureList = commonList.getType("Creature"); + commonNonCreatureList = commonList.filter(new CardListFilter() { + public boolean addCard(Card c) { + return !c.isCreature(); + } + }); + }//setup() + + + private CardList readFile(File file) { + CardList cardList = new CardList(); + + BufferedReader in; + try { + in = new BufferedReader(new FileReader(file)); + String line = in.readLine(); + + //stop reading if end of file or blank line is read + while(line != null && (line.trim().length() != 0)) { + Card c; + if(!line.startsWith(comment)) { + c = AllZone.CardFactory.getCard(line.trim(), Constant.Player.Human); + cardList.add(c); + } + + line = in.readLine(); + }//if + + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("ReadBoosterPack : readFile error, " + ex); + } + + return cardList; + }//readFile() +} + +/* +import java.util.*; +import java.io.*; + +public class ReadBoosterPack +{ +// final private String commonFilename = Constant.IO.baseDir +"data/common.txt"; +// final private String uncommonFilename = Constant.IO.baseDir +"data/uncommon.txt"; +// final private String rareFilename = Constant.IO.baseDir +"data/rare.txt"; + + final private String commonFilename = "common.txt"; + final private String uncommonFilename = "uncommon.txt"; + final private String rareFilename = "rare.txt"; + + final private String comment = "//"; + + private ArrayList commonList; + private ArrayList uncommonList; + private ArrayList rareList; + + + public static void main(String[] args) + { + ReadBoosterPack r = new ReadBoosterPack(); + CardList list = r.getBoosterPack(); + double n = 0; //total + int nCreature = 0; + int nSpell = 0; + + for(int i = 0; i < 2; i++) + { + int c = list.getType("Creature").size(); + nCreature += c; + nSpell += (15 -c); + + n += 15; + } + System.out.println(nCreature / n +" - " +nSpell / n); + + System.exit(0); + }//main() + + public ReadBoosterPack() {setup();} + + //returns "common", "uncommon", or "rare" + public String getRarity(String cardName) + { + if(commonList.contains(cardName)) + return "Common"; + if(uncommonList.contains(cardName)) + return "Uncommon"; + if(rareList.contains(cardName)) + return "Rare"; + + ArrayList land = new ArrayList(); + land.add("Forest"); + land.add("Plains"); + land.add("Swamp"); + land.add("Mountain"); + land.add("Island"); + land.add("Terramorphic Expanse"); + if(land.contains(cardName)) + return "Land"; + + return "error"; + } + + public CardList getBoosterPack5() + { + CardList list = new CardList(); + for(int i = 0; i < 5; i++) + list.addAll(getBoosterPack().toArray()); + + for(int i = 0; i < 40; i++) + { + list.add(AllZone.CardFactory.getCard("Forest", Constant.Player.Human)); + list.add(AllZone.CardFactory.getCard("Island", Constant.Player.Human)); + list.add(AllZone.CardFactory.getCard("Plains", Constant.Player.Human)); + list.add(AllZone.CardFactory.getCard("Mountain", Constant.Player.Human)); + list.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Human)); + } + + for(int i = 0; i < 4; i++) + list.add(AllZone.CardFactory.getCard("Terramorphic Expanse", Constant.Player.Human)); + + return list; + }//getBoosterPack5() + + public CardList getBoosterPack() + { + CardList pack = new CardList(); + + pack.add(getRandomCard(rareList)); + + for(int i = 0; i < 3; i++) + pack.add(getRandomCard(uncommonList)); + + for(int i = 0; i < 11; i++) + pack.add(getRandomCard(commonList)); + + return pack; + } + private Card getRandomCard(ArrayList list) + { + for(int i = 0; i < 10; i++) + Collections.shuffle(list, MyRandom.random); + + int index = MyRandom.random.nextInt(list.size()); + String name = list.get(index).toString(); + + Card c = AllZone.CardFactory.getCard(name, Constant.Player.Human); + c.setRarity("rare"); + return c; + }//getRandomCard() + + private void setup() + { + commonList = readFile(commonFilename); + uncommonList = readFile(uncommonFilename); + rareList = readFile(rareFilename); + + checkName(commonList); + checkName(uncommonList); + checkName(rareList); + } + private void checkName(ArrayList name) + { + for(int i = 0; i < name.size(); i++) + AllZone.CardFactory.getCard(name.get(i).toString(), Constant.Player.Human); + } + + //returns an ArrayList of Strings, the names of the cards read + private ArrayList readFile(String filename) + { + ArrayList cardName = new ArrayList(); + + BufferedReader in; + try{ + in = new BufferedReader(new FileReader(filename)); + String line = in.readLine(); + + //stop reading if end of file or blank line is read + while(line != null && (line.trim().length() != 0)) + { + if(! line.startsWith(comment)) + cardName.add(line.trim()); + + line = in.readLine(); + }//if + + }catch(Exception ex){throw new RuntimeException("ReadBoosterPack : readFile error, " + ex);} + + return cardName; + }//readFile() +} +*/ diff --git a/src/ReadCard.java b/src/ReadCard.java new file mode 100644 index 00000000000..c288441381e --- /dev/null +++ b/src/ReadCard.java @@ -0,0 +1,130 @@ +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.StringTokenizer; + +import forge.error.ErrorViewer; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + + +public class ReadCard implements Runnable, NewConstants { + private BufferedReader in; + private ArrayList allCards = new ArrayList(); + + public static void main(String args[]) throws Exception { + try { + ReadCard read = new ReadCard(ForgeProps.getFile(CARDS)); + + javax.swing.SwingUtilities.invokeAndWait(read); + // read.run(); + + Card c[] = new Card[read.allCards.size()]; + read.allCards.toArray(c); + for(int i = 0; i < c.length; i++) { + System.out.println(c[i].getName()); + System.out.println(c[i].getManaCost()); + System.out.println(c[i].getType()); + System.out.println(c[i].getSpellText()); + System.out.println(c[i].getKeyword()); + System.out.println(c[i].getBaseAttack() + "/" + c[i].getBaseDefense() + "\n"); + } + } catch(Exception ex) { + ErrorViewer.showError(ex); + System.out.println("Error reading file " + ex); + } + } + + public ArrayList getCards() { + return new ArrayList(allCards); + } + + public ReadCard(String filename) { + this(new File(filename)); + } + + public ReadCard(File file) { + if(!file.exists()) + throw new RuntimeException("ReadCard : constructor error -- file not found -- filename is " + + file.getAbsolutePath()); + + //makes the checked exception, into an unchecked runtime exception + try { + in = new BufferedReader(new FileReader(file)); + } catch(Exception ex) { + ErrorViewer.showError(ex, "File \"%s\" not found", file.getAbsolutePath()); + throw new RuntimeException("ReadCard : constructor error -- file not found -- filename is " + + file.getPath()); + } + }//ReadCard() + + public void run() { + Card c; + String s = readLine(); + ArrayList cardNames = new ArrayList(); + + while(!s.equals("End")) { + c = new Card(); + if(s.equals("")) throw new RuntimeException("ReadCard : run() reading error, cardname is blank"); + c.setName(s); + +//for debugging +//System.out.println(c.getName()); + + + s = readLine(); + if(!s.equals("no cost")) c.setManaCost(s); + + s = readLine(); + addTypes(c, s); + + s = readLine(); + if(!s.equals("no text")) c.setText(s); + + s = readLine(); + if(c.isCreature()) { + + int n = s.indexOf("/"); + int att = Integer.parseInt(s.substring(0, n)); + int def = Integer.parseInt(s.substring(n + 1)); + c.setBaseAttack(att); + c.setBaseDefense(def); + s = readLine(); + } + + while(!s.equals("")) { + c.addIntrinsicKeyword(s); + s = readLine(); + } + s = readLine(); + + if(cardNames.contains(c.getName())) { + System.out.println("ReadCard:run() error - duplicate card name: " + c.getName()); + throw new RuntimeException("ReadCard:run() error - duplicate card name: " + c.getName()); + } + + cardNames.add(c.getName()); + allCards.add(c); + } + }//run() + + private void addTypes(Card c, String types) { + StringTokenizer tok = new StringTokenizer(types); + while(tok.hasMoreTokens()) + c.addType(tok.nextToken()); + } + + private String readLine() { + //makes the checked exception, into an unchecked runtime exception + try { + String s = in.readLine(); + if(s != null) s = s.trim(); + return s; + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("ReadCard : readLine(Card) error"); + } + }//readLine(Card) +} \ No newline at end of file diff --git a/src/Run.java b/src/Run.java new file mode 100644 index 00000000000..4eae973fff6 --- /dev/null +++ b/src/Run.java @@ -0,0 +1,206 @@ +public class Run { + public static void main(String[] args) { + AllZone.Computer = new ComputerAI_Input(new ComputerAI_General()); + + + //AllZone.Display = new GuiDisplay2(); + + Deck human = new Deck(Constant.GameType.Constructed); + Deck computer = new Deck(Constant.GameType.Constructed); + + for(int i = 0; i < 12; i++) { +// human.addMain("Plains"); +// computer.addMain("Plains"); + } + + AllZone.GameAction.newGame(human, computer); + AllZone.Display.setVisible(true); + + //*************************************************** + //testing purposes + + //CardFactory cf = AllZone.CardFactory; + + //AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Dauthi Marauder", Constant.Player.Computer)); + //AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Dauthi Marauder", Constant.Player.Computer)); + + + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Deeptread Merrow", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Vampire Bats", Constant.Player.Human)); + + //AllZone.Human_Hand.add(AllZone.CardFactory.getCard("Soul Feast", Constant.Player.Human)); + + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Plains", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Plains", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Forest", Constant.Player.Human)); + + + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Island", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Island", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Human)); + + /* + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Island", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Island", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Mountain", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Plains", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Mountain", Constant.Player.Human)); + */ + /* + for(int i = 0; i < 8; i++) + { + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Human)); + } + */ + +// AllZone.Human_Hand.add(AllZone.CardFactory.getCard("Giant Growth", Constant.Player.Human)); +// for(int i = 0; i < 9; i++) +// AllZone.Human_Play.add(AllZone.CardFactory.getCard("Mountain", Constant.Player.Human)); +// AllZone.Human_Hand.add(AllZone.CardFactory.getCard("Isochron Scepter", Constant.Player.Human)); +// AllZone.Human_Hand.add(AllZone.CardFactory.getCard("Isochron Scepter", Constant.Player.Human)); +// AllZone.Human_Hand.add(AllZone.CardFactory.getCard("Briarhorn", Constant.Player.Human)); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Bitterblossom", Constant.Player.Computer)); +// AllZone.Computer_Hand.add(AllZone.CardFactory.getCard("Anaconda", Constant.Player.Computer)); + + for(int i = 0; i < 17; i++) { + AllZone.Computer_Library.add(AllZone.CardFactory.getCard("Forest", Constant.Player.Computer)); + } + + //AllZone.Computer_Library.add(AllZone.CardFactory.getCard("Elvish Piper", Constant.Player.Computer)); + + + /* + AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Lantern Kami", Constant.Player.Computer)); + AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Lantern Kami", Constant.Player.Computer)); + AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Lantern Kami", Constant.Player.Computer)); + AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Lantern Kami", Constant.Player.Computer)); + AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Garruk Wildspeaker", Constant.Player.Computer)); + */ + + + /* + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Filthy Cur", Constant.Player.Human)); + AllZone.Human_Hand.add(AllZone.CardFactory.getCard("Shock", Constant.Player.Human)); + AllZone.Human_Hand.add(AllZone.CardFactory.getCard("Char", Constant.Player.Human)); + + AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Filthy Cur", Constant.Player.Computer)); + /* + AllZone.Human_Library.add(AllZone.CardFactory.getCard("Ancient Silverback", Constant.Player.Human)); + AllZone.Human_Library.add(AllZone.CardFactory.getCard("Ancient Silverback", Constant.Player.Human)); + AllZone.Human_Library.add(AllZone.CardFactory.getCard("Forest", Constant.Player.Human)); + AllZone.Human_Library.add(AllZone.CardFactory.getCard("Plains", Constant.Player.Human)); + + AllZone.Computer_Library.add(AllZone.CardFactory.getCard("Elvish Piper", Constant.Player.Computer)); + AllZone.Computer_Library.add(AllZone.CardFactory.getCard("Serra Angel", Constant.Player.Computer)); + AllZone.Computer_Library.add(AllZone.CardFactory.getCard("Birds of Paradise", Constant.Player.Computer)); + AllZone.Computer_Library.add(AllZone.CardFactory.getCard("Forest", Constant.Player.Computer)); + AllZone.Computer_Library.add(AllZone.CardFactory.getCard("Elvish Piper", Constant.Player.Computer)); + AllZone.Computer_Library.add(AllZone.CardFactory.getCard("Serra Angel", Constant.Player.Computer)); + AllZone.Computer_Library.add(AllZone.CardFactory.getCard("Birds of Paradise", Constant.Player.Computer)); + + + for(int i = 0; i < 2; i++) + { + AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Mountain", Constant.Player.Computer)); + AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Plains", Constant.Player.Computer)); + AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Computer)); + AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Forest", Constant.Player.Computer)); + AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Island", Constant.Player.Computer)); + + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Mountain", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Plains", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Forest", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Island", Constant.Player.Human)); + } + */ + + /* + + AllZone.Human_Hand.add(AllZone.CardFactory.getCard("Angelfire Crusader", Constant.Player.Human)); + AllZone.Human_Hand.add(AllZone.CardFactory.getCard("March of Souls", Constant.Player.Human)); + AllZone.Human_Hand.add(AllZone.CardFactory.getCard("Reviving Dose", Constant.Player.Human)); + AllZone.Human_Hand.add(AllZone.CardFactory.getCard("Breath of Life", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Mountain", Constant.Player.Human)); + + /* + AllZone.Human_Hand.add(AllZone.CardFactory.getCard("Nevinyrral's Disk", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Human)); + */ + /* + for(int i = 0; i < 5; i++) + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Mountain", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Plains", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Forest", Constant.Player.Human)); + AllZone.Human_Play.add(AllZone.CardFactory.getCard("Elvish Piper", Constant.Player.Human)); + + // AllZone.Computer_Play.add(AllZone.CardFactory.getCard("Tanglebloom", Constant.Player.Computer)); + + // AllZone.Human_Play.add(AllZone.CardFactory.getCard("Swamp", Constant.Player.Human)); + + + /* + Card c = null; + c = AllZone.CardFactory.getCard("Hymn to Tourach", Constant.Player.Human); + AllZone.Human_Hand.add(c); + + + c = AllZone.CardFactory.getCard("Swamp", Constant.Player.Human); + AllZone.Human_Play.add(c); + + c = AllZone.CardFactory.getCard("Swamp", Constant.Player.Human); + AllZone.Human_Play.add(c); + + /* + c = AllZone.CardFactory.getCard("Forest", Constant.Player.Human); + AllZone.Human_Play.add(c); + + c = AllZone.CardFactory.getCard("Birds of Paradise", Constant.Player.Human); + AllZone.Human_Play.add(c); + */ + + /* + Card c = null; + for(int i = 0; i < 3; i++) + { + c = AllZone.CardFactory.getCard(s[i], Constant.Player.Human); + AllZone.Human_Hand.add(c); + } + c = AllZone.CardFactory.getCard("Elvish Piper", Constant.Player.Human); + AllZone.Human_Play.add(c); + + c = AllZone.CardFactory.getCard("Swamp", Constant.Player.Human); + AllZone.Human_Play.add(c); + + c = AllZone.CardFactory.getCard("Forest", Constant.Player.Human); + AllZone.Human_Play.add(c); + + c = AllZone.CardFactory.getCard("Forest", Constant.Player.Human); + AllZone.Human_Play.add(c); + + c = AllZone.CardFactory.getCard("Forest", Constant.Player.Human); + AllZone.Human_Play.add(c); + + c = AllZone.CardFactory.getCard("Forest", Constant.Player.Human); + AllZone.Human_Play.add(c); + + CardFactory cf = AllZone.CardFactory; + for(int i = 0; i < 5; i++) + { + //graveyard - tests Dredge + //AllZone.Human_Graveyard.add(cf.getCard("Darkblast", Constant.Player.Human)); + AllZone.Human_Library.add(cf.getCard("Darkblast", Constant.Player.Human)); + } + AllZone.Human_Library.add(cf.getCard("Mountain", Constant.Player.Human)); + AllZone.Human_Library.add(cf.getCard("Plains", Constant.Player.Human)); + */ + }//main() +} \ No newline at end of file diff --git a/src/RunTest.java b/src/RunTest.java new file mode 100644 index 00000000000..8f267786a95 --- /dev/null +++ b/src/RunTest.java @@ -0,0 +1,312 @@ +import java.util.*; + +public class RunTest +{ + @SuppressWarnings("unchecked") // HashSet needs + static void test() + { + { + Card c; + CardFactory cf = AllZone.CardFactory; + //********* test Card + c = cf.getCard("Elvish Warrior", "a"); + check("1", c.getOwner().equals("a")); + check("1.1", c.getName().equals("Elvish Warrior")); + check("2", c.getManaCost().equals("G G")); + check("2.1", c.getType().contains("Creature")); + check("2.2", c.getType().contains("Elf")); + check("2.3", c.getType().contains("Warrior")); + check("3", c.getText().equals("")); + check("4", c.getNetAttack() == 2); + check("5", c.getNetDefense() == 3); + check("6", c.getKeyword().isEmpty()); + + c = cf.getCard("Shock", ""); + check("14", c.getType().contains("Instant")); + //check("15", c.getText().equals("Shock deals 2 damge to target creature or player.")); + + c = cf.getCard("Bayou", ""); + check("17", c.getManaCost().equals("")); + check("18", c.getType().contains("Land")); + check("19", c.getType().contains("Swamp")); + check("20", c.getType().contains("Forest")); + + //********* test ManaCost + ManaCost manaCost = new ManaCost("G"); + check("21", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Green); + check("22", manaCost.isPaid()); + + manaCost = new ManaCost("7"); + check("23", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Black); + check("24", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Blue); + check("25", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Colorless); + check("26", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Green); + check("27", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Red); + check("28", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.White); + check("29", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.White); + check("30", manaCost.isPaid()); + + manaCost = new ManaCost("2 W W G G B B U U R R"); + check("31", ! manaCost.isPaid()); + //manaCost.subtractMana(Constant.Color.White, 2); + //check("32", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Black); + check("33", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Black); + check("34", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Blue); + check("35", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Blue); + check("36", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Green); + check("37", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Green); + check("38", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Red); + check("39", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Red); + check("40", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Red); + check("41", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Blue); + check("42", manaCost.isPaid()); + + manaCost = new ManaCost("G G"); + check("43", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Green); + check("44", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Green); + check("45", manaCost.isPaid()); + + manaCost = new ManaCost("1 U B"); + check("45", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Black); + check("46", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Blue); + check("47", ! manaCost.isPaid()); + manaCost.subtractMana(Constant.Color.Blue); + check("48", manaCost.isPaid()); + + //********* test CardUtile.getColors() + c = new Card(); + c.setManaCost("G"); + ArrayList color = CardUtil.getColors(c); + check("49", color.contains(Constant.Color.Green)); + check("50", color.size() == 1); + + c = new Card(); + c.setManaCost("W B G R U"); + color = CardUtil.getColors(c); + Set set = new HashSet(color); + check("51", set.size() == 5); + check("52", color.contains(Constant.Color.Black)); + check("53", color.contains(Constant.Color.Blue)); + check("54", color.contains(Constant.Color.Green)); + check("55", color.contains(Constant.Color.Red)); + check("56", color.contains(Constant.Color.White)); + + c = new Card(); + c.setManaCost("2"); + color = CardUtil.getColors(c); + check("57", color.size() == 1); + check("58", color.contains(Constant.Color.Colorless)); + + c = new Card(); + color = CardUtil.getColors(c); + check("59", color.size() == 1); + check("60", color.contains(Constant.Color.Colorless)); + + c = new Card(); + c.setManaCost(""); + color = CardUtil.getColors(c); + check("61", color.size() == 1); + check("62", color.contains(Constant.Color.Colorless)); + + c = cf.getCard("Bayou", "a"); + color = CardUtil.getColors(c); + check("63", color.size() == 1); + check("64", color.contains(Constant.Color.Colorless)); + + c = cf.getCard("Elvish Warrior", "a"); + color = CardUtil.getColors(c); + check("65", color.size() == 1); + check("66", color.contains(Constant.Color.Green)); + + c = new Card(); + c.setManaCost("11 W W B B U U R R G G"); + color = CardUtil.getColors(c); + check("67", color.size() == 5); + + c = new Card(); + c = cf.getCard("Elvish Warrior", "a"); + c.setManaCost("11"); + color = CardUtil.getColors(c); + check("68", color.size() == 1); + check("69", color.contains(Constant.Color.Colorless)); + + check("70", c.isCreature()); + check("71", ! c.isArtifact()); + check("72", ! c.isBasicLand()); + check("73", ! c.isEnchantment()); + check("74", ! c.isGlobalEnchantment()); + check("75", ! c.isInstant()); + check("76", ! c.isLand()); + check("77", ! c.isLocalEnchantment()); + check("78", c.isPermanent()); + check("79", ! c.isSorcery()); + check("80", ! c.isTapped()); + check("81", c.isUntapped()); + + c = cf.getCard("Swamp", "a"); + check("82", c.isBasicLand()); + check("83", c.isLand()); + + c = cf.getCard("Bayou", "a"); + check("84", ! c.isBasicLand()); + check("85", c.isLand()); + + c = cf.getCard("Shock", "a"); + check("86", ! c.isCreature()); + check("87", ! c.isArtifact()); + check("88", ! c.isBasicLand()); + check("89", ! c.isEnchantment()); + check("90", ! c.isGlobalEnchantment()); + check("91", c.isInstant()); + check("92", ! c.isLand()); + check("93", ! c.isLocalEnchantment()); + check("94", ! c.isPermanent()); + check("95", ! c.isSorcery()); + check("96", ! c.isTapped()); + check("97", c.isUntapped()); + + //test Input_PayManaCostUtil + check("98", Input_PayManaCostUtil.getColor("G").equals(Constant.Color.Green)); + check("99", Input_PayManaCostUtil.getColor("1").equals(Constant.Color.Colorless)); + + /* + check("101", Input_PayManaCostUtil.isManaNeeded(Constant.Color.Green, new ManaCost("5")) == true); + check("102", Input_PayManaCostUtil.isManaNeeded(Constant.Color.Blue, new ManaCost("4")) == true); + check("103", Input_PayManaCostUtil.isManaNeeded(Constant.Color.White, new ManaCost("3")) == true); + check("104", Input_PayManaCostUtil.isManaNeeded(Constant.Color.Black, new ManaCost("2")) == true); + check("105", Input_PayManaCostUtil.isManaNeeded(Constant.Color.Red, new ManaCost("1")) == true); + */ + /* + ManaCost cost = new ManaCost("1 B B"); + Input_PayManaCostUtil.isManaNeeded(Constant.Color.Black, cost); + cost.subtractMana(Constant.Color.Black); + cost.subtractMana(Constant.Color.Green); + check("106", Input_PayManaCostUtil.isManaNeeded(Constant.Color.Green, cost) == false); + */ + + c = new Card(); + Card c2 = new Card(); + c.addIntrinsicKeyword("Flying"); + c2.addIntrinsicKeyword("Flying"); + //check("107", CombatUtil.canBlock(c, c2)); + //check("108", CombatUtil.canBlock(c2, c)); + + c = new Card(); + c2 = new Card(); + c2.addIntrinsicKeyword("Flying"); + check("109", CombatUtil.canBlock(c, c2)); + check("110", ! CombatUtil.canBlock(c2, c)); + + + c = cf.getCard("Fyndhorn Elves", ""); + c2 = cf.getCard("Talas Warrior", ""); + check("110a", !CombatUtil.canBlock(c2, c)); + check("110b", CombatUtil.canBlock(c, c2)); + + c = new Card(); + c.setName("1"); + c.setUniqueNumber(1); + c2 = new Card(); + c2.setName("2"); + c2.setUniqueNumber(2); + + //test CardList + CardList cardList = new CardList(new Card[] + {c, c2}); + check("111", cardList.contains(c)); + check("112", cardList.contains(c2)); + check("113", cardList.containsName(c)); + check("114", cardList.containsName(c.getName())); + check("115", cardList.containsName(c2)); + check("116", cardList.containsName(c2.getName())); + + c = new Card(); + check("117", c.hasSickness() == true); + c.addIntrinsicKeyword("Haste"); + check("118", c.hasSickness() == false); + + + } + + { + CardFactory cf = AllZone.CardFactory; + CardList c1 = new CardList(); + c1.add(cf.getCard("Shock", "")); + c1.add(cf.getCard("Royal Assassin", "")); + c1.add(cf.getCard("Hymn to Tourach", "")); + + CardList c2 = c1.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isCreature(); + } + }); + check("119", c2.containsName("Royal Assassin")); + check("119", c2.size() == 1); + + c2 = c1.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.isInstant(); + } + }); + check("120", c2.containsName("Shock")); + check("121", c2.size() == 1); + + c2 = c1.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + return c.getName().equals("Hymn to Tourach"); + } + }); + check("120", c2.containsName("Hymn to Tourach")); + check("121", c2.size() == 1); + + Card card = cf.getCard("Sylvan Basilisk", ""); + Card card2 = cf.getCard("Exalted Angel", ""); + + check("121a", !CombatUtil.canDestroyAttacker(card, card2)); + } + { + check("122", CardUtil.getConvertedManaCost("0") == 0); + check("123", CardUtil.getConvertedManaCost("R") == 1); + check("124", CardUtil.getConvertedManaCost("R R") == 2); + check("125", CardUtil.getConvertedManaCost("R R R") == 3); + check("126", CardUtil.getConvertedManaCost("1") == 1); + } + }//test() + static void check(String message, boolean ok) + { + if(! ok) + throw new RuntimeException("RunTest test error : " +message); + } + public static void main(String args[]) + { + RunTest.test(); + } +} \ No newline at end of file diff --git a/src/SimpleCombat.java b/src/SimpleCombat.java new file mode 100644 index 00000000000..392eaecad77 --- /dev/null +++ b/src/SimpleCombat.java @@ -0,0 +1,99 @@ +import java.util.*; + +class SimpleCombat +{ + private HashMap map = new HashMap(); + private CardList attackers = new CardList(); + + public SimpleCombat() {} + public SimpleCombat(CardList attackingCreatures) + { + CardList a = attackingCreatures; + for(int i = 0; i < a.size(); i++) + addAttacker(a.get(i)); + } + public CardList getAttackers() {return attackers;} + public void addAttacker(Card c) + { + attackers.add(c); + map.put(c, new CardList()); + } + public CardList getBlockers(Card attacker) + { + return (CardList)map.get(attacker); + } + public void addBlocker(Card attacker, Card blocker) + { + CardList list = (CardList)map.get(attacker); + if(list == null) + throw new RuntimeException("SimpleCombat : addBlocker() attacker not found - " +attacker); + + list.add(blocker); + } + public CardList getUnblockedAttackers() + { + CardList list = new CardList(); + Iterator it = map.keySet().iterator(); + while(it.hasNext()) + { + Card attack = (Card) it.next(); + CardList block = (CardList) map.get(attack); + if(block.size() == 0) + list.add(attack); + } + + return list; + } + //creatures destroy each other in combat damage + public CardList[] combatDamage() + { + //aDestroy holds the number of creatures of A's that were destroyed + CardList aDestroy = new CardList(); + CardList bDestroy = new CardList(); + + CardList allAttackers = this.getAttackers(); + for(int i = 0; i < allAttackers.size(); i++) + { + Card attack = allAttackers.get(i); + //for now, CardList blockers should only hold 1 Card + CardList blockers = (CardList) map.get(attack); + if(blockers.size() == 0) + { + } + else + { + + Card block = blockers.get(0); + int blockerDamage = block.getNetAttack(); + int attackerDamage = attack.getNetAttack(); + if(CombatUtil.isDoranInPlay()) { + blockerDamage = block.getNetDefense(); + attackerDamage = attack.getNetDefense(); + } + + if(attack.getNetDefense() <= blockerDamage) + aDestroy.add(attack); + + if(block.getNetDefense() <= attackerDamage) + bDestroy.add(block); + } + }//while + return new CardList[] {aDestroy, bDestroy}; + }//combatDamage() + public String toString() + { + String s = ""; + CardList attack = this.getAttackers(); + CardList block; + for(int i = 0; i < attack.size(); i++) + { + block = this.getBlockers(attack.get(i)); + if(block.isEmpty()) + s +=attack.get(i) +" "; + else + s += attack.get(i) +" - " +block.get(0) +" "; + } + + return s; + } +}//Combat \ No newline at end of file diff --git a/src/Spell.java b/src/Spell.java new file mode 100644 index 00000000000..5243a227583 --- /dev/null +++ b/src/Spell.java @@ -0,0 +1,49 @@ +abstract public class Spell extends SpellAbility implements java.io.Serializable, Cloneable { + + private static final long serialVersionUID = -7930920571482203460L; + + public Spell(Card sourceCard) { + super(SpellAbility.Spell, sourceCard); + + setManaCost(sourceCard.getManaCost()); + setStackDescription(sourceCard.getSpellText()); + + } + + @Override + public boolean canPlay() { + return canPlay(getSourceCard()); + }//canPlay() + + @Override + public String getStackDescription() { + return super.getStackDescription(); + +// return getSourceCard().getName() +" - " + super.getStackDescription(); + } + + public static boolean canPlay(Card card) { + String controller = card.getController(); + + String phase = AllZone.Phase.getPhase(); + String activePlayer = AllZone.Phase.getActivePlayer(); + PlayerZone zone = AllZone.getZone(card); + + if(card.isInstant()) return true; + else if((phase.equals(Constant.Phase.Main1) || phase.equals(Constant.Phase.Main2)) + && controller.equals(activePlayer) && AllZone.Stack.size() == 0 && zone.is(Constant.Zone.Hand)) { + return true; + } + return false; + }//canPlay(Card) + + @Override + public Object clone() { + try { + return super.clone(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Spell : clone() error, " + ex); + } + } +} diff --git a/src/SpellAbility.java b/src/SpellAbility.java new file mode 100644 index 00000000000..dda7c16e1e3 --- /dev/null +++ b/src/SpellAbility.java @@ -0,0 +1,156 @@ +//only SpellAbility can go on the stack +//override any methods as needed +public abstract class SpellAbility +{ + public Object[] choices_made;//open ended Casting choice storage + //choices for constructor isPermanent argument + public static final int Spell = 0; + public static final int Ability = 1; + public static final int Ability_Tap = 2; + + private String description = ""; + private String targetPlayer = ""; + private String stackDescription = ""; + private String manaCost = ""; + + private String type = "Intrinsic"; //set to Intrinsic by default + + private Card targetCard; + private Card sourceCard; + + private boolean spell; + private boolean tapAbility; + private boolean buyBackAbility = false; //false by default + + private Input beforePayMana; + private Input afterResolve; + private Input afterPayMana; + + private CommandArgs randomTarget = new CommandArgs() { + + private static final long serialVersionUID = 1795025064923737374L; + +public void execute(Object o) {}}; + + public SpellAbility(int spellOrAbility, Card i_sourceCard) + { + if(spellOrAbility == Spell) + spell = true; + else if(spellOrAbility == Ability) + spell = false; + else if(spellOrAbility == Ability_Tap) + { + spell = false; + tapAbility = true; + } + + else + throw new RuntimeException("SpellAbility : constructor error, invalid spellOrAbility argument = " +spellOrAbility); + + + + sourceCard = i_sourceCard; + } + //Spell, and Ability, and other Ability objects override this method + abstract public boolean canPlay(); + + //all Spell's and Abilities must override this method + abstract public void resolve(); + +/* + public boolean canPlayAI() + { + return true; + } + public void chooseTargetAI() + { + + } +*/ + public boolean canPlayAI() {return true;} + + public void chooseTargetAI() {randomTarget.execute(this);} + public void setChooseTargetAI(CommandArgs c) {randomTarget = c;} + public CommandArgs getChooseTargetAI() {return randomTarget;} + + public String getManaCost() {return manaCost;} + public void setManaCost(String cost) {manaCost = cost;} + + public boolean isSpell() {return spell; } + public boolean isAbility() {return ! isSpell(); } + public boolean isTapAbility() {return tapAbility;} + + public void setIsBuyBackAbility(boolean b) { buyBackAbility = b;} + public boolean isBuyBackAbility() {return buyBackAbility; } + + public void setSourceCard(Card c) {sourceCard=c;} + public Card getSourceCard() {return sourceCard;} + + //begin - Input methods + public Input getBeforePayMana() {return beforePayMana;} + public void setBeforePayMana(Input in) {beforePayMana = in; } + + public Input getAfterPayMana() {return afterPayMana;} + public void setAfterPayMana(Input in) {afterPayMana = in;} + + public Input getAfterResolve() {return afterResolve;} + public void setAfterResolve (Input in) {afterResolve = in;} + + public void setStackDescription(String s) {stackDescription = s;} + public String getStackDescription() + { + if(stackDescription.equals(getSourceCard().getText().trim())) + return getSourceCard().getName() +" - " +getSourceCard().getText(); + + return stackDescription; + } + + public boolean isIntrinsic() + { + return type.equals("Intrinsic"); + } + public boolean isExtrinsic() + { + return type.equals("Extrinsic"); + } + + public void setType(String s) //Extrinsic or Intrinsic: + { + type = s; + } + + //setDescription() includes mana cost and everything like + //"G, tap: put target creature from your hand into play" + public void setDescription(String s) {description = s;} + public String toString() {return description;} + + public Card getTargetCard() + { + if(targetCard == null) + return null; + + return targetCard; + } + public void setTargetCard(Card card) + { + targetPlayer = null;//reset setTargetPlayer() + + targetCard = card; + String desc = ""; + if (!card.isFaceDown()) + desc = getSourceCard().getName() + " - targeting " +card; + else + desc = getSourceCard().getName() + " - targeting Morph(" + card.getUniqueNumber() + ")"; + setStackDescription(desc); + } + public void setTargetPlayer(String p) + { + targetCard = null;//reset setTargetCard() + + if(p == null || (!(p.equals(Constant.Player.Human) || p.equals(Constant.Player.Computer)))) + throw new RuntimeException("SpellAbility : setTargetPlayer() error, argument is " +p +" source card is " +getSourceCard()); + targetPlayer = p; + setStackDescription(getSourceCard().getName() +" - targeting " +p); + } + public String getTargetPlayer() {return targetPlayer;} +} \ No newline at end of file diff --git a/src/SpellAbilityList.java b/src/SpellAbilityList.java new file mode 100644 index 00000000000..bb3a3474b85 --- /dev/null +++ b/src/SpellAbilityList.java @@ -0,0 +1,53 @@ +import java.util.*; + +public class SpellAbilityList +{ + private ArrayList list = new ArrayList(); + + public SpellAbilityList() {} + public SpellAbilityList(SpellAbility s) {add(s);} + public SpellAbilityList(SpellAbility[] s) + { + for(int i = 0; i < s.length; i++) + add(s[i]); + } + + public void remove(int n) {list.remove(n);} + public void add(SpellAbility s) {list.add(s);} + public int size() {return list.size();} + public SpellAbility get(int n) {return (SpellAbility) list.get(n);} + + public void addAll(SpellAbilityList s) + { + for(int i = 0; i < s.size(); i++) + add(s.get(i)); + } + + //Move1.getMax() uses this + public void execute() + { + for(int i = 0; i < size(); i++) + { + if(! ComputerUtil.canPlay(get(i))) + throw new RuntimeException("SpellAbilityList : execute() error, cannot pay for the spell " +get(i).getSourceCard() +" - " +get(i).getStackDescription()); + + ComputerUtil.playNoStack(get(i)); + } + }//execute() + public String toString() + { + String s = ""; + for(int i = 0; i < size(); i++) + { + s += get(i).getSourceCard().toString(); + s += " - "; + s += get(i).getStackDescription(); + s += "\r\n"; + } + return s; + }//toString() + public boolean equals(Object o) + { + return toString().equals(o.toString()); + } +} \ No newline at end of file diff --git a/src/SpellAbilityUtil.java b/src/SpellAbilityUtil.java new file mode 100644 index 00000000000..95c4fc23b46 --- /dev/null +++ b/src/SpellAbilityUtil.java @@ -0,0 +1,62 @@ +import java.util.*; + +public class SpellAbilityUtil +{ + //only works for MONO-COLORED spells + static public UndoCommand getPayCostCommand(final String player, final String manaCost) + { + return new UndoCommand() + { + /** + * + */ + private static final long serialVersionUID = 1L; + private CardList tapped = new CardList(); + public void execute() + { + tapped.clear(); + + int n = CardUtil.getConvertedManaCost(manaCost); + CardList mana = getAvailableMana(player); + if(mana.size() < n) + throw new RuntimeException("SpellAbilityUtil : payCost() error, not enough mana, trying to pay for the mana cost " +manaCost +" , player " +player); + + for(int i = 0; i < n; i++) + { + mana.get(i).tap(); + tapped.add(mana.get(i)); + } + } + public void undo() + { + for(int i = 0; i < tapped.size(); i++) + tapped.get(i).untap(); + + tapped.clear(); + } + };//UndoCommand + }//payCost() + + static public CardList getAvailableMana(String player) + { + PlayerZone play = AllZone.getZone(Constant.Zone.Play, player); + CardList all = new CardList(play.getCards()); + CardList mana = all.filter(new CardListFilter() + { + public boolean addCard(Card c) + { + if(c.isTapped()) + return false; + + ArrayList a = c.getManaAbility(); + for(Ability_Mana am : a) + return am.isBasic(); + + return false; + }//addCard() + });//CardListFilter + + return mana; + }//getUntappedMana + public static boolean canPlaySpell(Card c) {return Spell.canPlay(c);} +} \ No newline at end of file diff --git a/src/Spell_Evoke.java b/src/Spell_Evoke.java new file mode 100644 index 00000000000..ae1081660e5 --- /dev/null +++ b/src/Spell_Evoke.java @@ -0,0 +1,35 @@ + + +public class Spell_Evoke extends Spell_Permanent +{ + /** + * + */ + private static final long serialVersionUID = 1L; + @SuppressWarnings("unused") // evoke +private boolean evoke; + + public Spell_Evoke(Card sourceCard, String manaCost) + { + super(sourceCard); + this.setManaCost(manaCost); + this.setDescription("Evoke " +manaCost +" - Sacrifice this creature when it comes into play."); + } + public void resolve() + { + super.resolve(); + + final Card card = getSourceCard(); + + final SpellAbility ability = new Ability(card, "0") + { + public void resolve() + { + AllZone.GameAction.sacrifice(card); + } + }; + + ability.setStackDescription("Evoke - sacrifice " +card); + AllZone.Stack.add(ability); + }//resolve() +} \ No newline at end of file diff --git a/src/Spell_Permanent.java b/src/Spell_Permanent.java new file mode 100644 index 00000000000..b0265d0b609 --- /dev/null +++ b/src/Spell_Permanent.java @@ -0,0 +1,44 @@ +public class Spell_Permanent extends Spell +{ + + + + private static final long serialVersionUID = 2413495058630644447L; + + public Spell_Permanent(Card sourceCard) + { + super(sourceCard); + + setManaCost(sourceCard.getManaCost()); + + if(sourceCard.isCreature()) + setStackDescription(sourceCard.getName() +" - Creature " +sourceCard.getNetAttack() +" / " +sourceCard.getNetDefense()); + else + setStackDescription(sourceCard.getName()); + + setDescription(getStackDescription()); + }//Spell_Permanent() + + public boolean canPlay() + { + return super.canPlay() || (getSourceCard().getKeyword().contains("Flash") && !AllZone.GameAction.isCardInPlay(getSourceCard())); + } + + public boolean canPlayAI() + { + //check on legendary crap + if(getSourceCard().getType().contains("Legendary")) + { + CardList list = new CardList(AllZone.Computer_Play.getCards()); + return ! list.containsName(getSourceCard().getName()); + } + return true; + }//canPlayAI() + + public void resolve() + { + Card c = getSourceCard(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getController()); + play.add(c); + } +} \ No newline at end of file diff --git a/src/StackObserver.java b/src/StackObserver.java new file mode 100644 index 00000000000..8c0d3d9cd39 --- /dev/null +++ b/src/StackObserver.java @@ -0,0 +1,17 @@ +import java.util.*; + +//when something is put on the stack, this objects observers the Stack +//and pushes an Input so the other player can play +//for example: computer plays a spell, StackObserver pushes and Input so the human can respond +public class StackObserver implements Observer +{ + public StackObserver (MagicStack stack) + { + stack.addObserver(this); + } + public void update(Observable a, Object b) + { +// if(AllZone.Stack.size() > 0) +// AllZone.InputControl.setInput(new Input_Instant(Input_Instant.NO_NEXT_PHASE, "Spell or Abilities are on the Stack")); + } +} diff --git a/src/StateBasedEffects.java b/src/StateBasedEffects.java new file mode 100644 index 00000000000..875793226c0 --- /dev/null +++ b/src/StateBasedEffects.java @@ -0,0 +1,196 @@ +import java.util.*; + + +public class StateBasedEffects +{ + //this is used to keep track of all state-based effects in play: + private HashMap stateBasedMap = new HashMap(); + + //this is used to define all cards that are state-based effects, and map the corresponding commands to their cardnames + private static HashMap cardToEffectsList = new HashMap(); + + public StateBasedEffects() + { + initStateBasedEffectsList(); + } + + + public void initStateBasedEffectsList() + { //value has to be an array, since certain cards have multiple commands associated with them + cardToEffectsList.put("Conspiracy", new String[] {"Conspiracy"}); + cardToEffectsList.put("Serra Avatar", new String[] {"Serra_Avatar"}); + cardToEffectsList.put("Avatar", new String[] {"Ajani_Avatar_Token"}); + cardToEffectsList.put("Windwright Mage", new String[] {"Windwright_Mage"}); + //cardToEffectsList.put("Baru, Fist of Krosa", new String[] {"Baru"}); + //cardToEffectsList.put("Reach of Brances", new String[] {"Reach_of_Branches"}); + //cardToEffectsList.put("Essence Warden", new String[] {"Essence_Warden"}); + //cardToEffectsList.put("Soul Warden", new String[] {"Soul_Warden"}); + //cardToEffectsList.put("Wirewood Hivemaster", new String[] {"Wirewood_Hivemaster"}); + //cardToEffectsList.put("Angelic Chorus", new String[] {"Angelic_Chorus"}); + cardToEffectsList.put("Uril, the Miststalker", new String[] {"Uril"}); + cardToEffectsList.put("Rabid Wombat", new String[] {"Rabid_Wombat"}); + cardToEffectsList.put("Kithkin Rabble", new String[] {"Kithkin_Rabble"}); + cardToEffectsList.put("Nightmare", new String[] {"Nightmare"}); + cardToEffectsList.put("Aven Trailblazer", new String[] {"Aven_Trailblazer"}); + cardToEffectsList.put("Rakdos Pit Dragon", new String[] {"Rakdos_Pit_Dragon"}); + cardToEffectsList.put("Nyxathid", new String[] {"Nyxathid"}); + cardToEffectsList.put("Lord of Extinction", new String[] {"Lord_of_Extinction"}); + cardToEffectsList.put("Terravore", new String[] {"Terravore"}); + cardToEffectsList.put("Magnivore", new String[] {"Magnivore"}); + cardToEffectsList.put("Tarmogoyf", new String[] {"Tarmogoyf"}); + cardToEffectsList.put("Dakkon Blackblade", new String[] {"Dakkon"}); + cardToEffectsList.put("Korlash, Heir to Blackblade", new String[] {"Korlash"}); + cardToEffectsList.put("Dauntless Dourbark", new String[] {"Dauntless_Dourbark"}); + cardToEffectsList.put("Vexing Beetle", new String[] {"Vexing_Beetle"}); + cardToEffectsList.put("Kird Ape", new String[] {"Kird_Ape"}); + cardToEffectsList.put("Sedge Troll", new String[] {"Sedge_Troll"}); + cardToEffectsList.put("Hedge Troll", new String[] {"Hedge_Troll"}); + cardToEffectsList.put("Wild Nacatl", new String[] {"Wild_Nacatl"}); + cardToEffectsList.put("Liu Bei, Lord of Shu", new String[] {"Liu_Bei"}); + cardToEffectsList.put("Bant Sureblade", new String[] {"Bant_Sureblade"}); + cardToEffectsList.put("Esper Stormblade", new String[] {"Esper_Stormblade"}); + cardToEffectsList.put("Grixis Grimblade", new String[] {"Grixis_Grimblade"}); + cardToEffectsList.put("Jund Hackblade", new String[] {"Jund_Hackblade"}); + cardToEffectsList.put("Naya Hushblade", new String[] {"Naya_Hushblade"}); + cardToEffectsList.put("Mystic Enforcer", new String[] {"Mystic_Enforcer"}); + cardToEffectsList.put("Nimble Mongoose", new String[] {"Nimble_Mongoose"}); + cardToEffectsList.put("Werebear", new String[] {"Werebear"}); + cardToEffectsList.put("Divinity of Pride", new String[] {"Divinity_of_Pride"}); + cardToEffectsList.put("Yavimaya Enchantress", new String[] {"Yavimaya_Enchantress"}); + cardToEffectsList.put("Knight of the Reliquary", new String[] {"Knight_of_the_Reliquary"}); + cardToEffectsList.put("Zuberi, Golden Feather", new String[] {"Zuberi"}); + cardToEffectsList.put("Master of Etherium", new String[] {"Master_of_Etherium", "Master_of_Etherium_Pump", "Master_of_Etherium_Other"}); + cardToEffectsList.put("Relentless Rats", new String[] {"Relentless_Rats_Other"}); + cardToEffectsList.put("Privileged Position", new String[] {"Privileged_Position", "Privileged_Position_Other"}); + cardToEffectsList.put("Elvish Archdruid", new String[] {"Elvish_Archdruid_Pump", "Elvish_Archdruid_Other"}); + cardToEffectsList.put("Wizened Cenn", new String[] {"Wizened_Cenn_Pump", "Wizened_Cenn_Other"}); + cardToEffectsList.put("Goblin King", new String[] {"Goblin_King_Pump", "Goblin_King_Other"}); + cardToEffectsList.put("Lord of Atlantis", new String[] {"Lord_of_Atlantis_Pump","Lord_of_Atlantis_Other"}); + cardToEffectsList.put("Elvish Champion", new String[] {"Elvish_Champion_Pump","Elvish_Champion_Other"}); + cardToEffectsList.put("Field Marshal", new String[] {"Field_Marshal_Pump", "Field_Marshal_Other"}); + cardToEffectsList.put("Aven Brigadier", new String[] {"Aven_Brigadier_Soldier_Pump", "Aven_Brigadier_Bird_Pump", "Aven_Brigadier_Other"}); + cardToEffectsList.put("Scion of Oona", new String[] {"Scion_of_Oona_Pump", "Scion_of_Oona_Other"}); + cardToEffectsList.put("Covetous Dragon", new String[] {"Covetous_Dragon"}); + cardToEffectsList.put("Tethered Griffin", new String[] {"Tethered_Griffin"}); + cardToEffectsList.put("Shared Triumph", new String[] {"Shared_Triumph"}); + cardToEffectsList.put("Crucible of Fire", new String[] {"Crucible_of_Fire"}); + cardToEffectsList.put("Glorious Anthem", new String[] {"Glorious_Anthem"}); + cardToEffectsList.put("Gaea's Anthem", new String[] {"Gaeas_Anthem"}); + cardToEffectsList.put("Bad Moon", new String[] {"Bad_Moon"}); + cardToEffectsList.put("Crusade", new String[] {"Crusade"}); + cardToEffectsList.put("Honor of the Pure", new String[] {"Honor_of_the_Pure"}); + cardToEffectsList.put("Beastmaster Ascension", new String[] {"Beastmaster_Ascension"}); + cardToEffectsList.put("Spidersilk Armor", new String[] {"Spidersilk_Armor"}); + cardToEffectsList.put("Eldrazi Monument", new String[] {"Eldrazi_Monument"}); + cardToEffectsList.put("Muraganda Petroglyphs", new String[] {"Muraganda_Petroglyphs"}); + cardToEffectsList.put("Engineered Plague", new String[] {"Engineered_Plague"}); + cardToEffectsList.put("Night of Souls' Betrayal", new String[] {"Night_of_Souls_Betrayal"}); + cardToEffectsList.put("Thelonite Hermit", new String[] {"Thelonite_Hermit"}); + cardToEffectsList.put("Jacques le Vert", new String[] {"Jacques"}); + cardToEffectsList.put("Kaysa", new String[] {"Kaysa"}); + cardToEffectsList.put("Meng Huo, Barbarian King", new String[] {"Meng_Huo"}); + cardToEffectsList.put("Eladamri, Lord of Leaves", new String[] {"Eladamri"}); + cardToEffectsList.put("Tolsimir Wolfblood", new String[] {"Tolsimir"}); + cardToEffectsList.put("Imperious Perfect", new String[] {"Imperious_Perfect"}); + cardToEffectsList.put("Mad Auntie", new String[] {"Mad_Auntie"}); + cardToEffectsList.put("Veteran Armorer", new String[] {"Veteran_Armorer"}); + cardToEffectsList.put("Radiant, Archangel", new String[] {"Radiant_Archangel"}); + cardToEffectsList.put("Castle", new String[] {"Castle"}); + cardToEffectsList.put("Castle Raptors", new String[] {"Castle_Raptors"}); + cardToEffectsList.put("Mobilization", new String[] {"Mobilization"}); + cardToEffectsList.put("Serra's Blessing", new String[] {"Serras_Blessing"}); + cardToEffectsList.put("Cover of Darkness", new String[] {"Cover_of_Darkness"}); + cardToEffectsList.put("Steely Resolve", new String[] {"Steely_Resolve"}); + cardToEffectsList.put("Concordant Crossroads", new String[] {"Concordant_Crossroads"}); + cardToEffectsList.put("Mass Hysteria", new String[] {"Mass_Hysteria"}); + cardToEffectsList.put("Fervor", new String[] {"Fervor"}); + cardToEffectsList.put("Madrush Cyclops", new String[] {"Madrush_Cyclops"}); + cardToEffectsList.put("Rolling Stones", new String[] {"Rolling_Stones"}); + cardToEffectsList.put("Sun Quan, Lord of Wu", new String[] {"Sun_Quan"}); + cardToEffectsList.put("Kobold Overlord", new String[] {"Kobold_Overlord"}); + cardToEffectsList.put("Kinsbaile Cavalier", new String[] {"Kinsbaile_Cavalier"}); + cardToEffectsList.put("Wren's Run Packmaster", new String[] {"Wrens_Run_Packmaster"}); + cardToEffectsList.put("Sliver Legion", new String[] {"Sliver_Legion"}); + cardToEffectsList.put("Muscle Sliver", new String[] {"Muscle_Sliver"}); + cardToEffectsList.put("Bonesplitter Sliver", new String[] {"Bonesplitter_Sliver"}); + cardToEffectsList.put("Might Sliver", new String[] {"Might_Sliver"}); + cardToEffectsList.put("Watcher Sliver", new String[] {"Watcher_Sliver"}); + cardToEffectsList.put("Winged Sliver", new String[] {"Winged_Sliver"}); + cardToEffectsList.put("Synchronous Sliver", new String[] {"Synchronous_Sliver"}); + cardToEffectsList.put("Fury Sliver", new String[] {"Fury_Sliver"}); + cardToEffectsList.put("Plated Sliver", new String[] {"Plated_Sliver"}); + cardToEffectsList.put("Sidewinder Sliver", new String[] {"Sidewinder_Sliver"}); + cardToEffectsList.put("Crystalline Sliver", new String[] {"Crystalline_Sliver"}); + cardToEffectsList.put("Essence Sliver", new String[] {"Essence_Sliver"}); + cardToEffectsList.put("Sinew Sliver", new String[] {"Sinew_Sliver"}); + cardToEffectsList.put("Horned Sliver", new String[] {"Horned_Sliver"}); + cardToEffectsList.put("Heart Sliver", new String[] {"Heart_Sliver"}); + cardToEffectsList.put("Reflex Sliver", new String[] {"Reflex_Sliver"}); + cardToEffectsList.put("Gemhide Sliver", new String[] {"Gemhide_Sliver"}); + cardToEffectsList.put("Blade Sliver", new String[] {"Blade_Sliver"}); + cardToEffectsList.put("Battering Sliver", new String[] {"Battering_Sliver"}); + cardToEffectsList.put("Marrow-Gnawer", new String[] {"Marrow_Gnawer"}); + cardToEffectsList.put("Joiner Adept", new String[] {"Joiner_Adept"}); + + } + + public HashMap getCardToEffectsList() + { + return cardToEffectsList; + } + + public void addStateBasedEffect(String s) + { + if (stateBasedMap.containsKey(s)) + stateBasedMap.put(s, stateBasedMap.get(s)+1); + else + stateBasedMap.put(s, 1); + } + + public void removeStateBasedEffect(String s) + { + stateBasedMap.put(s, stateBasedMap.get(s)-1); + if(stateBasedMap.get(s) == 0) + stateBasedMap.remove(s); + } + + public HashMap getStateBasedMap() + { + return stateBasedMap; + } + + public void reset() + { + stateBasedMap.clear(); + } + + public void rePopulateStateBasedList() + { + reset(); + PlayerZone playerZone = AllZone.getZone(Constant.Zone.Play, + Constant.Player.Human); + PlayerZone computerZone = AllZone.getZone(Constant.Zone.Play, + Constant.Player.Computer); + + CardList cards = new CardList(); + cards.addAll(playerZone.getCards()); + cards.addAll(computerZone.getCards()); + + System.out.println("== Start add state effects =="); + for (int i=0;i 0) + rarity = rarity.substring(0,1); + return rarity; + + default: return "error"; + } + } + public void addListeners(final JTable table) + { + //updates card detail, listens to any key strokes + table.addKeyListener(new KeyListener() + { + public void keyPressed(KeyEvent ev){} + public void keyTyped(KeyEvent ev){} + public void keyReleased(KeyEvent ev) + { + int row = table.getSelectedRow(); + if(row != -1) + { + cardDetail.updateCardDetail(dataNoCopies.get(row)); + } + } + }); + //updates card detail, listens to any mouse clicks + table.addMouseListener(new MouseAdapter() + { + public void mousePressed(MouseEvent e) + { + int row = table.getSelectedRow(); + if(row != -1) + { + cardDetail.updateCardDetail(dataNoCopies.get(row)); + } + } + }); + + //sorts + MouseListener mouse = new MouseAdapter() + { + public void mousePressed(MouseEvent e) + { + TableColumnModel columnModel = table.getColumnModel(); + int viewColumn = columnModel.getColumnIndexAtX(e.getX()); + int column = table.convertColumnIndexToModel(viewColumn); + + + + if(column != -1) + { + //sort ascending + @SuppressWarnings("unused") + boolean change = sort(column, true); + + //if(! change) + // sort(column, false);//sort descending + + //fireTableDataChanged(); + } + }//mousePressed() + };//MouseListener + table.getTableHeader().addMouseListener(mouse); + }//addCardListener() + + //called by the GUI when a card is added to re-sort + public void resort() + { + sort(recentSortedColumn, recentAscending); + //this.fireTableDataChanged(); + } + + //returns true if any data changed positions + @SuppressWarnings("unchecked") // Arrays.sort +public boolean sort(int column, boolean ascending) + { + //used by addCard() to resort the cards + recentSortedColumn = column; + recentAscending = ascending; + + CardList all = new CardList(); + all.addAll(dataNoCopies.toArray()); + all.addAll(dataCopies.toArray()); + + TableSorter sorter = new TableSorter(all, column, ascending); + Card[] array = all.toArray(); + Arrays.sort(array, sorter); + + /* + //determine if any data changed position + boolean hasChanged = false; + CardList check = removeDuplicateNames(array); + for(int i = 0; i < check.size(); i++) + //do the card names match? + if(! check.get(i).getName().equals(dataNoCopies.get(i).getName())) + hasChanged = true; + */ + + //clear everything, and add sorted data back into the model + dataNoCopies.clear(); + dataCopies.clear(); + addCard(new CardList(array)); + + //this value doesn't seem to matter: + //return hasChanged; + return true; + }//sort() + /* + private CardList removeDuplicateNames(Card[] c) + { + TreeSet check = new TreeSet(); + CardList list = new CardList(); + + for(int i = 0; i < c.length; i++) + { + if(! check.contains(c[i].getName())) + { + check.add(c[i].getName()); + list.add(c[i]); + } + } + + return list; + } + */ +}//CardTableModel \ No newline at end of file diff --git a/src/TableSorter.java b/src/TableSorter.java new file mode 100644 index 00000000000..34d10da7645 --- /dev/null +++ b/src/TableSorter.java @@ -0,0 +1,157 @@ +import java.util.*; + +import forge.properties.ForgeProps; +import forge.properties.NewConstants; +@SuppressWarnings("unchecked") // Comparable needs + +public class TableSorter implements Comparator, NewConstants +{ + private final int column; + private boolean ascending; + + private CardList all; + + //used by compare() + private Comparable aCom = null; + private Comparable bCom = null; + private Card a; + private Card b; + + //used if in_column is 7, new cards first - the order is based on cards.txt + //static because this should only be read once + //static to try to reduce file io operations + private static HashMap cardsTxt = null; + + // 0 1 2 3 4 5 6 7 + //private String column[] = {"Qty", "Name", "Cost", "Color", "Type", "Stats", "Rarity"}; New cards first - the order is based on cards.txt + public TableSorter(CardList in_all, int in_column, boolean in_ascending) + { + all = new CardList(in_all.toArray()); + column = in_column; + ascending = in_ascending; + + if(cardsTxt == null) + cardsTxt = readCardsTxt(); + } + //reads the file "cards.txt" + private HashMap readCardsTxt() + { + HashMap map = new HashMap (); + ArrayList list = FileUtil.readFile(ForgeProps.getFile(CARDS)); + + for(int i = 0; i < list.size(); i++) + map.put(list.get(i).toString().trim(), new Integer(i)); + + return map; + } + + + final public int compare(Object in_a, Object in_b) + { + a = (Card)in_a; + b = (Card)in_b; + + if(column == 0)//Qty + { + aCom = new Integer(countCardName(a.getName(), all)); + bCom = new Integer(countCardName(b.getName(), all)); + } + else if (column == 1)//Name + { + aCom = a.getName(); + bCom = b.getName(); + } + else if (column == 2)//Cost + { + aCom = new Integer(CardUtil.getConvertedManaCost(a.getManaCost())); + bCom = new Integer(CardUtil.getConvertedManaCost(b.getManaCost())); + + if(a.isLand()) + aCom = new Integer(-1); + if(b.isLand()) + bCom = new Integer(-1); + } + else if (column == 3)//Color + { + aCom = getColor(a); + bCom = getColor(b); + } + else if (column == 4)//Type + { + aCom = getType(a); + bCom = getType(b); + } + else if (column == 5)//Stats, attack and defense + { + aCom = new Float(-1); + bCom = new Float(-1); + + if(a.isCreature()) + aCom = new Float(a.getBaseAttack() +"." +a.getBaseDefense()); + if(b.isCreature()) + bCom = new Float(b.getBaseAttack() +"." +b.getBaseDefense()); + } + else if (column == 6)//Rarity + { + aCom = getRarity(a); + bCom = getRarity(b); + } + else if (column == 7)//New First + { + aCom = sortNewFirst(a); + bCom = sortNewFirst(b); + } + + if(ascending) + return aCom.compareTo(bCom); + else + return bCom.compareTo(aCom); + }//compare() + + final private int countCardName(String name, CardList c) + { + int count = 0; + for(int i = 0; i < c.size(); i++) + if(name.equals(c.get(i).getName())) + count++; + + return count; + } + + final private Integer getRarity(Card c) + { + if(c.getRarity().equals("Common")) + return new Integer(1); + else if(c.getRarity().equals("Uncommon")) + return new Integer(2); + else if(c.getRarity().equals("Rare")) + return new Integer(3); + else if(c.getRarity().equals("Land")) + return new Integer(4); + else + return new Integer(5); + } + + final public static String getColor(Card c) + { + ArrayList list = CardUtil.getColors(c); + + if(list.size() == 1) + return list.get(0).toString(); + + return "multi"; + } + + final private Comparable getType(Card c) + { + return c.getType().toString(); + } + + final private Comparable sortNewFirst(Card c) + { + if(! cardsTxt.containsKey(c.getName())) + throw new RuntimeException("TableSorter : sortNewFirst() error, Card not found - " +c.getName() +" in hashmap - " +cardsTxt); + + return cardsTxt.get(c.getName()); + } +} \ No newline at end of file diff --git a/src/TempRun.java b/src/TempRun.java new file mode 100644 index 00000000000..77250a98228 --- /dev/null +++ b/src/TempRun.java @@ -0,0 +1,13 @@ +class TempRun +{ + public static void main(String[] args) + { +// CardFactory cf = AllZone.CardFactory; + + for(int i = 0; i < 10; i++) + System.out.println(MyRandom.percentTrue(10)); + + + System.exit(0); + }//main +} \ No newline at end of file diff --git a/src/Test.java b/src/Test.java new file mode 100644 index 00000000000..fb33ba00f6f --- /dev/null +++ b/src/Test.java @@ -0,0 +1,9 @@ +class Test +{ + public static void main(String[] args) + { + + + System.exit(0); + } +} diff --git a/src/TestMove.java b/src/TestMove.java new file mode 100644 index 00000000000..8a176b9a374 --- /dev/null +++ b/src/TestMove.java @@ -0,0 +1,87 @@ +import java.util.*; + +class TestMove extends Move +{ + private final int myNumber; + + private static int classNumber = - 1; + private static int[] array; + + private static int classIndex; + private int myIndex = -1; + + public static void main(String[] args) + { + test(); + } + //branching 2 + //fully test depths 1 and 2, one test of depth 3 + public static void test() + { + TestMove t; + + t = new TestMove(new int[] {4,1,6,3,2,7,6,9}); + test("1", t.max(t, 3, true) == 7); + + t = new TestMove(new int[] {1,2}); + test("2", t.max(t, 1, true) == 2); + + t = new TestMove(new int[] {2,1}); + test("3", t.max(t, 1, true) == 2); + + + t = new TestMove(new int[] {1,2,3,4}); + test("4", t.max(t, 2, true) == 3); + + t = new TestMove(new int[] {2,1,4,3}); + test("5", t.max(t, 2, true) == 3); + + t = new TestMove(new int[] {4,3,1,2}); + test("6", t.max(t, 2, true) == 3); + + t = new TestMove(new int[] {3,4,2,1}); + test("7", t.max(t, 2, true) == 3); + } + public static void test(String message, boolean shouldBeTrue) + { + if(! shouldBeTrue) + throw new RuntimeException(message); + } + + public TestMove(int i_array[]) + { + this(); + + classIndex = 0; + array = i_array; + } + public TestMove() + { + myNumber = classNumber; + classNumber++; + } + + public int getClassNumber() {return classNumber;} + public int getMyNumber() {return myNumber;} + + public Move[] generateMoves() + { + ArrayList list = new ArrayList(); + + for(int i = 0; i < 2; i++) + list.add(new TestMove()); + + Move m[] = new Move[list.size()]; + list.toArray(m); + return m; + } + public int getScore() + { + if(myIndex == -1) + { + myIndex = classIndex; + classIndex++; + } + return array[myIndex]; + }//getScore() +} \ No newline at end of file diff --git a/src/TestPanel.java b/src/TestPanel.java new file mode 100644 index 00000000000..2e8a50ae228 --- /dev/null +++ b/src/TestPanel.java @@ -0,0 +1,42 @@ +import java.awt.Color; +import java.awt.Rectangle; + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + + +public class TestPanel extends JFrame { + /** + * + */ + private static final long serialVersionUID = 1L; + private JPanel jPanel1 = new JPanel(); + private JLabel jLabel1 = new JLabel(); + + public static void main(String[] args) { + TestPanel p = new TestPanel(); + p.setSize(300, 300); + p.setVisible(true); + } + + public TestPanel() { + try { + jbInit(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + ex.printStackTrace(); + } + } + + private void jbInit() throws Exception { + this.getContentPane().setLayout(null); + jPanel1.setForeground(Color.orange); + jPanel1.setBounds(new Rectangle(15, 36, 252, 156)); + jLabel1.setFont(new java.awt.Font("Dialog", 1, 12)); + jLabel1.setForeground(new Color(70, 90, 163)); + jLabel1.setText("jLabel1"); + this.getContentPane().add(jPanel1, null); + jPanel1.add(jLabel1, null); + } +} \ No newline at end of file diff --git a/src/Time.java b/src/Time.java new file mode 100644 index 00000000000..65fdf6a76df --- /dev/null +++ b/src/Time.java @@ -0,0 +1,23 @@ +public class Time +{ + private long startTime; + private long stopTime; + + public Time() {start();} + + public void start() + { + startTime = System.currentTimeMillis(); + } + + public double stop() + { + stopTime = System.currentTimeMillis(); + return getTime(); + } + + public double getTime() + { + return (stopTime - startTime) / 1000.0; + } +} \ No newline at end of file diff --git a/src/UndoCommand.java b/src/UndoCommand.java new file mode 100644 index 00000000000..113246fd3b1 --- /dev/null +++ b/src/UndoCommand.java @@ -0,0 +1,5 @@ +interface UndoCommand extends Command +{ + public void execute(); + public void undo(); +} diff --git a/src/Wait.java b/src/Wait.java new file mode 100644 index 00000000000..4c235cf3986 --- /dev/null +++ b/src/Wait.java @@ -0,0 +1,10 @@ +public class Wait { + public static void delay() { + try { + Thread.sleep(1000); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("Wait : delay() " + ex); + } + } +} \ No newline at end of file diff --git a/src/WinLose.java b/src/WinLose.java new file mode 100644 index 00000000000..43a01ecf869 --- /dev/null +++ b/src/WinLose.java @@ -0,0 +1,16 @@ +public class WinLose +{ + private int win; + private int lose; + private boolean winRecently; + + public void reset() {win = 0; lose = 0;} + public void addWin() {win++; winRecently = true;} + public void addLose(){lose++; winRecently = false;} + + public int getWin() {return win;} + public int getLose() {return lose;} + public int countWinLose() {return win + lose;} + + public boolean didWinRecently() {return winRecently;} +} \ No newline at end of file diff --git a/src/forge.properties b/src/forge.properties new file mode 100644 index 00000000000..27f98ca1aab --- /dev/null +++ b/src/forge.properties @@ -0,0 +1,46 @@ +#properties-file for mtg forge + +##################### +## The file format ## +##################### + +# maybe you're familiar with property files. it's a simple way for key/value mappings: +# a line starting with '#' is a comment and is ignored. empty lines are also ignored +# other lines are interpreted as =. If you want to use special characters, +# you have to escape them, by prepending '\'. +# so for the key "contains'='", write "contains'\='", and for the key "contains'\'", write "contains'\\'" +# line breaks can be added as \n + + +# this file uses a slightly enhanced concept, including key suffixes. +# you can't use keys containing "--" for this reason: + +# a property ending with "--transparent-properties" results in the referenced properties-file being added + +# a property ending with "--properties" also result in adding, but the name used to add it is prepended. + +# assume a properties file: +# #example.properties +# property=value +# referencing it with +# example--properties=example.properties +# will result in the key "example/property". referencing it with +# example--transparent-properties=example.properties +# will result in the key "property". + +# the third suffix is "--file", and used to reference other files/directories needed in forge +# all paths specified, no matter what suffix, are relative to the current file and not neccessarily to this one + +# some substitutions are applied to a path. "$$" is replaced with "$", a "~/" or "~\" at the path's beginning is +# replaced with the user's home directory. a pattern like "${*}" ("*" being any string) is replaced with the +# system variable, for example, ${user.home} is (at the beginning) the same as "~" + +# all that said, the only thing of importance is that the keys do not change, and that all files are referenced +# correctly. the structure of your properties is not of relevance. you could also include all information in this +# file if you preserve the full keys. + + + +# this link includes the main properties file. you can move/rename etc. the res-folder. you just have to change +# this single line +main--transparent-properties=res/main.properties \ No newline at end of file diff --git a/src/forge/error/ErrorViewer.java b/src/forge/error/ErrorViewer.java new file mode 100644 index 00000000000..f1f9bcce62f --- /dev/null +++ b/src/forge/error/ErrorViewer.java @@ -0,0 +1,215 @@ +package forge.error; + + +import static java.awt.event.InputEvent.*; +import static java.awt.event.KeyEvent.*; +import static javax.swing.JOptionPane.*; + +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Map; +import java.util.Map.Entry; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.KeyStroke; + +import forge.properties.ForgeProps; +import forge.properties.NewConstants; + + + +/** + * The class ErrorViewer. Enables showing and saving error messages that occured in forge. + * + * @version V1.0 02.08.2009 + * @author Clemens Koza + */ +public class ErrorViewer implements NewConstants, NewConstants.LANG.ErrorViewer { + public static final Action ALL_THREADS_ACTION = new ShowAllThreadsAction(); + + /** + * Shows an error dialog taking the exception's message as the error message. + */ + public static void showError(Throwable ex) { + showError(ex, null); + } + + /** + * Shows an error dialog creating the error message by a formatting operation. + */ + public static void showError(Throwable ex, String format, Object... args) { + if(ex == null) return; + showError(ex, String.format(format, args)); + } + + /** + * Shows an error dialog with the specified error message. + */ + public static void showError(final Throwable ex, String message) { + if(ex == null) return; + + final StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + printError(pw, ex, message); + + showDialog(sw.toString()); + } + + /** + * Shows an error without an exception that caused it. + */ + public static void showError(String format, Object... args) { + showError(String.format(format, args)); + } + + /** + * Shows an error without an exception that caused it. + */ + public static void showError(String message) { + showError(new Exception(), message); + } + + /** + * Shows an error message for all running threads. + */ + public static void showErrorAllThreads(String format, Object... args) { + showErrorAllThreads(String.format(format, args)); + } + + /** + * Shows an error message for all running threads. + */ + public static void showErrorAllThreads(String message) { + final StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + printError(pw, message); + + showDialog(sw.toString()); + } + + private static void showDialog(String fullMessage) { + JTextArea area = new JTextArea(fullMessage, 40, 90); + area.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 10)); + area.setEditable(false); + area.setLineWrap(true); + area.setWrapStyleWord(true); + + //Button is not modified, String gets the automatic listener to hide the dialog + Object[] options = { + new JButton(new SaveAction(area)), ForgeProps.getLocalized(BUTTON_CLOSE), + new JButton(new ExitAction())}; + JOptionPane pane = new JOptionPane(new JScrollPane(area), ERROR_MESSAGE, DEFAULT_OPTION, null, options, + options[1]); + JDialog dlg = pane.createDialog(ForgeProps.getLocalized(TITLE)); + dlg.setResizable(true); + dlg.setVisible(true); + dlg.dispose(); + } + + /** + * Prints the error message for the specified exception to the print writer + */ + private static void printError(PrintWriter pw, Throwable ex, String message) { + if(message != null) System.err.println(message); + ex.printStackTrace(); + + pw.printf(ForgeProps.getLocalized(MESSAGE), ForgeProps.getProperty(FORUM), ForgeProps.getProperty(MAIL), + message != null? message:ex.getMessage()); + ex.printStackTrace(pw); + } + + /** + * Prints the error message to the print writer, showing all running threads' stack traces. + */ + private static void printError(PrintWriter pw, String message) { + System.err.println(message); + + pw.printf(ForgeProps.getLocalized(MESSAGE), ForgeProps.getProperty(FORUM), ForgeProps.getProperty(MAIL), + message); + Map traces = Thread.getAllStackTraces(); + for(Entry e:traces.entrySet()) { + pw.println(); + pw.printf("%s (%s):%n", e.getKey().getName(), e.getKey().getId()); + for(StackTraceElement el:e.getValue()) { + pw.println(el); + } + } + } + + private static class SaveAction extends AbstractAction { + + private static final long serialVersionUID = 9146834661273525959L; + + private static JFileChooser c; + + private JTextArea area; + + public SaveAction(JTextArea area) { + super(ForgeProps.getLocalized(BUTTON_SAVE)); + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(VK_S, CTRL_DOWN_MASK)); + this.area = area; + } + + public void actionPerformed(ActionEvent e) { + if(c == null) c = new JFileChooser(); + + File f; + for(int i = 0;; i++) { + String name = String.format("%TF-%02d.txt", System.currentTimeMillis(), i); + f = new File(name); + if(!f.exists()) break; + } + c.setSelectedFile(f); + c.showSaveDialog(null); + f = c.getSelectedFile(); + + try { + BufferedWriter bw = new BufferedWriter(new FileWriter(f)); + bw.write(area.getText()); + bw.close(); + } catch(IOException ex) { + showError(ex, ForgeProps.getLocalized(ERRORS.SAVE_MESSAGE)); + } + } + } + + private static class ExitAction extends AbstractAction { + + private static final long serialVersionUID = 276202595758381626L; + + public ExitAction() { + super(ForgeProps.getLocalized(BUTTON_EXIT)); + } + + + public void actionPerformed(ActionEvent e) { + System.exit(0); + } + } + + private static class ShowAllThreadsAction extends AbstractAction { + + private static final long serialVersionUID = 5638147106706803363L; + + public ShowAllThreadsAction() { + super(ForgeProps.getLocalized(SHOW_ERROR)); + } + + public void actionPerformed(ActionEvent e) { + showErrorAllThreads(ForgeProps.getLocalized(ERRORS.SHOW_MESSAGE)); + } + } +} diff --git a/src/forge/error/ExceptionHandler.java b/src/forge/error/ExceptionHandler.java new file mode 100644 index 00000000000..3d45be62e2c --- /dev/null +++ b/src/forge/error/ExceptionHandler.java @@ -0,0 +1,42 @@ +/** +* ExceptionHandler.java +* +* Created on 27.09.2009 +*/ + +package forge.error; + + +import java.lang.Thread.UncaughtExceptionHandler; + + +/** +* This class handles all exceptions that weren't caught by showing the error to the user. +*/ +public class ExceptionHandler implements UncaughtExceptionHandler { + static { + //Tells Java to let this class handle any uncaught exception + Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler()); + //Tells AWT to let this class handle any uncaught exception + System.setProperty("sun.awt.exception.handler", ExceptionHandler.class.getName()); + } + + /** + * Call this at the beginning to make sure that the class is loaded and the static initializer has run + */ + public static void registerErrorHandling() { + System.out.println("Error handling registered!"); + } + + + public void uncaughtException(Thread t, Throwable ex) { + ErrorViewer.showError(ex); + } + + /** + * This Method is called by AWT when an error is thrown in the event dispatching thread and not caught. + */ + public void handle(Throwable ex) { + ErrorViewer.showError(ex); + } +} diff --git a/src/forge/gui/ForgeAction.java b/src/forge/gui/ForgeAction.java new file mode 100644 index 00000000000..074bc8b310f --- /dev/null +++ b/src/forge/gui/ForgeAction.java @@ -0,0 +1,50 @@ +package forge.gui; +/** + * ForgeAction.java + * + * Created on 02.09.2009 + */ + + + + +import javax.swing.AbstractAction; +import javax.swing.AbstractButton; +import javax.swing.JMenuItem; + +import forge.properties.ForgeProps; + + + + +/** + * The class ForgeAction. + * + * @version V0.0 02.09.2009 + * @author Clemens Koza + */ +public abstract class ForgeAction extends AbstractAction { + + private static final long serialVersionUID = -1881183151063146955L; + private String property; + + /** + * @param property A Property key containing the keys "/button" and "/menu". + */ + public ForgeAction(String property) { + super(ForgeProps.getLocalized(property + "/button")); + this.property = property; + putValue("buttonText", ForgeProps.getLocalized(property + "/button")); + putValue("menuText", ForgeProps.getLocalized(property + "/menu")); + } + + protected String getProperty() { + return property; + } + + public T setupButton(T button) { + button.setAction(this); + button.setText((String) getValue(button instanceof JMenuItem? "menuText":"buttonText")); + return button; + } +} diff --git a/src/forge/gui/ListChooser.java b/src/forge/gui/ListChooser.java new file mode 100644 index 00000000000..cf8f0df6323 --- /dev/null +++ b/src/forge/gui/ListChooser.java @@ -0,0 +1,292 @@ +/** + * ListChooser.java + * + * Created on 31.08.2009 + */ + +package forge.gui; + + +import static java.util.Arrays.*; +import static java.util.Collections.*; +import static javax.swing.JOptionPane.*; +import static javax.swing.WindowConstants.*; + +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.AbstractList; +import java.util.List; + +import javax.swing.AbstractAction; +import javax.swing.AbstractListModel; +import javax.swing.Action; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + + +/** + * A simple class that shows a list of choices in a dialog. Two properties influence the behavior of a list + * chooser: minSelection and maxSelection. These two give the allowed number of selected items for the dialog to be + * closed. + *
    + *
  • If minSelection is 0, there will be a Cancel button.
  • + *
  • If minSelection is 0 or 1, double-clicking a choice will also close the dialog.
  • + *
  • If the number of selections is out of bounds, the "OK" button is disabled.
  • + *
  • The dialog was "committed" if "OK" was clicked or a choice was double clicked.
  • + *
  • The dialog was "canceled" if "Cancel" or "X" was clicked.
  • + *
  • If the dialog was canceled, the selection will be empty.
  • + *
  • + *
+ */ +public class ListChooser { + public static void main(String[] args) { + ListChooser c = new ListChooser("test", "choose a or b", 0, 2, "a", "b"); + System.out.println(c.show()); + for(String s:c.getSelectedValues()) { + System.out.println(s); + } + } + + //Data and number of choices for the list + private List list; + private int minChoices, maxChoices; + + //Decoration + private String title; + + //Flag: was the dialog already shown? + private boolean called; + //initialized before; listeners may be added to it + private JList jList; + //Temporarily stored for event handlers during show + private JDialog d; + private JOptionPane p; + private Action ok, cancel; + + public ListChooser(String title, T... list) { + this(title, 1, list); + } + + public ListChooser(String title, int numChoices, T... list) { + this(title, numChoices, numChoices, list); + } + + public ListChooser(String title, int minChoices, int maxChoices, T... list) { + this(title, null, minChoices, maxChoices, list); + } + + public ListChooser(String title, String message, T... list) { + this(title, message, 1, list); + } + + public ListChooser(String title, String message, int numChoices, T... list) { + this(title, message, numChoices, numChoices, list); + } + + public ListChooser(String title, String message, int minChoices, int maxChoices, T... list) { + this(title, message, minChoices, maxChoices, asList(list)); + } + + public ListChooser(String title, List list) { + this(title, 1, list); + } + + public ListChooser(String title, int numChoices, List list) { + this(title, numChoices, numChoices, list); + } + + public ListChooser(String title, int minChoices, int maxChoices, List list) { + this(title, null, minChoices, maxChoices, list); + } + + public ListChooser(String title, String message, List list) { + this(title, message, 1, list); + } + + public ListChooser(String title, String message, int numChoices, List list) { + this(title, message, numChoices, numChoices, list); + } + + public ListChooser(String title, String message, int minChoices, int maxChoices, List list) { + this.title = title; + this.minChoices = minChoices; + this.maxChoices = maxChoices; + this.list = unmodifiableList(list); + jList = new JList(new ChooserListModel()); + jList.getSelectionModel().addListSelectionListener(null); + ok = new CloseAction(OK_OPTION, "OK"); + ok.setEnabled(minChoices == 0); + cancel = new CloseAction(CANCEL_OPTION, "Cancel"); + + Object[] options; + if(minChoices == 0) options = new Object[] {new JButton(ok), new JButton(cancel)}; + else options = new Object[] {new JButton(ok)}; + + p = new JOptionPane(new Object[] {message, new JScrollPane(jList)}, QUESTION_MESSAGE, DEFAULT_OPTION, + null, options, options[0]); + jList.getSelectionModel().addListSelectionListener(new SelListener()); + jList.addMouseListener(new DblListener()); + } + + /** + * Returns the JList used in the list chooser. this is useful for registering listeners before showing the + * dialog. + */ + public JList getJList() { + return jList; + } + + /** + * Shows the dialog and returns after the dialog was closed. + */ + public synchronized boolean show() { + if(called) throw new IllegalStateException("Already shown"); + int value; + do { + d = p.createDialog(p.getParent(),title); + if(minChoices != 0) d.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + jList.setSelectedIndex(0); + d.setVisible(true); + d.dispose(); + value = (Integer) p.getValue(); + if(value != OK_OPTION) jList.clearSelection(); + //can't stop closing by ESC, so repeat if cancelled + } while(minChoices != 0 && value != OK_OPTION); + /* an assertion checks if some condition is true. if not, an AssertionError is thrown, signaling an + * error in the program's logic + * by default, assertions are disabled at runtime, meaning the boolean expression is not evaluated. + * that is why you should NEVER do critical operations in the assert statement. + * instead of + * + * assert showConfirmDialog(...) == OK_OPTION; + * + * write + * + * int value = showConfirmDialog(...); + * assert value == OK_OPTION; + */ + //this assert checks if we really don't return on a cancel if input is mandatory + assert minChoices == 0 || value == OK_OPTION; + called = true; + return value == OK_OPTION; + } + + /** + * Returns if the dialog was closed by pressing "OK" or double clicking an option the last time + */ + public boolean isCommitted() { + if(!called) throw new IllegalStateException("not yet shown"); + return (Integer) p.getValue() == OK_OPTION; + } + + /** + * Returns the selected indices as a list of integers + */ + public List getSelectedIndices() { + if(!called) throw new IllegalStateException("not yet shown"); + final int[] indices = jList.getSelectedIndices(); + return new AbstractList() { + @Override + public int size() { + return indices.length; + } + + @Override + public Integer get(int index) { + return indices[index]; + } + }; + } + + /** + * Returns the selected values as a list of objects. no casts are necessary when retrieving the objects. + */ + public List getSelectedValues() { + if(!called) throw new IllegalStateException("not yet shown"); + final Object[] selected = jList.getSelectedValues(); + return new AbstractList() { + @Override + public int size() { + return selected.length; + } + + @SuppressWarnings("unchecked") + @Override + public T get(int index) { + return (T) selected[index]; + } + }; + } + + /** + * Returns the (minimum) selected index, or -1 + */ + public int getSelectedIndex() { + if(!called) throw new IllegalStateException("not yet shown"); + return jList.getSelectedIndex(); + } + + /** + * Returns the (first) selected value, or null + */ + @SuppressWarnings("unchecked") + public T getSelectedValue() { + if(!called) throw new IllegalStateException("not yet shown"); + return (T) jList.getSelectedValue(); + } + + private void commit() { + if(ok.isEnabled()) p.setValue(OK_OPTION); + } + + private class ChooserListModel extends AbstractListModel { + + private static final long serialVersionUID = 3871965346333840556L; + + public int getSize() { + return list.size(); + } + + + public Object getElementAt(int index) { + return list.get(index); + } + } + + private class CloseAction extends AbstractAction { + + private static final long serialVersionUID = -8426767786083886936L; + private int value; + + public CloseAction(int value, String label) { + super(label); + this.value = value; + } + + + public void actionPerformed(ActionEvent e) { + p.setValue(value); + } + } + + private class SelListener implements ListSelectionListener { + + public void valueChanged(ListSelectionEvent e) { + int num = jList.getSelectedIndices().length; + ok.setEnabled(num >= minChoices && num <= maxChoices); + } + } + + private class DblListener extends MouseAdapter { + @Override + public void mouseClicked(MouseEvent e) { + if(e.getClickCount() == 2) commit(); + } + } +} diff --git a/src/forge/properties/ForgeProps.java b/src/forge/properties/ForgeProps.java new file mode 100644 index 00000000000..05fb3b57344 --- /dev/null +++ b/src/forge/properties/ForgeProps.java @@ -0,0 +1,121 @@ +package forge.properties; +/** + * ForgeProps.java + * + * Created on 30.08.2009 + */ + + +import static java.lang.String.*; + +import java.io.File; +import java.io.IOException; +import java.util.Locale; + +import treeProperties.TreeProperties; +import forge.error.ErrorViewer; + + +/** + * The class ForgeProps. Wrapper around TreeProperties to support the uses in forge. + */ +public class ForgeProps { + private static final TreeProperties properties; + + static { + TreeProperties p; + try { + p = new TreeProperties("forge.properties"); + p.rethrow(); + } catch(IOException ex) { + ErrorViewer.showError(ex); + p = null; + } + properties = p; + } + + /** + * Returns the tree properties of forge + */ + public static TreeProperties getProperties() { + return properties; + } + + /** + * Returns the string property value, or null if there's no such property + */ + public static String getProperty(String key) { + return getProperty(key, null); + } + + /** + * Returns the string property value, or def if there's no such property + */ + public static String getProperty(String key, String def) { + String result; + try { + result = getProperties().getProperty(key); + if(result == null) result = def; + } catch(Exception ex) { + result = def; + } + return result; + } + + /** + * Returns the File property value, or null if there's no such property + */ + public static File getFile(String key) { + return getFile(key, null); + } + + /** + * Returns the File property value, or def if there's no such property + */ + public static File getFile(String key, File def) { + File result; + try { + result = getProperties().getFile(key); + if(result == null) result = def; + } catch(Exception ex) { + result = def; + } + return result; + } + + /** + * Returns the localized version of the specified property. The key is a format string containing "%s", which + * is replaced with a language code (ISO 639-1, see {@link Locale#getLanguage()}). First, the configured + * language is used. Second, the locale's code is used. If none of them contains the requested key, "en" is + * used as the language code. + */ + public static String getLocalized(String key) { + return getLocalized(key, null); + } + + /** + * Returns the localized version of the specified property. The key is a format string containing "%s", which + * is replaced with a language code (ISO 639-1, see {@link Locale#getLanguage()}). First, the configured + * language is used. Second, the locale's code is used. If none of them contains the requested key, "en" is + * used as the language code. If even that has no value, the def parameter is returned. + */ + public static String getLocalized(String key, String def) { + //the list of languages to look for, in the order to be used + //the first is the configured language + //the second is the default locale's language code + String[] languages = {getProperty(NewConstants.LANG.LANGUAGE), Locale.getDefault().getLanguage(), "en"}; + try { + for(String lang:languages) { + //could be if a property does not exist + //just skip it, and try the next + if(lang == null) continue; + String result = getProperty(format(key, lang)); + if(result != null) return result; + } + //exceptions are skipped here; also the error viewer uses this, and reporting exceptions may result + //in a more fatal error (stack overflow) + } catch(Exception ex) {} + //if no property was found, or an error occured, return the default value + return def; + } +} diff --git a/src/forge/properties/NewConstants.java b/src/forge/properties/NewConstants.java new file mode 100644 index 00000000000..74643a2dc93 --- /dev/null +++ b/src/forge/properties/NewConstants.java @@ -0,0 +1,235 @@ + +package forge.properties; + + +/** + * NewConstants.java + * + * Created on 22.08.2009 + */ + + +/** + * property keys + * + * @version V0.0 22.08.2009 + * @author Clemens Koza + */ +public interface NewConstants { + //General properties + public static final String MAIL = "program/mail"; + public static final String FORUM = "program/forum"; + + public static final String DECKS = "decks"; + public static final String BOOSTER_DECKS = "booster-decks"; + + public static final String TOKENS = "tokens"; + public static final String CARD_PICTURES = "card-pictures"; + public static final String CARDS = "cards"; + public static final String REMOVED = "removed-cards"; + public static final String NAME_MUTATOR = "name-mutator"; + + public static final String IMAGE_BASE = "image/base"; + + /** + * properties for regular game + */ + public static interface REGULAR { + public static final String COMMON = "regular/common"; + public static final String UNCOMMON = "regular/uncommon"; + public static final String RARE = "regular/rare"; + } + + /** + * properties for quest game + */ + public static interface QUEST { + public static final String COMMON = "quest/common"; + public static final String UNCOMMON = "quest/uncommon"; + public static final String RARE = "quest/rare"; + + public static final String EASY = "quest/easy"; + public static final String MEDIUM = "quest/medium"; + public static final String HARD = "quest/hard"; + + public static final String DATA = "quest/data"; + } + + /** + * gui-related properties + */ + public static interface GUI { + public static interface GuiDisplay { + public static final String LAYOUT = "gui/Display"; + } + } + + /** + * Localization properties + */ + public static interface LANG { + public static final String PROGRAM_NAME = "%s/program/name"; + public static final String LANGUAGE = "lang"; + + public static interface HowTo { + public static final String TITLE = "%s/HowTo/title"; + public static final String MESSAGE = "%s/HowTo/message"; + } + + public static interface ErrorViewer { + public static final String SHOW_ERROR = "%s/ErrorViewer/show"; + + public static final String TITLE = "%s/ErrorViewer/title"; + public static final String MESSAGE = "%s/ErrorViewer/message"; + public static final String BUTTON_SAVE = "%s/ErrorViewer/button/save"; + public static final String BUTTON_CLOSE = "%s/ErrorViewer/button/close"; + public static final String BUTTON_EXIT = "%s/ErrorViewer/button/exit"; + + public static interface ERRORS { + public static final String SAVE_MESSAGE = "%s/ErrorViewer/errors/save/message"; + public static final String SHOW_MESSAGE = "%s/ErrorViewer/errors/show/message"; + } + } + + public static interface Gui_BoosterDraft { + public static final String CLOSE_MESSAGE = "%s/BoosterDraft/close/message"; + public static final String SAVE_MESSAGE = "%s/BoosterDraft/save/message"; + public static final String SAVE_TITLE = "%s/BoosterDraft/save/title"; + public static final String RENAME_MESSAGE = "%s/BoosterDraft/rename/message"; + public static final String RENAME_TITLE = "%s/BoosterDraft/rename/title"; + public static final String SAVE_DRAFT_MESSAGE = "%s/BoosterDraft/saveDraft/message"; + public static final String SAVE_DRAFT_TITLE = "%s/BoosterDraft/saveDraft/title"; + } + + public static interface GuiDisplay { + public static interface MENU_BAR { + public static interface MENU { + public static final String TITLE = "%s/Display/menu/title"; + } + } + + public static final String HUMAN_TITLE = "%s/Display/human/title"; + + public static interface HUMAN_HAND { + public static final String TITLE = "%s/Display/human/hand/title"; + } + + public static interface HUMAN_LIBRARY { + public static final String TITLE = "%s/Display/human/library/title"; + } + + public static final String HUMAN_GRAVEYARD = "%s/Display/human/graveyard"; + + public static interface HUMAN_GRAVEYARD { + public static final String TITLE = "%s/Display/human/graveyard/title"; + public static final String BUTTON = "%s/Display/human/graveyard/button"; + public static final String MENU = "%s/Display/human/graveyard/menu"; + } + + public static final String HUMAN_REMOVED = "%s/Display/human/removed"; + + public static interface HUMAN_REMOVED { + public static final String TITLE = "%s/Display/human/removed/title"; + public static final String BUTTON = "%s/Display/human/removed/button"; + public static final String MENU = "%s/Display/human/removed/menu"; + } + + public static final String COMBAT = "%s/Display/combat/title"; + + public static final String HUMAN_FLASHBACK = "%s/Display/human/flashback"; + + public static interface HUMAN_FLASHBACK { + public static final String TITLE = "%s/Display/human/flashback/title"; + public static final String BUTTON = "%s/Display/human/flashback/button"; + public static final String MENU = "%s/Display/human/flashback/menu"; + } + + public static final String COMPUTER_TITLE = "%s/Display/computer/title"; + + public static interface COMPUTER_HAND { + public static final String TITLE = "%s/Display/computer/hand/title"; + } + + public static interface COMPUTER_LIBRARY { + public static final String TITLE = "%s/Display/computer/library/title"; + } + + + public static final String COMPUTER_GRAVEYARD = "%s/Display/human/graveyard"; + + public static interface COMPUTER_GRAVEYARD { + public static final String TITLE = "%s/Display/computer/graveyard/title"; + public static final String BUTTON = "%s/Display/computer/graveyard/button"; + public static final String MENU = "%s/Display/computer/graveyard/menu"; + } + + + public static final String COMPUTER_REMOVED = "%s/Display/human/removed"; + + public static interface COMPUTER_REMOVED { + public static final String TITLE = "%s/Display/computer/removed/title"; + public static final String BUTTON = "%s/Display/computer/removed/button"; + public static final String MENU = "%s/Display/computer/removed/menu"; + } + + public static final String CONCEDE = "%s/Display/concede"; + + public static interface CONCEDE { + public static final String BUTTON = "%s/Display/concede/button"; + public static final String MENU = "%s/Display/concede/menu"; + } + } + + public static interface Gui_DownloadPictures { + public static final String TITLE = "%s/DownloadPictures/title"; + + public static final String PROXY_ADDRESS = "%s/DownloadPictures/proxy/address"; + public static final String PROXY_PORT = "%s/DownloadPictures/proxy/port"; + + public static final String NO_PROXY = "%s/DownloadPictures/proxy/type/none"; + public static final String HTTP_PROXY = "%s/DownloadPictures/proxy/type/http"; + public static final String SOCKS_PROXY = "%s/DownloadPictures/proxy/type/socks"; + + public static final String NO_MORE = "%s/DownloadPictures/no-more"; + + public static final String BAR_BEFORE_START = "%s/DownloadPictures/bar/before-start"; + public static final String BAR_WAIT = "%s/DownloadPictures/bar/wait"; + public static final String BAR_CLOSE = "%s/DownloadPictures/bar/close"; + + public static interface BUTTONS { + public static final String START = "%s/DownloadPictures/button/start"; + public static final String CANCEL = "%s/DownloadPictures/button/cancel"; + public static final String CLOSE = "%s/DownloadPictures/button/close"; + } + + public static interface ERRORS { + public static final String PROXY_CONNECT = "%s/DownloadPictures/errors/proxy/connect"; + public static final String OTHER = "%s/DownloadPictures/errors/other"; + } + } + + public static interface Gui_NewGame { + public static interface MENU_BAR { + public static interface MENU { + public static final String TITLE = "%s/NewGame/menu/title"; + public static final String LF = "%s/NewGame/menu/lookAndFeel"; + public static final String DOWNLOAD = "%s/NewGame/menu/download"; + public static final String CARD_SIZES = "%s/NewGame/menu/cardSizes"; + public static final String ABOUT = "%s/NewGame/menu/about"; + } + + public static interface OPTIONS { + public static final String TITLE = "%s/NewGame/options/title"; + + public static interface GENERATE { + public static final String TITLE = "%s/NewGame/options/generate/title"; + public static final String REMOVE_SMALL = "%s/NewGame/options/generate/removeSmall"; + public static final String REMOVE_ARTIFACTS = "%s/NewGame/options/generate/removeArtifacts"; + } + } + } + + public static interface ERRORS {} + } + } +} diff --git a/src/org/jdesktop/swingx/MultiSplitLayout.java b/src/org/jdesktop/swingx/MultiSplitLayout.java new file mode 100644 index 00000000000..cf078ab6a1c --- /dev/null +++ b/src/org/jdesktop/swingx/MultiSplitLayout.java @@ -0,0 +1,1358 @@ +/* + * $Id: MultiSplitLayout.java,v 1.15 2005/10/26 14:29:54 hansmuller Exp $ + * + * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, + * Santa Clara, California 95054, U.S.A. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.jdesktop.swingx; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Rectangle; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.IOException; +import java.io.Reader; +import java.io.StreamTokenizer; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import javax.swing.UIManager; + + +/** + * The MultiSplitLayout layout manager recursively arranges its + * components in row and column groups called "Splits". Elements of + * the layout are separated by gaps called "Dividers". The overall + * layout is defined with a simple tree model whose nodes are + * instances of MultiSplitLayout.Split, MultiSplitLayout.Divider, + * and MultiSplitLayout.Leaf. Named Leaf nodes represent the space + * allocated to a component that was added with a constraint that + * matches the Leaf's name. Extra space is distributed + * among row/column siblings according to their 0.0 to 1.0 weight. + * If no weights are specified then the last sibling always gets + * all of the extra space, or space reduction. + * + *

+ * Although MultiSplitLayout can be used with any Container, it's + * the default layout manager for MultiSplitPane. MultiSplitPane + * supports interactively dragging the Dividers, accessibility, + * and other features associated with split panes. + * + *

+ * All properties in this class are bound: when a properties value + * is changed, all PropertyChangeListeners are fired. + * + * @author Hans Muller + * @see MultiSplitPane + */ + +public class MultiSplitLayout implements LayoutManager { + private final Map childMap = new HashMap(); + private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + private Node model; + private int dividerSize; + private boolean floatingDividers = true; + + /** + * Create a MultiSplitLayout with a default model with a single + * Leaf node named "default". + * + * #see setModel + */ + public MultiSplitLayout() { + this(new Leaf("default")); + } + + /** + * Create a MultiSplitLayout with the specified model. + * + * #see setModel + */ + public MultiSplitLayout(Node model) { + this.model = model; + this.dividerSize = UIManager.getInt("SplitPane.dividerSize"); + if (this.dividerSize == 0) { + this.dividerSize = 7; + } + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + if (listener != null) { + pcs.addPropertyChangeListener(listener); + } + } + public void removePropertyChangeListener(PropertyChangeListener listener) { + if (listener != null) { + pcs.removePropertyChangeListener(listener); + } + } + public PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + + private void firePCS(String propertyName, Object oldValue, Object newValue) { + if (!(oldValue != null && newValue != null && oldValue.equals(newValue))) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + } + + /** + * Return the root of the tree of Split, Leaf, and Divider nodes + * that define this layout. + * + * @return the value of the model property + * @see #setModel + */ + public Node getModel() { return model; } + + /** + * Set the root of the tree of Split, Leaf, and Divider nodes + * that define this layout. The model can be a Split node + * (the typical case) or a Leaf. The default value of this + * property is a Leaf named "default". + * + * @param model the root of the tree of Split, Leaf, and Divider node + * @throws IllegalArgumentException if model is a Divider or null + * @see #getModel + */ + public void setModel(Node model) { + if ((model == null) || (model instanceof Divider)) { + throw new IllegalArgumentException("invalid model"); + } + Node oldModel = model; + this.model = model; + firePCS("model", oldModel, model); + } + + /** + * Returns the width of Dividers in Split rows, and the height of + * Dividers in Split columns. + * + * @return the value of the dividerSize property + * @see #setDividerSize + */ + public int getDividerSize() { return dividerSize; } + + /** + * Sets the width of Dividers in Split rows, and the height of + * Dividers in Split columns. The default value of this property + * is the same as for JSplitPane Dividers. + * + * @param dividerSize the size of dividers (pixels) + * @throws IllegalArgumentException if dividerSize < 0 + * @see #getDividerSize + */ + public void setDividerSize(int dividerSize) { + if (dividerSize < 0) { + throw new IllegalArgumentException("invalid dividerSize"); + } + int oldDividerSize = this.dividerSize; + this.dividerSize = dividerSize; + firePCS("dividerSize", oldDividerSize, dividerSize); + } + + /** + * @return the value of the floatingDividers property + * @see #setFloatingDividers + */ + public boolean getFloatingDividers() { return floatingDividers; } + + + /** + * If true, Leaf node bounds match the corresponding component's + * preferred size and Splits/Dividers are resized accordingly. + * If false then the Dividers define the bounds of the adjacent + * Split and Leaf nodes. Typically this property is set to false + * after the (MultiSplitPane) user has dragged a Divider. + * + * @see #getFloatingDividers + */ + public void setFloatingDividers(boolean floatingDividers) { + boolean oldFloatingDividers = this.floatingDividers; + this.floatingDividers = floatingDividers; + firePCS("floatingDividers", oldFloatingDividers, floatingDividers); + } + + + /** + * Add a component to this MultiSplitLayout. The + * name should match the name property of the Leaf + * node that represents the bounds of child. After + * layoutContainer() recomputes the bounds of all of the nodes in + * the model, it will set this child's bounds to the bounds of the + * Leaf node with name. Note: if a component was already + * added with the same name, this method does not remove it from + * its parent. + * + * @param name identifies the Leaf node that defines the child's bounds + * @param child the component to be added + * @see #removeLayoutComponent + */ + public void addLayoutComponent(String name, Component child) { + if (name == null) { + throw new IllegalArgumentException("name not specified"); + } + childMap.put(name, child); + } + + /** + * Removes the specified component from the layout. + * + * @param child the component to be removed + * @see #addLayoutComponent + */ + public void removeLayoutComponent(Component child) { + String name = child.getName(); + if (name != null) { + childMap.remove(name); + } + } + + private Component childForNode(Node node) { + if (node instanceof Leaf) { + Leaf leaf = (Leaf)node; + String name = leaf.getName(); + return (name != null) ? childMap.get(name) : null; + } + return null; + } + + + private Dimension preferredComponentSize(Node node) { + Component child = childForNode(node); + return (child != null) ? child.getPreferredSize() : new Dimension(0, 0); + + } + + @SuppressWarnings("unused") + private Dimension minimumComponentSize(Node node) { + Component child = childForNode(node); + return (child != null) ? child.getMinimumSize() : new Dimension(0, 0); + + } + + private Dimension preferredNodeSize(Node root) { + if (root instanceof Leaf) { + return preferredComponentSize(root); + } + else if (root instanceof Divider) { + int dividerSize = getDividerSize(); + return new Dimension(dividerSize, dividerSize); + } + else { + Split split = (Split)root; + List splitChildren = split.getChildren(); + int width = 0; + int height = 0; + if (split.isRowLayout()) { + for(Node splitChild : splitChildren) { + Dimension size = preferredNodeSize(splitChild); + width += size.width; + height = Math.max(height, size.height); + } + } + else { + for(Node splitChild : splitChildren) { + Dimension size = preferredNodeSize(splitChild); + width = Math.max(width, size.width); + height += size.height; + } + } + return new Dimension(width, height); + } + } + + private Dimension minimumNodeSize(Node root) { + if (root instanceof Leaf) { + Component child = childForNode(root); + return (child != null) ? child.getMinimumSize() : new Dimension(0, 0); + } + else if (root instanceof Divider) { + int dividerSize = getDividerSize(); + return new Dimension(dividerSize, dividerSize); + } + else { + Split split = (Split)root; + List splitChildren = split.getChildren(); + int width = 0; + int height = 0; + if (split.isRowLayout()) { + for(Node splitChild : splitChildren) { + Dimension size = minimumNodeSize(splitChild); + width += size.width; + height = Math.max(height, size.height); + } + } + else { + for(Node splitChild : splitChildren) { + Dimension size = minimumNodeSize(splitChild); + width = Math.max(width, size.width); + height += size.height; + } + } + return new Dimension(width, height); + } + } + + private Dimension sizeWithInsets(Container parent, Dimension size) { + Insets insets = parent.getInsets(); + int width = size.width + insets.left + insets.right; + int height = size.height + insets.top + insets.bottom; + return new Dimension(width, height); + } + + public Dimension preferredLayoutSize(Container parent) { + Dimension size = preferredNodeSize(getModel()); + return sizeWithInsets(parent, size); + } + + public Dimension minimumLayoutSize(Container parent) { + Dimension size = minimumNodeSize(getModel()); + return sizeWithInsets(parent, size); + } + + + private Rectangle boundsWithYandHeight(Rectangle bounds, double y, double height) { + Rectangle r = new Rectangle(); + r.setBounds((int)(bounds.getX()), (int)y, (int)(bounds.getWidth()), (int)height); + return r; + } + + private Rectangle boundsWithXandWidth(Rectangle bounds, double x, double width) { + Rectangle r = new Rectangle(); + r.setBounds((int)x, (int)(bounds.getY()), (int)width, (int)(bounds.getHeight())); + return r; + } + + + private void minimizeSplitBounds(Split split, Rectangle bounds) { + Rectangle splitBounds = new Rectangle(bounds.x, bounds.y, 0, 0); + List splitChildren = split.getChildren(); + Node lastChild = splitChildren.get(splitChildren.size() - 1); + Rectangle lastChildBounds = lastChild.getBounds(); + if (split.isRowLayout()) { + int lastChildMaxX = lastChildBounds.x + lastChildBounds.width; + splitBounds.add(lastChildMaxX, bounds.y + bounds.height); + } + else { + int lastChildMaxY = lastChildBounds.y + lastChildBounds.height; + splitBounds.add(bounds.x + bounds.width, lastChildMaxY); + } + split.setBounds(splitBounds); + } + + + private void layoutShrink(Split split, Rectangle bounds) { + Rectangle splitBounds = split.getBounds(); + ListIterator splitChildren = split.getChildren().listIterator(); + @SuppressWarnings("unused") + Node lastWeightedChild = split.lastWeightedChild(); + + if (split.isRowLayout()) { + int totalWidth = 0; // sum of the children's widths + int minWeightedWidth = 0; // sum of the weighted childrens' min widths + int totalWeightedWidth = 0; // sum of the weighted childrens' widths + for(Node splitChild : split.getChildren()) { + int nodeWidth = splitChild.getBounds().width; + int nodeMinWidth = Math.min(nodeWidth, minimumNodeSize(splitChild).width); + totalWidth += nodeWidth; + if (splitChild.getWeight() > 0.0) { + minWeightedWidth += nodeMinWidth; + totalWeightedWidth += nodeWidth; + } + } + + double x = bounds.getX(); + double extraWidth = splitBounds.getWidth() - bounds.getWidth(); + double availableWidth = extraWidth; + boolean onlyShrinkWeightedComponents = + (totalWeightedWidth - minWeightedWidth) > extraWidth; + + while(splitChildren.hasNext()) { + Node splitChild = splitChildren.next(); + Rectangle splitChildBounds = splitChild.getBounds(); + double minSplitChildWidth = minimumNodeSize(splitChild).getWidth(); + double splitChildWeight = (onlyShrinkWeightedComponents) + ? splitChild.getWeight() + : (splitChildBounds.getWidth() / (double)totalWidth); + + if (!splitChildren.hasNext()) { + double newWidth = Math.max(minSplitChildWidth, bounds.getMaxX() - x); + Rectangle newSplitChildBounds = boundsWithXandWidth(bounds, x, newWidth); + layout2(splitChild, newSplitChildBounds); + } + else if ((availableWidth > 0.0) && (splitChildWeight > 0.0)) { + double allocatedWidth = Math.rint(splitChildWeight * extraWidth); + double oldWidth = splitChildBounds.getWidth(); + double newWidth = Math.max(minSplitChildWidth, oldWidth - allocatedWidth); + Rectangle newSplitChildBounds = boundsWithXandWidth(bounds, x, newWidth); + layout2(splitChild, newSplitChildBounds); + availableWidth -= (oldWidth - splitChild.getBounds().getWidth()); + } + else { + double existingWidth = splitChildBounds.getWidth(); + Rectangle newSplitChildBounds = boundsWithXandWidth(bounds, x, existingWidth); + layout2(splitChild, newSplitChildBounds); + } + x = splitChild.getBounds().getMaxX(); + } + } + + else { + int totalHeight = 0; // sum of the children's heights + int minWeightedHeight = 0; // sum of the weighted childrens' min heights + int totalWeightedHeight = 0; // sum of the weighted childrens' heights + for(Node splitChild : split.getChildren()) { + int nodeHeight = splitChild.getBounds().height; + int nodeMinHeight = Math.min(nodeHeight, minimumNodeSize(splitChild).height); + totalHeight += nodeHeight; + if (splitChild.getWeight() > 0.0) { + minWeightedHeight += nodeMinHeight; + totalWeightedHeight += nodeHeight; + } + } + + double y = bounds.getY(); + double extraHeight = splitBounds.getHeight() - bounds.getHeight(); + double availableHeight = extraHeight; + boolean onlyShrinkWeightedComponents = + (totalWeightedHeight - minWeightedHeight) > extraHeight; + + while(splitChildren.hasNext()) { + Node splitChild = splitChildren.next(); + Rectangle splitChildBounds = splitChild.getBounds(); + double minSplitChildHeight = minimumNodeSize(splitChild).getHeight(); + double splitChildWeight = (onlyShrinkWeightedComponents) + ? splitChild.getWeight() + : (splitChildBounds.getHeight() / (double)totalHeight); + + if (!splitChildren.hasNext()) { + double oldHeight = splitChildBounds.getHeight(); + double newHeight = Math.max(minSplitChildHeight, bounds.getMaxY() - y); + Rectangle newSplitChildBounds = boundsWithYandHeight(bounds, y, newHeight); + layout2(splitChild, newSplitChildBounds); + availableHeight -= (oldHeight - splitChild.getBounds().getHeight()); + } + else if ((availableHeight > 0.0) && (splitChildWeight > 0.0)) { + double allocatedHeight = Math.rint(splitChildWeight * extraHeight); + double oldHeight = splitChildBounds.getHeight(); + double newHeight = Math.max(minSplitChildHeight, oldHeight - allocatedHeight); + Rectangle newSplitChildBounds = boundsWithYandHeight(bounds, y, newHeight); + layout2(splitChild, newSplitChildBounds); + availableHeight -= (oldHeight - splitChild.getBounds().getHeight()); + } + else { + double existingHeight = splitChildBounds.getHeight(); + Rectangle newSplitChildBounds = boundsWithYandHeight(bounds, y, existingHeight); + layout2(splitChild, newSplitChildBounds); + } + y = splitChild.getBounds().getMaxY(); + } + } + + /* The bounds of the Split node root are set to be + * big enough to contain all of its children. Since + * Leaf children can't be reduced below their + * (corresponding java.awt.Component) minimum sizes, + * the size of the Split's bounds maybe be larger than + * the bounds we were asked to fit within. + */ + minimizeSplitBounds(split, bounds); + } + + + private void layoutGrow(Split split, Rectangle bounds) { + Rectangle splitBounds = split.getBounds(); + ListIterator splitChildren = split.getChildren().listIterator(); + Node lastWeightedChild = split.lastWeightedChild(); + + /* Layout the Split's child Nodes' along the X axis. The bounds + * of each child will have the same y coordinate and height as the + * layoutGrow() bounds argument. Extra width is allocated to the + * to each child with a non-zero weight: + * newWidth = currentWidth + (extraWidth * splitChild.getWeight()) + * Any extraWidth "left over" (that's availableWidth in the loop + * below) is given to the last child. Note that Dividers always + * have a weight of zero, and they're never the last child. + */ + if (split.isRowLayout()) { + double x = bounds.getX(); + double extraWidth = bounds.getWidth() - splitBounds.getWidth(); + double availableWidth = extraWidth; + + while(splitChildren.hasNext()) { + Node splitChild = splitChildren.next(); + Rectangle splitChildBounds = splitChild.getBounds(); + double splitChildWeight = splitChild.getWeight(); + + if (!splitChildren.hasNext()) { + double newWidth = bounds.getMaxX() - x; + Rectangle newSplitChildBounds = boundsWithXandWidth(bounds, x, newWidth); + layout2(splitChild, newSplitChildBounds); + } + else if ((availableWidth > 0.0) && (splitChildWeight > 0.0)) { + double allocatedWidth = (splitChild.equals(lastWeightedChild)) + ? availableWidth + : Math.rint(splitChildWeight * extraWidth); + double newWidth = splitChildBounds.getWidth() + allocatedWidth; + Rectangle newSplitChildBounds = boundsWithXandWidth(bounds, x, newWidth); + layout2(splitChild, newSplitChildBounds); + availableWidth -= allocatedWidth; + } + else { + double existingWidth = splitChildBounds.getWidth(); + Rectangle newSplitChildBounds = boundsWithXandWidth(bounds, x, existingWidth); + layout2(splitChild, newSplitChildBounds); + } + x = splitChild.getBounds().getMaxX(); + } + } + + /* Layout the Split's child Nodes' along the Y axis. The bounds + * of each child will have the same x coordinate and width as the + * layoutGrow() bounds argument. Extra height is allocated to the + * to each child with a non-zero weight: + * newHeight = currentHeight + (extraHeight * splitChild.getWeight()) + * Any extraHeight "left over" (that's availableHeight in the loop + * below) is given to the last child. Note that Dividers always + * have a weight of zero, and they're never the last child. + */ + else { + double y = bounds.getY(); + double extraHeight = bounds.getMaxY() - splitBounds.getHeight(); + double availableHeight = extraHeight; + + while(splitChildren.hasNext()) { + Node splitChild = splitChildren.next(); + Rectangle splitChildBounds = splitChild.getBounds(); + double splitChildWeight = splitChild.getWeight(); + + if (!splitChildren.hasNext()) { + double newHeight = bounds.getMaxY() - y; + Rectangle newSplitChildBounds = boundsWithYandHeight(bounds, y, newHeight); + layout2(splitChild, newSplitChildBounds); + } + else if ((availableHeight > 0.0) && (splitChildWeight > 0.0)) { + double allocatedHeight = (splitChild.equals(lastWeightedChild)) + ? availableHeight + : Math.rint(splitChildWeight * extraHeight); + double newHeight = splitChildBounds.getHeight() + allocatedHeight; + Rectangle newSplitChildBounds = boundsWithYandHeight(bounds, y, newHeight); + layout2(splitChild, newSplitChildBounds); + availableHeight -= allocatedHeight; + } + else { + double existingHeight = splitChildBounds.getHeight(); + Rectangle newSplitChildBounds = boundsWithYandHeight(bounds, y, existingHeight); + layout2(splitChild, newSplitChildBounds); + } + y = splitChild.getBounds().getMaxY(); + } + } + } + + + /* Second pass of the layout algorithm: branch to layoutGrow/Shrink + * as needed. + */ + private void layout2(Node root, Rectangle bounds) { + if (root instanceof Leaf) { + Component child = childForNode(root); + if (child != null) { + child.setBounds(bounds); + } + root.setBounds(bounds); + } + else if (root instanceof Divider) { + root.setBounds(bounds); + } + else if (root instanceof Split) { + Split split = (Split)root; + boolean grow = split.isRowLayout() + ? (split.getBounds().width <= bounds.width) + : (split.getBounds().height <= bounds.height); + if (grow) { + layoutGrow(split, bounds); + root.setBounds(bounds); + } + else { + layoutShrink(split, bounds); + // split.setBounds() called in layoutShrink() + } + } + } + + + /* First pass of the layout algorithm. + * + * If the Dividers are "floating" then set the bounds of each + * node to accomodate the preferred size of all of the + * Leaf's java.awt.Components. Otherwise, just set the bounds + * of each Leaf/Split node so that it's to the left of (for + * Split.isRowLayout() Split children) or directly above + * the Divider that follows. + * + * This pass sets the bounds of each Node in the layout model. It + * does not resize any of the parent Container's + * (java.awt.Component) children. That's done in the second pass, + * see layoutGrow() and layoutShrink(). + */ + private void layout1(Node root, Rectangle bounds) { + if (root instanceof Leaf) { + root.setBounds(bounds); + } + else if (root instanceof Split) { + Split split = (Split)root; + Iterator splitChildren = split.getChildren().iterator(); + Rectangle childBounds = null; + int dividerSize = getDividerSize(); + + /* Layout the Split's child Nodes' along the X axis. The bounds + * of each child will have the same y coordinate and height as the + * layout1() bounds argument. + * + * Note: the column layout code - that's the "else" clause below + * this if, is identical to the X axis (rowLayout) code below. + */ + if (split.isRowLayout()) { + double x = bounds.getX(); + while(splitChildren.hasNext()) { + Node splitChild = splitChildren.next(); + Divider dividerChild = + (splitChildren.hasNext()) ? (Divider)(splitChildren.next()) : null; + + double childWidth = 0.0; + if (getFloatingDividers()) { + childWidth = preferredNodeSize(splitChild).getWidth(); + } + else { + if (dividerChild != null) { + childWidth = dividerChild.getBounds().getX() - x; + } + else { + childWidth = split.getBounds().getMaxX() - x; + } + } + childBounds = boundsWithXandWidth(bounds, x, childWidth); + layout1(splitChild, childBounds); + + if (getFloatingDividers() && (dividerChild != null)) { + double dividerX = childBounds.getMaxX(); + Rectangle dividerBounds = boundsWithXandWidth(bounds, dividerX, dividerSize); + dividerChild.setBounds(dividerBounds); + } + if (dividerChild != null) { + x = dividerChild.getBounds().getMaxX(); + } + } + } + + /* Layout the Split's child Nodes' along the Y axis. The bounds + * of each child will have the same x coordinate and width as the + * layout1() bounds argument. The algorithm is identical to what's + * explained above, for the X axis case. + */ + else { + double y = bounds.getY(); + while(splitChildren.hasNext()) { + Node splitChild = splitChildren.next(); + Divider dividerChild = + (splitChildren.hasNext()) ? (Divider)(splitChildren.next()) : null; + + double childHeight = 0.0; + if (getFloatingDividers()) { + childHeight = preferredNodeSize(splitChild).getHeight(); + } + else { + if (dividerChild != null) { + childHeight = dividerChild.getBounds().getY() - y; + } + else { + childHeight = split.getBounds().getMaxY() - y; + } + } + childBounds = boundsWithYandHeight(bounds, y, childHeight); + layout1(splitChild, childBounds); + + if (getFloatingDividers() && (dividerChild != null)) { + double dividerY = childBounds.getMaxY(); + Rectangle dividerBounds = boundsWithYandHeight(bounds, dividerY, dividerSize); + dividerChild.setBounds(dividerBounds); + } + if (dividerChild != null) { + y = dividerChild.getBounds().getMaxY(); + } + } + } + /* The bounds of the Split node root are set to be just + * big enough to contain all of its children, but only + * along the axis it's allocating space on. That's + * X for rows, Y for columns. The second pass of the + * layout algorithm - see layoutShrink()/layoutGrow() + * allocates extra space. + */ + minimizeSplitBounds(split, bounds); + } + } + + /** + * The specified Node is either the wrong type or was configured + * incorrectly. + */ + + public static class InvalidLayoutException extends RuntimeException { + + private static final long serialVersionUID = -5960249230256779327L; + private final Node node; + public InvalidLayoutException (String msg, Node node) { + super(msg); + this.node = node; + } + /** + * @return the invalid Node. + */ + public Node getNode() { return node; } + } + + private void throwInvalidLayout(String msg, Node node) { + throw new InvalidLayoutException(msg, node); + } + + private void checkLayout(Node root) { + if (root instanceof Split) { + Split split = (Split)root; + if (split.getChildren().size() <= 2) { + throwInvalidLayout("Split must have > 2 children", root); + } + Iterator splitChildren = split.getChildren().iterator(); + double weight = 0.0; + while(splitChildren.hasNext()) { + Node splitChild = splitChildren.next(); + if (splitChild instanceof Divider) { + throwInvalidLayout("expected a Split or Leaf Node", splitChild); + } + if (splitChildren.hasNext()) { + Node dividerChild = splitChildren.next(); + if (!(dividerChild instanceof Divider)) { + throwInvalidLayout("expected a Divider Node", dividerChild); + } + } + weight += splitChild.getWeight(); + checkLayout(splitChild); + } + if (weight > 1.0) { + throwInvalidLayout("Split children's total weight > 1.0", root); + } + } + } + + /** + * Compute the bounds of all of the Split/Divider/Leaf Nodes in + * the layout model, and then set the bounds of each child component + * with a matching Leaf Node. + */ + public void layoutContainer(Container parent) { + checkLayout(getModel()); + Insets insets = parent.getInsets(); + Dimension size = parent.getSize(); + int width = size.width - (insets.left + insets.right); + int height = size.height - (insets.top + insets.bottom); + Rectangle bounds = new Rectangle(insets.left, insets.top, width, height); + layout1(getModel(), bounds); + layout2(getModel(), bounds); + } + + + private Divider dividerAt(Node root, int x, int y) { + if (root instanceof Divider) { + Divider divider = (Divider)root; + return (divider.getBounds().contains(x, y)) ? divider : null; + } + else if (root instanceof Split) { + Split split = (Split)root; + for(Node child : split.getChildren()) { + if (child.getBounds().contains(x, y)) { + return dividerAt(child, x, y); + } + } + } + return null; + } + + /** + * Return the Divider whose bounds contain the specified + * point, or null if there isn't one. + * + * @param x x coordinate + * @param y y coordinate + * @return the Divider at x,y + */ + public Divider dividerAt(int x, int y) { + return dividerAt(getModel(), x, y); + } + + private boolean nodeOverlapsRectangle(Node node, Rectangle r2) { + Rectangle r1 = node.getBounds(); + return + (r1.x <= (r2.x + r2.width)) && ((r1.x + r1.width) >= r2.x) && + (r1.y <= (r2.y + r2.height)) && ((r1.y + r1.height) >= r2.y); + } + + @SuppressWarnings("unchecked") + private List dividersThatOverlap(Node root, Rectangle r) { + if (nodeOverlapsRectangle(root, r) && (root instanceof Split)) { + List dividers = new ArrayList(); + for(Node child : ((Split)root).getChildren()) { + if (child instanceof Divider) { + if (nodeOverlapsRectangle(child, r)) { + dividers.add((Divider)child); + } + } + else if (child instanceof Split) { + dividers.addAll(dividersThatOverlap(child, r)); + } + } + return dividers; + } + else { + return Collections.emptyList(); + } + } + + /** + * Return the Dividers whose bounds overlap the specified + * Rectangle. + * + * @param r target Rectangle + * @return the Dividers that overlap r + * @throws IllegalArgumentException if the Rectangle is null + */ + public List dividersThatOverlap(Rectangle r) { + if (r == null) { + throw new IllegalArgumentException("null Rectangle"); + } + return dividersThatOverlap(getModel(), r); + } + + + /** + * Base class for the nodes that model a MultiSplitLayout. + */ + public static abstract class Node { + private Split parent = null; + private Rectangle bounds = new Rectangle(); + private double weight = 0.0; + + /** + * Returns the Split parent of this Node, or null. + * + * @return the value of the parent property. + * @see #setParent + */ + public Split getParent() { return parent; } + + /** + * Set the value of this Node's parent property. The default + * value of this property is null. + * + * @param parent a Split or null + * @see #getParent + */ + public void setParent(Split parent) { + this.parent = parent; + } + + /** + * Returns the bounding Rectangle for this Node. + * + * @return the value of the bounds property. + * @see #setBounds + */ + public Rectangle getBounds() { + return new Rectangle(this.bounds); + } + + /** + * Set the bounding Rectangle for this node. The value of + * bounds may not be null. The default value of bounds + * is equal to new Rectangle(0,0,0,0). + * + * @param bounds the new value of the bounds property + * @throws IllegalArgumentException if bounds is null + * @see #getBounds + */ + public void setBounds(Rectangle bounds) { + if (bounds == null) { + throw new IllegalArgumentException("null bounds"); + } + this.bounds = new Rectangle(bounds); + } + + /** + * Value between 0.0 and 1.0 used to compute how much space + * to add to this sibling when the layout grows or how + * much to reduce when the layout shrinks. + * + * @return the value of the weight property + * @see #setWeight + */ + public double getWeight() { return weight; } + + /** + * The weight property is a between 0.0 and 1.0 used to + * compute how much space to add to this sibling when the + * layout grows or how much to reduce when the layout shrinks. + * If rowLayout is true then this node's width grows + * or shrinks by (extraSpace * weight). If rowLayout is false, + * then the node's height is changed. The default value + * of weight is 0.0. + * + * @param weight a double between 0.0 and 1.0 + * @see #getWeight + * @see MultiSplitLayout#layoutContainer + * @throws IllegalArgumentException if weight is not between 0.0 and 1.0 + */ + public void setWeight(double weight) { + if ((weight < 0.0)|| (weight > 1.0)) { + throw new IllegalArgumentException("invalid weight"); + } + this.weight = weight; + } + + private Node siblingAtOffset(int offset) { + Split parent = getParent(); + if (parent == null) { return null; } + List siblings = parent.getChildren(); + int index = siblings.indexOf(this); + if (index == -1) { return null; } + index += offset; + return ((index > -1) && (index < siblings.size())) ? siblings.get(index) : null; + } + + /** + * Return the Node that comes after this one in the parent's + * list of children, or null. If this node's parent is null, + * or if it's the last child, then return null. + * + * @return the Node that comes after this one in the parent's list of children. + * @see #previousSibling + * @see #getParent + */ + public Node nextSibling() { + return siblingAtOffset(+1); + } + + /** + * Return the Node that comes before this one in the parent's + * list of children, or null. If this node's parent is null, + * or if it's the last child, then return null. + * + * @return the Node that comes before this one in the parent's list of children. + * @see #nextSibling + * @see #getParent + */ + public Node previousSibling() { + return siblingAtOffset(-1); + } + } + + /** + * Defines a vertical or horizontal subdivision into two or more + * tiles. + */ + public static class Split extends Node { + private List children = Collections.emptyList(); + private boolean rowLayout = true; + + /** + * Returns true if the this Split's children are to be + * laid out in a row: all the same height, left edge + * equal to the previous Node's right edge. If false, + * children are laid on in a column. + * + * @return the value of the rowLayout property. + * @see #setRowLayout + */ + public boolean isRowLayout() { return rowLayout; } + + /** + * Set the rowLayout property. If true, all of this Split's + * children are to be laid out in a row: all the same height, + * each node's left edge equal to the previous Node's right + * edge. If false, children are laid on in a column. Default + * value is true. + * + * @param rowLayout true for horizontal row layout, false for column + * @see #isRowLayout + */ + public void setRowLayout(boolean rowLayout) { + this.rowLayout = rowLayout; + } + + /** + * Returns this Split node's children. The returned value + * is not a reference to the Split's internal list of children + * + * @return the value of the children property. + * @see #setChildren + */ + public List getChildren() { + return new ArrayList(children); + } + + /** + * Set's the children property of this Split node. The parent + * of each new child is set to this Split node, and the parent + * of each old child (if any) is set to null. This method + * defensively copies the incoming List. Default value is + * an empty List. + * + * @param children List of children + * @see #getChildren + * @throws IllegalArgumentException if children is null + */ + public void setChildren(List children) { + if (children == null) { + throw new IllegalArgumentException("children must be a non-null List"); + } + for(Node child : this.children) { + child.setParent(null); + } + this.children = new ArrayList(children); + for(Node child : this.children) { + child.setParent(this); + } + } + + /** + * Convenience method that returns the last child whose weight + * is > 0.0. + * + * @return the last child whose weight is > 0.0. + * @see #getChildren + * @see Node#getWeight + */ + public final Node lastWeightedChild() { + List children = getChildren(); + Node weightedChild = null; + for(Node child : children) { + if (child.getWeight() > 0.0) { + weightedChild = child; + } + } + return weightedChild; + } + + public String toString() { + int nChildren = getChildren().size(); + StringBuffer sb = new StringBuffer("MultiSplitLayout.Split"); + sb.append(isRowLayout() ? " ROW [" : " COLUMN ["); + sb.append(nChildren + ((nChildren == 1) ? " child" : " children")); + sb.append("] "); + sb.append(getBounds()); + return sb.toString(); + } + } + + + /** + * Models a java.awt Component child. + */ + public static class Leaf extends Node { + private String name = ""; + + /** + * Create a Leaf node. The default value of name is "". + */ + public Leaf() { } + + /** + * Create a Leaf node with the specified name. Name can not + * be null. + * + * @param name value of the Leaf's name property + * @throws IllegalArgumentException if name is null + */ + public Leaf(String name) { + if (name == null) { + throw new IllegalArgumentException("name is null"); + } + this.name = name; + } + + /** + * Return the Leaf's name. + * + * @return the value of the name property. + * @see #setName + */ + public String getName() { return name; } + + /** + * Set the value of the name property. Name may not be null. + * + * @param name value of the name property + * @throws IllegalArgumentException if name is null + */ + public void setName(String name) { + if (name == null) { + throw new IllegalArgumentException("name is null"); + } + this.name = name; + } + + public String toString() { + StringBuffer sb = new StringBuffer("MultiSplitLayout.Leaf"); + sb.append(" \""); + sb.append(getName()); + sb.append("\""); + sb.append(" weight="); + sb.append(getWeight()); + sb.append(" "); + sb.append(getBounds()); + return sb.toString(); + } + } + + + /** + * Models a single vertical/horiztonal divider. + */ + public static class Divider extends Node { + /** + * Convenience method, returns true if the Divider's parent + * is a Split row (a Split with isRowLayout() true), false + * otherwise. In other words if this Divider's major axis + * is vertical, return true. + * + * @return true if this Divider is part of a Split row. + */ + public final boolean isVertical() { + Split parent = getParent(); + return (parent != null) ? parent.isRowLayout() : false; + } + + /** + * Dividers can't have a weight, they don't grow or shrink. + * @throws UnsupportedOperationException + */ + public void setWeight(double weight) { + throw new UnsupportedOperationException(); + } + + public String toString() { + return "MultiSplitLayout.Divider " + getBounds().toString(); + } + } + + + private static void throwParseException(StreamTokenizer st, String msg) throws Exception { + throw new Exception("MultiSplitLayout.parseModel Error: " + msg); + } + + private static void parseAttribute(String name, StreamTokenizer st, Node node) throws Exception { + if ((st.nextToken() != '=')) { + throwParseException(st, "expected '=' after " + name); + } + if (name.equalsIgnoreCase("WEIGHT")) { + if (st.nextToken() == StreamTokenizer.TT_NUMBER) { + node.setWeight(st.nval); + } + else { + throwParseException(st, "invalid weight"); + } + } + else if (name.equalsIgnoreCase("NAME")) { + if (st.nextToken() == StreamTokenizer.TT_WORD) { + if (node instanceof Leaf) { + ((Leaf)node).setName(st.sval); + } + else { + throwParseException(st, "can't specify name for " + node); + } + } + else { + throwParseException(st, "invalid name"); + } + } + else { + throwParseException(st, "unrecognized attribute \"" + name + "\""); + } + } + + @SuppressWarnings("unchecked") + private static void addSplitChild(Split parent, Node child) { + List children = new ArrayList(parent.getChildren()); + if (children.size() == 0) { + children.add(child); + } + else { + children.add(new Divider()); + children.add(child); + } + parent.setChildren(children); + } + + private static void parseLeaf(StreamTokenizer st, Split parent) throws Exception { + Leaf leaf = new Leaf(); + int token; + while ((token = st.nextToken()) != StreamTokenizer.TT_EOF) { + if (token == ')') { + break; + } + if (token == StreamTokenizer.TT_WORD) { + parseAttribute(st.sval, st, leaf); + } + else { + throwParseException(st, "Bad Leaf: " + leaf); + } + } + addSplitChild(parent, leaf); + } + + private static void parseSplit(StreamTokenizer st, Split parent) throws Exception { + int token; + while ((token = st.nextToken()) != StreamTokenizer.TT_EOF) { + if (token == ')') { + break; + } + else if (token == StreamTokenizer.TT_WORD) { + if (st.sval.equalsIgnoreCase("WEIGHT")) { + parseAttribute(st.sval, st, parent); + } + else { + addSplitChild(parent, new Leaf(st.sval)); + } + } + else if (token == '(') { + if ((token = st.nextToken()) != StreamTokenizer.TT_WORD) { + throwParseException(st, "invalid node type"); + } + String nodeType = st.sval.toUpperCase(); + if (nodeType.equals("LEAF")) { + parseLeaf(st, parent); + } + else if (nodeType.equals("ROW") || nodeType.equals("COLUMN")) { + Split split = new Split(); + split.setRowLayout(nodeType.equals("ROW")); + addSplitChild(parent, split); + parseSplit(st, split); + } + else { + throwParseException(st, "unrecognized node type '" + nodeType + "'"); + } + } + } + } + + private static Node parseModel (Reader r) { + StreamTokenizer st = new StreamTokenizer(r); + try { + Split root = new Split(); + parseSplit(st, root); + return root.getChildren().get(0); + } + catch (Exception e) { + System.err.println(e); + } + finally { + try { r.close(); } catch (IOException ignore) {} + } + return null; + } + + /** + * A convenience method that converts a string to a + * MultiSplitLayout model (a tree of Nodes) using a + * a simple syntax. Nodes are represented by + * parenthetical expressions whose first token + * is one of ROW/COLUMN/LEAF. ROW and COLUMN specify + * horizontal and vertical Split nodes respectively, + * LEAF specifies a Leaf node. A Leaf's name and + * weight can be specified with attributes, + * name=myLeafName weight=myLeafWeight. + * Similarly, a Split's weight can be specified with + * weight=mySplitWeight. + * + *

For example, the following expression generates + * a horizontal Split node with three children: + * the Leafs named left and right, and a Divider in + * between: + *

+     * (ROW (LEAF name=left) (LEAF name=right weight=1.0))
+     * 
+ * + *

Dividers should not be included in the string, + * they're added automatcially as needed. Because + * Leaf nodes often only need to specify a name, one + * can specify a Leaf by just providing the name. + * The previous example can be written like this: + *

+     * (ROW left (LEAF name=right weight=1.0))
+     * 
+ * + *

Here's a more complex example. One row with + * three elements, the first and last of which are columns + * with two leaves each: + *

+     * (ROW (COLUMN weight=0.5 left.top left.bottom) 
+     *      (LEAF name=middle)
+     *      (COLUMN weight=0.5 right.top right.bottom))
+     * 
+ * + * + *

This syntax is not intended for archiving or + * configuration files . It's just a convenience for + * examples and tests. + * + * @return the Node root of a tree based on s. + */ + public static Node parseModel(String s) { + return parseModel(new StringReader(s)); + } + + + private static void printModel(String indent, Node root) { + if (root instanceof Split) { + Split split = (Split)root; + System.out.println(indent + split); + for(Node child : split.getChildren()) { + printModel(indent + " ", child); + } + } + else { + System.out.println(indent + root); + } + } + + /** + * Print the tree with enough detail for simple debugging. + */ + public static void printModel(Node root) { + printModel("", root); + } +} diff --git a/src/org/jdesktop/swingx/MultiSplitPane.java b/src/org/jdesktop/swingx/MultiSplitPane.java new file mode 100644 index 00000000000..5f462f4178f --- /dev/null +++ b/src/org/jdesktop/swingx/MultiSplitPane.java @@ -0,0 +1,403 @@ +/* + * $Id: MultiSplitPane.java,v 1.15 2005/10/26 14:29:54 hansmuller Exp $ + * + * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, + * Santa Clara, California 95054, U.S.A. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.jdesktop.swingx; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.swing.JPanel; +import javax.swing.event.MouseInputAdapter; +import org.jdesktop.swingx.MultiSplitLayout.Divider; +import org.jdesktop.swingx.MultiSplitLayout.Node; + +/** + * + *

+ * All properties in this class are bound: when a properties value + * is changed, all PropertyChangeListeners are fired. + * + * @author Hans Muller + */ + +public class MultiSplitPane extends JPanel { + + private static final long serialVersionUID = 3379001167792141242L; + + private AccessibleContext accessibleContext = null; + private boolean continuousLayout = true; + private DividerPainter dividerPainter = new DefaultDividerPainter(); + + /** + * Creates a MultiSplitPane with it's LayoutManager set to + * to an empty MultiSplitLayout. + */ + public MultiSplitPane() { + super(new MultiSplitLayout()); + InputHandler inputHandler = new InputHandler(); + addMouseListener(inputHandler); + addMouseMotionListener(inputHandler); + addKeyListener(inputHandler); + setFocusable(true); + } + + /** + * A convenience method that returns the layout manager cast + * to MutliSplitLayout. + * + * @return this MultiSplitPane's layout manager + * @see java.awt.Container#getLayout + * @see #setModel + */ + public final MultiSplitLayout getMultiSplitLayout() { + return (MultiSplitLayout)getLayout(); + } + + /** + * A convenience method that sets the MultiSplitLayout model. + * Equivalent to getMultiSplitLayout.setModel(model) + * + * @param model the root of the MultiSplitLayout model + * @see #getMultiSplitLayout + * @see MultiSplitLayout#setModel + */ + public final void setModel(Node model) { + getMultiSplitLayout().setModel(model); + } + + /** + * A convenience method that sets the MultiSplitLayout dividerSize + * property. Equivalent to + * getMultiSplitLayout().setDividerSize(newDividerSize). + * + * @param dividerSize the value of the dividerSize property + * @see #getMultiSplitLayout + * @see MultiSplitLayout#setDividerSize + */ + public final void setDividerSize(int dividerSize) { + getMultiSplitLayout().setDividerSize(dividerSize); + } + + /** + * Sets the value of the continuousLayout property. + * If true, then the layout is revalidated continuously while + * a divider is being moved. The default value of this property + * is true. + * + * @param continuousLayout value of the continuousLayout property + * @see #isContinuousLayout + */ + public void setContinuousLayout(boolean continuousLayout) { + boolean oldContinuousLayout = continuousLayout; + this.continuousLayout = continuousLayout; + firePropertyChange("continuousLayout", oldContinuousLayout, continuousLayout); + } + + /** + * Returns true if dragging a divider only updates + * the layout when the drag gesture ends (typically, when the + * mouse button is released). + * + * @return the value of the continuousLayout property + * @see #setContinuousLayout + */ + public boolean isContinuousLayout() { + return continuousLayout; + } + + /** + * Returns the Divider that's currently being moved, typically + * because the user is dragging it, or null. + * + * @return the Divider that's being moved or null. + */ + public Divider activeDivider() { + return dragDivider; + } + + /** + * Draws a single Divider. Typically used to specialize the + * way the active Divider is painted. + * + * @see #getDividerPainter + * @see #setDividerPainter + */ + public static abstract class DividerPainter { + /** + * Paint a single Divider. + * + * @param g the Graphics object to paint with + * @param divider the Divider to paint + */ + public abstract void paint(Graphics g, Divider divider); + } + + private class DefaultDividerPainter extends DividerPainter { + public void paint(Graphics g, Divider divider) { + if ((divider == activeDivider()) && !isContinuousLayout()) { + Graphics2D g2d = (Graphics2D)g; + g2d.setColor(Color.black); + g2d.fill(divider.getBounds()); + } + } + } + + /** + * The DividerPainter that's used to paint Dividers on this MultiSplitPane. + * This property may be null. + * + * @return the value of the dividerPainter Property + * @see #setDividerPainter + */ + public DividerPainter getDividerPainter() { + return dividerPainter; + } + + /** + * Sets the DividerPainter that's used to paint Dividers on this + * MultiSplitPane. The default DividerPainter only draws + * the activeDivider (if there is one) and then, only if + * continuousLayout is false. The value of this property is + * used by the paintChildren method: Dividers are painted after + * the MultiSplitPane's children have been rendered so that + * the activeDivider can appear "on top of" the children. + * + * @param dividerPainter the value of the dividerPainter property, can be null + * @see #paintChildren + * @see #activeDivider + */ + public void setDividerPainter(DividerPainter dividerPainter) { + this.dividerPainter = dividerPainter; + } + + /** + * Uses the DividerPainter (if any) to paint each Divider that + * overlaps the clip Rectangle. This is done after the call to + * super.paintChildren() so that Dividers can be + * rendered "on top of" the children. + *

+ * {@inheritDoc} + */ + protected void paintChildren(Graphics g) { + super.paintChildren(g); + DividerPainter dp = getDividerPainter(); + Rectangle clipR = g.getClipBounds(); + if ((dp != null) && (clipR != null)) { + Graphics dpg = g.create(); + try { + MultiSplitLayout msl = getMultiSplitLayout(); + for(Divider divider : msl.dividersThatOverlap(clipR)) { + dp.paint(dpg, divider); + } + } + finally { + dpg.dispose(); + } + } + } + + private boolean dragUnderway = false; + private MultiSplitLayout.Divider dragDivider = null; + private Rectangle initialDividerBounds = null; + private boolean oldFloatingDividers = true; + private int dragOffsetX = 0; + private int dragOffsetY = 0; + private int dragMin = -1; + private int dragMax = -1; + + private void startDrag(int mx, int my) { + requestFocusInWindow(); + MultiSplitLayout msl = getMultiSplitLayout(); + MultiSplitLayout.Divider divider = msl.dividerAt(mx, my); + if (divider != null) { + MultiSplitLayout.Node prevNode = divider.previousSibling(); + MultiSplitLayout.Node nextNode = divider.nextSibling(); + if ((prevNode == null) || (nextNode == null)) { + dragUnderway = false; + } + else { + initialDividerBounds = divider.getBounds(); + dragOffsetX = mx - initialDividerBounds.x; + dragOffsetY = my - initialDividerBounds.y; + dragDivider = divider; + Rectangle prevNodeBounds = prevNode.getBounds(); + Rectangle nextNodeBounds = nextNode.getBounds(); + if (dragDivider.isVertical()) { + dragMin = prevNodeBounds.x; + dragMax = nextNodeBounds.x + nextNodeBounds.width; + dragMax -= dragDivider.getBounds().width; + } + else { + dragMin = prevNodeBounds.y; + dragMax = nextNodeBounds.y + nextNodeBounds.height; + dragMax -= dragDivider.getBounds().height; + } + oldFloatingDividers = getMultiSplitLayout().getFloatingDividers(); + getMultiSplitLayout().setFloatingDividers(false); + dragUnderway = true; + } + } + else { + dragUnderway = false; + } + } + + private void repaintDragLimits() { + Rectangle damageR = dragDivider.getBounds(); + if (dragDivider.isVertical()) { + damageR.x = dragMin; + damageR.width = dragMax - dragMin; + } + else { + damageR.y = dragMin; + damageR.height = dragMax - dragMin; + } + repaint(damageR); + } + + private void updateDrag(int mx, int my) { + if (!dragUnderway) { + return; + } + Rectangle oldBounds = dragDivider.getBounds(); + Rectangle bounds = new Rectangle(oldBounds); + if (dragDivider.isVertical()) { + bounds.x = mx - dragOffsetX; + bounds.x = Math.max(bounds.x, dragMin); + bounds.x = Math.min(bounds.x, dragMax); + } + else { + bounds.y = my - dragOffsetY; + bounds.y = Math.max(bounds.y, dragMin); + bounds.y = Math.min(bounds.y, dragMax); + } + dragDivider.setBounds(bounds); + if (isContinuousLayout()) { + revalidate(); + repaintDragLimits(); + } + else { + repaint(oldBounds.union(bounds)); + } + } + + private void clearDragState() { + dragDivider = null; + initialDividerBounds = null; + oldFloatingDividers = true; + dragOffsetX = dragOffsetY = 0; + dragMin = dragMax = -1; + dragUnderway = false; + } + + private void finishDrag(int x, int y) { + if (dragUnderway) { + clearDragState(); + if (!isContinuousLayout()) { + revalidate(); + repaint(); + } + } + } + + private void cancelDrag() { + if (dragUnderway) { + dragDivider.setBounds(initialDividerBounds); + getMultiSplitLayout().setFloatingDividers(oldFloatingDividers); + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + repaint(); + revalidate(); + clearDragState(); + } + } + + private void updateCursor(int x, int y, boolean show) { + if (dragUnderway) { + return; + } + int cursorID = Cursor.DEFAULT_CURSOR; + if (show) { + MultiSplitLayout.Divider divider = getMultiSplitLayout().dividerAt(x, y); + if (divider != null) { + cursorID = (divider.isVertical()) ? + Cursor.E_RESIZE_CURSOR : + Cursor.N_RESIZE_CURSOR; + } + } + setCursor(Cursor.getPredefinedCursor(cursorID)); + } + + + private class InputHandler extends MouseInputAdapter implements KeyListener { + + public void mouseEntered(MouseEvent e) { + updateCursor(e.getX(), e.getY(), true); + } + + public void mouseMoved(MouseEvent e) { + updateCursor(e.getX(), e.getY(), true); + } + + public void mouseExited(MouseEvent e) { + updateCursor(e.getX(), e.getY(), false); + } + + public void mousePressed(MouseEvent e) { + startDrag(e.getX(), e.getY()); + } + public void mouseReleased(MouseEvent e) { + finishDrag(e.getX(), e.getY()); + } + public void mouseDragged(MouseEvent e) { + updateDrag(e.getX(), e.getY()); + } + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { + cancelDrag(); + } + } + public void keyReleased(KeyEvent e) { } + public void keyTyped(KeyEvent e) { } + } + + public AccessibleContext getAccessibleContext() { + if( accessibleContext == null ) { + accessibleContext = new AccessibleMultiSplitPane(); + } + return accessibleContext; + } + + protected class AccessibleMultiSplitPane extends AccessibleJPanel { + + private static final long serialVersionUID = 4177114112369591280L; + + public AccessibleRole getAccessibleRole() { + return AccessibleRole.SPLIT_PANE; + } + } +} diff --git a/src/res/AllTokens.txt b/src/res/AllTokens.txt new file mode 100644 index 00000000000..f31beb8a787 --- /dev/null +++ b/src/res/AllTokens.txt @@ -0,0 +1,836 @@ +Angel +B +Creature Angel +3/3 +Flying + +Angel +W +Creature Angel +4/4 +Flying + +Ape +G +Creature Ape +2/2 + +Ape +G +Creature Ape +3/3 + +Assembly-Worker +C +Artifact Creature Assembly-Worker +2/2 + +Avatar +W +Creature Avatar +N/N +This creature's power and toughness are each equal to your life total. + +Bat +B +Creature Bat +1/1 +Flying + +Bat +B +Creature Bat +1/2 +"1B, Sacrifice the creature: Return to play under its owner's control, a card named Sengir Nosferatu that's removed from the game." + +Bear +G +Creature Bear +2/2 + +Beast +G +Creature Beast +2/2 + +Beast +G +Creature Beast +3/3 + +Beast +G +Creature Beast +4/4 + +Beast +G +Creature Beast +5/5 + +Beast +R G W +Creature Beast +8/8 + +Bird +R +Creature Bird +4/4 +Flying + +Bird +U +Creature Bird +1/1 + +Bird +W +Creature Bird +1/1 +Flying + +Bird +W U +Creature Bird +1/1 +Flying + +Butterfly +G +Creature Insect +1/1 +Flying + +Camarid +U +Creature Camarid +1/1 + +Caribou +W +Creature Caribou +0/1 + +Carnivore +R +Creature Beast +3/1 + +Cat +B +Creature Cat +2/1 + +Cat +G +Creature Cat +1/1 + +Cat Warrior +G +Creature Cat Warrior +2/2 +Forestwalk + +Centaur +G +Creature Centaur +3/3 + +Centaur +G +Creature Centaur +3/3 +Protection from black + +Citizen +W +Creature Citizen +1/1 + +Demon +B +Creature Demon +X/X + +Deserter +W +Creature Deserter +0/1 + +Djinn +C +Artifact Creature Djinn +5/5 + +Dragon +R +Creature Dragon +4/4 +Flying + +Dragon +R +Creature Dragon +5/5 +Flying + +Dragon Spirit +U +Creature Dragon Spirit +5/5 +Flying + +Drake +U G +Creature Drake +2/2 +Flying + +Elemental +B R +Creature Elemental +5/5 + +Elemental +G +Creature Elemental +4/4 + +Elemental +G +Creature Elemental +7/7 +Trample + +Elemental +G +Creature Elemental +X/X + +Elemental +R +Creature Elemental +1/1 +Haste + +Elemental +R +Creature Elemental +3/1 + +Elemental +R +Creature Elemental +3/1 +Haste + +Elemental +R +Creature Elemental +3/3 + +Elemental +U +Creature Elemental +2/2 +Flying + +Elemental +U R +Creature Elemental +5/5 +Flying + +Elemental +W +Creature Elemental +4/4 +Flying + +Elemental Cat +R +Creature Elemental Cat +1/1 + +Elemental Shaman +R +Creature Elemental Shaman +3/1 + +Elephant +G +Creature Elephant +3/3 + +Elephant +G +Creature Elephant +N/N +This creature's power and toughness are each equal to the number of creature cards in its controller's graveyard. + +Elf Warrior +G +Creature Elf Warrior +1/1 + +Elf Warrior +G W +Creature Elf Warrior +1/1 + +Faerie +U +Creature Faerie +1/1 +Flying + +Faerie Rogue +B +Creature Faerie Rogue +1/1 +Flying + +Faerie Rogue +U B +Creature Faerie Rogue +1/1 +Flying + +Giant +R +Creature Giant +4/4 + +Giant Warrior +R G +Creature Giant Warrior +4/4 +Haste + +Giant Warrior +W +Creature Giant Warrior +5/5 + +Gnome +C +Artifact Creature Gnome +1/1 + +Goat +W +Creature Goat +0/1 + +Goblin +R +Creature Goblin +1/1 + +Goblin +R +Creature Goblin +1/1 +Haste + +Goblin +R +Creature Goblin +2/1 +Haste + +Goblin Rogue +B +Creature Goblin Rogue +1/1 + +Goblin Scout +R +Creature Goblin Scout +1/1 +Mountainwalk + +Goblin Soldier +R W +Creature Goblin Soldier +1/1 + +Goblin Warrior +R G +Creature Goblin Warrior +1/1 + +Graveborn +Creature Graveborn +B R +3/1 +Haste + +Griffin +W +Creature Griffin +2/2 +Flying + +Hippo +G +Creature Hippo +1/1 + +Homunculus +U +Artifact Creature +0/1 + +Hornet +C +Haste +1/1 +Flying + +Horror +B +Creature Horror +4/4 + +Hound +G +Creature Hound +1/1 + +Illusion +U +Creature Illusion +1/1 +Flying + +Insect +B +Creature Insect +0/1 + +Insect +G +Creature Insect +1/1 + +Insect +G +Creature Insect +6/1 +Shroud + +Kaldra +C +Legendary Creature Avatar +4/4 + +Kavu +B +Creature Kavu +3/3 + +Kelp +U +Creature Plant Wall +0/1 +Defender + +Kithkin Soldier +W +Creature Kithkin Soldier +1/1 + +Knight +B +Protection from white +2/2 +Flanking + +Knight +W +Creature Knight +1/1 +Banding + +Knight +W +Creature Knight +2/2 +First Strike + +Knight +W +Creature Knight +2/2 + +Kobolds of Kher Keep +R +Creature Kobold +0/1 + +Marit Lage +B +Indestructible +20/20 +Flying + +Merfolk Wizard +U +Creature Merfolk Wizard +1/1 + +Minion +B +Creature Minion +1/1 + +Minion +B +Creature Minion +X/X + +Minor Demon +B R +Creature Demon +1/1 + +Myr +C +Artifact Creature Myr +1/1 + +Ooze +G +Creature Ooze +X/X + +Orb +U +Creature Orb +X/X +Flying + +Pegasus +W +Creature Pegasus +1/1 +Flying + +Pentavite +C +Artifact Creature Pentavite +1/1 + +Pest +C +Artifact Creature Pest +0/1 + +Pincher +C +Creature Pincher +2/2 + +Plant Wall +G +Creature Plant Wall +0/1 +Defender + +Prism +C +Artifact Creature Prism +0/1 + +Rat +B +Creature Rat +1/1 + +Reflection +W +Creature Reflection +2/2 + +Reflection +W +Creature Reflection +X/X + +Sand +C +Creature Sand +1/1 + +Sand Warrior +R G W +Creature Sand Warrior +1/1 +"When a permanent name Hazezon Tamar isn't in play, remove this creature from the game." + +Saproling +G +Creature Saproling +1/1 + +Saproling +G +Creature Saproling +N/N +This creature's power and toughness are each equal to the number of fade counters on Saproling Burst. + +Serf +B +Creature Serf +0/1 + +Shapeshifter +C +Creature Shapeshifter +1/1 +Changeling + +Sheep +G +Creature Sheep +0/1 + +Skeleton +B +Creature Skeleton +1/1 +B: Regenerate this creature. + +Sliver +C +Creature Sliver +1/1 + +Snake +C +Artifact Creature Snake +1/1 +"Whenever this creature deals damage to a player, that player gets a poison counter." + +Snake +G +Creature Snake +1/1 + +Snake +G U +Creature Snake +1/1 + +Soldier +W +Creature Soldier +1/1 + +Spawn +C +Artifact Creature Spawn +2/2 + +Spider +B +Creature Spider +2/4 +Reach + +Spider +G +Creature Spider +1/2 +Reach + +Spike +G +Creature Spike +1/1 + +Spirit +B +Creature Spirit +N/N + +Spirit +C +Creature Spirit +1/1 + +Spirit +W +Creature Spirit +1/1 +Flying + +Spirit +W +Creature Spirit +3/3 +Flying + +Spirit +W B +Creature Spirit +1/1 +Flying + +Splinter +G +Cumulative upkeep - G +1/1 +Flying + +Squirrel +G +Creature Squirrel +1/1 + +Stangg Twin +R G +Legendary Creature Human Warrior +3/4 + +Starfish +U +Creature Starfish +0/1 + +Survivor +R +Creature Survivor +1/1 + +Tetravite +C +This creature can't be enchanted. +1/1 +Flying + +Thopter +C +Artifact Creature Thopter +1/1 +Flying + +Thopter +U +Creature Thopter +1/1 +Flying + +Thrull +B +Creature Thrull +0/1 + +Thrull +B +Creature Thrull +1/1 + +Tombspawn +B +Creature Zombie +2/2 +Haste + +Treefolk Shaman +G +Creature Treefolk Shaman +2/1 + +Triskelavite +C +Artifact Creature +1/1 +Flying + +Voja +G W +Legendary Creature Wolf +2/2 + +Wall +C +Artifact Creature Wall +0/2 +Defender + +Wall +U +Creature Wall +5/5 +Defender + +Warrior +R +Creature Warrior +1/1 + +Wasp +C +Artifact Creature Insect +1/1 +Flying + +Weird +U +Flying +3/3 +Defender + +Wirefly +C +Artifact Creature Insect +2/2 +Flying + +Wolf +G +Creature Wolf +1/1 +This creature gets +1/+1 for each card named Sound the Call in each graveyard. + +Wolf +G +Creature Wolf +2/2 + +Wolves of the Hunt +G +Creature Wolf +1/1 +Bands with other Wolves + +Worm +B G +Creature Worm +1/1 + +Wurm +B +Creature Wurm +6/6 +Trample + +Wurm +G +Creature Wurm +6/6 + +Wurm +G +Creature Wurm +X/X + +Zombie +B +Creature Zombie +2/2 + diff --git a/src/res/all-decks2 b/src/res/all-decks2 new file mode 100644 index 0000000000000000000000000000000000000000..38c6da9c83a678c049bad352494f98c7d355e712 GIT binary patch literal 27877 zcmdU2d6*?tb$?qk)3bC>&#);GO9WAvfym+li1t1`(>>Gl>zN+;L#=+Vx?j=tsvfmW zcTZem1QU%>`J#TosEK~Y#C)!a8kM*ZKyX82V%(A#7ZkU+fC{ep{Z3Wgs(Q;z*FgS| z4-WP2cFsNb+;h)8_uSiW`$3`4a|^q!(~s&G1-@xrH0-+i`n2i!YcKrVqi()ae|@=7 zoGMg2^O&*LDijKTzFGmi3zaHkMs4M5e|7!`uH1L*rczkTE!|$exazy6y?o_#q0-b%+b^6J=8>L@ z6+O(h^`>!s;rWH~bfMof>&Bv^yLBd1KwGik7q-?M+w#pCZk*~}h^a}&y zo@dxKLt8-a4V$Su1fb$x-EBHH1`Bv+)@zRC_zl0Xt=e*(z}Kp)$OiJc#=570722Fp zH;kqsJUkV+s=nhkwY`R02e+zDV5M-JP8_F$7jqahaM4-P#vKnMIROTmM|F!S^RBaE z3Q1?OxPZ<467Fu{m#|6rAl)5c+8}{+Vu)Wm33d^jN^ly1pg)6OXRd+w)23-I8ET9R zGR9lhB%!ncS=c$I2exk+o~MmDfxD=?D{T90zi|4PI0n)biXHd6q7new2PWKKMhnNQ?g zav&|3?fiX7H<01_r7RJGG}|r%XR7O9x9iwW;AvIM#K5ua<(O6rj#9jkh zCY5$2%U+q%HAyp9QG0=$Rnvxmrs_P6b)E*I!m`@5u^h?d)yxqd3qys0!k){RaXEo> zR=V{R{uElT;FnNx6~CnYt2y~Y1i6R*lu${4!b#UWcFbDWM$m1ju&p!Bnl|1vT-}1= z>*udoyuznXzrgSu`#4nC?g8 za1eBE59y4W$xUN_Ok-;GJ3<260aP71YU+_DU0DYo!wGZ*-Iz1hb!|*vwHLYe3kSDF zlu51Jgem3?j2XJ$;KHh}KrLcqCM;*w^D!y3(T45PH< zN!t|jY+%B0k7CRsI?`kiquDlOQ27+aeTJ<3*QKN}8ONx_+%ze6rBq?ZOxRw%J}_O^ zu(SgZZ5U>lFP`7Tf0+2gUd^!MRY&j(nE_~v=0d9U$1|BY|yne97)MOd5W^L^9CZl0TPWx)5n_0v2C`Z33p@L zh)P+48gA?K&BQD{FJtp5;1|xE44|o=8SK`oG_SE-z;JX;2h-rxX)}NlGL+WSLJqIzz+mE>(3<)VryN)wn!Uo9ZB0KbMw z0wnV_Kz(Y6dUz_TE*5ldD%4s4CAkL1v|0_*70dp0MEN=l=suW5o(a}XJI)Hs=O}$} z0j%=Ks|C}8EeDb|g(O{)n+l~FI;eOvv4sFK)Xu3lbCs<@$VkRP$JP^Zii@(o{1Yml z6I#ZKA=$++Ll~ub9mal5tJ+YmMDaF)w-dYrG(;0WEF@)evqXut@wc(W?F4s#Qfa$s+6I`tqiq^K1mWK?Vg*=b z>a=N=9mm7wb!d`9s8z##68^WGwbDq@X9zw`aJT#fQM*E-4%xL(wQ!e}TL4ZK0eA$A z-)Zav9PF8~7dslZ^Lb+G3Oecg50(u?ba6+3aKlF zzlgpKgnf(ausR zA<gZ`ovpbx1C-`LiwA1p1c!?kD8?vK{0Fp+5wCrLzkK|5U+MyY2^d3sZKVSDeD z6&dE*e#fqJSuS1(ogVv!wP_f0Uc$k!<8i+qZgMYeC-*XXrc4gz5?udKd~hR#0)Htf zy^P>;P!~B5LhACb_)5e&1f5=Cvm&8Q0~e<-#Y6WzX`Uk3 z2ZZrrD~|iz*ak%B?&vamXNlkh0PL7=nD&Y`ziNsZSiFX{1W46uKwvbdq@a|`O{8K; zc1kZ0*FsOXmgEAz@?(kbD>rf_itXd^EFyT8UpT9(yDeSpfN|{SVHWMy4m;LG+Tke~ zBq{goL^M?K+@$ngptukh+X2*l6`NIijeEa+v`*o#rbVtqhMBpkQ0|1Zja1~m{5Sw- z1qZQyLs#g2YEzJ;cBqWGR(svD2OrFT=L<{)MgC5?yN#rjay4_1sU3` zZs}aPy81)W(!Ri6#$iyk0Z%B34NSvR3Ewmj*KsTb#MtdQz9GX5L{&q!#n|2XMyr+L z`aGN%IAuk(+`U#)v4htyAzwp4!DDABck@QG<%?e#ERWo3l9?N|8t@L(uO#Yrz%5H) z<8YKmbg|QFApjdQ=O>9Epfn5Trc2GrEzzm*g0YCMa@V3x3cC6Hihn_}Z*E^iUJHt% zMPwMhdc#F?xoH}V)%vbcM`j1kk8pm3jfobP+kfsUL3xD9bK zvhF(x-XUKJ+PJW4ccUx15|9l3_x8XK0gbjg)7aV>I8WNP9|vd%i_mx+N22J=D!vbt zMJg=H&rO)p-y6Du8U>qiJShS3jTbxTT8>0E8_(u|E#U*mnqy{TX)5l2D z$IxRKpYVl52UwCwa3?VD4BZ}KffYI6>W!V1ZdcjS2&v{mY|=1L?qvV~*snS(*+dy_ zr_w0%+q&Jw<8#FRImifIRJQM8FA_xpM7AjM2CBjJ=MVe322~Cdm^J@A z+)}$`!defPD+HNz=-#hDe~mZ}k3?;_-gb?dEz4;_;n%dOW)qG=2@NQInZ$hs#6{L% zQY<%NN}q9@gIV^^cqrmPN_o+p7n4Y(!2sKFV% z?gsFZj;_}%r$s!)?xMUYVf3Fnvf_Vw6*98^LxkdX`=rMjklJ z%P0vtc|6qW$c&0>`Pzk=G0fbU{ zh6aD$q=f=ZJxc&unJ^@#2>W^{dIOP6;QS{<1nrN^n!P$sNO!N{EX(uH0SCLRX(i?w-L?&q&MN zFjL^7>MnO9%oV`Us*-T`Qhr@Va5;f+N%--UymH4dtkM+(=ybc>Nv{#_)l2TA!%t^r z^ru7aq+2853XqmOB~=^MdTQ?)(?N^}5&+!L0#I;c>xdtADCwa|DXC#%Zlqo91>!uE zT3vy8ud|Bd4LAkDQY&l()CY&WHkJ^~iOk-JbRcS35zODql1N};1S4}3 zwW20+)1urCse}BI!}c8v8*QjmOh~E43;|N41rnl7S`-G*8$W9{Rd&j5N!n~-eHx{$ zkA-T}nCUfPbV8YoM`7O8n$F`Dp-t#W7@&e+E>##dI&FqzdyZ4?j?OZmsbcwV(t#8RVRtlDBVDOH$Xn<-Ph*ekz3V$ zoGS|RZe-?-=y2LHWZH`%YqXWLnROT-org{=^Ctqj%xLlFk-+)a=T>P(b+KRM=Z)CSdMEREli1bp521RBK#Lrj_9r6QOBA0rY z*jqx`&dn-2T9BCd`UHS4`+50fzhTJCe|^|h#tbu^$*P5o&S9m*I@tVHB5numV=HBn z*%*yGqjbfv?70ss{jH)@t%Hh(Y?O|+(mSEdstu*O-la0$1(cEYjPg};8|}Cn<3Vg} z7Ug6WyGNXc6UqA$lY~G2Nz&viVR>9FH)hr0^gf%7e@Fo4+Z;5x+=M70By8K9zGx!g z5*K`QvE)At8lt6CvcjC)WGJI&U}D{_H*gCeyf4xzU9e1WKRc zsuf;ZAsYM?-i(>Bwro0hqtzOVYLu26Z6)?4Cv%8u42Mp*$uNoit3k~FPVjjkjHYdv zpBtHST&IyK`9||wLi>@^Hh1H@;$^q1TKzhBH)=US-7|1Ai@RYJf;I#96Azx!a+lS$ zibOCVZNQ*TbYTMbj>6kujCW~CTs2wtbpkrmO5Y^7hu~WT-zK=1;5!80O;|hcAXeZw zS^_v>)OK9OQwnPUcbOW#Y|%#$H=WYKMD$|;NSq5+8rt}>7=J%fIX?j%kpf`>^fclu;bb|QQi!pg1Lb^P!=wAiO-|FiDYah z=m#y)q?@o1E1q96)PSURab;X~R6DK@}wjeM9Sy0^$=i!Pdh%mbfeCqSeIe? zrF;=7=n6p4yoo5z z46Hg~A*J-yl$y-{kP34=-LJBedq%pGi+QSM?%)iPEuwG7$;Sp15r_2gcQro zD0PaP79qC$%#>1uLckWz!=e%8#40PTHJEj6TXzzcMfG#jr)0jJKJF;XA;8$p!x8VB z%|*x;4CC;Svy8K$0bDh=4FsRBXtP0++tYG7lttCbO;=C8(YeCei0gFS=z>|ta7!%h zdTpKLaGzV|@k1x2+#1GeLs9w=q;AIq0)*s(73HG|y`*GSfur&T65`cAs@$7Z ztdOjOY6@o55z9PR0A@cp!Lw-%C#pDsDD;owMu?@2(?Nwie$N;#FL+CZM3|y_y(z(@ z=w=rx`@VxD_-oEOxahdf?kJ9mr%QagAT*P)-#TaqI41@T(R7p2xhYUa|5-EU3a)z* z;V4XQ$StNk5#lmUdR75pv=3l~-1vGC}V`ZfmlNTEb3M)u3K7GcT3ARsbBq@tXS=foD7BH1h7XdG4`NBeX$mHYJV#Q#MG^^a zNf5^cdLw3q_p5A$Z%Y_ax#-9P7v+zpXCbTHs=!C(D;fKwqH1-c9wtppP&|gwe*bu2 z#Ki$EFD79hWI4om7fOvGM$<-g%zS`dIuk#R#JvvVIDMRQEOT!eFF(xwq=5FWe2S@X zpmYrQruxc@a45$*~Pg9cfFIwc(t`h*z4D$V~dgyyt)c;BZ3uur--;+#0_q5NM;*t^TjeI)F@PMNu%>Gy9$ zW`4$!KkF$oKWFyOyUEN0%z5BAGDA;R`N8AM%r98x7g?G4CDVS{CNsZc;;*{M%&(d8 z>l4Y$Z&>O#oig)VrvJ99%v9+2sua4)OocA8O0kQ~$bbm1raY7+%>@U z8(OKAe)jAC1qid~dhDMcug;%%?p97wBX-=87$C*Jli>IxG01-XzW`y@AVwl`JI3Oz zD~4}$iX=9-+N)=bAy_vDOawLR*pFG(9=VK;Nq-2JEOmGoTA}q-IgMRCo!|@tJ{cEH z++oXF?@bj8?^4;@V?Si#HLE;|MNR-fD322n~3rRw-bM@u0e+JBv4)%k7&AD5v;L>#!` zns%sd311|na*$kt-2{6QT2wnHPs^_T`Y~8=c-V&VsZE4giIq}mzx7(VjJO3{Dqo;N zIq{_hX&^Tt=cuhiTO>utCZTdA@glS?wKJ$NtgbugTx%;&W8tm<@&(I^fgUifu?NA^ z8n6%Pm#bWXc^V&pGgKQ^9BiSkmUu+pE{cfP!m(lUU?m!fr+I1>6Y3EZxbuKfbDd>G z;mG?ueBm;?)?up$f}3p~8SHjU#dZIQ2l8V26z6zUO)nC>E|jeXXvlbcAzw@6>2x$!kz z9Dx*uo}mij5Yq?~$&Vvm!NfSedPMhmBR--?8p=(PV%urMwOY``i?qD*vmdXz;O5mb z9V8V~K$pS0ju}0HRJ#uJMcZJspPM?xuc2`pYlVTp_&PUN%YjfPQjOriw05|jL`lZ= zz#T2OaqavUKb0LcAQ5x$Z7k!?bEq#@i3%54y9Lu#)|koBk$U2V5Sm5r<96H7h#9?- zHH($GZi+Lia*VZ(f$njrX1(ch8jpq{WtBgGFIT40qt1u@r=( z_&n5BZzNTo&)Qu9G}A1uxbYDqzQYHDA$--d@&Z`uVgSwzrPW-7gjnA^Z#GwqF% z0cs*wd0cxu|LXyYJE;S%-Sl$h#GONpxR~1*25Zyt)R^=ZgPrg7#91JSua-&xq%A$WiTYrDbwL*Q1 zx0hF7MIVM$1bYa_4nyNS!Pzr`xuIPf;1fqt*_e6gsBB1;v`g>-kRE$S!-jLyex(>6 zN6=2Yo4bPd=S~^JQ+uLADz_8i?dU?61I@}E%)A49oW?z4?%)nbwQvDAy~N$ga(B{% z?DoKQVc@!++(4|*Q(u9nKABu#bT$Zb^C8;{nmDBaCDB+N5*=s#sfT;YC*nWr+!BITk z=T%;~A2Iz$Tq2?fL;hx*W#z{irTY^mg#e4~G;W46+)>{8tlY;uxVHP@;Iqx6c=(zL z_Y07bmiR!Mzv*i24p3b^q|HL~$5!C&9;_my4%328#J%Aq%nIGK6}Y-_0fK)k;V}9` zj#VB&adm94S8w8)I+Gt1kj_gM6S{aS0)#{0#NdRE=cy4$07hBR1S|kv;9fk`&LR#o zS1@E#WFj5`!dcj;(~KV74EZD6kk0=!CFUJscf9BYqLlulkDKuhFm9}b`!c$w!|uQn zzhj}nr|G~Kn8$t~uWv%3$Af^Yvbn{mEDC)KHitdlCxb@b54(K@_C#z~Clffz$&FR5 zz_GT+!Zx`I{#xs}orjl`@#L48RVLs=AL0Pjk#h%ow;Z8$JdA-%&1XCls72B`0eV5(e`mq(lU=PDpc@P=jd zc;6);G7h%F0cZm+E#;%hk4^rPPqDw7Q7y`8{^i8qhDWy{QYo7q<8|>bp z?dT-R6*{vv*y$hB>+D;o(Bt;uD*F>q?)2pWgAiA;JVAD_Dhi!EC(W0%;hi#b} zge4{{2{RL6r-!vK1R05MFg*lWv6poO3t;Ln?zbnwmOBO$@J!NrUZ?) zJ^|0>*K-Jjql^3!P6%xKP8XtAs^KL44}8hQBU0 zl>AAuz0kNbdaG~Kmv6o8^ymC*xlo!YY_Z@9!zL5QeN%;gAF*d1PdC + + + + + 0 + 0 + 1440 + 827 + + + + + + + + 0 + 0 + 242 + 827 + + + + + + + + 0 + 0 + 242 + 145 + + + + info + + + + + + 0.2 + + + + + + + + 0 + 145 + 242 + 10 + + + + + + + + + + + + 0 + 155 + 242 + 171 + + + + compy + + + + + + 0.2 + + + + + + + + 0 + 326 + 242 + 10 + + + + + + + + + + + + 0 + 336 + 242 + 115 + + + + stack + + + + + + 0.2 + + + + + + + + 0 + 451 + 242 + 10 + + + + + + + + + + + + 0 + 461 + 242 + 107 + + + + combat + + + + + + 0.2 + + + + + + + + 0 + 568 + 242 + 10 + + + + + + + + + + + + 0 + 578 + 242 + 249 + + + + human + + + + + + 0.2 + + + + + + + + + + + + false + + + + + + + + 242 + 0 + 10 + 827 + + + + + + + + + + + + 252 + 0 + 906 + 827 + + + + + + + + 252 + 0 + 906 + 163 + + + + compyLand + + + + + + 0.2 + + + + + + + + 252 + 163 + 906 + 10 + + + + + + + + + + + + 252 + 173 + 906 + 166 + + + + compyPlay + + + + + + 0.2 + + + + + + + + 252 + 339 + 906 + 10 + + + + + + + + + + + + 252 + 349 + 906 + 140 + + + + humanPlay + + + + + + 0.2 + + + + + + + + 252 + 489 + 906 + 10 + + + + + + + + + + + + 252 + 499 + 906 + 145 + + + + humanLand + + + + + + 0.2 + + + + + + + + 252 + 644 + 906 + 10 + + + + + + + + + + + + 252 + 654 + 906 + 173 + + + + humanHand + + + + + + 0.2 + + + + + + + + + + + + false + + + 1.0 + + + + + + + + 1158 + 0 + 10 + 827 + + + + + + + + + + + + 1168 + 0 + 272 + 827 + + + + + + + + 1168 + 0 + 272 + 424 + + + + detail + + + + + + 0.5 + + + + + + + + 1168 + 424 + 272 + 10 + + + + + + + + + + + + 1168 + 434 + 272 + 393 + + + + picture + + + + + + 0.5 + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + diff --git a/src/res/gui/gui.properties b/src/res/gui/gui.properties new file mode 100644 index 00000000000..566de3ed222 --- /dev/null +++ b/src/res/gui/gui.properties @@ -0,0 +1 @@ +Display--file=display_layout.xml \ No newline at end of file diff --git a/src/res/lang/de.properties b/src/res/lang/de.properties new file mode 100644 index 00000000000..04904080d1f --- /dev/null +++ b/src/res/lang/de.properties @@ -0,0 +1,105 @@ +program/name=MTG Forge - 10/2009 - http://mtgrares.blogspot.com + + + +BoosterDraft/close/message=Dein Fortschritt kann nicht gespeichert werden, wirklich schließen? +BoosterDraft/save/message=Willst du dieses Deck Speichern +BoosterDraft/save/title=Deck speichern +BoosterDraft/rename/message=Deck Name +BoosterDraft/rename/title=Deck umbenennen +BoosterDraft/saveDraft/message=Draft Name +BoosterDraft/saveDraft/title=Draft benennen + + + +Display/menu/title=Menü + +Display/human/title=Spieler +Display/human/hand/title=Hand: +Display/human/removed/menu=Entfernte Karten ansehen +Display/human/removed/button=Entfernt: +Display/human/removed/title=Deine entfernten Karten +Display/human/library/title=Bibliothek: +Display/human/graveyard/menu=Friedhof ansehen +Display/human/graveyard/button=Friedhof: +Display/human/graveyard/title=Dein Friedhof +Display/human/flashback/menu=Karte mit Rückblende spielen +Display/human/flashback/button=Rückblende: +Display/human/flashback/title=Karte mit Rückblende spielen + +Display/combat/title=Kampf + +Display/computer/title=Computer +Display/computer/hand/title=Hand: +Display/computer/removed/menu=Computer - Entfernte Karten ansehen +Display/computer/removed/button=Entfernt: +Display/computer/removed/title=Computer's entfernte Karten +Display/computer/library/title=Bibliothek: +Display/computer/graveyard/menu=Computer - Friedhof ansehen +Display/computer/graveyard/button=Friedhof: +Display/computer/graveyard/title=Computer's Friedhof + +Display/concede/menu=Aufgeben + + + +DownloadPictures/title=Download +DownloadPictures/no-more=Es wurden bereits alle Bilder heruntergeladen! + +#Das sind die Vorgabewerte für Proxyverbindungen +DownloadPictures/proxy/address=Proxy Addresse +DownloadPictures/proxy/port=Proxy Port + +DownloadPictures/proxy/type/none=Kein Proxy +DownloadPictures/proxy/type/http=HTTP Proxy +DownloadPictures/proxy/type/socks=SOCKS Proxy + +DownloadPictures/button/start=Start Download +DownloadPictures/button/cancel=Abbrechen +DownloadPictures/button/close=Schließen + +DownloadPictures/bar/before-start=Proxy konfigurieren, dann Start drücken +DownloadPictures/bar/wait=%d von %d Karten heruntergeladen! Bitte warten! +DownloadPictures/bar/close=%d von %d Karten heruntergeladen! Bitte schließen! + +DownloadPictures/errors/proxy/connect=Proxy-Verbindung konnte nicht hergestellt werden!\n\ + Proxy Addresse: %s\n\ + Proxy Port: %s +DownloadPictures/errors/other=Du musst mit dem Internet Verbunden sein. Fehler beim herunterladen:\n\ + Karte: %s\n\ + URL: %s + + + +ErrorViewer/show=Stapel-Report +ErrorViewer/title=Fehler +ErrorViewer/message=Ein Fehler ist aufgetreten. Du kannst diese Nachricht kopieren oder in einer Datei speichern.\n\ + Bitte melde diese Nachricht, und wie er aufgetreten ist, hier:\n\ + \t%s\n\ + Falls du keine Konto anlegen willst, schreibe eine Mail an\n\ + \t%s\n\n\ + %s\n\n\ + Detaillierter Stapelverlauf:\n +ErrorViewer/button/save=Speichern... +ErrorViewer/button/close=Schließen +ErrorViewer/button/exit=Programm verlassen + +ErrorViewer/errors/save/message=Entschuldigung, während des Speicherns ist ein Fehler aufgetreten! +ErrorViewer/errors/show/message=Du hast einen vollständigen Report verlangt + + + +#Das Tutorial ist ziemlich lang, deshalb ist es in einem eigenen File +HowTo--properties=howTo/de.properties + + + +NewGame/menu/title=Menü +NewGame/menu/lookAndFeel=Anzeige-Einstellungen +NewGame/menu/download=Bilder downloaden +NewGame/menu/cardSizes=Kartengröße einstellen +NewGame/menu/about=Über +NewGame/options/title=Optionen +NewGame/options/generate/title=Deckgenerator +NewGame/options/generate/removeSmall=1/1 und 0/X Kreaturen entfernen +NewGame/options/generate/removeArtifacts=Artefakte entfernen diff --git a/src/res/lang/en.properties b/src/res/lang/en.properties new file mode 100644 index 00000000000..539ece7b931 --- /dev/null +++ b/src/res/lang/en.properties @@ -0,0 +1,105 @@ +program/name=MTG Forge - 10/2009 - http://mtgrares.blogspot.com + + + +BoosterDraft/close/message=Your progress cannot be saved, do you want to exit? +BoosterDraft/save/message=Do you want to save this deck? +BoosterDraft/save/title=Save Deck +BoosterDraft/rename/message=Deck Name +BoosterDraft/rename/title=Rename Deck +BoosterDraft/saveDraft/message=Please name this draft +BoosterDraft/saveDraft/title=Save Draft + + + +Display/menu/title=Menu + +Display/human/title=Player +Display/human/hand/title=Hand: +Display/human/removed/menu=View Removed +Display/human/removed/button=Removed: +Display/human/removed/title=Player's Removed +Display/human/library/title=Library: +Display/human/graveyard/menu=View Graveyard +Display/human/graveyard/button=Grave: +Display/human/graveyard/title=Player's Grave +Display/human/flashback/menu=Play card with Flashback +Display/human/flashback/button=Flashback: +Display/human/flashback/title=Play card with Flashback + +Display/combat/title=Combat + +Display/computer/title=Computer +Display/computer/hand/title=Hand: +Display/computer/removed/menu=Computer - View Removed +Display/computer/removed/button=Removed: +Display/computer/removed/title=Computer's Removed +Display/computer/library/title=Library: +Display/computer/graveyard/menu=Computer - View Graveyard +Display/computer/graveyard/button=Grave: +Display/computer/graveyard/title=Computer's Grave + +Display/concede/menu=Concede Game + + + +DownloadPictures/title=Downloading +DownloadPictures/no-more=All card pictures have been downloaded. + +#These are the default values for the proxy textfields +DownloadPictures/proxy/address=Proxy Address +DownloadPictures/proxy/port=Proxy Port + +DownloadPictures/proxy/type/none=No Proxy +DownloadPictures/proxy/type/http=HTTP Proxy +DownloadPictures/proxy/type/socks=SOCKS Proxy + +DownloadPictures/button/start=Start download +DownloadPictures/button/cancel=Cancel +DownloadPictures/button/close=Close + +DownloadPictures/bar/before-start=Configure Proxy, then press Start +DownloadPictures/bar/wait=%d of %d cards finished! Please wait! +DownloadPictures/bar/close=%d of %d cards finished! Please close! + +DownloadPictures/errors/proxy/connect=Proxy connection could not be established!\n\ + Proxy address: %s\n\ + Proxy port: %s +DownloadPictures/errors/other=You must be connected to the Internet. Error downloading card:\n\ + Card name: %s\n\ + URL: %s + + + +ErrorViewer/show=Stack Report +ErrorViewer/title=Error +ErrorViewer/message=An error has occured. You can copy/paste this message or save it to a file.\n\ + Please report this, plus what you tried to do, to:\n\ + \t%s\n\ + If you don't want to register an account, you can mail it directly to\n\ + \t%s\n\n\ + %s\n\n\ + Detailed error trace:\n +ErrorViewer/button/save=Save... +ErrorViewer/button/close=Close +ErrorViewer/button/exit=Exit Application + +ErrorViewer/errors/save/message=There was an error during saving, sorry! +ErrorViewer/errors/show/message=You requested a full error report + + + +#The how to text is pretty long, so it's moved to a separate file +HowTo--properties=howTo/en.properties + + + +NewGame/menu/title=Menu +NewGame/menu/lookAndFeel=Display Options +NewGame/menu/download=Download Card Pictures +NewGame/menu/cardSizes=Specify Card Size +NewGame/menu/about=About +NewGame/options/title=Options +NewGame/options/generate/title=Generate Deck +NewGame/options/generate/removeSmall=Remove 1/1 and 0/X Creatures +NewGame/options/generate/removeArtifacts=Remove Artifacts diff --git a/src/res/lang/howTo/de.properties b/src/res/lang/howTo/de.properties new file mode 100644 index 00000000000..b978bd877b0 --- /dev/null +++ b/src/res/lang/howTo/de.properties @@ -0,0 +1,79 @@ +title=(Wie man spielt) +message=--- Du bist gefragt! ---\n\n\ +Dieser Text wurde noch nicht übersetzt! Wenn Du Interesse hast, etwas für MTG Forge beizutragen, aber keine Programmierkenntnisse hast, könntest du zum Beispiel diesen Text übersetzen - auch in eine andere Sprache als Deutsch.\n\n\ +Die zugehörige Datei findest Du im forge-Ordner unter\n\ +\tres/lang/howTo/de.properties\n\ +Lass Dich von den vielen "\\" nicht verwirren - pass nur auf, dass sie bleiben wo sie sind ;)\n\ +Poste dein Resultat dann bitte auf\n\ +\thttp://www.slightlymagic.net/forum/viewforum.php?f=26\n\ +oder schicke es an\n\ +\tmtgrares@yahoo.com\n\ +Vergiss bei anderen Sprachen nicht, zu erwähnen, um welche Sprache es sich eigentlich handelt ;)\n\ +Danke!\n\n\n\n\ +How to Play - (Revised: September 2009.)\n\n\n\ +Introduction\n\n\ +1. This game is similar to many other trading card games. You start out with 20 life and your goal is to reduce your opponents life to zero by attacking with your creatures. The game will end when your life or the computer's life is reduced to zero. You play \"matches\" against the computer as a set of \"best two out of three\" games."\n\n\ +2. You use land to pay for spells. You can play one land a turn.\n\n\ +3. Each land produces a different magical energy. This magical energy is shortened to one letter on cards.\n\n\ +\ Forests make G\n\ +\ Swamps make B\n\ +\ Plains make W\n\ +\ Islands make U\n\ +\ Mountains make R\n\n\ +4. Each non-land card has a name and a cost. The cost looks like this \"2GG\" A cost like that would require two Forest lands and two other lands. The number 2 can be paid for by any land. A cost like \"R\", would require a Mountain land.\n\n\ +5. Creature cards stay in play and can attack on the turn AFTER they are played. A creature's attack and defense is shown like 2/4 meaning that the creature has an attack power of 2 and a defense of 4. If this creature receives 4 damage it is put into the graveyard.\n\n\ +6. When you attack with your creatures the computer has a chance to block with his creatures. When you attack you \"tap\" your creatures by turning them sideways. Your creatures will untap during your next turn. When you block, only untapped creatures can block. Usually a creature cannot attack and block during the same turn.\n\n\ +7. Sorcery and Instant cards have an effect on the game. After you play any card it goes on the stack to the left, click OK and the stack will clear. Sorcery cards can only be played during your turn and when the stack is empty. Instant cards can be played at any time and are more versatile.\n\n\ +8. If a card has a target, you get to choose that target. If the target is a player, click on that player's life points.\n\n\ +9. When you mulligan, the cards in your hand are shuffled into you deck and you are given 1 less card.\n\n\n\ +Legendary Cards\n\n\ +Legendary cards are powerful cards that can be either creatures, enchantments, lands, artifacts or planeswalkers. These cards can only exist once in the battlefield, and if another copy of the legendary card is played, all copies of the card are destroyed and sent to the graveyard.\n\n\n\ +Planeswalkers\n\n\ +There are 7 planeswalkers (Ajani Goldmane; Liliana Vess; Garruk Wildspeaker; Chandra Nalaar; Nicol Bolas; Elspeth, Knight-Errant; Nissa Revane) and they have specific rules for their special abilities.\n\n\ +You can only use one ability a turn. A planeswalker can be attacked, but you can also block with your creatures. For each 1 damage a planeswalker receives, you remove 1 counter. When a planeswalker doesn't have any counters, it goes to the graveyard.\n\n\n\ +Hybrid Mana and Multicolored Cards\n\n\ +1. Hybrid Mana Cards are unique in their casting cost as seen in the card. Instead of seeing a single color per mana symbol, these cards have 2 colors per mana symbol indicating that the player has the choice of playing either of the two. There are also cases where numbers and colors are combined together in one mana symbol, which indicates that either colorless or colored mana can be paid for each symbol. Hybrid cards are treated as two colors and as such can be said to be multicolored.\n\n\ +2. Multicolored Cards are slightly different than hybrid mana cards, as they require two or more different colors of mana, which may or not be in a single mana symbol. An example would be a card like Lightning Helix which requires one red and one white mana to be played.\n\n\n\ +Game Types\n\n\ +1. In Constructed Deck mode you can use any of the cards to make your deck. To make a constructed deck, from the Deck Editor select \"New Deck \u2013 Constructed\". A list of all the cards will be displayed.\n\n\ +2. In Sealed Deck mode you are given 75 cards and you have to make your deck from just those cards.\n\n\ +3. In Booster Draft mode you select 1 card at a time and then make your deck from just those cards. After you are done drafting you have to type in a filename, then go to the Deck Editor and from the menu select \"Open Deck - Draft\" and find the filename. This will allow you to construct your deck. You can then play against the other 7 computer opponents that were drafting with you.\n\n\ +4. In Quest Mode you start out with 275 cards, 200 are Basic Lands. As you complete matches in your quest you will win more cards. In easy mode you get more cards after every game, whether you win or lose. Your goal is to become world champion. Once you reach the end of your quest you can continue to play additional matches and win even more cards or you can start a new quest at anytime.\n\n\ +At the Quest Options screen you will be given a choice of four different difficulty levels. These difficulty levels control:\n\n\ +1) the length of the quest in matches,\n\ +2) the hardness of the AI deck that you will face as an opponent,\n\ +3) the number of wins or loses needed to get more cards,\n\ +4) the number of wins needed to advance a player to the next rank.\n\n\n\ +Quick Games\n\n\ +There may be occasions where you only have a few minutes to play a quick game or two. At the top of the New Game window you will see the three different game types with radio buttons. Click on the Constructed (Easy) button and it will become highlighted.\n\n\ +In the middle area of the New Game window you will see two menus, one labeled \"Your Deck\" and the other \"Opponent\". For a quick game you should select the \"Generate Deck\" or the \"Random\" option for both you and the computer.\n\n\ +1. The \"Generate Deck\" option creates a 2 color deck. This option randomly picks cards and sometimes your mana curve may be too high.\n\n\ +2. The \"Random\" option will randomly select one of the constructed decks that appear in the two deck menus. You either construct these decks in the Deck Editor or you imported a .deck file from the Deck Editor.\n\n\ +If you select the \"Random\" option and click on the \"Start Game\" button and the match fails to begin \u2026 well, this happens if you fail to have any constructed decks saved to your all-decks2 file. You should choose the \"Generate Deck\" option instead.\n\n\n\ +Resizable Game Area & Stack AI Land\n\n\ +1. The \"Resizable Game Area\" check box should be set to on if your monitor will display more than 1024 x 768 pixels. The window containing the Battlefield and the informational displays will fill the entire screen.\n\n\ +2. The \"Stack AI Land\" option will make the computer a more difficult opponent to beat. The computer will draw non-land cards from it's library after it has drawn enough lands to cover the cost of it's spells. Set the check box to on for a stronger opponent and set the check box to off for a weaker opponent.\n\n\ +At times, you may notice that when you click the \"Start Game\" button that the match fails to begin. In this case you should turn the \"Stack AI Land\" option to off.\n\n\n\ +Abilities\n\n\ +There are three kinds of abilities: Activated, Triggered, and Static.\n\n\ +1. Activated abilities contain a colon that separates cost and effect, these can be played any time you could play an instant. An example is Elvish Piper's ability. That cost also contains the tap symbol. For creatures only, abilities containing the tap- or untap symbol can be played starting the turn after the creature came into play. Another common cost for an activated ability is sacrificing the card. You do that by putting it into your graveyard. Such abilities can only be played once.\n\n\n\ +2. Triggered abilities aren't played, they simply trigger when their condition occurs. An example is Angel of Mercy: You don't play the ability, but gain 3 life when it comes into play.\n\n\ +3. Static abilities are neither played, nor do they trigger. They still have an effect for as long as they are in play. An example is Glorious Anthem. There is no condition or cost, your creatures are just stronger.\n\n\n\ +Keyword Abilities\n\n\ +1. Flying: Creatures with flying are harder to block. Only creatures with flying or reach can block other flyers.\n\n\ +2. Haste: Haste lets a creature attack or use any abilities immediately during this turn.\n\n\ +3. Fear: Creatures with fear can only be blocked by artifact or black creatures. Creatures with fear are harder to block.\n\n\ +4. Cycling: When you cycle a card you pay some cost like 2 and then you discard that card, and then draw a new card. Cycling helps make your deck more versatile.\n\n\ +5. Vigilance: This means that the creature will not tap when attacking. This creature can both attack and block during the same turn.\n\n\ +6. Trample: If you use 2/1 creature to block an attacking 3/4 creature with trample, you will still receive 2 damage because the 3/4 trampled over your 2/1 creature. Trample damage is calculated by (attack - blocker's defense), in this case 3-1 which is 2.\n\n\ +7. Deathtouch: When a creatures with deathtouch deals damage to a creature, that creature is destroyed.\n\n\ +8. Defender: Creatures with defender can not attack, they can only block another attacker.\n\n\ +9. First Strike and Double Strike: Creatures with first strike deals their combat damage first. Creatures with double strike deals their combat damage first, and then deals their combat damage a second time during the combat damage step.\n\n\ +10. Flash: You can play a creature with flash anytime that you can play an Instant.\n\n\ +11. Landwalk: Allows your creature to attack without being blocked if your opponent controls the appropriate land type.\n\n\ +12. Lifelink: With lifeline you gain life equal to the amount of damage dealt.\n\n\ +13. Protection: Can not be damaged, blocked or targeted by sources that match the protection type.\n\n\ +14. Reach: Creatures with reach can block flying creatures.\n\n\ +15. Shroud: Permanents with shroud can not be targeted by abilities or spells.\n\n\ +16. Regenerate: Regenerate is an ability that some creatures have which prevents them from being destroyed and put into the graveyard. When you regenerate a creature, it acts like a shield until end of turn.\n\n\ +17. Morph: A creature with morph can be played by usually paying 3 mana of any color and be treated as a 2/2 creature with no abilities rather than playing the creature's actual cost. This creature is placed face down in the battlefield and can be flipped face up anytime as long as you pay its morph cost which is indicated on the card. Once flipped face up the card is treated as the original card, the one that you would normally play with its original-full casting cost. diff --git a/src/res/lang/howTo/en.properties b/src/res/lang/howTo/en.properties new file mode 100644 index 00000000000..5fa2ad3dbe2 --- /dev/null +++ b/src/res/lang/howTo/en.properties @@ -0,0 +1,68 @@ +title=(How to Play) +message=How to Play - (Revised: September 2009.)\n\n\n\ +Introduction\n\n\ +1. This game is similar to many other trading card games. You start out with 20 life and your goal is to reduce your opponents life to zero by attacking with your creatures. The game will end when your life or the computer's life is reduced to zero. You play \"matches\" against the computer as a set of \"best two out of three\" games."\n\n\ +2. You use land to pay for spells. You can play one land a turn.\n\n\ +3. Each land produces a different magical energy. This magical energy is shortened to one letter on cards.\n\n\ +\ Forests make G\n\ +\ Swamps make B\n\ +\ Plains make W\n\ +\ Islands make U\n\ +\ Mountains make R\n\n\ +4. Each non-land card has a name and a cost. The cost looks like this \"2GG\" A cost like that would require two Forest lands and two other lands. The number 2 can be paid for by any land. A cost like \"R\", would require a Mountain land.\n\n\ +5. Creature cards stay in play and can attack on the turn AFTER they are played. A creature's attack and defense is shown like 2/4 meaning that the creature has an attack power of 2 and a defense of 4. If this creature receives 4 damage it is put into the graveyard.\n\n\ +6. When you attack with your creatures the computer has a chance to block with his creatures. When you attack you \"tap\" your creatures by turning them sideways. Your creatures will untap during your next turn. When you block, only untapped creatures can block. Usually a creature cannot attack and block during the same turn.\n\n\ +7. Sorcery and Instant cards have an effect on the game. After you play any card it goes on the stack to the left, click OK and the stack will clear. Sorcery cards can only be played during your turn and when the stack is empty. Instant cards can be played at any time and are more versatile.\n\n\ +8. If a card has a target, you get to choose that target. If the target is a player, click on that player's life points.\n\n\ +9. When you mulligan, the cards in your hand are shuffled into you deck and you are given 1 less card.\n\n\n\ +Legendary Cards\n\n\ +Legendary cards are powerful cards that can be either creatures, enchantments, lands, artifacts or planeswalkers. These cards can only exist once in the battlefield, and if another copy of the legendary card is played, all copies of the card are destroyed and sent to the graveyard.\n\n\n\ +Planeswalkers\n\n\ +There are 7 planeswalkers (Ajani Goldmane; Liliana Vess; Garruk Wildspeaker; Chandra Nalaar; Nicol Bolas; Elspeth, Knight-Errant; Nissa Revane) and they have specific rules for their special abilities.\n\n\ +You can only use one ability a turn. A planeswalker can be attacked, but you can also block with your creatures. For each 1 damage a planeswalker receives, you remove 1 counter. When a planeswalker doesn't have any counters, it goes to the graveyard.\n\n\n\ +Hybrid Mana and Multicolored Cards\n\n\ +1. Hybrid Mana Cards are unique in their casting cost as seen in the card. Instead of seeing a single color per mana symbol, these cards have 2 colors per mana symbol indicating that the player has the choice of playing either of the two. There are also cases where numbers and colors are combined together in one mana symbol, which indicates that either colorless or colored mana can be paid for each symbol. Hybrid cards are treated as two colors and as such can be said to be multicolored.\n\n\ +2. Multicolored Cards are slightly different than hybrid mana cards, as they require two or more different colors of mana, which may or not be in a single mana symbol. An example would be a card like Lightning Helix which requires one red and one white mana to be played.\n\n\n\ +Game Types\n\n\ +1. In Constructed Deck mode you can use any of the cards to make your deck. To make a constructed deck, from the Deck Editor select \"New Deck \u2013 Constructed\". A list of all the cards will be displayed.\n\n\ +2. In Sealed Deck mode you are given 75 cards and you have to make your deck from just those cards.\n\n\ +3. In Booster Draft mode you select 1 card at a time and then make your deck from just those cards. After you are done drafting you have to type in a filename, then go to the Deck Editor and from the menu select \"Open Deck - Draft\" and find the filename. This will allow you to construct your deck. You can then play against the other 7 computer opponents that were drafting with you.\n\n\ +4. In Quest Mode you start out with 275 cards, 200 are Basic Lands. As you complete matches in your quest you will win more cards. In easy mode you get more cards after every game, whether you win or lose. Your goal is to become world champion. Once you reach the end of your quest you can continue to play additional matches and win even more cards or you can start a new quest at anytime.\n\n\ +At the Quest Options screen you will be given a choice of four different difficulty levels. These difficulty levels control:\n\n\ +1) the length of the quest in matches,\n\ +2) the hardness of the AI deck that you will face as an opponent,\n\ +3) the number of wins or loses needed to get more cards,\n\ +4) the number of wins needed to advance a player to the next rank.\n\n\n\ +Quick Games\n\n\ +There may be occasions where you only have a few minutes to play a quick game or two. At the top of the New Game window you will see the three different game types with radio buttons. Click on the Constructed (Easy) button and it will become highlighted.\n\n\ +In the middle area of the New Game window you will see two menus, one labeled \"Your Deck\" and the other \"Opponent\". For a quick game you should select the \"Generate Deck\" or the \"Random\" option for both you and the computer.\n\n\ +1. The \"Generate Deck\" option creates a 2 color deck. This option randomly picks cards and sometimes your mana curve may be too high.\n\n\ +2. The \"Random\" option will randomly select one of the constructed decks that appear in the two deck menus. You either construct these decks in the Deck Editor or you imported a .deck file from the Deck Editor.\n\n\ +If you select the \"Random\" option and click on the \"Start Game\" button and the match fails to begin \u2026 well, this happens if you fail to have any constructed decks saved to your all-decks2 file. You should choose the \"Generate Deck\" option instead.\n\n\n\ +Resizable Game Area & Stack AI Land\n\n\ +1. The \"Resizable Game Area\" check box should be set to on if your monitor will display more than 1024 x 768 pixels. The window containing the Battlefield and the informational displays will fill the entire screen.\n\n\ +2. The \"Stack AI Land\" option will make the computer a more difficult opponent to beat. The computer will draw non-land cards from it's library after it has drawn enough lands to cover the cost of it's spells. Set the check box to on for a stronger opponent and set the check box to off for a weaker opponent.\n\n\ +At times, you may notice that when you click the \"Start Game\" button that the match fails to begin. In this case you should turn the \"Stack AI Land\" option to off.\n\n\n\ +Abilities\n\n\ +There are three kinds of abilities: Activated, Triggered, and Static.\n\n\ +1. Activated abilities contain a colon that separates cost and effect, these can be played any time you could play an instant. An example is Elvish Piper's ability. That cost also contains the tap symbol. For creatures only, abilities containing the tap- or untap symbol can be played starting the turn after the creature came into play. Another common cost for an activated ability is sacrificing the card. You do that by putting it into your graveyard. Such abilities can only be played once.\n\n\n\ +2. Triggered abilities aren't played, they simply trigger when their condition occurs. An example is Angel of Mercy: You don't play the ability, but gain 3 life when it comes into play.\n\n\ +3. Static abilities are neither played, nor do they trigger. They still have an effect for as long as they are in play. An example is Glorious Anthem. There is no condition or cost, your creatures are just stronger.\n\n\n\ +Keyword Abilities\n\n\ +1. Flying: Creatures with flying are harder to block. Only creatures with flying or reach can block other flyers.\n\n\ +2. Haste: Haste lets a creature attack or use any abilities immediately during this turn.\n\n\ +3. Fear: Creatures with fear can only be blocked by artifact or black creatures. Creatures with fear are harder to block.\n\n\ +4. Cycling: When you cycle a card you pay some cost like 2 and then you discard that card, and then draw a new card. Cycling helps make your deck more versatile.\n\n\ +5. Vigilance: This means that the creature will not tap when attacking. This creature can both attack and block during the same turn.\n\n\ +6. Trample: If you use 2/1 creature to block an attacking 3/4 creature with trample, you will still receive 2 damage because the 3/4 trampled over your 2/1 creature. Trample damage is calculated by (attack - blocker's defense), in this case 3-1 which is 2.\n\n\ +7. Deathtouch: When a creatures with deathtouch deals damage to a creature, that creature is destroyed.\n\n\ +8. Defender: Creatures with defender can not attack, they can only block another attacker.\n\n\ +9. First Strike and Double Strike: Creatures with first strike deals their combat damage first. Creatures with double strike deals their combat damage first, and then deals their combat damage a second time during the combat damage step.\n\n\ +10. Flash: You can play a creature with flash anytime that you can play an Instant.\n\n\ +11. Landwalk: Allows your creature to attack without being blocked if your opponent controls the appropriate land type.\n\n\ +12. Lifelink: With lifeline you gain life equal to the amount of damage dealt.\n\n\ +13. Protection: Can not be damaged, blocked or targeted by sources that match the protection type.\n\n\ +14. Reach: Creatures with reach can block flying creatures.\n\n\ +15. Shroud: Permanents with shroud can not be targeted by abilities or spells.\n\n\ +16. Regenerate: Regenerate is an ability that some creatures have which prevents them from being destroyed and put into the graveyard. When you regenerate a creature, it acts like a shield until end of turn.\n\n\ +17. Morph: A creature with morph can be played by usually paying 3 mana of any color and be treated as a 2/2 creature with no abilities rather than playing the creature's actual cost. This creature is placed face down in the battlefield and can be flipped face up anytime as long as you pay its morph cost which is indicated on the card. Once flipped face up the card is treated as the original card, the one that you would normally play with its original-full casting cost. diff --git a/src/res/lang/lang.properties b/src/res/lang/lang.properties new file mode 100644 index 00000000000..c15bb66f7ac --- /dev/null +++ b/src/res/lang/lang.properties @@ -0,0 +1,6 @@ +#the preferred language (a key from the list below) +lang=en + +#the languages availabe +en--properties=en.properties +de--properties=de.properties diff --git a/src/res/main.properties b/src/res/main.properties new file mode 100644 index 00000000000..a788f955cc6 --- /dev/null +++ b/src/res/main.properties @@ -0,0 +1,24 @@ +program/mail=mtgrares@yahoo.com +program/forum=http://www.slightlymagic.net/forum/viewforum.php?f=26 + +tokens--file=AllTokens.txt + +decks--file=all-decks2 +booster-decks--file=booster-decks + +card-pictures--file=card-pictures.txt +cards--file=cards.txt +removed.cards--file=removedCards.txt + +regular/common--file=common.txt +regular/uncommon--file=uncommon.txt +regular/rare--file=rare.txt + +name-mutator--file=name-mutator.txt + +gui--properties=gui/gui.properties +quest--properties=quest/quest.properties + +lang--transparent-properties=lang/lang.properties + +image/base--file=pics \ No newline at end of file diff --git a/src/res/name-mutator.txt b/src/res/name-mutator.txt new file mode 100644 index 00000000000..f375da3de1d --- /dev/null +++ b/src/res/name-mutator.txt @@ -0,0 +1,442 @@ +Adarkar Valkyrie : Soaring Justice +Aggressive Urge : Rapid Assault +Air Elemental : Air Demon +Akki Drillmaster : Harsh Taskmaster +Akroma, Angel of Fury : Aksima, Angel of Chaos +Akroma, Angel of Wrath : Aksima, Angel of Order +Allied Strategies : Stand Together +Amnesia : Forget +Anarchist : Goblin Librarian +Ancestral Recall : Ancient Knowledge +Ancient Silverback : Old Monkey +Angel of Mercy : Brown-winged Hawk +Angelfire Crusader : Stalwart Crusader +Angelic Blessing : Gift from God +Anger : Chaos +Animate Dead : Necromancy +Animate Land : Fast Growth +Arashi, the Sky Asunder : Ancient Tree +Archangel : Higher Power +Armageddon : The Last Battle +Ashcoat Bear : Silver Fox +Ashen-Skin Zubera : Darken Zebri +Ashes to Ashes : Death March +Assault Zeppelid : Mighty Zeal +Aven Fisher : Cloud Soldier +Avian Changeling : Sky Morph +Axegrinder Giant : Angry Giant +Azure Drake : Mighty Drake +Balduvian Barbarians : Mean Dwarves +Ball Lightning : Fire-Lightning +Baru, Fist of Krosa : Earth Mage of Kinth +Bayou : Muckland +Beacon of Destruction : Times of Chaos +Beacon of Unrest : Time to Die +Birds of Paradise : Paradise Birds +Blade of the Sixth Pride : Battle Lion +Blind Phantasm : Ancient Ghost +Blinding Light : Kneel +Blinkmoth Nexus : Dark Knoll +Blistering Firecat : Elemental Rage +Blizzard Elemental : Ice Ghost +Blood Crypt : Defiled Tomb +Bog Imp : Murky Fiend +Boil : Bake +Bonded Fetch : Humble Servant +Bottle Gnomes : Tin Man +Breath of Life : Redemption +Breeding Pool : Life Water +Briarhorn : Thornwood +Bribery : Thievery +Brute Force : Chaotic Rage +Cackling Flames : Burning Fire +Cackling Imp : Laughing Fiend +Caller of the Claw : Bear Master +Cao Cao, Lord of Wei : Dark Lord +Carnassid : Relentless Goat +Castle Raptors : Sky Guardians +Centaur Glade : Sacred Grounds +Chandra Nalaar : Chaos Wizard +Char : Flamed +Chittering Rats : Thieving Rats +Cloud of Faeries : Unwelcome Friends +Cloudcrown Oak : Mighty Oak +Cloudseeker : Cloudseeker +Coastal Hornclaw : Island Pelican +Coercion : Force +Commune with Nature : Wandering Tree +Concentrate : Think +Control Magic : Steal +Coral Eel : Water Snake +Counsel of the Soratami : Meeting of the Minds +Counterspell : Stop +Courier Hawk : Messenger Pigeon +Cranial Extraction : Change of Plans +Craw Wurm : Grass Snake +Crazed Skirge : Wild Fiend of Nagir +Crib Swap : Change +Daggerclaw Imp : Fierce Fiend +Damnation : Dust +Dancing Scimitar : Canopy Ghost +Dark Banishing : Disband +Darksteel Colossus : Giant of Tyig +Darksteel Gargoyle : Owl from Tyig +Defiant Elf : Mean Elf +Delirium Skeins : Madness +Demonic Tutor : Search +Devour in Shadow : Midnight Scream +Disciple of Kangee : Teacher of Kindness +Distress : Plea-bargain +Diving Griffin : Attacking Eagle +Do or Die : Depart +Douse in Gloom : Rotten Apple +Dragon Roost : Nest of Dragons +Drekavac : Dark Dealings +Dripping-Tongue Zubera : Grass Zebra +Dross Prowler : Rust Thieve +Drudge Skeletons : Necro Soldier +Dryad Arbor : Wild Daisy +Dusk Imp : Night Dagger +Eager Cadet : Meager Fighter +Echoing Decay : Mirror Death +Echoing Truth : Mirror Bounce +Elvish Fury : Quick Harvest +Elvish Piper : Lyrical Harp +Elvish Warrior : Small Solider +Ember-Fist Zubera : Fury Zebra +Enormous Baloth : Mammoth Beast +Epic Proportions : Vast Size +Erratic Explosion : Unpredictable Bomb +Essence Warden : Spirit Keeper +Eternal Witness : Undying Seer +Evacuation : Migration +Expunge : Noxious Gas +Faceless Butcher : Nameless Killer +Fangren Hunter : Sourin Tree-Seeker +Feral Lightning : Untamed Strike +Fighting Drake : Bird of War +Filthy Cur : Dirty Mongrel +Fire Imp : Bonfire Rascal +Firebolt : Flame Strike +Flamebreak : Red Sunrise +Flametongue Kavu : Bonfire King +Fledgling Djinn : Baby Demon +Floating-Dream Zubera : Sky Zebra +Flying Men : Aladdin +Fomori Nomad : Fierce Wanderer +Foot Soldiers : Ground Troup’s +Force of Savagery : Tree Roots +Forest : Grass +Foul Imp : Tainted Pixie +Frost Ogre : Hornfrost Troll +Frostling : Cold Statue +Frostweb Spider : Ice Shield +Funeral Charm : Pyre Relic +Furnace Whelp : Kiln Helper +Gaea's Anthem : Earth Spirit +Garruk Wildspeaker : Gaea’s Voice +Ghost Ship : Poltergeist +Ghost Warden : Phantom Keeper +Ghost-Lit Redeemer : Spirit-Keen Wizard +Giant Cockroach : Oversized Germ +Giant Dustwasp : Massive Honeybee +Giant Growth : Artificial Growth +Giant Octopus : Colossal Jellyfish +Giant Warthog : Huge Boar +Gift of Estates : Free Domain +Glorious Anthem : Wonderful Praise +Glory Seeker : Scarred Warrior +Gluttonous Zombie : Greedy Zombie +Gnarled Mass : Thornbriar +Goblin Balloon Brigade : Flying Fool +Goblin Chariot : Sudden Soldier +Goblin Piker : Goblin Guard +Goblin Ringleader : Goblin Inciter +Goblin Sky Raider : Goblin Interceptor +Goblin Skycutter : Goblin Rocketeer +Godless Shrine : Fallen Temple +Goldmeadow Lookout : Rolling-Pasture Scout +Goretusk Firebeast : Enflamed Wildebeest +Gravedigger : Necromancer +Greater Forgeling : Glowing Elemental +Grizzly Bears : Graven-Claw +Groundbreaker : Impulsive Weed +Hallowed Fountain : Holy Spring +Hammerfist Giant : Mallet Wielder +Hand of Cruelty : Dark Knight +Harmonize : Rite of Spring +Haunted Angel : Haunted Specter +Helldozer : Omen of Misery +Hex : Noxious Charm +Hidetsugu's Second Rite : Chaos Oath Ritual +Highway Robber : Opportune Thief +Hill Giant : Bridge Troll +Horned Turtle : Water Terrapin +Horseshoe Crab : Worn Sand Crab +Howling Mine : Treasure Trove +Hunted Troll : Wayward Seeker +Hymn to Tourach : Secret Ritual of Zechim +Ice Storm : Snow Shards +Ichor Slick : Hidden Venom +Ifh-Biff Efreet : Emerald Eagle +Imperiosaur : Peridot Rex +Impulse : Desire +Incendiary Command : Fire-Raising +Infernal Kirin : Underworld Vulture +Infest : Swarm +Inner-Flame Acolyte : Burning Passion +Inspirit : Quickening +Intrepid Hero : Fearless Champion +Isamaru, Hound of Konda : White Fang +Island : Underwater +Jackal Pup : Rabid Dog +Jokulhaups : End of the World +Jugan, the Rising Star : Willow-branch Drifter +Juzam Djinn : Grinning Fiend +Kabuto Moth : Sharp-eyed Eagle +Kami of Old Stone : Kami of Great Peace +Karplusan Strider : Forest-root Walker +Kavu Climber : Creeping Vine +Keening Banshee : Screaming Ghoul +Keiga, the Tide Star : Sea-foam Dragon +Kemuri-Onna : Obsidian Creeper +Kiki-Jiki, Mirror Breaker : Ogg, the Trickster +Killer Whale : Jumping Fish +Kjeldoran War Cry : Battle Song +Kodama of the North Tree : Wise Elder-Branch +Kodama's Reach : Finding Gaia +Kokusho, the Evening Star : Blackwind, Midnight Storm +Korlash, Heir to Blackblade : Cursed Soldier +Lantern Kami : Single Light +Lava Spike : Flame Blast +Lay Waste : Ruin Land +Leaf Glider : Flower Sprite +Leonin Skyhunter : Brave Wingrider +Library of Alexandria : Ancient Lore +Life Burst : Wellspring +Lightning Angel : Thunder Angel +Lightning Bolt : Thunder Bolt +Lightning Elemental : Thunder Beast +Lignify : Thorn Snare +Liliana Vess : Blackheart +Llanowar Behemoth : Jade Beast +Llanowar Elves : Jade Elf +Llanowar Mentor : Jade Teacher +Lucent Liminid : Trans-Mirror Force +Lumengrid Warden : Silent Watchkeeper +Magus of the Disk : Keeper of the Disk +Magus of the Library : Keeper of the Library +Mahamoti Djinn : Stormcloud Djinn +Malach of the Dawn : Seer of the Dawn +Man-o'-War : Jellyfish +Manta Riders : Sea Rider +Marble Titan : Stone Goliath +March of Souls : Soul Reversal +Mass of Ghouls : Fierce Undead +Mawcor : Cloud-born Wizard +Meloku the Clouded Mirror : All-seeing Eye +Memnarch : Overseer +Might of Oaks : Hard As Rocks +Minions' Murmurs : Deathhelm Keeper +Minotaur Explorer : Angry Wildebeest +Mishra's Factory : Meetog’s Workshop +Mistral Charger : Winged Savior +Mogg Fanatic : Chaos Follower +Molten Rain : Lava Ash +Moorish Cavalry : Clean-Bridle +Mountain : Rock +Mox Emerald : Leaf Rune +Mox Jet : Dark Rune +Mox Pearl : Peaceful Rune +Mox Ruby : Burning Rune +Mox Sapphire : Tranquil Rune +Mudbutton Torchrunner : Wild Traveler +Mulldrifter : Prehistoric Elemental +Nameless Inversion : Stink Bomb +Nantuko Shade : Dark-haven Claw +Needle Storm : Early Freeze +Needlespeak Spider : Spiderwick +Nessian Courser : Tired Centaur +Nettletooth Djinn : Calm Giant +Nevinyrral's Disk : Final Answer +Night's Whisper : Dark Thoughts +Nightmare : Knife-wing +Norwood Ranger : Tree Elfkin +Oakgnarl Warrior : Beryl-knot Elder +Oblivion Ring : Peace Amulet +Opt : Switch +Orcish Artillery : Rageful Gunner +Order of the Sacred Bell : Leafstorm Monks +Ornithopter : Flying Contraption +Oubliette : Imprison +Overgrown Tomb : Overrun Crypt +Path of Anger's Flame : Final Battle Cry +Peel from Reality : Change the Future +Penumbra Bobcat : Necro-leaf Cat +Penumbra Kavu : Necro-leaf Beast +Peregrine Drake : Wide-Span Dragon +Pestilence : The Plague +Phantom Monster : Unseen Terror +Phantom Warrior : Unseen Soldier +Phyrexian Gargantua : Marsh Brute +Phyrexian Hulk : Marsh Skeleton +Phyrexian Rager : Marsh Warrior +Plague Wind : Infectious Swarm +Plains : White Sand +Pongify : Transmorph +Primal Boost : Quick Sprout +Primal Clay : Terraformer +Primal Plasma : Old Shapeshifter +Prodigal Pyromancer : Wondering Mage +Prodigal Sorcerer : Wondering Trickster +Psionic Blast : Mental Anguish +Pulse of the Tangle : Tree Followers +Puppeteer : Puppet Master +Pyroclasm : Ground Fire +Pyrohemia : Random Napalm +Radiant, Archangel : Shining Spirit +Raging Goblin : Angry Ghoul +Raging Minotaur : Drunken Dwarf +Raise Dead : Necro-Incantation +Raise the Alarm : Urgent Fight +Reckless Wurm : Wild Beast +Redwood Treefolk : Giant Oaktreek of Old +Regress : Relapse +Regrowth : New Growth +Relentless Rats : Swarming Rats +Remand : Revert +Remove Soul : Spirit Crush +Renewed Faith : Undying Peace +Repulse : Repel +Resurrection : Rebirth +Revered Dead : Twice-dead Soldiers +Reviving Dose : Heal Potion +Rootbreaker Wurm : Thick-headed Snake +Rorix Bladewing : Scair, Dragon Menace +Royal Assassin : Shadow Killer +Ryusei, the Falling Star : Firewing, The Red Death +Sacred Foundry : Holy Forge +Sakura-Tribe Elder : Leaf-wise Sage +Saltblast : Crystal Light +Sarcomite Myr : Diamond Beetle +Savannah Lions : Quick Jackals +Scathe Zombies : Wondering Zombie +Scryb Sprites : Tree Sprite +Seizan, Perverter of Truth : Corrupt Judge +Sengir Autocrat : Leader of None +Sengir Vampire : Decaying Vampire +Sentinels of Glen Elendra : Guards of Fenwer +Serendib Efreet : Soaring Genie +Serpent Warrior : Fallen Soldier +Serra Angel : Sand Angel +Serra Avenger : Sand Avenger +Serra Sphinx : Sand Chimera +Shinka Gatekeeper : Fierce Doorkeeper +Shivan Dragon : Crimson Dragon +Shock : Singe +Shriekmaw : Pointed-teeth Guard +Silent-Chant Zubera : Meditating Zebra +Silvos, Rogue Elemental : Dorsach, Oakwood Leader +Simic Sky Swallower : Sin, Sky Demon +Sinkhole : Rout the Land +Skirk Shaman : Blind-eyed Sage +Sky Swallower : Horned Wingsage +Skyhunter Prowler : Heaven’s Sentries +Skyknight Legionnaire : Heaven’s Fairies +Slaughterhouse Bouncer : Dark-Cloaked Thug +Sliver Legion : Crystal Mass +Sliversmith : Crystal Forge +Snapping Drake : Trickster Genie +Sorceress Queen : Dark Witch of Moor +Soul Warden : Peacekeeper +Sower of Temptation : Queen of the Fae +Spark Elemental : Flicker-flame +Spark Spray : Lava Drop +Sparksmith : Flamesmith +Sparkspitter : Flamespitter +Spined Wurm : Horned Oakgnarl +Spitting Spider : Venus Flytrap +Spotted Griffin : Sharp-eye Eagle +Sprout Swarm : Ash Saplings +Squall Drifter : Freeform Bird +Steam Vents : Mist Generator +Steel Wall : Diamond Shield +Stern Judge : Wondering Sage +Stomping Ground : Ancient Tomb +Stone Rain : Meteor Strike +Storm Crow : Hurricane Squall +Strangling Soot : Deadly Smog +Stuffy Doll : Cryptic Gift +Sunlance : Saltlance +Suntail Hawk : Windseeker +Swamp : Bog +Swords to Plowshares : Inner Peace +Sylvan Messenger : Oakleaf Envoy +Symbiotic Elf : Mighty Ashroot +Take Possession : Final Control +Tanglebloom : Wild Honey +Tarox Bladewing : Ruby Dragon +Temple Garden : Peaceful Shrine +Tendrils of Corruption : Deadly Vice +Terramorphic Expanse : Terraform +Terror : Quick Defeat +Test Destroy : Test Destroy +That Which Was Taken : Forbidden Ring +The Hive : Swarm Maker +The Unspeakable : Horrifying Mutation +Thought Courier : Reflective Wizard +Thoughtseize : Dream-seeker +Threaten : Forceful Answer +Timberwatch Elf : Peaceful Rowan +Timetwister : Clockspinner +Tithe : Thoughful Reply +Torii Watchward : Sunwatcher +Tortuga : Tortuga +Trained Armodon : Bitter Yew +Transluminant : Quick Poplar +Tremor : Quake +Tribal Flames : Bonfire +Troll Ascetic : Newborn Yew +Tromp the Domains : Leaves Falling +Turtleshell Changeling : Timid Tortoise +Undying Beast : Zombie Dog +Urborg Syphon-Mage : Hateful Wizard +Utopia Tree : Calm Statue +Valor : Courage +Vedalken Mastermind : Silent Rulegiver +Venerable Monk : Wise Elder +Veteran Armorer : Blacksmith of Yore +Veteran Cavalier : Horse Master +Villainous Ogre : Treacherous Oaf +Vine Trellis : Oakroot Barrier +Visara the Dreadful : Blacksoot, the Hateful Wing +Vodalian Merchant : Fisherman +Volcanic Hammer : Flaming Geyser +Vulshok Sorcerer : Flame-seared Wizard +Wall of Kelp : Coral Reef +Wandering Stream : Overflowing River +Watchwolf : Clawthorn Fox +Watery Grave : Ocean Tomb +Wayward Soul : Unforgiven Sins +Weathered Wayfarer : Wondering Nomad +Wellwisher : Yew Farmer +Wheel of Fortune : Wheel of Misfortune +Whiptongue Frog : Croaking Toad +Whirlpool Rider : Sea Urchin +White Shield Crusader : Sunrise Warrior +Wild Elephant : Untamed Camel +Wild Mongrel : Untamed Boar +Wildsize : Yewroot Strength +Will-o'-the-Wisp : Midnight Fire +Wind Drake : Storm Drake +Wings of Velis Vel : Give Strength +Wirewood Elf : Yewleaf Elf +Wit's End : No Solution +Wojek Embermage : Ogg’s Firebrand +Wonder : Marvel +Words of Wisdom : All Understanding +Worldly Tutor : Searcher of Secrets +Wrap in Vigor : Renew Strength +Wrath of God : Peaceful Solution +Zombify : Rise Again + diff --git a/src/res/quest/common.txt b/src/res/quest/common.txt new file mode 100644 index 00000000000..e8c4673d9db --- /dev/null +++ b/src/res/quest/common.txt @@ -0,0 +1,800 @@ +AEtherflame Wall +Advance Scout +Aesthir Glider +Aggressive Urge +Akki Drillmaster +Akrasan Squire +Alaborn Grenadier +Alaborn Musketeer +Alaborn Trooper +Alley Grifters +Alpha Myr +Ambassador Oak +Ambush Party +Amrou Scout +Amrou Seekers +Anaba Bodyguard +Anaba Shaman +Anarchist +Ancient Den +Angelfire Crusader +Angelic Blessing +Angelic Curator +Angelic Wall +Anodet Lurker +Anurid Murkdiver +Ardent Militia +Argothian Swine +Armored Pegasus +Ascending Aven +Ashcoat Bear +Ashen-Skin Zubera +Assault Zeppelid +Aven Cloudchaser +Aven Envoy +Aven Fisher +Aven Flock +Aven Riftwatcher +Aven Squire +Aven Trailblazer +Avian Changeling +Axegrinder Giant +Azimaet Drake +Balduvian Barbarians +Balduvian Bears +Barbarian Horde +Barbary Apes +Barbtooth Wurm +Barkhide Mauler +Barren Moor +Battering Craghorn +Battering Sliver +Battle Rampart +Bay Falcon +Bayou Dragonfly +Bear Cub +Belbe's Percher +Benalish Cavalry +Benalish Knight +Bird Maiden +Blade of the Sixth Pride +Blanchwood Treefolk +Blastoderm +Blightspeaker +Blind Phantasm +Blistering Barrier +Blistering Dieflyn +Blockade Runner +Bog Imp +Bog Raiders +Bog Smugglers +Bonesplitter Sliver +Boomerang +Border Guard +Border Patrol +Boreal Druid +Boros Recruit +Brainbite +Brainstorm +Breath of Life +Breath of Malfegor +Breathstealer +Brute Force +Burning Shield Askari +Cackling Flames +Cackling Imp +Cadaverous Knight +Canopy Spider +Canyon Minotaur +Canyon Wildcat +Capashen Knight +Capashen Templar +Carnivorous Plant +Castle Raptors +Cat Warriors +Cateran Brute +Cateran Persuader +Cavern Crawler +Cavern Harpy +Cavern Thoctar +Cemetery Gate +Cerodon Yearling +Changeling Sentinel +Charging Slateback +Chartooth Cougar +Chittering Rats +Chorus of Woe +Cinderbones +Clay Statue +Cloud Elemental +Cloud Pirates +Cloud Spirit +Cloud Sprite +Cloud of Faeries +Cloudchaser Eagle +Cloudcrown Oak +Cloudheath Drake +Coast Watcher +Coastal Hornclaw +Cobalt Golem +Coercion +Coiled Tinviper +Colos Yearling +Commune with Nature +Copper Myr +Coral Eel +Coral Merfolk +Corrupt +Counsel of the Soratami +Courier Hawk +Court Archers +Covert Operative +Crash of Rhinos +Craven Giant +Craven Knight +Craw Wurm +Crimson Acolyte +Crimson Kobolds +Crookshank Kobolds +Cylian Elf +Dakmor Bat +Dakmor Scorpion +Dandan +Dark Banishing +Darkling Stalker +Darklit Gargoyle +Darksteel Citadel +Darksteel Ingot +Daru Lancer +Dauthi Marauder +Deadly Insect +Death Speakers +Deeptread Merrow +Defender of Chaos +Defender of Law +Defiant Elf +Defiant Falcon +Deft Duelist +Delirium Skeins +Demystify +Devoted Hero +Devouring Deep +Dirtwater Wraith +Disciple of Grace +Disciple of Kangee +Disciple of Law +Disciple of Malice +Disenchant +Distress +Diving Griffin +Douse in Gloom +Drake Hatchling +Dream Stalker +Dreg Reaver +Drifting Meadow +Dripping-Tongue Zubera +Dross Crocodile +Dross Prowler +Drowned +Drudge Reavers +Drudge Skeletons +Druid of the Anima +Dungeon Shade +Duress +Durkwood Boars +Dusk Imp +Duskrider Falcon +Dwarven Grunt +Dwarven Trader +Eager Cadet +Ebony Rhino +Echoing Decay +Echoing Truth +Ekundu Griffin +Elite Cat Warrior +Elvish Fury +Elvish Herder +Elvish Lookout +Elvish Ranger +Elvish Warrior +Ember-Fist Zubera +Emerald Dragonfly +Empty the Warrens +Enslaved Scout +Erratic Explosion +Esper Cormorants +Essence Warden +Ethercaste Knight +Exclude +Expunge +Faceless Butcher +Fallen Askari +Fangren Hunter +Femeref Knight +Femeref Scouts +Feral Shadow +Festival of Trokin +Fetid Horror +Filthy Cur +Fire Ambush +Fire Elemental +Firebolt +Flamekin Brawler +Fledgling Djinn +Floating-Dream Zubera +Flowstone Giant +Flowstone Shambler +Flowstone Wall +Flying Men +Fog of Gnats +Folk of the Pines +Fomori Nomad +Foot Soldiers +Forest Bear +Forgotten Cave +Foul Imp +Foxfire Oak +Freewind Falcon +Fresh Volunteers +Frost Ogre +Frostling +Frostweb Spider +Frozen Shade +Fugitive Wizard +Funeral Charm +Furnace Spirit +Fyndhorn Elves +Gaea's Skyfolk +Galina's Knight +Game-Trail Changeling +Gemhide Sliver +Gerrard's Command +Gerrard's Irregulars +Ghost Warden +Ghostfire +Giant Cockroach +Giant Dustwasp +Giant Growth +Giant Mantis +Giant Spider +Giant Warthog +Glintwing Invoker +Glory Seeker +Gnarled Mass +Goblin Bully +Goblin Cavaliers +Goblin Chariot +Goblin Deathraiders +Goblin Hero +Goblin Matron +Goblin Mountaineer +Goblin Outlander +Goblin Piker +Goblin Raider +Goblin Sky Raider +Goblin Skycutter +Goblin Spelunkers +Goblin Striker +Gold Myr +Golden Bear +Goldmeadow Dodger +Goliath Beetle +Goretusk Firebeast +Gorger Wurm +Gorilla Chieftain +Gorilla Warrior +Gravedigger +Gray Ogre +Grayscaled Gharial +Great Furnace +Grizzled Leotau +Grizzly Bears +Guardians of Akrasa +Guided Strike +Halberdier +Hand of Cruelty +Harvest Gwyllion +Havenwood Wurm +Headless Horseman +Heart Sliver +Hematite Golem +Highland Giant +Highway Robber +Hill Giant +Hillcomber Giant +Hoar Shade +Hobgoblin Dragoon +Honor Guard +Hooded Kavu +Horned Kavu +Horned Troll +Horned Turtle +Hornet Cobra +Horseshoe Crab +Hulking Goblin +Humble Budoka +Hundroog +Hurloon Minotaur +Hush +Hyalopterous Lemure +Hymn to Tourach +Icatian Scout +Ichor Slick +Immaculate Magistrate +Imperious Perfect +Impulse +Incurable Ogre +Independent Troops +Inner-Flame Acolyte +Iron Myr +Ironroot Treefolk +Jamuraan Lion +Jedit's Dragoons +Jhessian Lookout +Jolrael's Centaur +Jukai Messenger +Jungle Lion +Jungle Weaver +Juvenile Gloomwidow +Kabuto Moth +Kavu Climber +Kavu Glider +Keen-Eyed Archers +Keeneye Aven +Keeper of Kookus +Keepers of the Faith +Kird Ape +Kjeldoran Outrider +Kjeldoran War Cry +Knight Errant +Kobolds of Kher Keep +Kodama's Reach +Kranioceros +Krovikan Scoundrel +Kyren Glider +Lab Rats +Land Leeches +Lantern Kami +Lava Axe +Lava Spike +Lay Waste +Leaden Myr +Leaf Dancer +Leaf Gilder +Leaping Lizard +Life Burst +Lightning Blast +Lightning Bolt +Lightning Elemental +Lightning Hounds +Lignify +Lim-Dul's High Guard +Lionheart Maverick +Living Airship +Lizard Warrior +Llanowar Cavalry +Llanowar Dead +Llanowar Elves +Llanowar Knight +Loamdragger Giant +Loch Korrigan +Lonely Sandbar +Looming Shade +Lost Soul +Lowland Giant +Lucent Liminid +Lumengrid Warden +Macetail Hystrodon +Maggot Carrier +Magnify +Malachite Golem +Man-o'-War +Manakin +Manta Riders +Marsh Boa +Marsh Goblins +Mass of Ghouls +Meadowboon +Meng Huo's Horde +Merfolk of the Pearl Trident +Merrow Levitator +Mesa Falcon +Metallic Sliver +Metathran Soldier +Metathran Zombie +Minotaur Warrior +Mire Boa +Misshapen Fiend +Moaning Spirit +Molten Rain +Monk Realist +Mons's Goblin Raiders +Moonglove Changeling +Moonglove Winnower +Moonwing Moth +Moor Fiend +Moorish Cavalry +Morsel Theft +Moss Kami +Moss Monster +Mountain Bandit +Mountain Goat +Mountain Yeti +Mourning Thrull +Mtenda Herder +Muck Rats +Mudbutton Torchrunner +Mulldrifter +Muscle Sliver +Nacatl Outlander +Nacatl Savage +Nameless Inversion +Nantuko Husk +Naturalize +Needlepeak Spider +Needleshot Gourna +Nessian Courser +Nezumi Cutthroat +Nightguard Patrol +Nightshade Stinger +Nightwind Glider +Nip Gwyllion +Norwood Archers +Norwood Ranger +Oakgnarl Warrior +Obelisk of Bant +Obelisk of Esper +Obelisk of Grixis +Obelisk of Jund +Obelisk of Naya +Oblivion Ring +Obsidian Acolyte +Obsidian Giant +Odious Trow +Ogre Berserker +Ogre Warrior +Old Ghastbark +Omega Myr +Onulet +Oona's Gatewarden +Opt +Oraxid +Order of Leitbur +Order of the Ebon Hand +Order of the Sacred Bell +Ornithopter +Orochi Sustainer +Ostracize +Oubliette +Outrider of Jhess +Pallid Mycoderm +Panther Warriors +Parapet Watchers +Path of Anger's Flame +Pearled Unicorn +Peel from Reality +Pegasus Charger +Pendrell Drake +Penumbra Bobcat +Penumbra Spider +Pestilent Kathari +Pewter Golem +Phyrexian Battleflies +Phyrexian Ghoul +Phyrexian Monitor +Phyrexian Rager +Phyrexian Walker +Pincher Beetles +Pit Imp +Plague Beetle +Plated Rootwalla +Plated Sliver +Plated Spider +Plated Wurm +Plover Knights +Polluted Mire +Prickly Boggart +Primal Plasma +Prodigal Pyromancer +Prodigal Sorcerer +Pygmy Pyrosaur +Pygmy Razorback +Python +Raging Bull +Raging Cougar +Raging Goblin +Raging Minotaur +Raiding Nightstalker +Raise Dead +Raise the Alarm +Ramosian Lieutenant +Ramosian Sergeant +Rathi Intimidator +Ravenous Rats +Razorfin Hunter +Razorfoot Griffin +Razortooth Rats +Redwood Treefolk +Reflex Sliver +Regal Unicorn +Regress +Remote Isle +Remove Soul +Renewed Faith +Repentant Blacksmith +Repulse +Restless Bones +Restless Dead +Revered Dead +Reviving Dose +Rhox Bodyguard +Rhox Brute +Rib Cage Spider +Ridge Rannet +Ridgeline Rager +Righteous Avengers +Rip-Clan Crasher +Rishadan Airship +River Boa +River Kaijin +Rock Badger +Roofstalker Wight +Rootwalla +Rootwater Commando +Roterothopter +Rowan Treefolk +Royal Falcon +Rune-Cervin Rider +Rushwood Dryad +Rustrazor Butcher +Sabretooth Tiger +Sakura-Tribe Elder +Sandbar Merfolk +Sandstone Warrior +Scaled Wurm +Scare Tactics +Scarwood Goblins +Scarwood Treefolk +Scathe Zombies +Scavenging Scarab +Scorching Spear +Scornful Egotist +Scryb Sprites +Scuzzback Scrapper +Sea Eagle +Sea Sprite +Seat of the Synod +Secluded Steppe +Sengir Bats +Serpent Warrior +Serpentine Kavu +Serra Zealot +Severed Legion +Sewn-Eye Drake +Shade of Trokair +Shadow Rider +Shambling Strider +Shanodin Dryads +Shatter +Shield Sphere +Shield Wall +Shinka Gatekeeper +Shivan Zombie +Shock +Shore Snapper +Shu Elite Infantry +Shu Foot Soldiers +Sickle Ripper +Sidewinder Sliver +Sighted-Caste Sorcerer +Sigiled Behemoth +Silent-Chant Zubera +Silkenfist Fighter +Silver Myr +Silverback Ape +Simic Ragworm +Sinew Sliver +Sinkhole +Sisters of the Flame +Skeletal Changeling +Skeletal Crocodile +Skeletal Snake +Skirk Shaman +Skyhunter Patrol +Skyhunter Prowler +Skyknight Legionnaire +Skyshroud Falcon +Skyshroud Troll +Skyshroud Troopers +Slaughterhouse Bouncer +Sleight of Hand +Slippery Karst +Smoldering Butcher +Smoldering Crater +Snapping Drake +Sokenzan Bruiser +Solidarity +Soltari Foot Soldier +Sootfeather Flock +Southern Elephant +Spark Spray +Sparksmith +Spined Basher +Spined Wurm +Spineless Thug +Spitting Gourna +Spotted Griffin +Sprout Swarm +Squall Drifter +Squire +Squirming Mass +Standing Troops +Steadfast Guard +Steel Leaf Paladin +Steward of Valeron +Stone Kavu +Stone Rain +Stone-Throwing Devils +Stonewood Invoker +Storm Crow +Strangling Soot +Straw Soldiers +Stream Hopper +Streetbreaker Wurm +Sunlance +Suntail Hawk +Suq'Ata Lancer +Symbiotic Elf +Synchronous Sliver +Talas Air Ship +Talas Merchant +Talas Scout +Talon Trooper +Talruum Minotaur +Tanglebloom +Tarfire +Tarpan +Tattered Drake +Tel-Jilad Archers +Tel-Jilad Chosen +Tel-Jilad Exile +Tel-Jilad Outrider +Tendrils of Corruption +Terminate +Teroh's Faithful +Terramorphic Expanse +Terror +Thalakos Sentry +Thallid +Thallid Shell-Dweller +Thermal Glider +Thorn-Thrash Viashino +Thornweald Archer +Thought Courier +Tidehollow Strix +Timberwatch Elf +Titanic Bulvox +Titanium Golem +Tor Giant +Torch Drake +Torii Watchward +Tormented Angel +Tower Drake +Trained Armodon +Trained Jackal +Tranquil Thicket +Tranquility +Transluminant +Tree Monkey +Tree of Tales +Treespring Lorian +Tremor +Tribal Flames +Trinket Mage +Trokin High Guard +Tundra Wolves +Tyrranax +Unmake +Unworthy Dead +Urborg Elf +Urborg Syphon-Mage +Valeron Outlander +Valiant Guard +Vampire Bats +Vault of Whispers +Vectis Agents +Vectis Silencers +Vedalken Outlander +Venerable Monk +Venser's Sliver +Veteran Armorer +Veteran Cavalier +Viashino Fangtail +Viashino Grappler +Viashino Slasher +Viashino Warrior +Vigilant Drake +Villainous Ogre +Vine Trellis +Virtuous Charge +Viscerid Deepwalker +Viscid Lemures +Vodalian Merchant +Vodalian Soldiers +Vodalian Zombie +Volcanic Hammer +Volcano Imp +Volunteer Militia +Votary of the Conclave +Vulshok Berserker +Vulshok Sorcerer +Walking Dead +Wall of Diffusion +Wall of Earth +Wall of Heat +Wall of Ice +Wall of Spears +Wall of Wood +Wandering Ones +Wandering Stream +War Mammoth +War-Spike Changeling +Warrior's Charge +Warrior's Honor +Watcher Sliver +Waveskimmer Aven +Wayward Soul +Weatherseed Elf +Weatherseed Faeries +Wei Infantry +Wellwisher +Whip-Spine Drake +Whiptail Wurm +Whiptongue Frog +Whirlpool Rider +Whispering Shade +Wild Aesthir +Wild Colos +Wild Elephant +Wild Griffin +Wild Jhovall +Wild Mongrel +Wild Nacatl +Wildsize +Wildslayer Elves +Willow Dryad +Willow Elf +Willow Faerie +Wind Drake +Windseeker Centaur +Windwright Mage +Winged Coatl +Winged Sliver +Wings of Velis Vel +Winnower Patrol +Wirewood Elf +Woodland Changeling +Woodland Druid +Words of Wisdom +Wrap in Vigor +Wu Infantry +Yavimaya Ancients +Yavimaya Barbarian +Yavimaya Scion +Yavimaya Wurm +Yellow Scarves Troops +Yoked Plowbeast +Yotian Soldier +Young Wei Recruits +Youthful Knight +Zealous Guardian +Zephyr Falcon +Zhalfirin Knight +Zodiac Dog +Zodiac Goat +Zodiac Monkey +Zodiac Rabbit +Zodiac Rat +Zodiac Rooster +Zodiac Snake +Zombie Outlander diff --git a/src/res/quest/easy.txt b/src/res/quest/easy.txt new file mode 100644 index 00000000000..23a1eea4929 --- /dev/null +++ b/src/res/quest/easy.txt @@ -0,0 +1,11 @@ +Buffy I +Catwoman 1 +Crocodile Dundee 1 +Da Vinci 1 +Genghis Khan 1 +King Edward I +Kojak 1 +Sherlock Holmes 1 +Storm 1 +Tarzan I +Wyatt Earp 1 \ No newline at end of file diff --git a/src/res/quest/hard.txt b/src/res/quest/hard.txt new file mode 100644 index 00000000000..93b4d461cc5 --- /dev/null +++ b/src/res/quest/hard.txt @@ -0,0 +1,41 @@ +Abraham Lincoln +Albert Einstein +Batman +Blackbeard +Boba Fett +Buffy III +C3PO +Comic Book Guy +Crocodile Dundee 3 +Cyclops +Da Vinci 3 +Darth Vador +Data +Frodo +Genghis Khan 3 +Green Lantern +Han Solo +Iceman +Jabba the Hut +James T Kirk +King Edward III +Kojak 3 +Luke Skywalker +Magneto +Morpheus +Napoleon +Neo +Newton +Picard +Pinky and the Brain +Professor X +R2-D2 +Rogue +Sherlock Holmes 3 +Silver Surfer +Storm 3 +Superman +Terminator +Uncle Owen +Wolverine +Wyatt Earp 3 \ No newline at end of file diff --git a/src/res/quest/medium.txt b/src/res/quest/medium.txt new file mode 100644 index 00000000000..85c0ed73ea6 --- /dev/null +++ b/src/res/quest/medium.txt @@ -0,0 +1,14 @@ +Buffy II +Catwoman 2 +Crocodile Dundee 2 +Da Vinci 2 +Genghis Khan 2 +King Edward II +Kojak 2 +Scotty +Sherlock Holmes 2 +Spiderman +Spock +Storm 2 +Tarzan II +Wyatt Earp 2 \ No newline at end of file diff --git a/src/res/quest/quest.properties b/src/res/quest/quest.properties new file mode 100644 index 00000000000..1a3313a2ac7 --- /dev/null +++ b/src/res/quest/quest.properties @@ -0,0 +1,9 @@ +common--file=common.txt +uncommon--file=uncommon.txt +rare--file=rare.txt + +easy--file=easy.txt +medium--file=medium.txt +hard--file=hard.txt + +data--file=questData \ No newline at end of file diff --git a/src/res/quest/questData b/src/res/quest/questData new file mode 100644 index 0000000000000000000000000000000000000000..87ddbd4d3ac76072c72389c2f3861a87411eb258 GIT binary patch literal 41369 zcmeI5d3Wc=N?qy)lr3^_7FVh4Rc6i_t5-{v8EUMY zU$U26o4G!dJ-m={|FZna)A7xE@00c3CpX{Qwekyp^|9lw{!~7b8_29F2j0|xH(3v= z44^(+^=q?1dFt@OC6`(|S1+#O?+f_fQ_pmbK6QKFQ)#rI7vA^!Gd^_T&Lg*gf`gfr zrCMLro30Hc78!#2c@oJ+!s~TIV(SOLBY*nYsPs={&g%-X%xN~t~@EYy9=I$rt5)7D5C zjMnt)gfvjktYlu8U#oJW{ak32-Pj+)^W%-mRMpd?CmCS$2ZHKUtr$!f50q+C!Mw5` zD_|JhpwvczO#+(*wg_w$I7Yz6L!Va<2ZxIzzE_3N*C{>bEiBBIs)h#}fOYvqJ@Xg= z>%n6WE4kA8yOx>E*nF-z%sS|;29v>5sq7c~=(X<`pK7(B)flnpX+0Ox!TO${8q|uT z{$#aLV&+!&R!bAbu|;n|RZmaM#}k$HL~yXXG&5VTXyUpnGd=@YH5@c5^(OV6scL5? zu>X6?`aST=guo~o`uQXS(8{QPsB}n;^#u;|zYj)6OAB?VzSvv!CV1nRU-c_f^sIln z>ihI_&Dh*hacrSfRi}^T$6Q67D(?1Yps$JtA{oqhP%RFYAW6OJDTxU^TUlq*^nR}l z3L3Ry@2ppy;i)bA{VA_J$MV?QsEZc;s;UL$Nv~3xEJpNsu9`Tvp4rr0nS>Koy|VD= zmCMRMjY0G@%H?9OUk#>$NokR(P;(vkta5_gBgqhhOoh zisKDf5X}#j%H_#me!_1Krk*)&CVWo{REvcOsNeLR>bc{S#Hs@hz?Pf?L! z@u^CkBLFhi9)t+J$>Lz()s0w-Da5*BkH1(C+{%0y0$tHvZZP+1z25*lx5rxwjD`l3 zGr;V$@uW6(w6Pz?P+@uwln50gdwz&5&1}4=Qj>HNM+G zNX#@m>eZRO$yvv0_NaUh?Tq?mrm{@yMQYfX_p0nS1uUvDwkb&2_~(e)8liV%EYyh> zhrCR=mw^!$?EC_xascWRbLwIHtp)SejWJa+Uc}kro zaHYUA1Z;d~*d8%aDwmFg`)4##8{bu+Xw;jV^NPc6U$nv4I4)8{a2;3b z*#c3&F0nbhJe-ecuh}|Ms=$6>jYYAZo@#5CZB1ft_)xgfz$Do!M4NqnZ2|twkh&|S zd3YZ=9+bAJ$M+`Tk5t)L(dtxpX2}<0o(x#NeI<{TDWdE@ywIRM)wsq06T1UW>MxY0 zibHT*THg)2yoy)cZ!3NSXqnLF=-SXj!|=7yV2OsiYc;P{bHbOg8Useo5ir7j!~iBe z4xLm>Wnis1)Iyj6C?phUH3rj~L^QxYq zyRQnmrW>})Osm}Z{;X0Zp6~PKDa^_S78Ezi-W?*#SSF?t^W(BsM_NmH#s_bDi zt}G#Jm(Qq$Rfbg>p~P@tL$FR;A2po^*vMwp{9rI;v@;o!K}0(RDGZkXFpPgyk2h5u z4jjU+OCgUG%1}SAHvo+^QLdlQhnq59=);M6FG!Nm4XSekoNutfa-H^lx8)Bl%~y)` zpg0~hs@^1&c+#$*3fGw328orbDl%~yc06UXb(7k;sgv}^{K^dV_rs%`0^W;SJX=rv zxBobRG_$Wd5maZ2V@nIOL1jB6fQYjR8Kf*38ba8PAZzpZhw8?40?!jLJU(Bk7YG=R zZdB@p0yfl}qwPU?FA}i9{K4`R`-esuhf^qH{VoZC{Zor5I!IY+>|sb`b5E%$jE}H5 zrkYC2Eqd}6Rzgp;c%;w;VL4iv4AOo{ihH<#apQ{miB} zUoAoZY&lvsgDf}%h$1orER0Ulb|@q;(jAqGU)?@XMq?{>PX^_sIw;;63CZCrkRJAU zb%+T*PL;$4{~C4cHME@A;9slU*D80mTJq=Sy+vi*NjJw9P{WeFe;q_M?v-XtVR^kO zzFv~stki*OC@go4qbeD>zL943scZ)M7haBDs)ycWfU*>k_suGMGX&Hw@}{g$Rb?7B z^ay>%7j~DX?ZvmM=r)1d1zs-j3V~M&+#&EPfmeegDQLl>Qz8vVhLSr~{5k;}=Npt_ zIP1sJUf}087dFv0m^T~Ez1T96(#VG1U|zC75X=<^8%tK>D4W;@wjybS#XVlx^Wb@% z^16ERP6PGKF#~>MYL2DmSD~i;eig=!AhpK2Hvw9V0l!# z0xzB{Y1a}f0+kU>^6R7>+U)ByG(8?x%ZgZy5q z*r?e`2AT}>os!x8>LIsTzDrdNZ|_m+E`j$7Fz&)InupRh+;OG$39!3?lEcN(#sp@g z4wc(*paG7e55xvo&zvy2)TsHTZMJI;z!Jo!kOrlip_f)Y=C((Ie;gejv}ySB6q4&y z)XzzfUAh3Q5u9%T`jJ8y>9rRs+r&gCE9&PN0!}K1u=Y-r(XbJ%Mw?yyI~Au2$SN?Q z@ySY^C2)2UoTHzSlz6Uw8aPiWlU|>u)YAp5%g+!G4d_D!CghhJmAR(${I{xdfj~5d zXX>ZxK0R;IaPbPiF5yNK*fg3PZ8D?rnQRvVzH`{|L>E1r7MB-_)7Dpq5Pz{PjUg_)Q3ShA$h)r`5FK<{qVN z$c*d6UBO%fL#$hd{a7!fW%zJ%*=Ng0Tedf~AL@61EfC zEu(>2x2v|S{~?7qHYTK(9g+N^_q;TGAk>G}cOwzTBm-eXYQ5F`Cp~nl#FnIm=nf`g z80kM)oM;NhY>{y`{V%MU5!fnwAk4cqZ?o!z2sMe|uzsvGImeEIfo;Lf?zdEe?64M* zVzIJ_Ma_u^EeYZ%dW`M6Z`Jc})z(lA7SLR<3x_7$??}f%ws1z&2UPQZfj<_oQNBf~ zTLr#B6CHM(O+(mQeND+87DLlybcd?{Gd+G-OU2Q7KFCW~c>YB%_@perV3|FJUNs9*=43nk>zi*uK=EUs-;2 zu8gHnoFG^#OG3+LRLGvYslP@GMO3Nz03SfThC(q64{)obA4;i~8uNN0XMj0L+Tyc$ zwRD*Qu#JdWZz-T-OO;?sPZeNjjSW>?bYeh*KO8a*(JCgZl2 z>?#$s?6}?4$=P|BnO?SbYj4SUFCJ3wej)HnfnTXwhRN^qWe1#ec3722uFGOg zUq4V@5+-}S>Vhm|#}CO)x2-rfTUvl8@9_>Hgq!Vl&5kPD?rtz|FBg(xjA*}penj9e z)pCfcY(YP}1Xc(z$_-9=jP*uCT)&^Kp@i*n267NpWmgNV0a*u7cv#D_iA(1*!h0}< z@K%gX2K9O*`GWPPV~LiMzJk#1nmt}`!NIac8j_<0NTJwUHvJ@f0*&-SC1sSH_9d++ zajmqQWR-mqkG1TwYX_^|A%Chg=>n1~vu6m{7_7@r5=CXVrcl(%p2qa_(j(L0 zH+IjM{|)CuaUa^X+B}!8B`t&Ty)i4{GW#?T*75>mC23}#&cyVX?*ty;Az`vH_5?G< z9cC9NHG{y8X?}kDAa+?jaRIZ|=gq;`iam}HE({4!<xRg#=8Qq_y;Y)pmEUZTuP1wh2cv7kDMXOHKIC9usb+oQ5x z0ULL}QUgY7Pf4M*{2o8B?4xX#8+u?;#ZXCBgJT9*MQH}4tR%(kI5P-6X{*y52_;Q- zAsI4jg5)5nrWmi(4n~BIiU5>&nYet`Sp81bN(Eqf(2Ou<6>zNPfSwZwolxs`;#7y- zc2D^W#=WXQZ72}aqcyePY9@(#sG~OU4GxKVJ7$-U^yAdDak=oFsie&vljc@59+C)z$WE&(#;pyBhO=vw zC(Bt@Hd{Ad8=;M9!3gSEDFn5#yG+;X#ePCU>V7jW;_AjhHDb6(FjP`UFW$5d7pkZ4%ptec#Y|qaGfKfHt+J3mT5*bg%3S zk3xDkLE{JH8($2{Hgh*K+5@uw!sMrl2fU?esMO@B7x9`1liBC#twLJ%dZl*L(H%7` z9MuNC7BfzR-d*_qSkYU=;b3&Vs1iu>c<)V>F~(xN_W5e(1p*;Dvf^uUkefP{bl3Fs>kWYYAmv%}ZKDpx>`Cuw2NE3h`EiUWn|S%E9Web{y^T zTD)r|#q4cGe5r5W?R(QqB5S9_%OJL9u|LJJpj?`6IN|bk6}_AeB}@mYc16{Eg}^HX3~#TBNi%e4)UP$F$OTQe zZuZrxh!1BoW`nXn;Z=NQub(lSoc3Ckf{QKVLAizsUM*rzoSwkuXRH$o%%%gg3af+E zQG@CYi;2s=UXQ)OsPw<5aJ4vwBo92l5IFJ<4O zml{Ibu!>P?-QX+}q@_3IM7Fz-jw6#aDB6WvuGo!goZ_*_zFbW+16W?_(h!3H=TP4@ zrHb)z!*zu4kXqY=#IheyGX@+<>Zhd)%?{Vfa}=o5>jd5{U=$S%F`}8fRQg`lWt()X z?Dq*sigF{kTdAm{f2yBv6|g?BY_^Pf+HP!kdrDX?Cv3xv`e;3~PQ6XfxhZ}}IBAh> zC_cqeP@kUZm||tRAwo@QN>A#X>Z#iVY<1W`-7G0D8fY|HH!Ui4B(GF74a?7fNE}Y) zL~5dSeGfrp%N5v5=Dj6UazZpvD&Q2fXKO#2u8%11r2=mhc$0t)CYrspAw<2mK1b6O zb^OoNR75Z~BY&wpo0g9%<>uzYDRa{`wh$1_OeJ$x>u=-_IMbptFHq+40>Q6e3VmYT zshD&);z_urjqKkTU|or;Y#*Cb>>;8hJBJEBVE|-zT5MRQ{pCYYXi;`DW5w&68KbDm z((PImn%k{1YKr#tBQ7AxX2ZZzWlH8xnBF1eqRg>7*trPQMr$?sTS1a?j;}S|KZp`* zt?$P09V}v$Yd*Fy%os-7l`On*Pf%TiQASPmEWZwN=D<8kiMe z)A+1k#*Rl9hKL?hyr|-_N<=A|h~Gqzq3;vMX8$^6o>!piQ*)V#4jJrmppYohn)wR% z&R0qcffRNaWOr2({**<6uC?InG4@0A$Yj5y$@vo9=OwVj8Em;k5-47Z1=AbIEm7Rd z2vGqJ*;euu9*8NPgKVjT4frubviP3vxvEz)cJoy={Z)jP&?cY#nzEJ$bYs{@+n8m? z*48=2?yM*7qkw=|5a$ejJ7>|`Rq%BKV0A>n-@$xLD9heY*-_=uP0mdbc|z3KiUi0U zQX_{zMY}$tYF`leqJUxX%Swgl$=dL3toKon*)L#g+d3WgF8fbxYbYy-@w=)Rk8H`P z7nwsw5uZz;h?Tp7YrMH)wC5g0GTfv9Gg+w*`gmQ+CEM`vjjTsY$H>Xfs}m3E`UAA$ zY@qt}-88^D8}xiR|5yTw*436=A&?vq8{53i$-gCL{QGLA9negN7cu(-)%*c7-LW~- zSqldsOvH?#nAb-ARJ|BY#yA23Zz}+G` zjD>Mx&_mdg4m3n0KFf41frSJFx8mpA1bk1g0i&A;1R^lIiXK)YipQzjhE_w{4^{0) z;0{*~hHGf4Y2LEsV;C}2{8aTAc{MAj`?v{&}~bh}N^ql*c}ATm=V0!Ehgpl2PzcqLj)eUZ&h&NEZr zAkFn-Y>sI56^?osQ_bP2Svy{u_v?#hX;jaJ)(C64b#xM)ns!2Gv1$ovxjZYssWjmx zt(lW2*A)^#BtdT2-I(LOb4!al*x*8!m$iJT`SA!amQ?*U_c(RoaSXsTNOor843+hG zfD0?%VJTJw9E}}~r6yGpi9+_HxJU$Qnk=o`qVUzs6AW}PJLR6z0%k49UM~j7)`ttT z6)KiHl`1kLY#q^gp4KWKN1ibUXVT1(!nJaz>m34ZyOFaR+^hlv-%v{Ea`*@bpDU7Q zV{{`?pRK#iuBlXyMSD{2H2oaupomy6ZWb@dos=@e&D|)e9;EXEn#exT0&el7?lYr0Vox*jTom;f#U{B{Y)Un1o)X-uRO=umHKz(ZBXiwtaa5>Cv%&W z3Okg`>ZdxCJ67O${fseV<(;5Bx2*K@L__tNX{g4MTtRQOBCVpMZ2aqzj;u6~OYUrF z9537iR*I&tnY}d%aL=6sMI^nUxpURSb9rtEqs^kXR2&T^P&So&o&lIfNAxldz!}c# z$!kq4sa3{l*53JtM~Ub5du1_uy#Z^0^E3%BQeHM3IEKq{gamcT8M3k_gcw?6ddC}#@d44SdEn7H;T&W_i5t7d=?1Y+sgJ0@`ngA`z0e`P z-kQmX9Cg5Jje@!rZO-?%@!R4Y_pqEN^zbO6CPzl=+gg2ZBHC!8-{wAPbza@{o+l&7 zvW~HV%*f&IYl}uq=n)rDyeF7M_N@qo zke%APBm|c#b*bc>wivVAvsKa^0{q*{N0nv!>0F99c{PvcuBNOrEw9+ zfT@U&93@gU_bk26Fev23@FZF@KX~prO7*MMFyI;K>`Nh?4TIS2iGeEaLJ@ytE{n}F z`8ZF|&IXPwMX$t66?*9c+$7CSp1W41*Fq9@kYWMT84UjPHSR1W^P+S!nE27yoq@{a?jN(p9@vCc|78NjokB8 z>3K2NMecg#AX>Wf5^bKX9R9bp3c?`ROKum{y#Z7lK#hk_5d%2sBJ6U3iWUS6U&izp z|8f0ge1CP0678~s%iH_$_SiY)TwRqL0@yr`+u0zR!+BFjOA0YJf2v9s1&kP$=uARw zST_Cizp6$Rg{9o^t0+lT4~fCMveEI|S$_ zSV)Niiwz%QSUcoT;TOlMV19|*i(}peweb=GhY0Os@zB^DSlJkJ)9=B;tlBaf$ME2& zLwSag2rVs&NIzVz2W}B?WD=$fj}bBrqwTY=%6}vf&Gd`)Gd39ge5t^aKwFoiK1Mxo zue4eF!-r)J2`wRg*4oI{t#$P!n#8st7{%H+BEob-uwBDWu^@JOFdVh>3IoY0B9zEb z@=BE%sk%wfPfOtnPt(=zP=z~K{$Z$b?p4Y%U{kijy`3rvJuqbh$So!a0x1lALiY zw`3$&$b{9mKaN0~Hf_Qr$5_iAF|#EO6>!*>X+ZF?yvQYh2|~9P^y0&;d+_Bg7W+Eh zAW8<)#e$5(Ea;t_+a;7i@dP2i*1O*p0a_nfnwdwd@s0#|geI|YCYbd*RQDZBY0ES1 z!V?&vB4ucu9ozXPbMI2sck$kFYOCB13YgmJ?d>3XGhUN zUs0p`2nc4Js{clTH_;1)S|tv+<=(6!L+M+T`V)aaWmslqH1`Ca8N1FUC!b;N&jkLQ zy=E77D#Vzh$7;gqqGN=5(s1{7r3^FgREjZgM%KoYUMcQphu>GNHEi>Jw@PimcPaH= zf%h2|-kCy$>vnRgu~r-};?sQuZmt<-syFbflQzBKnOkPMPX<%5{0_Zz#V{U^(!Bcd zakkmLauQ88uU{A?cUb}d*DQdp*_RtcM01+U-R_{sqTELX{z~Al>3yH*6*WP>KL*fo zn~l4$`)ccjLDe8{WtS1`cbDe3_ce4PZ>Z^-iw0^jZh7JTFTW@nR_p=)XT-#WS#dg3D`-o zabQ#B5(ei($T2r-4*2CV*3)KOREQNDg$=;^9(6JI|9Fv^-g4?e)R)|+)q{HkJ|l21 zzID>T~X^2AI4K z|Dp=MW`KE!V*7IUDepe|+Z*8PK-shN8OoI7EcbO-Xi}}r-LL%n?TKW(W$vF;f`cs) zZ<+gsa=*c}wjKFV_CFg~R!C+b9oOXOiEkQ!BoY@*<-VotZ}HF&alkmur--fzZ!5}u zTczKo--+uZl=-g)U|pf>H1{24{pSUsW;lL#R_+0f=Yfv>M!DZLpeGVS_4kzhJzL+2 z>qv6{rUIN~ries`3Uc39KAx7f!vrL79mX`)I%Yj4m`mz|reir4QJatseymph^8$!3 z%_*3Z2|9;swBu5m+)q`4$1LV#&HYSyI1bz6&Tfa#zItp&(#=XrFlX-xR1z~(=S!}OFgBN zqKJh}3G7$O|CKCco#D(B)cB?` zN#lpc{*2H4i=HsnWsJ)Bk+B|}w#&p)AG^DRELvR>kMAz~hjk}G$x}PFpufvdhrLDQ zRAsSPPZ}=G1#{eTM$jxCR2RP?ueZDL!L40eqa3e3>dj9GNHR2}pP|qFK=1pZz>frM zy&8!dH5>UFsTxrl1sbUtT^ad^Rvbatq%*N?-cdKbHla3!D@<@r3(w$a57!tH?)aM< z!a|pM{zUcbL?}Pa5SD)oTr#@-P*qQ22Er(g{A1bs;*q=glNndiu#tb9>O_XGG}l9D z+=}Z$`BU`1Q+PUlsw{u1a!<9T8gQWv>IsuRP$pDO1*gGrh~kj8*28r+Zb_WZDr#OM zmbil`e}=7r_RE`C77b#7io=cS+?4K)Q^O|+7_x*D9lv6Iah{m>wI8O;pQO5v6*yVo zaRQHL9Ng1HC|VDfI6!MUh-As6eJir9MwTu;Ulc2KCfXjfP;>R>pFsbeKH1IwPaIAa zOJ{T{sgs{NoEi#GQ>$QREr%H7IWG=*(i!qk6gWe~mp>*&ER2XRVQR@A7uJoW`6h9x zDTg_wK;LGr)#ARf8o>g^-6-4alDOK5h;PPE!0tOP4#+TSg^!_kHTqCUjLcX0=&VR=Yz!oL^YU8Dxg zW%nNjEFd8Qc66(Geye4XP_OL$_o_ShLS(~svY4)8@fS9-e*kbAl&MiDa_dHC*(xly zTq56U7ZHOUNv+vHaa3;VCtR$EaI}Dvta--7MNNpB!fqV5lQ21gAkmS~e0VMQfD%f= zOLShBgU6;Ds^PGk`CV#2-EzvFx|Js)WVO5L60V|*VXf`x-UEum^ZPc{X)d}|d%OiC zpxFJDdPx-a+g#gp&XyqK)3uCx+vP3Lem}^dS|E(`xIP`Tcjo@Fk}uP@q$WLfh4dkJ z!LBSRSQAG0s~}vJ9&CXq~M4xx4IyRzA%n3qHw`Dd$iECCD^y1G;6^Ed+H*SHB) z-lxs6-xjN&;aRL}{tC6FfyT$EpW_1i1oi{+S1L8ER5Tn7BHl~=bltLPPIITN7~wJt z?iW*Q%LYq9K1oG53d=PMO=PBt%qp??rBBj$WS?+G3dxLdV+uc`g{8^cJj&6K?c6Ji zFpL$ziL`CA7PDiRG2?W#5`wmvCTHsS237JQw%a={<{0(V#ShEk(;md6W#*7St<(r0 z)))1_Ufyn9$xj%blfI^C8%_9`evNIE*EP2fBr<1$RF-WEh-I-uR{P!UTq?DtYQQ9u zNIYrnj|m%PeqPTQh<1@^k4)Ph+qM_CEvgmv#&#QJUMiUb(Y6@vh$he3aH0;oZtAh^ zVb^}GU9MtlVm4()R*f|Xpuj+N^i{!YvtQ6I7P~tt z2e9KR@%$lG7dT1~`)^aatlE_{p5zTlhb5(=49l&R(AM)u)XgK>UJ_b#{<+G>9le}B ze4WY#vRaT9-|kQs;i{o3AqMjDN4efCk+S%9_jY^Lb=J>?w8?CRn#3nFJ<{Z9>PiHj zuAdPQIc5c12*u_4DS1s{CZP|2-}xI_Ap1-eBhDoiqZ`?=QtrLVBHks}+)ZleCVWg| zlZ_)sm%%8ae) z_3DcO%kPn0?%r|Z_*TUtvw0L3QOXEiP!zlR^AgF`I;Ti*V0frDp~JomnIY-m({r~N zkQ63CKlJ=<-gON!f+QK)fw;q6beX@+0Ct@4b_AmC-F=1m+f{bE)>6|nOSPCmP`-O| z!b@7hyIbquSv6@R{m8#g`7aiDiNH$*UM6r0Qd_$0s?u8p3@?nm!|9iD&>2*>U9*vY zx!QPzfZ^f}rEJWvW{k0`H{2Lst703)>x|0Mf(5vW0)Lm(OiV=&!|CaEHx>jAJOugR(`q9aMUmf>V$lrk+2j7BW~G)!_lr$=L8pu6gq)w;~YJ453biT z=76$Svq&uN;dAlqs_-_k2yR9%ajMj4`t7h-d6pJA{xz?Ow;*(RAkD2jjqGF>ZkllY zPGy$}HNh{8+j+qbovp-4tKd>K|8Dj63kIml(M3g)tJN{${8iySDjNl4S4M!Uoxy7P zyHsDmIDG!Cqzq+lHw^J&+ndA7`>Emt+>a>rmw^1A3%pI>?E>#$xZHxv4Wk@5K*=H) z-(4e-xD`DAPSt&vKschduIKME!g$M3*-ug)`yXN5m|4RXLbMueNkr?y7DpR!+(dn2 z)x-k@l=UHjTa&<6P6Xbd(l-e>t`MedO{4+0>{ZWFwm4YtNI4abBuX9Wh$zT^Sk*tw zMzyc9#9gRG3{8Y&HHkVJuZ_({^m;uIb>I4HU45epqW)S3-<<5sU)ak8{-@2#-65u9 zmIuzTOt`DThZ^SaTV7qErR(8@VyQO8B@&Th zqe={*b6eAU|61>LBay^GAj@Rz`x+Ex8PYL!!cnJ0W7o3i!Eu580=5t}PN(sFoRmxq zYnmno&XlQagm>UFAt12CUf8HL!?A6o%~7#s*^aUod9v*u1e^Ddq|E#3R)A1+*ChMk za+g!2+_aVd6x&HMLMUdnzDI*`fNJscHPV}!(LYCt2-4%9Wi&~tA-S*<`}RNT2?yGC zXYt)U`b3+5OBrT#Gx^W%8|YlFM(tnbwaJj5{8!W_?($^Fk1{zed$hQp{HIh2`&L`r z54^tPHjiY$m7X(%enzQ#1wc?rP*DDJWVfA6Q|-^U>~Xw2`8k6&xd0MOLK$o zB8mE(<3ka8>knEWBdcB$aCxf>o^7!eE`UUY-3u?%J(%ls7#4w+&xY7NO!*(_QOV!G zHE@^6ypX1JA5KT4U;f9G~|4N-PP*=);ZA=aQbik+rXAm3gc76F`zId=f7?4MeLZ$_N*Oq{$ zZm(V#xi2x5iTH&MhkYTZz6dlG|1kAjr6O>heultFfDsD9(c9Q;Sj`^rm~A(OEUDOw ztYxR;Ka?^t8@uroa|;9!k`<)qhn40#4+Q9SD;d8nR~!~iccBv?)GKGZCS|ucMId7m z=DXQQ`2Zl-?AJZT0CUJ!ch{<`h1Gh9oi?Tsn#EjYYXI&Lj;+|c^)m!oTd^;Iss36B z1xrikXTVgr4iH;%EA%r2kvtv=4%{}&#w!mR>AvwIz9Hn~Pgd4}fWlrrRbJ^@<#HIT&SORAvt$c%=(r2K%dORMBY=7J}QAlKK_s${rdUGfWi}%dW(Q{{!f&;RRvLZ(|Y=2)wAyYsZ!Qw>txhF>s4Ea-psT&gDY%Tfx3|< zs5lv=@T3&PujF!|>ii=M2Z|rMEu4ec-MVbJa4yTgEo2qTQ-68;kax{B-Zk*V{^r$4 zV|;W&j_;%nEvu@1$Ap^gs?nCnZpsM;yNsP(Es}9vC??kf=>$gds~&Od7d?#JzO4X` z!X*i_XyH;xesa*uLaTETNu8_EBc)X*SfJ?E*G+h&{R2CNJ_Zzq+79LK{%QgW>LA8HShz|W^o#OLVs&o~dAH$O-VG$$IlD442vka)DE%Ko7Y?VA4 z93(w#h36>$Im>P0SF7}DJyo}R%KNaEN*l%8r;{gkG@Nh^R!bBQ@6at4R5&1TxqzX} z26tr&>DYj*@77K0lf4>8Mm(s|sN}LVDskVI!-n**AqX4XeP67Q)|Fy~Yt%ylW2-UV zy4+^+yWdCD1M%tzT{$dn5&k%mwCU<9;71Lu}(p zHLlY!A~BvI5bZ3{=xqaad#6=N*-D}pyVtm;Y;I;!<_5<$7S{n>4dDXTyVLgZ%sW)_ z;Sh*HG*zZfQP61@recJ8hEt>7qsQ(NcwZ8{Uq6=x!zx`C+^y0Gd_X@V@In2Iz=!nn zF9f0y8Mo5}G}R*QX*#pxjzXdFsHm;$)>oT?kEql-XMOmneo7^BefXe+sOMSTnfMfw<{feiMokSBlypiwNuM}KYnOV~4m1c*kNSQc9kAn% z;j7j+#h<7SNL}Xw3tQd!Z8mU_HQcC8VsmJ<7Bh;nJEVQ;w7^7$_uPfZdp?swQ~d7~=9`SiFUg+i=ZEP|-oTXn;2epEn9H!=0aWDKNnsxa>>5nAlTx>r>%S z3Lk2Uw2?RNC}iI`hoREVQ=$93AU&(_R!G)@!SzEP$-HmCQy4((3yTHVQ!L7$AnsWB5JFDuGhPL8%feqU ztaxmGL3@D%QcDZcG#%0n&p5i13WJK@Ch&Fv@!rBa1++mFWMV6b!4|YP6y7VK4Wb|} zTM%0HF)jJ%Z8)>H}3LjGy z15Z=R#CZef>*q5BE_ozlt6@H=TiPekIn$?PaQG4`wqCcrz;K0kk_as$0_#{IvQ zZ2*-g<%`}0!gtfidWW7f6xbklLVo%Jwr+DJ+(tKVn?N58J~nPWDyL%MZv;Le5RL3_ z_0xvnI;)?qe@guy0o$MdUMWJYS02R2i7UjW^`j}%x_Jz~qcb90xnI_)??=Q}qV4n^ zz33juD0v|a_zk~Ft-<41*V>AGhOF>eI8b zx^#g1fa`X)-`$S7aS!p*^5gb$5`jIHd9n{8qS-b-8KxJ0N!jhU3~x{bi9SH9i>u}* zRPQSawCKE4FwQW)rh4swzK!#_p9x)E33In|H;`rGQq;oNCG@o2kgdk;*7sm|^N3=a5GJjEdgLb{c&yA0#HOs&{S3vI*pO+a_s=}!H81Yo!75hb#U z06Q)(_tf>Sl?Fh`?gj@T>bUE$5ZV1|U8_{IiUIE>x-I@0->%gv5m;WuYt#KkRM`On z>g?=q%X!|a`75q~hQrmeA!%No+3fu_{8@skP8*%Olu%?vTk?sBkH#UtTikyk{ zTD|F7LvQw%>W%GO&wHf#spVe26|%i~LrZ4Nuw;SI_EExUf;)Dt#C^zx4ramY9LKyT zOhv2yhsrZx>)0sxtIBhWF-#eA|CxS9;69dWr|q+AGqnsjuGd=>ks_c(mYAlsrld|CyG741WlOTpTPT z7#fNNCLu=<61%zO!S5j=*00(}L^^M+TFb|7VTpVwqro$q28edBsP*QjKH1)*AmaSq z1$g6TcXcrL%)n9kkeR+~g0BW46(5}0eBg%2sq&$i@qx?M%1iR}5pJ%)r=dXC#?uhj zHYC5IjI@h$3?8b}u=IwHdvB+IXgque1f>r7Q(`%45Mg5Jhp*YZdWp)#%{E-(yYrlq zr#Goqtga`~TyMaYO&V4EwM@LdU4fyY@C#EYK6So~r7PV!J}MK%?=wdGw)7;(VNiBM zCSx25@Kq9&KLy4&_DEBeF2!j``vB>t-Hmzn4_!)tp^Do_nB;!lHjfXRC+JxBVcj&Q zX=lT;TW9!+4AZ6yj(V%XB%f{2CyQgB6Q(2F>@Zo!g|w)j?lU<0rDIa!1p~k z0Bzw>v@^<+XQhW6>l&fEeF?aAJMHp^V-E8j zLT(>%PQbk1zzf3}{<^$ePDlLA9WlbH<{$vKtEms#P7 zC1fIOXz$Oy!30*>0iE<|f~U!xCWo2`YGUc51x-2hzZ6Q&)WknYV4J{`1)d`CRDp8^ zWIXOVU%=`q{H5z60a=T?x&?X#`UPYZ?vm=>wM#%2g08&+mkEps>=QU3aD~8?0?!h7 zj({gHDc}pt2$Te54(gg02n4PbcvLrfR5ubGJgO-F*R~y;p-DDY^?OPgANqZzjA?CG z$~f0qN*Vh)TPfpV=O|^2>^!B6n>}4AV`*{$y7n$m%9z_Tl`;-@u~Nq7E>+5SU5`@6 z@cNW8t~a2RvA!XtjQ{Oa%9x;RvW^q(QOek%877S getType(); + + /** + * Returns the value of the element. + */ + public Object getValue(); + + /** + * Sets the property value as a string. + */ + public void setValue(String value); +} diff --git a/src/treeProperties/PropertyType.java b/src/treeProperties/PropertyType.java new file mode 100644 index 00000000000..d01f2c77a88 --- /dev/null +++ b/src/treeProperties/PropertyType.java @@ -0,0 +1,34 @@ + +package treeProperties; + + +/** + * PropertyTypeHandler.java + * + * Created on 19.08.2009 + */ + + +/** + * The class PropertyType. A property type is used to process special, suffixed entries in a {@link TreeProperties} + * ' properties-file + * + * @version V0.0 19.08.2009 + * @author Clemens Koza + */ +public interface PropertyType { + /** + * The suffix, not including "--", that identifies this content type. + */ + public String getSuffix(); + + /** + * The class that identifies this content type. + */ + public Class getType(); + + /** + * Returns an object for the specified value, in the context of a TreeProperties. + */ + public T toObject(TreeProperties p, String s); +} diff --git a/src/treeProperties/TreeProperties.java b/src/treeProperties/TreeProperties.java new file mode 100644 index 00000000000..ff6efd4ccfe --- /dev/null +++ b/src/treeProperties/TreeProperties.java @@ -0,0 +1,396 @@ + +package treeProperties; + + +/** + * TreeProperties.java + * + * Created on 19.08.2009 + */ + + +import static java.lang.String.*; +import static java.util.Collections.*; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Properties; +import java.util.Set; +import java.util.Map.Entry; + +import treeProperties.types.FileType; + + +/** + * The class TreeProperties. This class allows for a tree-like structure of properties-files. This class lays some + * restrictions on the keys used in properties-files: + *
    + *
  • The use of "--" is forbidden
  • + *
  • The suffixes "--properties" and "--transparent-properties" are reserved for specifying additional + * properties-files in the tree (relative paths are relative to the properties-file where they are referenced)
  • + *
  • Other suffixes are used by {@link PropertyType}s. PropertyTypes are registered or unregistered using + * {@link #addType(PropertyType)} or {@link #removeType(PropertyType)}.
  • + *
+ * Take a look at these files: + * + *
+ * #root.properties
+ * title=directions
+ * icons--properties=img/icons.properties
+ * 
+ * #img/icons.properties
+ * left--file=left.jpg
+ * right--file=right.jpg
+ * up--file=up.jpg
+ * down--file=down.jpg
+ * #note that the path does not contain "img/"
+ * size--transparent-properties=size.properties
+ * 
+ * #img/size.properties
+ * width=20
+ * height=20
+ * 
+ * + * These properties are retrieved with + * + *
+ * getProperty("title") //directions
+ * getFile("icons/left") //img/left.jpg
+ * getFile("icons/right") //img/right.jpg
+ * getFile("icons/up") //img/up.jpg
+ * getFile("icons/down") //img/down.jpg
+ * getProperty("icons/width") //20
+ * getProperty("icons/height") //20
+ * 
+ * + * As you can see, a properties file included with "--transparent-properties" hides its existence from the user. A + * file included with "--properties" is not hidden. The child properties are accessible as if their keys were + * prepended with the parent key, separated by a slash. + * + * Note that --file, --properties and --transparent-properties entries will be relative to the included file, even + * if the properties file is transparent. + * + * Also, the TreeProperties can be retrieved: + * + *
+ * getChildProperties("icons")
+ * getTransparentProperties("icons/size")
+ * 
+ * + * + * TODO add edit & save support + * + * @version V0.0 19.08.2009 + * @author Clemens Koza + * @see Properties + */ +public class TreeProperties implements Iterable { + private static final Map> suffixes; + private static final Map, PropertyType> types; + + private static final String transparent = "transparent-properties"; + private static final String child = "properties"; + + static { + types = new HashMap, PropertyType>(); + suffixes = new HashMap>(); + PropertyType[] pt = {new FileType()}; + for(PropertyType type:pt) { + addType(type); + } + } + + private File path; + private Map, PropertyType> instanceTypes; + private Map> instanceSuffixes; + private HashMap properties; + private List exceptions; + + public static void addType(PropertyType type) { + types.put(type.getType(), type); + suffixes.put(type.getSuffix(), type); + } + + public static void removeType(PropertyType type) { + types.remove(type.getType()); + suffixes.remove(type.getSuffix()); + } + + /** + * Delegate to {@link #TreeProperties(File)} with a new {@link File#File(String)} + */ + public TreeProperties(String f) throws IOException { + this(new File(f)); + } + + /** + * Delegate to {@link #TreeProperties(File)} with a new {@link File#File(File, String)} + */ + public TreeProperties(File parent, String f) throws IOException { + this(new File(parent, f)); + } + + /** + * The constructor is forgiving in the way that Exceptions are not directly forwarded. The only fatal exception + * is if the parameter is null or not found. Instead, the rest of the properties are processed, so that the + * erroneous properties are the only ones not present in this TreeProperties. Afterwards, the exceptions can be + * accessed. + */ + public TreeProperties(File f) throws IOException { + if(f == null) throw new FileNotFoundException("null"); + this.path = f.getParentFile(); + instanceTypes = new HashMap, PropertyType>(types); + instanceSuffixes = new HashMap>(suffixes); + Properties p = new Properties(); + +// BufferedReader r = new BufferedReader(new FileReader(f)); +// p.load(r); +// r.close(); + BufferedInputStream is = new BufferedInputStream(new FileInputStream(f)); + p.load(is); + is.close(); + + Set> entries = p.entrySet(); + properties = new HashMap(); + List exceptions = new ArrayList(); + this.exceptions = unmodifiableList(exceptions); + for(Entry entry:entries) { + String key = (String) entry.getKey(); + String value = (String) entry.getValue(); + try { + String[] parts = key.split("--", 2); + Object result; + if(parts.length == 1) { + //Regular + result = value; + } else { + //suffix + if(parts[1].equals(transparent) || parts[1].equals(child)) { + TreeProperties child = new TreeProperties(path, FileType.getPath(value)); + exceptions.addAll(child.exceptions); + result = child; + } else { + PropertyType t = instanceSuffixes.get(parts[1]); + if(t == null) throw new IllegalArgumentException("No content type: " + parts[1]); + result = t.toObject(this, value); + } + } + properties.put(key, result); + } catch(Exception ex) { + exceptions.add(new Exception(format("File '%s', Property '%s':%n %s", f, key, ex.getMessage()), + ex.getCause())); + } + } + } + + /** + * Returns the exceptions that were thrown while creating the tree properties. + */ + public List getExceptions() { + return exceptions; + } + + /** + * If exceptions occured during construction, this method throws an IOException that combines the messages of + * those exceptions. + */ + public void rethrow() throws IOException { + if(exceptions.isEmpty()) return; + StringBuilder sb = new StringBuilder("The following exceptions occured:"); + for(Exception ex:exceptions) { + sb.append("\n"); + sb.append(ex.getMessage()); + } + throw new IOException(sb.toString()); + } + + /** + * Returns the parent directory of this TreeProperties. + */ + public File getPath() { + return path; + } + + /** + * Checks if the key is valid for a query and throws an {@link IllegalArgumentException} if not. Slashes are + * allowed in this method, but suffixes are not + */ + private void checkQueryKey(String key) { + if(key.contains("--")) throw new IllegalArgumentException("Invalid key: " + key); + } + + /** + * Retrieves the string property for the given key. + */ + public String getProperty(String key) { + return getProperty(key, String.class); + } + + /** + * Convenience for {@code getProperty(key, File.class)}. + */ + public File getFile(String key) { + return getProperty(key, File.class); + } + + /** + * Retrieves the child properties for the given key. Transparent properties can't be retrieved this way. + */ + public TreeProperties getChildProperties(String key) { + return (TreeProperties) getProperty(key, "--" + child); + } + + /** + * Retrieves the child properties for the given key. + */ + public TreeProperties getTransparentProperties(String key) { + return (TreeProperties) getProperty(key, "--" + transparent); + } + + /** + * Returns a property of the given type. This does not work to retrieve tree properties. + */ + @SuppressWarnings("unchecked") + public T getProperty(String key, Class cls) { + String suffix; + if(cls == String.class) suffix = ""; + else { + PropertyType t = instanceTypes.get(cls); + suffix = "--" + t.getSuffix(); + } + return (T) getProperty(key, suffix); + } + + private Object getProperty(String key, String suffix) { + checkQueryKey(key); + //first, try the key in the current file, as if there were no slash + //No subpath - either directly in the properties... + Object result; + if((result = properties.get(key + suffix)) != null) return result; + + //...or in a transparent properties + + //look for all --transparent-properties + for(Entry entry:properties.entrySet()) { + if(entry.getKey().endsWith("--" + transparent)) { + TreeProperties p = (TreeProperties) entry.getValue(); + if((result = p.getProperty(key, suffix)) != null) { + return result; + } + } + } + + //if there is no immediate containment, try the children + //try every combination + //for a/b/c, there could be a child "a/b--properties" that contains "c" + //or "a--properties" with "b/c" + int index = -1; + while((index = key.indexOf('/', index + 1)) != -1) { + String first = key.substring(0, index), second = key.substring(index + 1); + + TreeProperties p = (TreeProperties) getProperty(first, "--" + child); + if(p == null) continue; + if((result = p.getProperty(second, suffix)) != null) { + return result; + } + } + return null; + } + + /** + * Returns an iterator over all the regular entries of this object. That means that transparent or child tree + * properties are not included. + */ + public Iterator iterator() { + return iterator(""); + }; + + private TreePropertiesIterator iterator(String prefix) { + return new TreePropertiesIterator(prefix); + } + + private final class TreePropertiesIterator implements Iterator { + private final String prefix; + private Iterator> entries; + private TreePropertiesIterator child; + private PropertyElement next; + + private TreePropertiesIterator(String prefix) { + entries = properties.entrySet().iterator(); + this.prefix = prefix; + } + + //After this call, the next element is determined, or the child iterator has next + + public boolean hasNext() { + if(next != null) return true; + else if(child != null && child.hasNext()) return true; + else if(entries.hasNext()) { + Entry entry = entries.next(); + final String[] parts = entry.getKey().split("--"); + final Class cls; + final Object value = entry.getValue(); + + if(parts.length == 1) { + cls = String.class; + } else if(parts[1].equals(transparent)) { + child = ((TreeProperties) entry.getValue()).iterator(prefix); + //recursive, for the case that the child iterator is empty + return hasNext(); + } else if(parts[1].equals(TreeProperties.child)) { + child = ((TreeProperties) entry.getValue()).iterator(prefix + parts[0] + "/"); + //recursive, for the case that the child iterator is empty + return hasNext(); + } else { + //class is determined by the content type + PropertyType t = instanceSuffixes.get(parts[1]); + cls = t.getType(); + } + next = new PropertyElement() { + + public String getKey() { + return prefix + parts[0]; + } + + + public Class getType() { + return cls; + } + + + public Object getValue() { + return value; + } + + + public void setValue(String value) {} + }; + return true; + } else return false; + } + + + public PropertyElement next() { + if(!hasNext()) throw new NoSuchElementException(); + else if(next != null) { + PropertyElement next = this.next; + this.next = null; + return next; + } else return child.next(); + } + + + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/treeProperties/types/FileType.java b/src/treeProperties/types/FileType.java new file mode 100644 index 00000000000..22050200b1d --- /dev/null +++ b/src/treeProperties/types/FileType.java @@ -0,0 +1,61 @@ +/** + * FileType.java + * + * Created on 19.08.2009 + */ + +package treeProperties.types; + + +import java.io.File; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import treeProperties.PropertyType; +import treeProperties.TreeProperties; + + +/** + * The class FileType. + * + * @version V0.0 19.08.2009 + * @author Clemens Koza + */ +public class FileType implements PropertyType { + public static final String suffix = "file"; + public static final Class type = File.class; + + public String getSuffix() { + return suffix; + } + + public Class getType() { + return type; + } + + + public File toObject(TreeProperties p, String s) { + return new File(p.getPath(), getPath(s)); + } + + /** + * Returns a path path from a property value. Three substitutions are applied: + *
    + *
  • A "~/" or "~\" at the beginning is replaced with the user's home directory
  • + *
  • A "$$" anywhere is replaced with a single "$"
  • + *
  • A "${*}", where * is any string without "}", is replaced by {@link System#getProperty(String)}
  • + *
+ */ + public static String getPath(String s) { + if(s.startsWith("~/")) s = System.getProperty("user.home") + "/" + s.substring(2); + else if(s.startsWith("~\\")) s = System.getProperty("user.home") + "\\" + s.substring(2); + Matcher m = Pattern.compile("\\$\\$|\\$\\{([^\\}]*)\\}").matcher(s); + StringBuffer result = new StringBuffer(); + while(m.find()) { + if(m.group().equals("$$")) m.appendReplacement(result, Matcher.quoteReplacement("$")); + else m.appendReplacement(result, Matcher.quoteReplacement(System.getProperty(m.group(1)))); + } + m.appendTail(result); + return result.toString(); + } +}