From 9c3359ab16ae2bcb0efc0d924c87ac1362d036e0 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Mon, 11 Feb 2013 01:08:08 +0000 Subject: [PATCH] made distribute damage method return Map as decisions taken by player, combat.java now does not depend on player type and has no GUI references --- .../forge/game/ai/ComputerUtilCombat.java | 27 ++++++------- src/main/java/forge/game/phase/Combat.java | 39 ++++++------------- .../forge/game/player/PlayerController.java | 4 ++ .../forge/game/player/PlayerControllerAi.java | 11 ++++++ .../game/player/PlayerControllerHuman.java | 29 ++++++++++++++ src/main/java/forge/gui/match/CMatchUI.java | 13 +++++-- .../java/forge/gui/match/VAssignDamage.java | 19 ++------- 7 files changed, 82 insertions(+), 60 deletions(-) diff --git a/src/main/java/forge/game/ai/ComputerUtilCombat.java b/src/main/java/forge/game/ai/ComputerUtilCombat.java index a6ba928882e..2061f0933fc 100644 --- a/src/main/java/forge/game/ai/ComputerUtilCombat.java +++ b/src/main/java/forge/game/ai/ComputerUtilCombat.java @@ -1642,15 +1642,18 @@ public class ComputerUtilCombat { * @param damage * a int. */ - public static void distributeAIDamage(final Card attacker, final List block, int damage, Combat combat) { + public static Map distributeAIDamage(final Card attacker, final List block, int damage) { final Card c = attacker; - + Map damageMap = new HashMap(); + 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 cl = new ArrayList(); - 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() diff --git a/src/main/java/forge/game/phase/Combat.java b/src/main/java/forge/game/phase/Combat.java index e67e7ca80ed..e0c025faf3b 100644 --- a/src/main/java/forge/game/phase/Combat.java +++ b/src/main/java/forge/game/phase/Combat.java @@ -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; /** *

@@ -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 map = blocker.getController().getController().assignCombatDamage(blocker, attackers, damage, null); + for (Entry 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 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 map = this.getAttackingPlayer().getController().assignCombatDamage(attacker, blockers, damageDealt, this.getDefenderByAttacker(attacker)); + for (Entry 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; diff --git a/src/main/java/forge/game/player/PlayerController.java b/src/main/java/forge/game/player/PlayerController.java index b75d870c56c..f7ba8a79ebb 100644 --- a/src/main/java/forge/game/player/PlayerController.java +++ b/src/main/java/forge/game/player/PlayerController.java @@ -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 assignCombatDamage(Card attacker, List blockers, int damageDealt, GameEntity defender); + } diff --git a/src/main/java/forge/game/player/PlayerControllerAi.java b/src/main/java/forge/game/player/PlayerControllerAi.java index 62fbfb4aa05..42ceb320431 100644 --- a/src/main/java/forge/game/player/PlayerControllerAi.java +++ b/src/main/java/forge/game/player/PlayerControllerAi.java @@ -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 assignCombatDamage(Card attacker, List blockers, int damageDealt, GameEntity defender) { + return ComputerUtilCombat.distributeAIDamage(attacker, blockers, damageDealt); + } + } diff --git a/src/main/java/forge/game/player/PlayerControllerHuman.java b/src/main/java/forge/game/player/PlayerControllerHuman.java index df3a24a5e55..a6426b2d304 100644 --- a/src/main/java/forge/game/player/PlayerControllerHuman.java +++ b/src/main/java/forge/game/player/PlayerControllerHuman.java @@ -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 assignCombatDamage(Card attacker, List blockers, int damageDealt, GameEntity defender) { + Map map; + if (defender != null && assignDamageAsIfNotBlocked(attacker)) { + map = new HashMap(); + 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(); + 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?")); + } + } diff --git a/src/main/java/forge/gui/match/CMatchUI.java b/src/main/java/forge/gui/match/CMatchUI.java index b9d5fe5225d..20efb4267f0 100644 --- a/src/main/java/forge/gui/match/CMatchUI.java +++ b/src/main/java/forge/gui/match/CMatchUI.java @@ -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   {@link forge.CardList} * @param damage   int */ - public void assignDamage(final Card attacker, final List blockers, final int damage, GameEntity defender) { + public Map getDamageToAssign(final Card attacker, final List blockers, final int damage, GameEntity defender) { if (damage <= 0) { - return; + return new HashMap(); } // 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 res = new HashMap(); + res.put(firstBlocker, damage); + return res; } - new VAssignDamage(attacker, blockers, damage, defender); + VAssignDamage v = new VAssignDamage(attacker, blockers, damage, defender); + return v.getDamageMap(); } /** diff --git a/src/main/java/forge/gui/match/VAssignDamage.java b/src/main/java/forge/gui/match/VAssignDamage.java index 0531f537635..49e06a29fd9 100644 --- a/src/main/java/forge/gui/match/VAssignDamage.java +++ b/src/main/java/forge/gui/match/VAssignDamage.java @@ -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(); }