From 125d4e4bc7476a6146bdd11930c87fd98ecf6ebb Mon Sep 17 00:00:00 2001 From: Sloth Date: Sat, 30 Jun 2012 15:25:19 +0000 Subject: [PATCH 1/8] - Improved AI for Barl's Cage. --- .../java/forge/card/abilityfactory/AbilityFactoryPump.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryPump.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryPump.java index 16a8627bd32..0a51816a4d9 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactoryPump.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactoryPump.java @@ -43,6 +43,7 @@ import forge.card.spellability.Target; import forge.game.phase.CombatUtil; import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; +import forge.game.phase.Untap; import forge.game.player.ComputerUtil; import forge.game.player.Player; import forge.game.zone.ZoneType; @@ -325,7 +326,8 @@ public class AbilityFactoryPump { return false; } } else if (keyword.endsWith("This card doesn't untap during your next untap step.")) { - if (ph.getPhase().isBefore(PhaseType.MAIN2) || card.isUntapped() || ph.isPlayerTurn(human)) { + if (ph.getPhase().isBefore(PhaseType.MAIN2) || card.isUntapped() || ph.isPlayerTurn(human) + || !Untap.canUntap(card)) { return false; } } else if (keyword.endsWith("Prevent all combat damage that would be dealt by CARDNAME.")) { From 8a8fdd91be9f8645d54b7880c3dd4d8e0920140e Mon Sep 17 00:00:00 2001 From: Sloth Date: Sat, 30 Jun 2012 15:41:44 +0000 Subject: [PATCH 2/8] - Fixed sorcery speed AI bug in AF DealDamage. --- .../abilityfactory/AbilityFactoryDealDamage.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryDealDamage.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryDealDamage.java index 23d47998055..9478a2e2b6a 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactoryDealDamage.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactoryDealDamage.java @@ -37,6 +37,7 @@ import forge.card.spellability.Spell; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.card.spellability.TargetSelection; +import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.ComputerUtil; import forge.game.player.Player; @@ -592,6 +593,7 @@ public class AbilityFactoryDealDamage { private boolean damageChoosingTargets(final SpellAbility saMe, final Target tgt, final int dmg, final boolean isTrigger, final boolean mandatory) { final boolean noPrevention = this.abilityFactory.getMapParams().containsKey("NoPrevention"); + final PhaseHandler phase = Singletons.getModel().getGameState().getPhaseHandler(); // target loop tgt.resetTargets(); @@ -620,10 +622,8 @@ public class AbilityFactoryDealDamage { // on the stack // or from taking combat damage final boolean freePing = isTrigger || saMe.getPayCosts() == null || tgt.getNumTargeted() > 0 - || (Singletons.getModel().getGameState().getPhaseHandler().is(PhaseType.END_OF_TURN) && saMe.isAbility() - && Singletons.getModel().getGameState().getPhaseHandler().isNextTurn(AllZone.getComputerPlayer())) - || (Singletons.getModel().getGameState().getPhaseHandler().is(PhaseType.MAIN2) - && saMe.getRestrictions().getPlaneswalker()); + || (phase.is(PhaseType.END_OF_TURN) && saMe.isAbility()&& phase.isNextTurn(AllZone.getComputerPlayer())) + || (phase.is(PhaseType.MAIN2) && saMe.getRestrictions().getPlaneswalker()); if (freePing && saMe.canTarget(AllZone.getHumanPlayer()) && tgt.addTarget(AllZone.getHumanPlayer())) { continue; @@ -638,11 +638,11 @@ public class AbilityFactoryDealDamage { // TODO: Improve Damage, we shouldn't just target the player just // because we can - else if (saMe.canTarget(AllZone.getHumanPlayer()) && ((Singletons.getModel().getGameState().getPhaseHandler().is(PhaseType.END_OF_TURN) - && Singletons.getModel().getGameState().getPhaseHandler().isNextTurn(AllZone.getComputerPlayer())) - || saMe.getPayCosts() == null || isTrigger)) { + else if (saMe.canTarget(AllZone.getHumanPlayer()) + && ((phase.is(PhaseType.END_OF_TURN) && phase.isNextTurn(AllZone.getComputerPlayer())) + || (AbilityFactory.isSorcerySpeed(saMe) && phase.is(PhaseType.MAIN2)) + || saMe.getPayCosts() == null || isTrigger)) { if (tgt.addTarget(AllZone.getHumanPlayer())) { - System.out.println(saMe.getSourceCard() + " - damageChoosingTargets"); continue; } } From 333c9bb70964dfe29bc23ea6177be7ba1528acb6 Mon Sep 17 00:00:00 2001 From: Sloth Date: Sat, 30 Jun 2012 15:53:50 +0000 Subject: [PATCH 3/8] - Fixed Blaze AI targeting human. --- .../forge/card/abilityfactory/AbilityFactoryDealDamage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryDealDamage.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryDealDamage.java index 9478a2e2b6a..8aca91fa42e 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactoryDealDamage.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactoryDealDamage.java @@ -410,7 +410,7 @@ public class AbilityFactoryDealDamage { if (this.damage.equals("X") && source.getSVar(this.damage).equals("Count$xPaid")) { // If I can kill my target by paying less mana, do it final Target tgt = saMe.getTarget(); - if (tgt != null) { + if (tgt != null && tgt.getTargetPlayers().isEmpty()) { int actualPay = 0; final boolean noPrevention = this.abilityFactory.getMapParams().containsKey("NoPrevention"); final ArrayList cards = tgt.getTargetCards(); From bd882ca0b49afa02358dded9feef157ed5108098 Mon Sep 17 00:00:00 2001 From: Sloth Date: Sat, 30 Jun 2012 16:27:53 +0000 Subject: [PATCH 4/8] - ChosenX will now also be stored on the card and not only the spellAbility. - Fixed Tezzeret the Seeker. --- res/cardsfolder/t/tezzeret_the_seeker.txt | 2 +- src/main/java/forge/card/cost/CostUtil.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/res/cardsfolder/t/tezzeret_the_seeker.txt b/res/cardsfolder/t/tezzeret_the_seeker.txt index 42b0f7cf0c0..781eb0feef7 100644 --- a/res/cardsfolder/t/tezzeret_the_seeker.txt +++ b/res/cardsfolder/t/tezzeret_the_seeker.txt @@ -4,7 +4,7 @@ Types:Planeswalker Tezzeret Text:no text Loyalty:4 A:AB$ Untap | Cost$ AddCounter<1/LOYALTY> | ValidTgts$ Artifact | TgtPrompt$ Choose target artifact | TargetMin$ 0 | TargetMax$ 2 | Planeswalker$ True | SpellDescription$ Untap up to two target artifacts. -A:AB$ ChangeZone | Cost$ SubCounter | Origin$ Library | Destination$ Battlefield | ChangeType$ Artifact.cmcLEChosenX | ChangeNum$ 1 | Shuffle$ True | Planeswalker$ True | SpellDescription$ Search your library for an artifact card with converted mana cost X or less and put it onto the battlefield. Then shuffle your library. +A:AB$ ChangeZone | Cost$ SubCounter | Origin$ Library | Destination$ Battlefield | ChangeType$ Artifact.cmcLEChosenX | References$ X | ChangeNum$ 1 | Shuffle$ True | Planeswalker$ True | SpellDescription$ Search your library for an artifact card with converted mana cost X or less and put it onto the battlefield. Then shuffle your library. A:AB$ AnimateAll | Cost$ SubCounter<5/LOYALTY> | Power$ 5 | Toughness$ 5 | Types$ Creature,Artifact | ValidCards$ Artifact.YouCtrl | Planeswalker$ True | Ultimate$ True | SpellDescription$ Artifacts you control become 5/5 artifact creatures until end of turn. #ChosenX SVar created by Cost payment SVar:X:XChoice diff --git a/src/main/java/forge/card/cost/CostUtil.java b/src/main/java/forge/card/cost/CostUtil.java index 3a5e226ae7c..e55bf4de6cf 100644 --- a/src/main/java/forge/card/cost/CostUtil.java +++ b/src/main/java/forge/card/cost/CostUtil.java @@ -304,6 +304,7 @@ public class CostUtil { final Object o = GuiUtils.chooseOne(card.toString() + " - Choose a Value for X", choiceArray); final int chosenX = (Integer) o; sa.setSVar("ChosenX", "Number$" + Integer.toString(chosenX)); + card.setSVar("ChosenX", "Number$" + Integer.toString(chosenX)); return chosenX; } From ba5dc70a20c3cc55ac27219ec96faa0d91ddf9d1 Mon Sep 17 00:00:00 2001 From: Hellfish Date: Sat, 30 Jun 2012 18:04:19 +0000 Subject: [PATCH 5/8] *Made "Open Deck" dialog default to res/decks folder. --- .../forge/gui/deckeditor/controllers/CCurrentDeck.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/forge/gui/deckeditor/controllers/CCurrentDeck.java b/src/main/java/forge/gui/deckeditor/controllers/CCurrentDeck.java index 9d78f02a1e6..7d59597ce18 100644 --- a/src/main/java/forge/gui/deckeditor/controllers/CCurrentDeck.java +++ b/src/main/java/forge/gui/deckeditor/controllers/CCurrentDeck.java @@ -9,6 +9,7 @@ import javax.swing.JTextField; import javax.swing.SwingUtilities; import forge.Command; +import forge.Constant; import forge.deck.Deck; import forge.deck.DeckBase; import forge.deck.io.DeckSerializer; @@ -20,6 +21,9 @@ import forge.gui.deckeditor.views.VCurrentDeck; import forge.gui.framework.ICDoc; import forge.gui.toolbox.FLabel; import forge.item.InventoryItem; +import forge.model.FModel; +import forge.properties.ForgeProps; +import forge.properties.NewConstants; /** * Controls the "current deck" panel in the deck editor UI. @@ -32,6 +36,8 @@ public enum CCurrentDeck implements ICDoc { SINGLETON_INSTANCE; private static File previousDirectory = null; + + private File openStartDir = ForgeProps.getFile(NewConstants.NEW_DECKS); //========== Overridden methods @@ -159,6 +165,7 @@ public enum CCurrentDeck implements ICDoc { final JFileChooser open = new JFileChooser(previousDirectory); open.setDialogTitle("Import Deck"); open.addChoosableFileFilter(DeckSerializer.DCK_FILTER); + open.setCurrentDirectory(openStartDir); final int returnVal = open.showOpenDialog(null); if (returnVal == JFileChooser.APPROVE_OPTION) { From 2ecec74989397a772353b16c4ebd8cd6c5551bc1 Mon Sep 17 00:00:00 2001 From: Sloth Date: Sat, 30 Jun 2012 20:20:24 +0000 Subject: [PATCH 6/8] - Cleanup in CardFactoryCreatures. --- .../cardfactory/CardFactoryCreatures.java | 182 ------------------ 1 file changed, 182 deletions(-) diff --git a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java index cca25bfe957..81083676a22 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java @@ -54,7 +54,6 @@ import forge.game.zone.PlayerZone; import forge.game.zone.ZoneType; import forge.gui.GuiUtils; import forge.gui.match.CMatchUI; -import forge.util.MyRandom; import forge.view.ButtonUtil; /** @@ -958,187 +957,6 @@ public class CardFactoryCreatures { ability2.setStackDescription(sbStack.toString()); } - /*private static void getCard_AcademyRector(final Card card, final String cardName) { - final SpellAbility ability = new Ability(card, "0") { - - @Override - public void resolve() { - - if (card.getController().isHuman()) { - final StringBuilder question = new StringBuilder(); - if (card.getName().equals("Academy Rector")) { - question.append("Exile ").append(card.getName()).append(" and place "); - } else { - question.append("Place "); - } - question.append("an enchantment from your library onto the battlefield?"); - - if (GameActionUtil.showYesNoDialog(card, question.toString())) { - if (card.getName().equals("Academy Rector")) { - Singletons.getModel().getGameAction().exile(card); - } - CardList list = AllZone.getHumanPlayer().getCardsIn(ZoneType.Library); - list = list.getType("Enchantment"); - - if (list.size() > 0) { - final Object objectSelected = GuiUtils.chooseOneOrNone("Choose an enchantment", - list.toArray()); - - if (objectSelected != null) { - - final Card c = (Card) objectSelected; - Singletons.getModel().getGameAction().moveToPlay(c); - - if (c.isAura()) { - - final String[] enchantThisType = { "" }; - final String[] message = { "" }; - - // The type following "Enchant" maybe - // upercase or lowercase, cardsfolder - // has both - // Note that I am being overly cautious. - - if (c.hasKeyword("Enchant creature without flying") - || c.hasKeyword("Enchant Creature without flying")) { - enchantThisType[0] = "Creature.withoutFlying"; - message[0] = "Select a creature without flying"; - } else if (c.hasKeyword("Enchant creature with converted mana cost 2 or less") - || c.hasKeyword("Enchant Creature with " - + "converted mana cost 2 or less")) { - enchantThisType[0] = "Creature.cmcLE2"; - message[0] = "Select a creature with converted mana cost 2 or less"; - } else if (c.hasKeyword("Enchant red or green creature")) { - enchantThisType[0] = "Creature.Red,Creature.Green"; - message[0] = "Select a red or green creature"; - } else if (c.hasKeyword("Enchant tapped creature")) { - enchantThisType[0] = "Creature.tapped"; - message[0] = "Select a tapped creature"; - } else if (c.hasKeyword("Enchant creature") || c.hasKeyword("Enchant Creature")) { - enchantThisType[0] = "Creature"; - message[0] = "Select a creature"; - } else if (c.hasKeyword("Enchant wall") || c.hasKeyword("Enchant Wall")) { - enchantThisType[0] = "Wall"; - message[0] = "Select a Wall"; - } else if (c.hasKeyword("Enchant land you control") - || c.hasKeyword("Enchant Land you control")) { - enchantThisType[0] = "Land.YouCtrl"; - message[0] = "Select a land you control"; - } else if (c.hasKeyword("Enchant land") || c.hasKeyword("Enchant Land")) { - enchantThisType[0] = "Land"; - message[0] = "Select a land"; - } else if (c.hasKeyword("Enchant artifact") || c.hasKeyword("Enchant Artifact")) { - enchantThisType[0] = "Artifact"; - message[0] = "Select an artifact"; - } else if (c.hasKeyword("Enchant enchantment") - || c.hasKeyword("Enchant Enchantment")) { - enchantThisType[0] = "Enchantment"; - message[0] = "Select an enchantment"; - } - - final CardList allCards = AllZoneUtil.getCardsIn(ZoneType.Battlefield); - - // Make sure that we were able to match - // the selected aura with our list of - // criteria - - if ((enchantThisType[0] != "") && (message[0] != "")) { - - final CardList choices = allCards.getValidCards(enchantThisType[0], - card.getController(), card); - final String msg = message[0]; - - AllZone.getInputControl().setInput(new Input() { - private static final long serialVersionUID = -6271957194091955059L; - - @Override - public void showMessage() { - CMatchUI.SINGLETON_INSTANCE.showMessage(msg); - ButtonUtil.enableOnlyOK(); - } - - @Override - public void selectButtonOK() { - this.stop(); - } - - @Override - public void selectCard(final Card card, final PlayerZone zone) { - if (choices.contains(card)) { - - if (AllZoneUtil.isCardInPlay(card)) { - c.enchantEntity(card); - this.stop(); - } - } - } // selectCard() - }); // Input() - - } // if we were able to match the - // selected aura with our list of - // criteria - } // If enchantment selected is an aura - } // If an enchantment is selected - } // If there are enchantments in library - - card.getController().shuffle(); - } // If answered yes to may exile - } // If player is human - - // player is the computer - else { - CardList list = AllZone.getComputerPlayer().getCardsIn(ZoneType.Library); - list = list.filter(new CardListFilter() { - @Override - public boolean addCard(final Card c) { - return c.isEnchantment() && !c.isAura(); - } - }); - - if (list.size() > 0) { - final Card c = CardFactoryUtil.getBestEnchantmentAI(list, this, false); - - Singletons.getModel().getGameAction().moveToPlay(c); - if (card.getName().equals("Academy Rector")) { - Singletons.getModel().getGameAction().exile(card); - } - card.getController().shuffle(); - } - } // player is the computer - } // resolve() - }; // ability - - final StringBuilder sb = new StringBuilder(); - if (card.getName().equals("Academy Rector")) { - sb.append("Academy Rector - ").append(card.getController()); - sb.append(" may exile this card and place an enchantment "); - sb.append("from his library onto the battlefield."); - } else { - sb.append("Lost Auramancers - ").append(card.getController()); - sb.append(" may place an enchantment from his library onto the battlefield."); - } - ability.setStackDescription(sb.toString()); - - final Command destroy = new Command() { - private static final long serialVersionUID = -4352349741511065318L; - - @Override - public void execute() { - - if (card.getName().equals("Lost Auramancers") && (card.getCounters(Counters.TIME) <= 0)) { - AllZone.getStack().addSimultaneousStackEntry(ability); - - } else if (card.getName().equals("Academy Rector")) { - AllZone.getStack().addSimultaneousStackEntry(ability); - - } - - } // execute() - }; // Command destroy - - card.addDestroyCommand(destroy); - }*/ - private static void getCard_KinsbaileBorderguard(final Card card, final String cardName) { final SpellAbility ability = new Ability(card, "0") { @Override From e5eb596307001ea845812fdcc735f74926c066c8 Mon Sep 17 00:00:00 2001 From: Sloth Date: Sat, 30 Jun 2012 21:24:08 +0000 Subject: [PATCH 7/8] - Added Silent-Blade Oni. --- .gitattributes | 1 + res/cardsfolder/s/silent_blade_oni.txt | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 res/cardsfolder/s/silent_blade_oni.txt diff --git a/.gitattributes b/.gitattributes index 30b75d8d3c9..683611a1dbe 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8312,6 +8312,7 @@ res/cardsfolder/s/silence.txt -text res/cardsfolder/s/silent_arbiter.txt svneol=native#text/plain res/cardsfolder/s/silent_assassin.txt -text res/cardsfolder/s/silent_attendant.txt svneol=native#text/plain +res/cardsfolder/s/silent_blade_oni.txt -text res/cardsfolder/s/silent_chant_zubera.txt svneol=native#text/plain res/cardsfolder/s/silent_departure.txt -text res/cardsfolder/s/silent_specter.txt svneol=native#text/plain diff --git a/res/cardsfolder/s/silent_blade_oni.txt b/res/cardsfolder/s/silent_blade_oni.txt new file mode 100644 index 00000000000..634374ba3bc --- /dev/null +++ b/res/cardsfolder/s/silent_blade_oni.txt @@ -0,0 +1,14 @@ +Name:Silent-Blade Oni +ManaCost:3 U U B B +Types:Creature Demon Ninja +Text:no text +PT:6/5 +A:AB$ ChangeZone | Cost$ 4 U B Return<1/Creature.attacking+unblocked> | CostDesc$ Ninjutsu 4 U B | ActivationZone$ Hand | Origin$ Hand | Ninjutsu$ True | Destination$ Battlefield | Defined$ Self | SpellDescription$ (4 U B, Return an unblocked attacker you control to hand: Put this card onto the battlefield from your hand tapped and attacking.) +T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigReveal | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, look at that player's hand. You may cast a nonland card in it without paying that card's mana cost. +SVar:TrigReveal:DB$ RevealHand | Defined$ TriggeredTarget | SubAbility$ TrigPlay +SVar:TrigPlay:DB$ Play | Valid$ Card.nonLand+YouDontCtrl | ValidZone$ Hand | WithoutManaCost$ True | Optional$ True +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/silent_blade_oni.jpg +SetInfo:PC2|Rare|http://magiccards.info/scans/en/pc2/105.jpg +Oracle:Ninjutsu {4}{U}{B} ({4}{U}{B}, Return an unblocked attacker you control to hand: Put this card onto the battlefield from your hand tapped and attacking.)\nWhenever Silent-Blade Oni deals combat damage to a player, look at that player's hand. You may cast a nonland card in it without paying that card's mana cost. +End \ No newline at end of file From a9865634c6a672e052d83bbe7804687d87e60c6c Mon Sep 17 00:00:00 2001 From: Sloth Date: Sat, 30 Jun 2012 21:29:33 +0000 Subject: [PATCH 8/8] - Added Felidar Umbra. --- .gitattributes | 1 + res/cardsfolder/f/felidar_umbra.txt | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 res/cardsfolder/f/felidar_umbra.txt diff --git a/.gitattributes b/.gitattributes index 683611a1dbe..3a2abbb7b7d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3073,6 +3073,7 @@ res/cardsfolder/f/feeding_frenzy.txt svneol=native#text/plain res/cardsfolder/f/feeling_of_dread.txt -text res/cardsfolder/f/feldons_cane.txt svneol=native#text/plain res/cardsfolder/f/felidar_sovereign.txt svneol=native#text/plain +res/cardsfolder/f/felidar_umbra.txt -text res/cardsfolder/f/fellwar_stone.txt svneol=native#text/plain res/cardsfolder/f/femeref_archers.txt svneol=native#text/plain res/cardsfolder/f/femeref_enchantress.txt svneol=native#text/plain diff --git a/res/cardsfolder/f/felidar_umbra.txt b/res/cardsfolder/f/felidar_umbra.txt new file mode 100644 index 00000000000..3fd38e6f91a --- /dev/null +++ b/res/cardsfolder/f/felidar_umbra.txt @@ -0,0 +1,14 @@ +Name:Felidar Umbra +ManaCost:1 W +Types:Enchantment Aura +Text:no text +K:Enchant creature +K:Totem armor +A:SP$ Attach | Cost$ 1 W | ValidTgts$ Creature | AILogic$ Pump +S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddKeyword$ Lifelink | Description$ Enchanted creature has lifelink. +A:AB$ Attach | Cost$ 1 W | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | SpellDescription$ Attach CARDNAME to target creature you control. +SVar:Rarity:Uncommon +SVar:Picture:http://www.wizards.com/global/images/magic/general/felidar_umbra.jpg +SetInfo:PC2|Uncommon|http://magiccards.info/scans/en/pc2/6.jpg +Oracle:Enchant creature\nEnchanted creature has lifelink.\n{1}{W}: Attach Felidar Umbra to target creature you control.\nTotem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) +End \ No newline at end of file