- Cleanup of combat damage assignment. Fixed a bug with Double Strike.

- Improved the AI handling of trampling creatures.
This commit is contained in:
jendave
2011-08-06 14:59:11 +00:00
parent f0cc26420b
commit ebdccf3f8b
4 changed files with 106 additions and 79 deletions

View File

@@ -2832,6 +2832,31 @@ public class Card extends MyObservable {
receivedDamageFromThisTurn.clear(); receivedDamageFromThisTurn.clear();
} }
//how much damage is enough to kill the creature (for AI)
public int getEnoughDamageToKill(int maxDamage, Card source, boolean isCombat) {
int killDamage = getKillDamage();
if(getKeyword().contains("Indestructible") || getShield() > 0) {
if(!(source.getKeyword().contains("Wither") || source.getKeyword().contains("Infect")))
return maxDamage + 1;
}
else
if(source.getKeyword().contains("Deathtouch")
|| source.getKeyword().contains("Whenever CARDNAME deals combat damage to a creature, destroy that creature"))
for(int i=1; i < maxDamage+1;i++) {
if (predictDamage(i, source, isCombat) > 0)
return i;
}
for(int i=1; i < maxDamage+1;i++) {
if (predictDamage(i, source, isCombat) >= killDamage)
return i;
}
return maxDamage + 1;
}
//the amount of damage needed to kill the creature (for AI) //the amount of damage needed to kill the creature (for AI)
public int getKillDamage() { public int getKillDamage() {
int killDamage = getLethalDamage() + preventNextDamage; int killDamage = getLethalDamage() + preventNextDamage;

View File

@@ -10,7 +10,7 @@ public class Combat {
private Set<Card> blocked = new HashSet<Card>(); private Set<Card> blocked = new HashSet<Card>();
private HashMap<Card, CardList> unblockedMap = new HashMap<Card, CardList>(); private HashMap<Card, CardList> unblockedMap = new HashMap<Card, CardList>();
private HashMap<Card, Integer> defendingFirstStrikeDamageMap = new HashMap<Card, Integer>(); //private HashMap<Card, Integer> defendingFirstStrikeDamageMap = new HashMap<Card, Integer>();
private HashMap<Card, Integer> defendingDamageMap = new HashMap<Card, Integer>(); private HashMap<Card, Integer> defendingDamageMap = new HashMap<Card, Integer>();
// Defenders are the Defending Player + Each Planeswalker that player controls // Defenders are the Defending Player + Each Planeswalker that player controls
@@ -41,7 +41,7 @@ public class Combat {
attackingDamage = 0; attackingDamage = 0;
defendingDamageMap.clear(); defendingDamageMap.clear();
defendingFirstStrikeDamageMap.clear(); //defendingFirstStrikeDamageMap.clear();
attackingPlayer = null; attackingPlayer = null;
defendingPlayer = null; defendingPlayer = null;
@@ -163,11 +163,13 @@ public class Combat {
public HashMap<Card, Integer> getDefendingDamageMap() { public HashMap<Card, Integer> getDefendingDamageMap() {
return defendingDamageMap; return defendingDamageMap;
} }
/*
public HashMap<Card, Integer> getDefendingFirstStrikeDamageMap() { public HashMap<Card, Integer> getDefendingFirstStrikeDamageMap() {
return defendingFirstStrikeDamageMap; return defendingFirstStrikeDamageMap;
} }
*/
public int getTotalDefendingDamage() { public int getTotalDefendingDamage() {
int total = 0; int total = 0;
@@ -179,7 +181,8 @@ public class Combat {
return total; return total;
} }
/*
public int getTotalFirstStrikeDefendingDamage() { public int getTotalFirstStrikeDefendingDamage() {
int total = 0; int total = 0;
@@ -191,7 +194,8 @@ public class Combat {
return total; return total;
} }
*/
public void setDefendingDamage() { public void setDefendingDamage() {
defendingDamageMap.clear(); defendingDamageMap.clear();
CardList att = new CardList(getAttackers()); CardList att = new CardList(getAttackers());
@@ -211,7 +215,8 @@ public class Combat {
} // ! isBlocked... } // ! isBlocked...
}// for }// for
} }
/*
public void setDefendingFirstStrikeDamage() { public void setDefendingFirstStrikeDamage() {
defendingFirstStrikeDamageMap.clear(); defendingFirstStrikeDamageMap.clear();
CardList att = new CardList(getAttackers()); CardList att = new CardList(getAttackers());
@@ -231,6 +236,7 @@ public class Combat {
} }
} // for } // for
} }
*/
public void addDefendingDamage(int n, Card source) { public void addDefendingDamage(int n, Card source) {
String slot = getDefenderByAttacker(source).toString(); String slot = getDefenderByAttacker(source).toString();
@@ -249,7 +255,8 @@ public class Combat {
defendingDamageMap.put(source, defendingDamageMap.get(source) + n); defendingDamageMap.put(source, defendingDamageMap.get(source) + n);
} }
} }
/*
public void addDefendingFirstStrikeDamage(int n, Card source) { public void addDefendingFirstStrikeDamage(int n, Card source) {
String slot = getDefenderByAttacker(source).toString(); String slot = getDefenderByAttacker(source).toString();
Object o = defenders.get(Integer.parseInt(slot)); Object o = defenders.get(Integer.parseInt(slot));
@@ -268,6 +275,7 @@ public class Combat {
defendingFirstStrikeDamageMap.get(source) + n); defendingFirstStrikeDamageMap.get(source) + n);
} }
} }
*/
public void addAttackingDamage(int n) { public void addAttackingDamage(int n) {
attackingDamage += n; attackingDamage += n;
@@ -388,7 +396,7 @@ public class Combat {
// also assigns player damage by setPlayerDamage() // also assigns player damage by setPlayerDamage()
public void setAssignedFirstStrikeDamage() { public void setAssignedFirstStrikeDamage() {
setDefendingFirstStrikeDamage(); //setDefendingFirstStrikeDamage();
CardList block; CardList block;
CardList attacking = new CardList(getAttackers()); CardList attacking = new CardList(getAttackers());
@@ -396,51 +404,39 @@ public class Combat {
for (int i = 0; i < attacking.size(); i++) { for (int i = 0; i < attacking.size(); i++) {
block = getBlockers(attacking.get(i)); Card attacker = attacking.get(i);
block = getBlockers(attacker);
int damageDealt = attacking.get(i).getNetCombatDamage(); int damageDealt = attacker.getNetCombatDamage();
// attacker always gets all blockers' attack // attacker always gets all blockers' attack
for (Card b : block) { for (Card b : block) {
if (b.hasFirstStrike() || b.hasDoubleStrike()) { if (b.hasFirstStrike() || b.hasDoubleStrike()) {
attacking.get(i).addAssignedDamage(damageDealt, b); attacker.addAssignedDamage(damageDealt, b);
} }
} }
if (block.size() == 0){ if (block.size() == 0){
// this damage is assigned to a player by setPlayerDamage() // this damage is assigned to a player by setPlayerDamage()
addUnblockedAttacker(attacking.get(i)); addUnblockedAttacker(attacker);
} }
else if (attacking.get(i).hasFirstStrike() || attacking.get(i).hasDoubleStrike()) { else if (attacker.hasFirstStrike() || attacker.hasDoubleStrike()) {
if (getAttackingPlayer().isHuman()) {// human attacks if (getAttackingPlayer().isHuman()) {// human attacks
AllZone.Display.assignDamage(attacking.get(i), block, damageDealt); AllZone.Display.assignDamage(attacker, block, damageDealt);
} }
else {// computer attacks else {// computer attacks
if (block.size() == 1) { distributeAIDamage(attacker, block, damageDealt);
}
int trample = damageDealt - block.get(0).getKillDamage();
// trample
if (attacking.get(i).getKeyword().contains("Trample") && 0 < trample) {
block.get(0).addAssignedDamage(block.get(0).getKillDamage(), attacking.get(i));
this.addDefendingDamage(trample, attacking.get(i));
}
else block.get(0).addAssignedDamage(damageDealt, attacking.get(i));
}// 1 blocker
else {
distributeAIDamage(attacking.get(i), block, damageDealt);
}
} //Computer
}// if(hasFirstStrike || doubleStrike) }// if(hasFirstStrike || doubleStrike)
}// for }// for
}// setAssignedFirstStrikeDamage() }// setAssignedFirstStrikeDamage()
/* /*
private void addAssignedFirstStrikeDamage(Card attacker, CardList block, int damage) { private void distributeAIFirstStrikeDamage(Card attacker, CardList block, int damage) {
Card c = attacker; Card c = attacker;
for (Card b : block) { for (Card b : block) {
@@ -496,21 +492,8 @@ public class Combat {
AllZone.Display.assignDamage(attacking.get(i), block, damageDealt); AllZone.Display.assignDamage(attacking.get(i), block, damageDealt);
} }
else {// computer attacks else {// computer attacks
if (block.size() == 1) {
int trample = damageDealt - block.get(0).getKillDamage();
// trample
if (attacking.get(i).getKeyword().contains("Trample") && 0 < trample) {
block.get(0).addAssignedDamage(block.get(0).getKillDamage(), attacking.get(i));
this.addDefendingDamage(trample, attacking.get(i));
}
else block.get(0).addAssignedDamage(damageDealt, attacking.get(i));
}// 1 blocker
else {
distributeAIDamage(attacking.get(i), block, damageDealt); distributeAIDamage(attacking.get(i), block, damageDealt);
} }
} //Computer
}// if !hasFirstStrike ... }// if !hasFirstStrike ...
}// for }// for
@@ -520,25 +503,55 @@ public class Combat {
private void distributeAIDamage(Card attacker, CardList block, int damage) { private void distributeAIDamage(Card attacker, CardList block, int damage) {
Card c = attacker; Card c = attacker;
for (Card b : block) {
if (b.getKillDamage() <= damage) { if (block.size() == 1) {
damage -= b.getKillDamage();
CardList cl = new CardList(); Card blocker = block.get(0);
cl.add(attacker);
// trample
b.addAssignedDamage(b.getKillDamage(), c); if (attacker.getKeyword().contains("Trample")) {
// c.setAssignedDamage(c.getKillDamage());
int damageNeeded = 0;
//TODO: if the human can be killed distribute only the minimum of damage on the blocker
damageNeeded = blocker.getEnoughDamageToKill(damage, attacker, true);
if (damageNeeded > damage)
damageNeeded = blocker.getLethalDamage();
else
damageNeeded = Math.min(blocker.getLethalDamage(),damageNeeded);
int trample = damage - damageNeeded;
if (0 < trample) {
blocker.addAssignedDamage(damageNeeded, attacker);
this.addDefendingDamage(trample, attacker);
}
}
else blocker.addAssignedDamage(damage, attacker);
}// 1 blocker
else {
for (Card b : block) {
if (b.getKillDamage() <= damage) {
damage -= b.getKillDamage();
CardList cl = new CardList();
cl.add(attacker);
b.addAssignedDamage(b.getKillDamage(), c);
// 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);
block.get(index).addAssignedDamage(damage, c);
damage = 0;
} else if (c.getKeyword().contains("Trample")) {
this.addDefendingDamage(damage, c);
} }
}// 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);
block.get(index).addAssignedDamage(damage, c);
damage = 0;
} else if (c.getKeyword().contains("Trample")) {
this.addDefendingDamage(damage, c);
} }
}// setAssignedDamage() }// setAssignedDamage()
@@ -548,8 +561,7 @@ public class Combat {
boolean bFirstStrike = AllZone.Phase.is(Constant.Phase.Combat_FirstStrikeDamage); boolean bFirstStrike = AllZone.Phase.is(Constant.Phase.Combat_FirstStrikeDamage);
HashMap<Card, Integer> defMap = bFirstStrike ? AllZone.Combat.getDefendingFirstStrikeDamageMap() : HashMap<Card, Integer> defMap = AllZone.Combat.getDefendingDamageMap();
AllZone.Combat.getDefendingDamageMap();
for(Entry<Card, Integer> entry : defMap.entrySet()) { for(Entry<Card, Integer> entry : defMap.entrySet()) {
player.addCombatDamage(entry.getValue(), entry.getKey()); player.addCombatDamage(entry.getValue(), entry.getKey());

View File

@@ -1359,12 +1359,7 @@ class Gui_MultipleBlockers3 extends JFrame {
if (c.getName().equals("Player") && att.getKeyword().contains("Trample") && assignedLethalDamageToAllBlockers) if (c.getName().equals("Player") && att.getKeyword().contains("Trample") && assignedLethalDamageToAllBlockers)
{ {
//what happens with Double Strike??? AllZone.Combat.addDefendingDamage(1, att);
if (att.getKeyword().contains("First Strike"))
AllZone.Combat.addDefendingFirstStrikeDamage(1, att);
else
AllZone.Combat.addDefendingDamage(1, att);
c.addAssignedDamage(1, att); c.addAssignedDamage(1, att);
} }
else if (!c.getName().equals("Player")){ else if (!c.getName().equals("Player")){

View File

@@ -1333,19 +1333,14 @@ class Gui_MultipleBlockers4 extends JFrame {
boolean assignedLethalDamageToAllBlockers = true; boolean assignedLethalDamageToAllBlockers = true;
for (Card crd : blockers ) for (Card crd : blockers )
{ {
if (crd.getTotalAssignedDamage() < ( crd.getNetDefense() - crd.getDamage() )) if (crd.getLethalDamage() > 0 && (!att.getKeyword().contains("Deathtouch") || crd.getTotalAssignedDamage() < 1 ))
assignedLethalDamageToAllBlockers = false; assignedLethalDamageToAllBlockers = false;
} }
if (c.getName().equals("Player") && att.getKeyword().contains("Trample") && assignedLethalDamageToAllBlockers) if (c.getName().equals("Player") && att.getKeyword().contains("Trample") && assignedLethalDamageToAllBlockers)
{ {
//what happens with Double Strike??? AllZone.Combat.addDefendingDamage(1, att);
if (att.getKeyword().contains("First Strike"))
AllZone.Combat.addDefendingFirstStrikeDamage(1, att);
else
AllZone.Combat.addDefendingDamage(1, att);
c.addAssignedDamage(1, att); c.addAssignedDamage(1, att);
} }
else if (!c.getName().equals("Player")){ else if (!c.getName().equals("Player")){