- updates and fixes to damage prevention.

- Added the keyword Absorb.
- More AI improvements to handle damage prevention.
- Added Lymph Sliver.
This commit is contained in:
jendave
2011-08-06 11:11:39 +00:00
parent c2672ca4d0
commit e173f949e6
7 changed files with 101 additions and 88 deletions

1
.gitattributes vendored
View File

@@ -2761,6 +2761,7 @@ res/cardsfolder/lure.txt -text svneol=native#text/plain
res/cardsfolder/lurking_informant.txt -text svneol=native#text/plain res/cardsfolder/lurking_informant.txt -text svneol=native#text/plain
res/cardsfolder/lurking_nightstalker.txt -text svneol=native#text/plain res/cardsfolder/lurking_nightstalker.txt -text svneol=native#text/plain
res/cardsfolder/lux_cannon.txt -text svneol=native#text/plain res/cardsfolder/lux_cannon.txt -text svneol=native#text/plain
res/cardsfolder/lymph_sliver.txt -text svneol=native#text/plain
res/cardsfolder/lynx.txt -text svneol=native#text/plain res/cardsfolder/lynx.txt -text svneol=native#text/plain
res/cardsfolder/lys_alana_huntmaster.txt -text svneol=native#text/plain res/cardsfolder/lys_alana_huntmaster.txt -text svneol=native#text/plain
res/cardsfolder/ma_chao_western_warrior.txt -text svneol=native#text/plain res/cardsfolder/ma_chao_western_warrior.txt -text svneol=native#text/plain

View File

@@ -0,0 +1,9 @@
Name:Lymph Sliver
ManaCost:4 W
Types:Creature Sliver
Text:no text
PT:3/3
K:stPumpAll:Creature.Sliver:0/0/Absorb 1:no Condition:All Sliver creatures have absorb 1. (If a source would deal damage to a Sliver, prevent 1 of that damage.)
SVar:Rarity:Common
SVar:Picture:http://www.wizards.com/global/images/magic/general/lymph_sliver.jpg
End

View File

@@ -175,9 +175,10 @@ import java.util.Random;
} }
private boolean shouldTgtP(int d, final boolean noPrevention) { private boolean shouldTgtP(int d, final boolean noPrevention) {
int restDamage = d;
if (AllZone.HumanPlayer.preventAllDamageToPlayer(AF.getHostCard(), false) if (!noPrevention)
|| !AllZone.HumanPlayer.canTarget(AF.getHostCard())) return false; restDamage = AllZone.HumanPlayer.staticDamagePrevention(restDamage,AF.getHostCard(),false);
PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, AllZone.ComputerPlayer); PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, AllZone.ComputerPlayer);
CardList hand = new CardList(compHand.getCards()); CardList hand = new CardList(compHand.getCards());
@@ -197,10 +198,12 @@ import java.util.Random;
CardList hPlay = new CardList(human.getCards()); CardList hPlay = new CardList(human.getCards());
hPlay = hPlay.filter(new CardListFilter() { hPlay = hPlay.filter(new CardListFilter() {
public boolean addCard(Card c) { public boolean addCard(Card c) {
int restDamage = d;
if (!noPrevention)
restDamage = c.staticDamagePrevention(d,AF.getHostCard(),false);
// will include creatures already dealt damage // will include creatures already dealt damage
return c.isCreature() && (c.getKillDamage() <= d) return c.isCreature() && (c.getKillDamage() <= restDamage)
&& CardFactoryUtil.canTarget(AF.getHostCard(), c) && CardFactoryUtil.canTarget(AF.getHostCard(), c)
&& !(c.preventAllDamageToCard(AF.getHostCard(),false) && !noPrevention)
&& !c.getKeyword().contains("Indestructible") && !c.getKeyword().contains("Indestructible")
&& !(c.getSVar("SacMe").length() > 0); && !(c.getSVar("SacMe").length() > 0);
} }

View File

@@ -2216,11 +2216,11 @@ public class Card extends MyObservable {
} }
// This is for keywords with a number like Bushido, Annihilator and Rampage. It returns the total. // This is for keywords with a number like Bushido, Annihilator and Rampage. It returns the total.
public int getKeywordMagnitute(String k) { public int getKeywordMagnitude(String k) {
int count = 0; int count = 0;
ArrayList<String> keywords = getKeyword(); ArrayList<String> keywords = getKeyword();
for(String kw:keywords) { for(String kw:keywords) {
if(kw.contains(k)) { if(kw.startsWith(k)) {
String[] parse = kw.split(" "); String[] parse = kw.split(" ");
String s = parse[1]; String s = parse[1];
count += Integer.parseInt(s); count += Integer.parseInt(s);
@@ -2661,10 +2661,8 @@ public class Card extends MyObservable {
return getNetDefense() + preventNextDamage - getDamage(); return getNetDefense() + preventNextDamage - getDamage();
} }
public void setDamage(int n) { public void setDamage(int n) {
if(this.getKeyword().contains("Prevent all damage that would be dealt to CARDNAME.")) n = 0; //if(this.getKeyword().contains("Prevent all damage that would be dealt to CARDNAME.")) n = 0;
damage = n; damage = n;
} }
@@ -2761,46 +2759,58 @@ public class Card extends MyObservable {
} }
} }
public boolean preventAllDamageToCard(Card source, boolean isCombat) { //This should be also usable by the AI to forecast an effect (so it must not change the game state)
boolean reduce = false; public int staticDamagePrevention(final int damage, final Card source, final boolean isCombat) {
int restDamage = damage;
if(isCombat) { if(isCombat) {
reduce = reduce || getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME."); if(getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME."))return 0;
reduce = reduce || getKeyword().contains("Prevent all combat damage that would be dealt to CARDNAME."); if(getKeyword().contains("Prevent all combat damage that would be dealt to CARDNAME."))return 0;
reduce = reduce || source.getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME."); if(source.getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME."))return 0;
reduce = reduce || source.getKeyword().contains("Prevent all combat damage that would be dealt by CARDNAME."); if(source.getKeyword().contains("Prevent all combat damage that would be dealt by CARDNAME."))return 0;
}
if(getKeyword().contains("Prevent all damage that would be dealt to CARDNAME."))return 0;
if(getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME."))return 0;
if(source.getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME."))return 0;
if(source.getKeyword().contains("Prevent all damage that would be dealt by CARDNAME."))return 0;
if(hasStartOfKeyword("Absorb")) {
int absorbed = this.getKeywordMagnitude("Absorb");
if (restDamage > absorbed) restDamage = restDamage - absorbed;
else return 0;
} }
reduce = reduce || getKeyword().contains("Prevent all damage that would be dealt to CARDNAME.");
reduce = reduce || getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME.");
reduce = reduce || source.getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME.");
reduce = reduce || source.getKeyword().contains("Prevent all damage that would be dealt by CARDNAME.");
//more specific prevents here: //more specific prevents here:
reduce = reduce || (getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by artifact creatures.") if((getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by artifact creatures.")
&& source.isCreature() && source.isArtifact()); && source.isCreature() && source.isArtifact()))return 0;
reduce = reduce || (getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by artifacts.") if((getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by artifacts.")
&& source.isArtifact()); && source.isArtifact()))return 0;
reduce = reduce || (getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by creatures.") if((getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by creatures.")
&& source.isCreature()); && source.isCreature()))return 0;
// specific Cards // specific Cards
reduce = reduce || (this.isCreature() && source.isCreature() && if(!isCreature()) { //and not a planeswalker
AllZoneUtil.isCardInPlay("Well-Laid Plans") && source.sharesColorWith(this)); if((this.isCreature() && source.isCreature() &&
reduce = reduce || (!isCombat && AllZoneUtil.isCardInPlay("Mark of Asylum", getController())); AllZoneUtil.isCardInPlay("Well-Laid Plans") && source.sharesColorWith(this)))return 0;
reduce = reduce || (source.getController() == getController() && AllZoneUtil.isCardInPlay("Light of Sanction", getController()));
return reduce; if((!isCombat && AllZoneUtil.isCardInPlay("Mark of Asylum", getController())))return 0;
if((source.getController().isPlayer(getController()) && AllZoneUtil.isCardInPlay("Light of Sanction", getController())))
return 0;
if (AllZoneUtil.isCardInPlay("Plated Pegasus") && source.isSpell()
&& restDamage > 0) restDamage = restDamage - 1;
} //Creature end
if (AllZoneUtil.isCardInPlay("Energy Storm") && source.isSpell()) return 0;
return restDamage;
} }
public int preventDamage(final int damage, Card source, boolean isCombat) { public int preventDamage(final int damage, Card source, boolean isCombat) {
int restDamage = damage; int restDamage = damage;
if (AllZoneUtil.isCardInPlay("Energy Storm") && source.isSpell()) return 0; restDamage = staticDamagePrevention(restDamage, source, isCombat);
if( preventAllDamageToCard(source, isCombat)) {
return 0;
}
if (AllZoneUtil.isCardInPlay("Plated Pegasus") && source.isSpell()
&& restDamage > 0) restDamage = restDamage - 1;
if(restDamage >= preventNextDamage) { if(restDamage >= preventNextDamage) {
restDamage = restDamage - preventNextDamage; restDamage = restDamage - preventNextDamage;

View File

@@ -454,7 +454,7 @@ public class CardFactoryUtil {
//Battle stats increasing keywords //Battle stats increasing keywords
if (c.hasKeyword("Double Strike")) value += power * 15; if (c.hasKeyword("Double Strike")) value += power * 15;
value += c.getKeywordMagnitute("Bushido") * 20; value += c.getKeywordMagnitude("Bushido") * 20;
value += c.getAmountOfKeyword("Flanking") * 20; value += c.getAmountOfKeyword("Flanking") * 20;
//Other good keywords //Other good keywords
@@ -465,8 +465,8 @@ public class CardFactoryUtil {
if (c.hasKeyword("Trample")) value += power * 3; if (c.hasKeyword("Trample")) value += power * 3;
if (c.hasKeyword("Vigilance")) value += power * 5 + toughness * 5; if (c.hasKeyword("Vigilance")) value += power * 5 + toughness * 5;
if (c.hasKeyword("Wither")) value += power * 10; if (c.hasKeyword("Wither")) value += power * 10;
value += c.getKeywordMagnitute("Rampage"); value += c.getKeywordMagnitude("Rampage");
value += c.getKeywordMagnitute("Annihilator") * 30; value += c.getKeywordMagnitude("Annihilator") * 30;
if (c.hasKeyword("Changeling")) value += 5; if (c.hasKeyword("Changeling")) value += 5;
if (c.hasKeyword("Whenever CARDNAME becomes blocked by a creature, destroy that creature at end of combat") && power > 0) value += 15; if (c.hasKeyword("Whenever CARDNAME becomes blocked by a creature, destroy that creature at end of combat") && power > 0) value += 15;
if (c.hasKeyword("Whenever a creature dealt damage by CARDNAME this turn is put into a graveyard, put a +1/+1 counter on CARDNAME.") && power > 0) value += 2; if (c.hasKeyword("Whenever a creature dealt damage by CARDNAME this turn is put into a graveyard, put a +1/+1 counter on CARDNAME.") && power > 0) value += 2;
@@ -4495,19 +4495,6 @@ public class CardFactoryUtil {
return list; return list;
} }
public static int getTotalBushidoMagnitude(Card c) {
int count = 0;
ArrayList<String> keywords = c.getKeyword();
for(String kw:keywords) {
if(kw.contains("Bushido")) {
String[] parse = kw.split(" ");
String s = parse[1];
count += Integer.parseInt(s);
}
}
return count;
}
public static ArrayList<Ability> getBushidoEffects(Card c) { public static ArrayList<Ability> getBushidoEffects(Card c) {
ArrayList<String> keywords = c.getKeyword(); ArrayList<String> keywords = c.getKeyword();
ArrayList<Ability> list = new ArrayList<Ability>(); ArrayList<Ability> list = new ArrayList<Ability>();

View File

@@ -471,8 +471,8 @@ public class CombatUtil {
if(!CardFactoryUtil.canDamage(defender, attacker)) return false; if(!CardFactoryUtil.canDamage(defender, attacker)) return false;
int defBushidoMagnitude = CardFactoryUtil.getTotalBushidoMagnitude(defender); int defBushidoMagnitude = defender.getKeywordMagnitude("Bushido");
int attBushidoMagnitude = CardFactoryUtil.getTotalBushidoMagnitude(attacker); int attBushidoMagnitude = attacker.getKeywordMagnitude("Bushido");
int defenderDamage = defender.getNetAttack() - flankingMagnitude + defBushidoMagnitude; int defenderDamage = defender.getNetAttack() - flankingMagnitude + defBushidoMagnitude;
int attackerDamage = attacker.getNetAttack() + attBushidoMagnitude; int attackerDamage = attacker.getNetAttack() + attBushidoMagnitude;
@@ -576,8 +576,8 @@ public class CombatUtil {
if(!CardFactoryUtil.canDamage(attacker,defender)) return false; if(!CardFactoryUtil.canDamage(attacker,defender)) return false;
int defBushidoMagnitude = CardFactoryUtil.getTotalBushidoMagnitude(defender); int defBushidoMagnitude = defender.getKeywordMagnitude("Bushido");
int attBushidoMagnitude = CardFactoryUtil.getTotalBushidoMagnitude(attacker); int attBushidoMagnitude = attacker.getKeywordMagnitude("Bushido");
int defenderDamage = defender.getNetAttack() - flankingMagnitude + defBushidoMagnitude; int defenderDamage = defender.getNetAttack() - flankingMagnitude + defBushidoMagnitude;
int attackerDamage = attacker.getNetAttack() + attBushidoMagnitude; int attackerDamage = attacker.getNetAttack() + attBushidoMagnitude;

View File

@@ -218,42 +218,22 @@ public abstract class Player extends MyObservable{
GameActionUtil.executePlayerDamageEffects(this, source, damageToDo, false); GameActionUtil.executePlayerDamageEffects(this, source, damageToDo, false);
} }
public boolean preventAllDamageToPlayer(final Card source, final boolean isCombat) { //This should be also usable by the AI to forecast an effect (so it must not change the game state)
boolean reduce = false; public int staticDamagePrevention(final int damage, final Card source, final boolean isCombat) {
int restDamage = damage;
if(isCombat) { if(isCombat) {
reduce = reduce || source.getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME."); if(source.getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME.")) return 0;
reduce = reduce || source.getKeyword().contains("Prevent all combat damage that would be dealt by CARDNAME."); if(source.getKeyword().contains("Prevent all combat damage that would be dealt by CARDNAME.")) return 0;
if (AllZoneUtil.isCardInPlay("Purity", this)) return 0;
} }
reduce = reduce || source.getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME."); if(source.getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME.")) return 0;
reduce = reduce || source.getKeyword().contains("Prevent all damage that would be dealt by CARDNAME."); if(source.getKeyword().contains("Prevent all damage that would be dealt by CARDNAME.")) return 0;
//Spirit of Resistance
if(AllZoneUtil.isCardInPlay("Spirit of Resistance", this)) {
if( AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Black).size() > 0
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Blue).size() > 0
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Green).size() > 0
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Red).size() > 0
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.White).size() > 0) {
reduce = true;
}
}
return reduce;
}
public int preventDamage(final int damage, Card source, boolean isCombat) { //specific cards
int restDamage = damage;
if (AllZoneUtil.isCardInPlay("Purity", this) && !isCombat) {
gainLife(restDamage,null);
return 0;
}
if (AllZoneUtil.isCardInPlay("Energy Storm") && source.isSpell()) return 0; if (AllZoneUtil.isCardInPlay("Energy Storm") && source.isSpell()) return 0;
if( preventAllDamageToPlayer(source, isCombat)) {
return 0;
}
if (AllZoneUtil.isCardInPlay("Spirit of Resistance", this) && !source.getController().equals(this) if (AllZoneUtil.isCardInPlay("Spirit of Resistance", this) && !source.getController().equals(this)
&& restDamage > 0) restDamage = restDamage - 1; && restDamage > 0) restDamage = restDamage - 1;
@@ -284,6 +264,29 @@ public abstract class Player extends MyObservable{
} }
if (AllZoneUtil.isCardInPlay("Urza's Armor", this) && restDamage > 0) restDamage = restDamage - 1; if (AllZoneUtil.isCardInPlay("Urza's Armor", this) && restDamage > 0) restDamage = restDamage - 1;
if(AllZoneUtil.isCardInPlay("Spirit of Resistance", this)) {
if( AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Black).size() > 0
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Blue).size() > 0
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Green).size() > 0
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Red).size() > 0
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.White).size() > 0) {
return 0;
}
}
return restDamage;
}
public int preventDamage(final int damage, Card source, boolean isCombat) {
int restDamage = damage;
// Purity has to stay here because it changes the game state
if (AllZoneUtil.isCardInPlay("Purity", this) && !isCombat) {
gainLife(restDamage,null);
return 0;
}
restDamage = staticDamagePrevention(restDamage, source, isCombat);
if(restDamage >= preventNextDamage) { if(restDamage >= preventNextDamage) {
restDamage = restDamage - preventNextDamage; restDamage = restDamage - preventNextDamage;