diff --git a/res/card-pictures.txt b/res/card-pictures.txt index 6b9bff37229..5a998538c1a 100644 --- a/res/card-pictures.txt +++ b/res/card-pictures.txt @@ -18,6 +18,8 @@ forest.jpg http://resources.wizards.com/magic/cards/unh/en-us/card73946.jpg forest1.jpg http://gatherer.wizards.com/handlers/image.ashx?type=card&multiverseid=2748 forest2.jpg http://gatherer.wizards.com/handlers/image.ashx?type=card&multiverseid=587 forest3.jpg http://gatherer.wizards.com/handlers/image.ashx?type=card&multiverseid=586 +phytohydra.jpg http://www.wizards.com/global/images/magic/general/phytohyrda.jpg +lichentrope.jpg http://www.wizards.com/global/images/magic/general/lichentrope.jpg feast_of_flesh.jpg http://www.wizards.com/global/images/magic/general/feast_of_flesh.jpg first_volley.jpg http://www.wizards.com/global/images/magic/general/first_volley.jpg svogthos_the_restless_tomb.jpg http://www.wizards.com/global/images/magic/general/svogthos_the_restless_tomb.jpg diff --git a/res/cards.txt b/res/cards.txt index 0d0be164424..f3c16333654 100644 --- a/res/cards.txt +++ b/res/cards.txt @@ -1,3 +1,21 @@ +Phytohydra +2 W W G +Creature Plant Hydra +If damage would be dealt to Phytohydra, put that many +1/+1 counters on it instead. +1/1 + +Callous Giant +4 R R +Creature Giant +If a source would deal 3 or less damage to Callous Giant, prevent that damage. +4/4 + +Lichentrope +3 G G +Creature Plant Fungus +If damage would be dealt to Lichenthrope, put that many -1/-1 counters on it instead. At the beginning of your upkeep, remove a -1/-1 counter from Lichenthrope +5/5 + Feast of Flesh B Sorcery @@ -374,7 +392,7 @@ TypeCycling:Basic:1 R Absorb Vis 6 B Sorcery -Target player loses 4 life and you gain 4 life. +no text spLoseLifeGainLife:4 TypeCycling:Basic:1 B @@ -628,31 +646,31 @@ Shroud Emberstrike Duo 1 BR Creature Elemental Warrior Shaman -Whenever you cast a black spell, Emberstrike Duo gets +1/+1 until end of turn. Whenever you cast a red spell, Emberstrike Duo gains first strike until end of turn. +Whenever you cast a black spell, Emberstrike Duo gets +1/+1 until end of turn. Whenever you cast a red spell, Emberstrike Duo gains first strike until end of turn. 1/1 Gravelgill Duo 2 UB Creature Merfolk Rogue Warrior -Whenever you cast a blue spell, Gravelgill Duo gets +1/+1 until end of turn. Whenever you cast a black spell, Gravelgill Duo gains fear until end of turn. (It can't be blocked except by artifact creatures and/or black creatures.) +Whenever you cast a blue spell, Gravelgill Duo gets +1/+1 until end of turn. Whenever you cast a black spell, Gravelgill Duo gains fear until end of turn. (It can't be blocked except by artifact creatures and/or black creatures.) 2/1 Safehold Duo 3 GW Creature Elf Warrior Shaman -Whenever you cast a green spell, Safehold Duo gets +1/+1 until end of turn. Whenever you cast a white spell, Safehold Duo gains vigilance until end of turn. +Whenever you cast a green spell, Safehold Duo gets +1/+1 until end of turn. Whenever you cast a white spell, Safehold Duo gains vigilance until end of turn. 2/4 Tattermunge Duo 2 RG Creature Goblin Warrior Shaman -Whenever you cast a red spell, Tattermunge Duo gets +1/+1 until end of turn. Whenever you cast a green spell, Tattermunge Duo gains forestwalk until end of turn. +Whenever you cast a red spell, Tattermunge Duo gets +1/+1 until end of turn. Whenever you cast a green spell, Tattermunge Duo gains forestwalk until end of turn. 2/3 Thistledown Duo 2 WU Creature Kithkin Soldier Wizard -Whenever you cast a white spell, Thistledown Duo gets +1/+1 until end of turn. Whenever you cast a blue spell, Thistledown Duo gains flying until end of turn. +Whenever you cast a white spell, Thistledown Duo gets +1/+1 until end of turn. Whenever you cast a blue spell, Thistledown Duo gains flying until end of turn. 2/2 Phantom Centaur @@ -692,44 +710,44 @@ As Meddling Mage enters the battlefield, name a nonland card. The named card can Shorecrasher Mimic 1 GU Creature Shapeshifter -Whenever you cast a spell that's both green and blue, Shorecrasher Mimic becomes 5/3 and gains trample until end of turn. +Whenever you cast a spell that�s both green and blue, Shorecrasher Mimic becomes 5/3 and gains trample until end of turn. 2/1 Woodlurker Mimic 1 BG Creature Shapeshifter -Whenever you cast a spell that's both black and green, Woodlurker Mimic becomes 4/5 and gains wither until end of turn. (It deals damage to creatures in the form of -1/-1 counters.) +Whenever you cast a spell that�s both black and green, Woodlurker Mimic becomes 4/5 and gains wither until end of turn. (It deals damage to creatures in the form of -1/-1 counters.) 2/1 Battlegate Mimic 1 RW Creature Shapeshifter -Whenever you cast a spell that's both red and white, Battlegate Mimic becomes 4/2 and gains first strike until end of turn. +Whenever you cast a spell that�s both red and white, Battlegate Mimic becomes 4/2 and gains first strike until end of turn. 2/1 Nightsky Mimic 1 WB Creature Shapeshifter -Whenever you cast a spell that's both white and black, Nightsky Mimic becomes 4/4 and gains flying until end of turn. +Whenever you cast a spell that�s both white and black, Nightsky Mimic becomes 4/4 and gains flying until end of turn. 2/1 Riverfall Mimic 1 UR Creature Shapeshifter -Whenever you cast a spell that's both blue and red, Riverfall Mimic becomes 3/3 and is unblockable until end of turn. +Whenever you cast a spell that�s both blue and red, Riverfall Mimic becomes 3/3 and is unblockable until end of turn. 2/1 Sapling of Colfenor 3 BG BG Legendary Creature Treefolk Shaman -Whenever Sapling of Colfenor attacks, reveal the top card of your library. If it's a creature card, you gain life equal to that card's toughness, lose life equal to its power, then put it into your hand. +Whenever Sapling of Colfenor attacks, reveal the top card of your library. If it�s a creature card, you gain life equal to that card�s toughness, lose life equal to its power, then put it into your hand. 2/5 Indestructible Dovescape 3 WU WU WU Enchantment -Whenever a player casts a noncreature spell, counter that spell. That player puts X 1/1 white and blue Bird creature tokens with flying onto the battlefield, where X is the spell's converted mana cost. +Whenever a player casts a noncreature spell, counter that spell. That player puts X 1/1 white and blue Bird creature tokens with flying onto the battlefield, where X is the spell�s converted mana cost. Lurking Informant 1 UB @@ -740,28 +758,28 @@ no text Belligerent Hatchling 3 RW Creature Elemental -Belligerent Hatchling enters the battlefield with four -1/-1 counters on it. Whenever you cast a red spell, remove a -1/-1 counter from Belligerent Hatchling. Whenever you cast a white spell, remove a -1/-1 counter from Belligerent Hatchling. +Belligerent Hatchling enters the battlefield with four -1/-1 counters on it. Whenever you cast a red spell, remove a -1/-1 counter from Belligerent Hatchling. Whenever you cast a white spell, remove a -1/-1 counter from Belligerent Hatchling. 6/6 First Strike Noxious Hatchling 3 BG Creature Elemental -Noxious Hatchling enters the battlefield with four -1/-1 counters on it. Whenever you cast a black spell, remove a -1/-1 counter from Noxious Hatchling. Whenever you cast a green spell, remove a -1/-1 counter from Noxious Hatchling. +Noxious Hatchling enters the battlefield with four -1/-1 counters on it. Whenever you cast a black spell, remove a -1/-1 counter from Noxious Hatchling. Whenever you cast a green spell, remove a -1/-1 counter from Noxious Hatchling. 6/6 Wither Sturdy Hatchling 3 GU Creature Elemental -Sturdy Hatchling enters the battlefield with four -1/-1 counters on it. Whenever you cast a green spell, remove a -1/-1 counter from Sturdy Hatchling. Whenever you cast a blue spell, remove a -1/-1 counter from Sturdy Hatchling. +Sturdy Hatchling enters the battlefield with four -1/-1 counters on it. Whenever you cast a green spell, remove a -1/-1 counter from Sturdy Hatchling. Whenever you cast a blue spell, remove a -1/-1 counter from Sturdy Hatchling. 6/6 KPump GU:Shroud Voracious Hatchling 3 WB Creature Elemental -Voracious Hatchling enters the battlefield with four -1/-1 counters on it. Whenever you cast a white spell, remove a -1/-1 counter from Voracious Hatchling. Whenever you cast a black spell, remove a -1/-1 counter from Voracious Hatchling. +Voracious Hatchling enters the battlefield with four -1/-1 counters on it. Whenever you cast a white spell, remove a -1/-1 counter from Voracious Hatchling. Whenever you cast a black spell, remove a -1/-1 counter from Voracious Hatchling. 6/6 Lifelink @@ -837,12 +855,12 @@ Exile all cards from target player's hand and graveyard. Lobotomy 2 U B Sorcery -Target player reveals his or her hand, then you choose a card other than a basic land card from it. Search that player's graveyard, hand, and library for all cards with the same name as the chosen card and remove them from the game. Then that player shuffles his or her library. +Target player reveals his or her hand, then you choose a card other than a basic land card from it. Search that player's graveyard, hand, and library for all cards with the same name as the chosen card and remove them from the game. Then that player shuffles his or her library. Haunting Echoes 3 B B Sorcery -Remove all cards in target player's graveyard other than basic land cards from the game. Search that player's library for all cards with the same name as cards removed this way, and remove them from the game. Then that player shuffles his or her library. +Remove all cards in target player's graveyard other than basic land cards from the game. Search that player's library for all cards with the same name as cards removed this way, and remove them from the game. Then that player shuffles his or her library. Daru Encampment no cost @@ -898,7 +916,7 @@ no text Wood Elves 2 G Creature Elf Scout -When Wood Elves comes into play, search your library for a Forest card and put that card into play. Then shuffle your library. +When Wood Elves comes into play, search your library for a Forest card and put that card into play. Then shuffle your library. 1/1 Assembly-Worker @@ -12609,7 +12627,7 @@ You gain 10 life. Then if you have more life than an opponent, put a 5/5 white G Reach of Branches 4 G Tribal Instant Treefolk -Put a 2/5 green Treefolk Shaman creature token into play. Whenever a Forest comes into play under your control, you may return Reach of Branches from your graveyard to your hand. +Put a 2/5 green Treefolk Shaman creature token into play. Whenever a Forest comes into play under your control, you may return Reach of Branches from your graveyard to your hand. Meadowboon 2 W W @@ -12751,7 +12769,7 @@ Sorcery Each player shuffles his or her hand and graveyard into his or her library and then draws seven cards. Inner-Flame Acolyte -1 R R +1 R R Creature Elemental Shaman When Inner-Flame Acolyte comes into play, target creature gets +2/+0 and gains haste until end of turn. 2/2 @@ -12764,7 +12782,7 @@ When Briarhorn comes into play, target creature gets +3/+3 until end of turn. Flash Shriekmaw -4 B +4 B Creature Elemental When Shriekmaw comes into play, destroy target nonartifact, nonblack creature. 3/2 @@ -12864,7 +12882,7 @@ Garruk Wildspeaker Planeswalker - Garruk no text -Liliana Vess +Liliana Vess 3 B B Planeswalker - Liliana no text @@ -13114,7 +13132,7 @@ no text Take Possession 5 U U Sorcery -Gain control of target permanent. (NOTE: "Split second" not implemented. This spell is currently treated as a Sorcery rather than as an Enchantment.) +Gain control of target permanent. (NOTE: "Split second" not implemented. This spell is currently treated as a Sorcery rather than as an Enchantment.) Cloudseeder 1 U @@ -13123,7 +13141,7 @@ no text 1/1 Flying -Goldmeadow Lookout +Goldmeadow Lookout 3 W Creature Kithkin Spellshaper no text @@ -13159,7 +13177,7 @@ Indestructible Animate Dead 1 B Sorcery -Put target creature card from any graveyard into play under your control. That creature gets -1/-0. (NOTE: This spell is currently treated as a Sorcery rather than as an Enchantment.) +Put target creature card from any graveyard into play under your control. That creature gets -1/-0. (NOTE: This spell is currently treated as a Sorcery rather than as an Enchantment.) Ashes to Ashes 1 B B @@ -13532,7 +13550,7 @@ no text Erratic Explosion 2 R Sorcery -Choose target creature or player. The computer will randomly choose a nonland card from your library. Erratic Explosion deals damage equal to that card's converted mana cost to that creature or player. +Choose target creature or player. The computer will randomly choose a nonland card from your library. Erratic Explosion deals damage equal to that card's converted mana cost to that creature or player. Tribal Flames 1 R @@ -13818,7 +13836,7 @@ All creatures get -2/-2 until end of turn. Do or Die 1 B Sorcery -Randomly destroy half of the creatures target player controls. They can't be regenerated. +Randomly destroy half of the creatures target player controls. They can't be regenerated. Cao Cao, Lord of Wei 3 B B @@ -14062,7 +14080,7 @@ Until end of turn, target land is 3/3 creature that's still a land. Kodama's Reach 2 G -Sorcery +Sorcery Search your library for two basic land cards, reveal those cards, and put one into play tapped and the other into your hand. Then shuffle your library. Wandering Stream @@ -14811,70 +14829,70 @@ PTPump B:+1/+1 Blood Crypt no cost Land Swamp Mountain -As Blood Crypt comes into play, you may pay 2 life. If you don't, Blood Crypt comes into play tapped instead. +As Blood Crypt comes into play, you may pay 2 life. If you don't, Blood Crypt comes into play tapped instead. tap: add B tap: add R Breeding Pool no cost Land Forest Island -As Breeding Pool into play, you may pay 2 life. If you don't, Breeding Pool comes into play tapped instead. +As Breeding Pool into play, you may pay 2 life. If you don't, Breeding Pool comes into play tapped instead. tap: add G tap: add U Godless Shrine no cost Land Plains Swamp -As Godless Shrine comes into play, you may pay 2 life. If you don't, Godless Shrine comes into play tapped instead. +As Godless Shrine comes into play, you may pay 2 life. If you don't, Godless Shrine comes into play tapped instead. tap: add W tap: add B Hallowed Fountain no cost Land Plains Island -As Hallowed Fountain comes into play, you may pay 2 life. If you don't, Hallowed Fountain comes into play tapped instead. +As Hallowed Fountain comes into play, you may pay 2 life. If you don't, Hallowed Fountain comes into play tapped instead. tap: add W tap: add U Overgrown Tomb no cost Land Swamp Forest -As Overgrown Tomb comes into play, you may pay 2 life. If you don't, Overgrown Tomb comes into play tapped instead. +As Overgrown Tomb comes into play, you may pay 2 life. If you don't, Overgrown Tomb comes into play tapped instead. tap: add B tap: add G Sacred Foundry no cost Land Mountain Plains -As Sacred Foundry comes into play, you may pay 2 life. If you don't, Sacred Foundry comes into play tapped instead. +As Sacred Foundry comes into play, you may pay 2 life. If you don't, Sacred Foundry comes into play tapped instead. tap: add R tap: add W Steam Vents no cost Land Island Mountain -As Steam Vents comes into play, you may pay 2 life. If you don't, Steam Vents comes into play tapped instead. +As Steam Vents comes into play, you may pay 2 life. If you don't, Steam Vents comes into play tapped instead. tap: add U tap: add R Stomping Ground no cost Land Mountain Forest -As Stomping Ground comes into play, you may pay 2 life. If you don't, Stomping Ground comes into play tapped instead. +As Stomping Ground comes into play, you may pay 2 life. If you don't, Stomping Ground comes into play tapped instead. tap: add R tap: add G Temple Garden no cost Land Forest Plains -As Temple Garden comes into play, you may pay 2 life. If you don't, Temple Garden comes into play tapped instead. +As Temple Garden comes into play, you may pay 2 life. If you don't, Temple Garden comes into play tapped instead. tap: add G tap: add W Watery Grave no cost Land Island Swamp -As Watery Grave comes into play, you may pay 2 life. If you don't, Watery Grave comes into play tapped instead. +As Watery Grave comes into play, you may pay 2 life. If you don't, Watery Grave comes into play tapped instead. tap: add U tap: add B diff --git a/res/main.properties b/res/main.properties index 09df9160df1..0229d954ec3 100644 --- a/res/main.properties +++ b/res/main.properties @@ -1,6 +1,6 @@ program/mail=mtgerror@yahoo.com program/forum=http://www.slightlymagic.net/forum/viewforum.php?f=26 -program/version=Forge -- official beta: 09/11/25, SVN revision: 142 +program/version=Forge -- official beta: 09/11/25, SVN revision: 181 tokens--file=AllTokens.txt diff --git a/src/forge/Ability_Hand.java b/src/forge/Ability_Hand.java index 5d72b25f378..78ff0c011d5 100644 --- a/src/forge/Ability_Hand.java +++ b/src/forge/Ability_Hand.java @@ -2,11 +2,8 @@ package forge; //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; - + + private static final long serialVersionUID = 7782525158887272529L; public Ability_Hand(Card sourceCard) { this(sourceCard, ""); diff --git a/src/forge/Card.java b/src/forge/Card.java index 750db934bb7..060a84e5a81 100644 --- a/src/forge/Card.java +++ b/src/forge/Card.java @@ -5,6 +5,7 @@ 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; @@ -485,17 +486,27 @@ public class Card extends MyObservable public String getRarity() {return rarity;} - public void addDamage(int n, CardList sources) + public void addDamage(HashMap sourcesMap) { - for(Card source : sources) - this.addDamage(n, source); + Iterator iter = sourcesMap.keySet().iterator(); + while(iter.hasNext()) { + Card source = iter.next(); + int damage = sourcesMap.get(source); + + this.addDamage(damage, source); + } + //for(Card source : sources) + // this.addDamage(n, source); + } public void addDamage(int n, Card source) { + System.out.println("addDamage called on " + this + " for " + n + " damage."); if (this.getName().equals("Cho-Manno, Revolutionary")) n = 0; - setDamage(getDamage() + n); + //setDamage(getDamage() + n); + damage += n; } public void setDamage(int n) { diff --git a/src/forge/CardFactory.java b/src/forge/CardFactory.java index f2d36856676..3ee3c68806e 100644 --- a/src/forge/CardFactory.java +++ b/src/forge/CardFactory.java @@ -17217,10 +17217,12 @@ return land.size() > 1 && CardFactoryUtil.AI_isMainPhase(); return c.isCreature() && !c.getKeyword().contains("Horsemanship") && !c.getKeyword().contains("Defender"); } }); - - Card c = CardFactoryUtil.AI_getBestCreature(list, card); - setTargetCard(c); - return list.size() > 0; + if (list.size() > 0) { + Card c = CardFactoryUtil.AI_getBestCreature(list, card); + setTargetCard(c); + return true; + } + return false; } public void resolve() diff --git a/src/forge/CardFactory_Creatures.java b/src/forge/CardFactory_Creatures.java index f51ba8e4518..2eeb46fa1f1 100644 --- a/src/forge/CardFactory_Creatures.java +++ b/src/forge/CardFactory_Creatures.java @@ -18358,7 +18358,7 @@ public class CardFactory_Creatures { { final Card newCard = new Card() { - public void addDamage(final int n, CardList sources) + public void addDamage(HashMap map) { final Ability ability = new Ability(card, "0") { @@ -18458,6 +18458,110 @@ public class CardFactory_Creatures { card.addComesIntoPlayCommand(intoPlay); }//*************** END ************ END ************************** + //*************** START *********** START ************************** + else if (cardName.equals("Lichentrope")) + { + final Card newCard = new Card() + { + public void addDamage(final int n, final Card source) + { + final Ability ability = new Ability(card, "0") + { + public void resolve(){ + for (int i=0;i a = c.getKeyword(); + for (int i = 0; i < a.size(); i++) + if (a.get(i).toString().startsWith(k)) + return i; + + return -1; + } + public static Card getCard(final Card card, String cardName, String owner) { - + // computer plays 2 land of these type instead of just 1 per turn @@ -2933,6 +2947,54 @@ class CardFactory_Lands { }; a1.setBeforePayMana(new Input_PayManaCost_Ability(a1.getManaCost(), paid1)); }//*************** END ************ END ************************** + + + if (hasKeyword(card, "Cycling") != -1) + { + int n = hasKeyword(card, "Cycling"); + 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 + + while (hasKeyword(card, "TypeCycling") != -1) + { + int n = hasKeyword(card, "TypeCycling"); + if (n != -1) + { + String parse = card.getKeyword().get(n).toString(); + card.removeIntrinsicKeyword(parse); + + String k[] = parse.split(":"); + final String type = k[1]; + final String manacost = k[2]; + + card.addSpellAbility(CardFactoryUtil.ability_typecycle(card, manacost,type)); + } + }//TypeCycling + + if (hasKeyword(card, "Transmute") != -1) + { + int n = hasKeyword(card, "Transmute"); + 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_transmute(card, manacost)); + } + }//transmute + return card; diff --git a/src/forge/Combat.java b/src/forge/Combat.java index 274ba95cb80..0d40731a7f5 100644 --- a/src/forge/Combat.java +++ b/src/forge/Combat.java @@ -223,7 +223,7 @@ public class Combat CardList attacking = new CardList(getAttackers()); for(int i = 0; i < attacking.size(); i++) { - if(attacking.get(i).hasFirstStrike() || (attacking.get(i).hasDoubleStrike() )){ + //if(attacking.get(i).hasFirstStrike() || (attacking.get(i).hasDoubleStrike() )){ block = getBlockers(attacking.get(i)); //attacker always gets all blockers' attack @@ -245,56 +245,61 @@ public class Combat //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(); - - CardList cl = new CardList(); - cl.add(attacking.get(i)); - - AllZone.GameAction.addAssignedDamage(block.get(0), attacking.get(i), damageDealt); - - - //trample - int trample = damageDealt - block.get(0).getNetDefense(); - if(attacking.get(i).getKeyword().contains("Trample") && 0 < trample) - { - this.addDefendingFirstStrikeDamage(trample, attacking.get(i)); - //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(); - addAssignedFirstStrikeDamage(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); - - /* - for (Card b : block) - { - AllZone.Display.assignDamage(attacking.get(i), b, damageDealt); - //System.out.println("setAssignedFirstStrikeDmg called for:" + damageDealt + " damage."); - } - AllZone.Display.addAssignDamage(attacking.get(i),damageDealt); - */ - } - }//if(hasFirstStrike || doubleStrike) + + else if(attacking.get(i).hasFirstStrike() || (attacking.get(i).hasDoubleStrike() )){ + + 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(); + + CardList cl = new CardList(); + cl.add(attacking.get(i)); + + AllZone.GameAction.addAssignedDamage(block.get(0), attacking.get(i), damageDealt); + + + //trample + int trample = damageDealt - block.get(0).getNetDefense(); + if(attacking.get(i).getKeyword().contains("Trample") && 0 < trample) + { + this.addDefendingFirstStrikeDamage(trample, attacking.get(i)); + //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(); + addAssignedFirstStrikeDamage(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); + + /* + for (Card b : block) + { + AllZone.Display.assignDamage(attacking.get(i), b, damageDealt); + //System.out.println("setAssignedFirstStrikeDmg called for:" + damageDealt + " damage."); + } + AllZone.Display.addAssignDamage(attacking.get(i),damageDealt); + */ + } + } + + }//if(hasFirstStrike || doubleStrike) }//for //should first strike affect the following? @@ -312,7 +317,6 @@ public class Combat defendingFirstStrikeDamageMap.clear(); } - } }//setAssignedFirstStrikeDamage() private void addAssignedFirstStrikeDamage (Card attacker, CardList block, int damage) @@ -320,16 +324,24 @@ public class Combat Card c = attacker; for (Card b:block) { - if(c.getKillDamage() <= damage) + if(b.getKillDamage() <= damage) { - damage -= c.getKillDamage(); + damage -= b.getKillDamage(); CardList cl = new CardList(); cl.add(attacker); - AllZone.GameAction.addAssignedDamage(b, c, c.getKillDamage()); + AllZone.GameAction.addAssignedDamage(b, c, b.getKillDamage()); //c.setAssignedDamage(c.getKillDamage()); } }//for + + //if attacker has no trample, and there's damage left, assign the rest to a random blocker + if (damage > 0) + { + int index = CardUtil.getRandomIndex(block); + AllZone.GameAction.addAssignedDamage(block.get(index), c, damage); + damage = 0; + } }//setAssignedFirstStrikeDamage() @@ -343,8 +355,8 @@ public class Combat CardList attacking = new CardList(getAttackers()); for(int i = 0; i < attacking.size(); i++) { - //if(!attacking.get(i).hasSecondStrike() ){ - if(!attacking.get(i).hasFirstStrike() || (attacking.get(i).hasFirstStrike() && attacking.get(i).hasDoubleStrike() )){ + //if(!attacking.get(i).hasSecondStrike() ){ + //if(!attacking.get(i).hasFirstStrike() || (attacking.get(i).hasFirstStrike() && attacking.get(i).hasDoubleStrike() )){ block = getBlockers(attacking.get(i)); //attacker always gets all blockers' attack @@ -353,10 +365,12 @@ public class Combat for (Card b : block) { - int attack = b.getNetAttack(); - if (CombatUtil.isDoranInPlay()) - attack = b.getNetDefense(); - AllZone.GameAction.addAssignedDamage(attacking.get(i), b, attack ); + if(!b.hasFirstStrike() || (b.hasFirstStrike() && b.hasDoubleStrike() )){ + int attack = b.getNetAttack(); + if (CombatUtil.isDoranInPlay()) + attack = b.getNetDefense(); + AllZone.GameAction.addAssignedDamage(attacking.get(i), b, attack ); + } } if(block.size() == 0)//this damage is assigned to a player by setPlayerDamage() @@ -364,49 +378,54 @@ public class Combat //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(); - - AllZone.GameAction.addAssignedDamage(block.get(0), attacking.get(i), damageDealt); - - //trample - int trample = damageDealt - block.get(0).getNetDefense(); - if(attacking.get(i).getKeyword().contains("Trample") && 0 < trample) - { - this.addDefendingDamage(trample, attacking.get(i)); - } - }//1 blocker - else if(getAttackingPlayer().equals(Constant.Player.Computer)) - { - int damageDealt = attacking.get(i).getNetAttack(); - if (CombatUtil.isDoranInPlay()) - damageDealt = attacking.get(i).getNetDefense(); - addAssignedDamage(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); - - /* - * - * - for (Card b :block) - AllZone.Display.addAssignDamage(attacking.get(i), b, damageDealt); - //System.out.println("setAssignedDmg called for:" + damageDealt + " damage."); - * - */ - } - }//if !hasFirstStrike ... + + else if(!attacking.get(i).hasFirstStrike() || (attacking.get(i).hasFirstStrike() && attacking.get(i).hasDoubleStrike() )){ + + if(block.size() == 1) + { + int damageDealt = attacking.get(i).getNetAttack(); + if (CombatUtil.isDoranInPlay()) + damageDealt = attacking.get(i).getNetDefense(); + + AllZone.GameAction.addAssignedDamage(block.get(0), attacking.get(i), damageDealt); + + //trample + int trample = damageDealt - block.get(0).getNetDefense(); + if(attacking.get(i).getKeyword().contains("Trample") && 0 < trample) + { + this.addDefendingDamage(trample, attacking.get(i)); + } + }//1 blocker + else if(getAttackingPlayer().equals(Constant.Player.Computer)) + { + int damageDealt = attacking.get(i).getNetAttack(); + if (CombatUtil.isDoranInPlay()) + damageDealt = attacking.get(i).getNetDefense(); + addAssignedDamage(attacking.get(i),block , damageDealt); + + } + else//human attacks + { + //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); + + /* + * + * + for (Card b :block) + AllZone.Display.addAssignDamage(attacking.get(i), b, 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()); @@ -424,6 +443,7 @@ public class Combat //AllZone.GameAction.setAssignedDamage(attacking.get(i), block , blockerDamage); } } + */ }//for //should first strike affect the following? @@ -465,16 +485,24 @@ public class Combat { Card c = attacker; for (Card b:block) { - if(c.getKillDamage() <= damage) + if(b.getKillDamage() <= damage) { - damage -= c.getKillDamage(); + damage -= b.getKillDamage(); CardList cl = new CardList(); cl.add(attacker); - AllZone.GameAction.addAssignedDamage(b, c, c.getKillDamage()); + AllZone.GameAction.addAssignedDamage(b, c, b.getKillDamage()); //c.setAssignedDamage(c.getKillDamage()); } }//for + + //if attacker has no trample, and there's damage left, assign the rest to a random blocker + if (damage > 0 && !c.getKeyword().contains("Trample")) + { + int index = CardUtil.getRandomIndex(block); + AllZone.GameAction.addAssignedDamage(block.get(index), c, damage); + damage = 0; + } }//setAssignedDamage() public Card[] getUnblockedAttackers() diff --git a/src/forge/GameAction.java b/src/forge/GameAction.java index babb5e396b2..4333cb19812 100644 --- a/src/forge/GameAction.java +++ b/src/forge/GameAction.java @@ -1139,31 +1139,72 @@ private int getDifferentLand(CardList list, String land) } public void playCard(Card c) { - - //TODO: add code for cards like Standstill ?? + if (c.isLand() && isCardInZone(c, AllZone.Human_Hand)) + { + HashMap map = new HashMap(); + SpellAbility[] sas = canPlaySpellAbility(c.getSpellAbility()); + + ArrayList choices = new ArrayList(); + + if (Input_Main.canPlayNumberOfLands > 0) + choices.add("Play land"); + + for (SpellAbility sa: sas) + { + if (sa.canPlay()) + { + choices.add(sa.toString()); + map.put(sa.toString(), sa); + } + } + + //String[] ch = (String[])choices.toArray(); + String[] ch = new String[choices.size()]; + for (int i=0;i map) { - int totalDamage = 0; + //int totalDamage = 0; CardList list = new CardList(); Iterator iter = map.keySet().iterator(); @@ -1305,11 +1346,12 @@ private int getDifferentLand(CardList list, String land) AllZone.Combat.removeFromCombat(card); } - totalDamage += damageToAdd; + //totalDamage += damageToAdd; + map.put(source, damageToAdd); } if (isCardInPlay(card)) - card.addDamage(totalDamage, list); + card.addDamage(map); } diff --git a/src/forge/GameActionUtil.java b/src/forge/GameActionUtil.java index 0e630467cbf..879f4c69159 100644 --- a/src/forge/GameActionUtil.java +++ b/src/forge/GameActionUtil.java @@ -21,6 +21,7 @@ public class GameActionUtil upkeep_Squee(); upkeep_Sporesower_Thallid(); upkeep_Scute_Mob(); + upkeep_Lichentrope(); upkeep_Heartmender(); upkeep_AEther_Vial(); upkeep_Ratcatcher(); @@ -4290,6 +4291,38 @@ public class GameActionUtil } // if creatures > 0 } + private static void upkeep_Lichentrope() + { + final String player = AllZone.Phase.getActivePlayer(); + PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player); + + CardList list = new CardList(playZone.getCards()); + list = list.getName("LichenTrope"); + + final CardList cl = list; + + if (list.size() > 0) + { + for (int i = 0; i < list.size(); i++) + { + + final int j = i; + Ability ability = new Ability(list.get(i), "0") + { + public void resolve() + { + Card c = cl.get(j); + c.subtractCounter(Counters.M1M1, 1); + } + + };// Ability + ability.setStackDescription("Lichentrope - Remove a -1/-1 counter."); + AllZone.Stack.add(ability); + } // for + } // if creatures > 0 + }//Lichentrope + + private static void upkeep_Heartmender() { final String player = AllZone.Phase.getActivePlayer(); diff --git a/src/forge/InputUtil.java b/src/forge/InputUtil.java index 60701ea6135..e69ed79c78c 100644 --- a/src/forge/InputUtil.java +++ b/src/forge/InputUtil.java @@ -16,9 +16,35 @@ public class InputUtil if(zone.is(Constant.Zone.Hand, Constant.Player.Human) && (card.isLand())) { - AllZone.Human_Hand.remove(card); - AllZone.Human_Play.add(card); - } + + //hacky stuff: see if there's cycling/transmute/other hand abilities on the land: + SpellAbility[] sa = card.getSpellAbility(); + if (sa.length > 0) + { + int count = 0; + for (SpellAbility s : sa) + { + if (s.canPlay() && (s instanceof Ability_Hand)) + count++; + } + if (count > 0) + AllZone.GameAction.playCard(card); + else //play the land + { + AllZone.Human_Hand.remove(card); + AllZone.Human_Play.add(card); + Input_Main.canPlayNumberOfLands--; + Input_Main.firstLandHasBeenPlayed = true; + } + } + else //play the land + { + AllZone.Human_Hand.remove(card); + AllZone.Human_Play.add(card); + Input_Main.canPlayNumberOfLands--; + Input_Main.firstLandHasBeenPlayed = true; + } + } //land else if(zone.is(Constant.Zone.Hand, Constant.Player.Human) && card.getManaCost().equals("0"))//for Mox Ruby and the like { diff --git a/src/forge/Input_Main.java b/src/forge/Input_Main.java index 17dff605a47..141d14e8f88 100644 --- a/src/forge/Input_Main.java +++ b/src/forge/Input_Main.java @@ -43,11 +43,26 @@ public class Input_Main extends Input } } InputUtil.playAnyCard(card, zone); - canPlayNumberOfLands--; - firstLandHasBeenPlayed = true; + //canPlayNumberOfLands--; + //firstLandHasBeenPlayed = true; AllZone.GameAction.checkStateEffects(); } - + + //card might have cycling/transmute/etc. + else { + SpellAbility[] sa = card.getSpellAbility(); + if (sa.length > 0) + { + int count = 0; + for (SpellAbility s : sa) + { + if (s.canPlay() && (s instanceof Ability_Hand)) + count++; + } + if (count > 0) + InputUtil.playAnyCard(card, zone); + } + } //TODO: add code for exploration / fastbond here }