made distribute damage method return Map<Card, int> as decisions taken by player, combat.java now does not depend on player type and has no GUI references

This commit is contained in:
Maxmtg
2013-02-11 01:08:08 +00:00
parent 5c529982d6
commit 9c3359ab16
7 changed files with 82 additions and 60 deletions

View File

@@ -1642,15 +1642,18 @@ public class ComputerUtilCombat {
* @param damage
* a int.
*/
public static void distributeAIDamage(final Card attacker, final List<Card> block, int damage, Combat combat) {
public static Map<Card, Integer> distributeAIDamage(final Card attacker, final List<Card> block, int damage) {
final Card c = attacker;
Map<Card, Integer> damageMap = new HashMap<Card, Integer>();
if (attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")
|| attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked.")) {
combat.addDefendingDamage(damage, attacker);
return;
damageMap.put(null, damage);
return damageMap;
}
final boolean hasTrample = attacker.hasKeyword("Trample");
if (block.size() == 1) {
@@ -1678,12 +1681,12 @@ public class ComputerUtilCombat {
// If Extra trample damage, assign to defending
// player/planeswalker
if (0 < trample) {
combat.addDefendingDamage(trample, attacker);
damageMap.put(null, trample);
}
blocker.addAssignedDamage(damageNeeded, attacker);
damageMap.put(blocker, damageNeeded);
} else {
blocker.addAssignedDamage(damage, attacker);
damageMap.put(blocker, damage);
}
} // 1 blocker
else {
@@ -1695,10 +1698,7 @@ public class ComputerUtilCombat {
final int enoughDamageToKill = ComputerUtilCombat.getEnoughDamageToKill(b, damage, attacker, true);
if (enoughDamageToKill <= damage) {
damage -= enoughDamageToKill;
final List<Card> cl = new ArrayList<Card>();
cl.add(attacker);
b.addAssignedDamage(enoughDamageToKill, c);
damageMap.put(b, enoughDamageToKill);
} else {
killsAllBlockers = false;
}
@@ -1708,13 +1708,14 @@ public class ComputerUtilCombat {
if (killsAllBlockers && damage > 0) {
// if attacker has no trample, and there's damage left, assign the rest to the last blocker
if (!hasTrample && lastBlocker != null) {
lastBlocker.addAssignedDamage(damage, c);
damageMap.put(lastBlocker, damage);
damage = 0;
} else if (hasTrample) {
combat.addDefendingDamage(damage, c);
damageMap.put(null, damage);
}
}
}
return damageMap;
} // setAssignedDamage()

View File

@@ -33,12 +33,9 @@ import forge.CardPredicates;
import forge.GameEntity;
import forge.Singletons;
import forge.card.trigger.TriggerType;
import forge.game.ai.ComputerUtilCombat;
import forge.game.event.BlockerAssignedEvent;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.GuiDialog;
import forge.gui.match.CMatchUI;
/**
* <p>
@@ -695,14 +692,10 @@ public class Combat {
if (!attackers.isEmpty()) {
assignedDamage = true;
if (blocker.getController().isHuman()) { // who is defending matters
if (attackers.size() > 1) {
CMatchUI.SINGLETON_INSTANCE.assignDamage(blocker, attackers, damage, null);
} else {
attackers.get(0).addAssignedDamage(damage, blocker);
}
} else { // computer attacks
ComputerUtilCombat.distributeAIDamage(blocker, attackers, damage, this);
Map<Card, Integer> map = blocker.getController().getController().assignCombatDamage(blocker, attackers, damage, null);
for (Entry<Card, Integer> dt : map.entrySet()) {
dt.getKey().addAssignedDamage(dt.getValue(), blocker);
dt.getKey().updateObservers();
}
}
}
@@ -711,12 +704,6 @@ public class Combat {
return assignedDamage;
}
private final boolean assignDamageAsIfNotBlocked(Card attacker) {
return attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked.")
|| (attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")
&& GuiDialog.confirm(attacker, "Do you want to assign its combat damage as though it weren't blocked?"));
}
private final boolean assignAttackersDamage(boolean firstStrikeDamage) {
this.defendingDamageMap.clear(); // this should really happen in deal damage
List<Card> blockers = null;
@@ -746,19 +733,17 @@ public class Combat {
continue;
}
} else {
if (this.getAttackingPlayer().isHuman()) { // human attacks
if (assignDamageAsIfNotBlocked(attacker)) {
this.addDefendingDamage(damageDealt, attacker);
Map<Card, Integer> map = this.getAttackingPlayer().getController().assignCombatDamage(attacker, blockers, damageDealt, this.getDefenderByAttacker(attacker));
for (Entry<Card, Integer> dt : map.entrySet()) {
if( dt.getKey() == null && trampler) {
if (dt.getValue() > 0)
addDefendingDamage(dt.getValue(), attacker);
} else {
if (trampler || (blockers.size() > 1)) {
CMatchUI.SINGLETON_INSTANCE.assignDamage(attacker, blockers, damageDealt, this.getDefenderByAttacker(attacker));
} else {
blockers.get(0).addAssignedDamage(damageDealt, attacker);
}
dt.getKey().addAssignedDamage(dt.getValue(), attacker);
dt.getKey().updateObservers();
}
} else { // computer attacks
ComputerUtilCombat.distributeAIDamage(attacker, blockers, damageDealt, this);
}
} // if !hasFirstStrike ...
} // for
return assignedDamage;

View File

@@ -1,8 +1,10 @@
package forge.game.player;
import java.util.List;
import java.util.Map;
import forge.Card;
import forge.GameEntity;
import forge.Singletons;
import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
@@ -88,4 +90,6 @@ public abstract class PlayerController {
public abstract Deck sideboard(final Deck deck, GameType gameType);
public abstract Map<Card, Integer> assignCombatDamage(Card attacker, List<Card> blockers, int damageDealt, GameEntity defender);
}

View File

@@ -1,8 +1,10 @@
package forge.game.player;
import java.util.List;
import java.util.Map;
import forge.Card;
import forge.GameEntity;
import forge.card.spellability.Spell;
import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
@@ -13,6 +15,7 @@ import forge.game.ai.AiController;
import forge.game.ai.AiInputBlock;
import forge.game.ai.AiInputCommon;
import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCombat;
import forge.gui.GuiChoose;
@@ -160,6 +163,14 @@ public class PlayerControllerAi extends PlayerController {
return deck;
}
/* (non-Javadoc)
* @see forge.game.player.PlayerController#assignCombatDamage(forge.Card, java.util.List, int, forge.GameEntity)
*/
@Override
public Map<Card, Integer> assignCombatDamage(Card attacker, List<Card> blockers, int damageDealt, GameEntity defender) {
return ComputerUtilCombat.distributeAIDamage(attacker, blockers, damageDealt);
}
}

View File

@@ -1,10 +1,13 @@
package forge.game.player;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JOptionPane;
import forge.Card;
import forge.GameEntity;
import forge.Singletons;
import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
@@ -170,6 +173,32 @@ public class PlayerControllerHuman extends PlayerController {
return res;
}
/* (non-Javadoc)
* @see forge.game.player.PlayerController#assignCombatDamage()
*/
@Override
public Map<Card, Integer> assignCombatDamage(Card attacker, List<Card> blockers, int damageDealt, GameEntity defender) {
Map<Card, Integer> map;
if (defender != null && assignDamageAsIfNotBlocked(attacker)) {
map = new HashMap<Card, Integer>();
map.put(null, damageDealt);
} else {
if (attacker.hasKeyword("Trample") || (blockers.size() > 1)) {
map = CMatchUI.SINGLETON_INSTANCE.getDamageToAssign(attacker, blockers, damageDealt, defender);
} else {
map = new HashMap<Card, Integer>();
map.put(blockers.get(0), damageDealt);
}
}
return map;
}
private final boolean assignDamageAsIfNotBlocked(Card attacker) {
return attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked.")
|| (attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")
&& GuiDialog.confirm(attacker, "Do you want to assign its combat damage as though it weren't blocked?"));
}
}

View File

@@ -20,7 +20,9 @@ package forge.gui.match;
import java.awt.Image;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.ImageIcon;
@@ -186,19 +188,22 @@ public enum CMatchUI implements CardContainer {
* @param blockers &emsp; {@link forge.CardList}
* @param damage &emsp; int
*/
public void assignDamage(final Card attacker, final List<Card> blockers, final int damage, GameEntity defender) {
public Map<Card, Integer> getDamageToAssign(final Card attacker, final List<Card> blockers, final int damage, GameEntity defender) {
if (damage <= 0) {
return;
return new HashMap<Card, Integer>();
}
// If the first blocker can absorb all of the damage, don't show the Assign Damage Frame
Card firstBlocker = blockers.get(0);
if (!attacker.hasKeyword("Deathtouch") && firstBlocker.getLethalDamage() >= damage) {
firstBlocker.addAssignedDamage(damage, attacker);
return;
Map<Card, Integer> res = new HashMap<Card, Integer>();
res.put(firstBlocker, damage);
return res;
}
new VAssignDamage(attacker, blockers, damage, defender);
VAssignDamage v = new VAssignDamage(attacker, blockers, damage, defender);
return v.getDamageMap();
}
/**

View File

@@ -38,7 +38,6 @@ import net.miginfocom.swing.MigLayout;
import forge.Card;
import forge.CounterType;
import forge.GameEntity;
import forge.Singletons;
import forge.game.MatchController;
import forge.game.player.Player;
import forge.gui.SOverlayUtils;
@@ -66,7 +65,6 @@ public class VAssignDamage {
// Damage storage
private final int totalDamageToAssign;
private final Card attacker;
private boolean attackerHasDeathtouch = false;
private boolean attackerHasTrample = false;
private boolean attackerHasInfect = false;
@@ -106,12 +104,11 @@ public class VAssignDamage {
}
// Mouse actions
private final MouseAdapter madDefender = new MouseAdapter() {
private final MouseAdapter mad = new MouseAdapter() {
@Override
public void mouseEntered(final MouseEvent evt) {
Card source = ((CardPanel) evt.getSource()).getCard();
if (!damage.containsKey(source))
source = null;
if (!damage.containsKey(source)) source = null; // to get player instead of fake card
FSkin.Colors brdrColor = VAssignDamage.this.canAssignTo(source) ? FSkin.Colors.CLR_ACTIVE : FSkin.Colors.CLR_INACTIVE;
((CardPanel) evt.getSource()).setBorder(new LineBorder(FSkin.getColor(brdrColor), 2));
@@ -149,7 +146,6 @@ public class VAssignDamage {
this.attackerHasDeathtouch = attacker0.hasKeyword("Deathtouch");
this.attackerHasInfect = attacker0.hasKeyword("Infect");
this.attackerHasTrample = defender != null && attacker0.hasKeyword("Trample");
this.attacker = attacker0;
// Top-level UI stuff
final JPanel overlay = SOverlayUtils.genericOverlay();
@@ -257,7 +253,7 @@ public class VAssignDamage {
cp.setCardBounds(0, 0, 105, 150);
cp.setOpaque(true);
pnlDefenders.add(cp, "w 145px!, h 170px!, gap 5px 5px 3px 3px, ax center");
cp.addMouseListener(madDefender);
cp.addMouseListener(mad);
}
/**
@@ -396,15 +392,6 @@ public class VAssignDamage {
if ( getRemainingDamage() > 0 )
return;
for (DamageTarget dt : defenders) {
if( dt.card == null && attackerHasTrample ) {
Singletons.getModel().getGame().getCombat().addDefendingDamage(dt.damage, this.attacker);
continue;
}
dt.card.addAssignedDamage(dt.damage, this.attacker);
dt.card.updateObservers();
}
dlg.dispose();
SOverlayUtils.hideOverlay();
}