mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 18:28:00 +00:00
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:
@@ -1642,15 +1642,18 @@ public class ComputerUtilCombat {
|
|||||||
* @param damage
|
* @param damage
|
||||||
* a int.
|
* 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;
|
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.")
|
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.")) {
|
|| attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked.")) {
|
||||||
combat.addDefendingDamage(damage, attacker);
|
damageMap.put(null, damage);
|
||||||
return;
|
return damageMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
final boolean hasTrample = attacker.hasKeyword("Trample");
|
final boolean hasTrample = attacker.hasKeyword("Trample");
|
||||||
|
|
||||||
if (block.size() == 1) {
|
if (block.size() == 1) {
|
||||||
@@ -1678,12 +1681,12 @@ public class ComputerUtilCombat {
|
|||||||
// If Extra trample damage, assign to defending
|
// If Extra trample damage, assign to defending
|
||||||
// player/planeswalker
|
// player/planeswalker
|
||||||
if (0 < trample) {
|
if (0 < trample) {
|
||||||
combat.addDefendingDamage(trample, attacker);
|
damageMap.put(null, trample);
|
||||||
}
|
}
|
||||||
|
|
||||||
blocker.addAssignedDamage(damageNeeded, attacker);
|
damageMap.put(blocker, damageNeeded);
|
||||||
} else {
|
} else {
|
||||||
blocker.addAssignedDamage(damage, attacker);
|
damageMap.put(blocker, damage);
|
||||||
}
|
}
|
||||||
} // 1 blocker
|
} // 1 blocker
|
||||||
else {
|
else {
|
||||||
@@ -1695,10 +1698,7 @@ public class ComputerUtilCombat {
|
|||||||
final int enoughDamageToKill = ComputerUtilCombat.getEnoughDamageToKill(b, damage, attacker, true);
|
final int enoughDamageToKill = ComputerUtilCombat.getEnoughDamageToKill(b, damage, attacker, true);
|
||||||
if (enoughDamageToKill <= damage) {
|
if (enoughDamageToKill <= damage) {
|
||||||
damage -= enoughDamageToKill;
|
damage -= enoughDamageToKill;
|
||||||
final List<Card> cl = new ArrayList<Card>();
|
damageMap.put(b, enoughDamageToKill);
|
||||||
cl.add(attacker);
|
|
||||||
|
|
||||||
b.addAssignedDamage(enoughDamageToKill, c);
|
|
||||||
} else {
|
} else {
|
||||||
killsAllBlockers = false;
|
killsAllBlockers = false;
|
||||||
}
|
}
|
||||||
@@ -1708,13 +1708,14 @@ public class ComputerUtilCombat {
|
|||||||
if (killsAllBlockers && damage > 0) {
|
if (killsAllBlockers && damage > 0) {
|
||||||
// if attacker has no trample, and there's damage left, assign the rest to the last blocker
|
// if attacker has no trample, and there's damage left, assign the rest to the last blocker
|
||||||
if (!hasTrample && lastBlocker != null) {
|
if (!hasTrample && lastBlocker != null) {
|
||||||
lastBlocker.addAssignedDamage(damage, c);
|
damageMap.put(lastBlocker, damage);
|
||||||
damage = 0;
|
damage = 0;
|
||||||
} else if (hasTrample) {
|
} else if (hasTrample) {
|
||||||
combat.addDefendingDamage(damage, c);
|
damageMap.put(null, damage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return damageMap;
|
||||||
} // setAssignedDamage()
|
} // setAssignedDamage()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,9 @@ import forge.CardPredicates;
|
|||||||
import forge.GameEntity;
|
import forge.GameEntity;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.trigger.TriggerType;
|
import forge.card.trigger.TriggerType;
|
||||||
import forge.game.ai.ComputerUtilCombat;
|
|
||||||
import forge.game.event.BlockerAssignedEvent;
|
import forge.game.event.BlockerAssignedEvent;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.GuiDialog;
|
|
||||||
import forge.gui.match.CMatchUI;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -695,14 +692,10 @@ public class Combat {
|
|||||||
|
|
||||||
if (!attackers.isEmpty()) {
|
if (!attackers.isEmpty()) {
|
||||||
assignedDamage = true;
|
assignedDamage = true;
|
||||||
if (blocker.getController().isHuman()) { // who is defending matters
|
Map<Card, Integer> map = blocker.getController().getController().assignCombatDamage(blocker, attackers, damage, null);
|
||||||
if (attackers.size() > 1) {
|
for (Entry<Card, Integer> dt : map.entrySet()) {
|
||||||
CMatchUI.SINGLETON_INSTANCE.assignDamage(blocker, attackers, damage, null);
|
dt.getKey().addAssignedDamage(dt.getValue(), blocker);
|
||||||
} else {
|
dt.getKey().updateObservers();
|
||||||
attackers.get(0).addAssignedDamage(damage, blocker);
|
|
||||||
}
|
|
||||||
} else { // computer attacks
|
|
||||||
ComputerUtilCombat.distributeAIDamage(blocker, attackers, damage, this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -711,12 +704,6 @@ public class Combat {
|
|||||||
return assignedDamage;
|
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) {
|
private final boolean assignAttackersDamage(boolean firstStrikeDamage) {
|
||||||
this.defendingDamageMap.clear(); // this should really happen in deal damage
|
this.defendingDamageMap.clear(); // this should really happen in deal damage
|
||||||
List<Card> blockers = null;
|
List<Card> blockers = null;
|
||||||
@@ -746,19 +733,17 @@ public class Combat {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.getAttackingPlayer().isHuman()) { // human attacks
|
Map<Card, Integer> map = this.getAttackingPlayer().getController().assignCombatDamage(attacker, blockers, damageDealt, this.getDefenderByAttacker(attacker));
|
||||||
if (assignDamageAsIfNotBlocked(attacker)) {
|
for (Entry<Card, Integer> dt : map.entrySet()) {
|
||||||
this.addDefendingDamage(damageDealt, attacker);
|
if( dt.getKey() == null && trampler) {
|
||||||
|
if (dt.getValue() > 0)
|
||||||
|
addDefendingDamage(dt.getValue(), attacker);
|
||||||
} else {
|
} else {
|
||||||
if (trampler || (blockers.size() > 1)) {
|
dt.getKey().addAssignedDamage(dt.getValue(), attacker);
|
||||||
CMatchUI.SINGLETON_INSTANCE.assignDamage(attacker, blockers, damageDealt, this.getDefenderByAttacker(attacker));
|
dt.getKey().updateObservers();
|
||||||
} else {
|
|
||||||
blockers.get(0).addAssignedDamage(damageDealt, attacker);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else { // computer attacks
|
|
||||||
ComputerUtilCombat.distributeAIDamage(attacker, blockers, damageDealt, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // if !hasFirstStrike ...
|
} // if !hasFirstStrike ...
|
||||||
} // for
|
} // for
|
||||||
return assignedDamage;
|
return assignedDamage;
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package forge.game.player;
|
package forge.game.player;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
|
import forge.GameEntity;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.control.input.Input;
|
import forge.control.input.Input;
|
||||||
@@ -88,4 +90,6 @@ public abstract class PlayerController {
|
|||||||
public abstract Deck sideboard(final Deck deck, GameType gameType);
|
public abstract Deck sideboard(final Deck deck, GameType gameType);
|
||||||
|
|
||||||
|
|
||||||
|
public abstract Map<Card, Integer> assignCombatDamage(Card attacker, List<Card> blockers, int damageDealt, GameEntity defender);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package forge.game.player;
|
package forge.game.player;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
|
import forge.GameEntity;
|
||||||
import forge.card.spellability.Spell;
|
import forge.card.spellability.Spell;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.control.input.Input;
|
import forge.control.input.Input;
|
||||||
@@ -13,6 +15,7 @@ import forge.game.ai.AiController;
|
|||||||
import forge.game.ai.AiInputBlock;
|
import forge.game.ai.AiInputBlock;
|
||||||
import forge.game.ai.AiInputCommon;
|
import forge.game.ai.AiInputCommon;
|
||||||
import forge.game.ai.ComputerUtil;
|
import forge.game.ai.ComputerUtil;
|
||||||
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.gui.GuiChoose;
|
import forge.gui.GuiChoose;
|
||||||
|
|
||||||
|
|
||||||
@@ -160,6 +163,14 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
return deck;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package forge.game.player;
|
package forge.game.player;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
|
import forge.GameEntity;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.control.input.Input;
|
import forge.control.input.Input;
|
||||||
@@ -170,6 +173,32 @@ public class PlayerControllerHuman extends PlayerController {
|
|||||||
return res;
|
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?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ package forge.gui.match;
|
|||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
|
|
||||||
@@ -186,19 +188,22 @@ public enum CMatchUI implements CardContainer {
|
|||||||
* @param blockers   {@link forge.CardList}
|
* @param blockers   {@link forge.CardList}
|
||||||
* @param damage   int
|
* @param damage   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) {
|
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
|
// If the first blocker can absorb all of the damage, don't show the Assign Damage Frame
|
||||||
Card firstBlocker = blockers.get(0);
|
Card firstBlocker = blockers.get(0);
|
||||||
if (!attacker.hasKeyword("Deathtouch") && firstBlocker.getLethalDamage() >= damage) {
|
if (!attacker.hasKeyword("Deathtouch") && firstBlocker.getLethalDamage() >= damage) {
|
||||||
firstBlocker.addAssignedDamage(damage, attacker);
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ import net.miginfocom.swing.MigLayout;
|
|||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.CounterType;
|
import forge.CounterType;
|
||||||
import forge.GameEntity;
|
import forge.GameEntity;
|
||||||
import forge.Singletons;
|
|
||||||
import forge.game.MatchController;
|
import forge.game.MatchController;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.gui.SOverlayUtils;
|
import forge.gui.SOverlayUtils;
|
||||||
@@ -66,7 +65,6 @@ public class VAssignDamage {
|
|||||||
// Damage storage
|
// Damage storage
|
||||||
private final int totalDamageToAssign;
|
private final int totalDamageToAssign;
|
||||||
|
|
||||||
private final Card attacker;
|
|
||||||
private boolean attackerHasDeathtouch = false;
|
private boolean attackerHasDeathtouch = false;
|
||||||
private boolean attackerHasTrample = false;
|
private boolean attackerHasTrample = false;
|
||||||
private boolean attackerHasInfect = false;
|
private boolean attackerHasInfect = false;
|
||||||
@@ -106,12 +104,11 @@ public class VAssignDamage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mouse actions
|
// Mouse actions
|
||||||
private final MouseAdapter madDefender = new MouseAdapter() {
|
private final MouseAdapter mad = new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseEntered(final MouseEvent evt) {
|
public void mouseEntered(final MouseEvent evt) {
|
||||||
Card source = ((CardPanel) evt.getSource()).getCard();
|
Card source = ((CardPanel) evt.getSource()).getCard();
|
||||||
if (!damage.containsKey(source))
|
if (!damage.containsKey(source)) source = null; // to get player instead of fake card
|
||||||
source = null;
|
|
||||||
|
|
||||||
FSkin.Colors brdrColor = VAssignDamage.this.canAssignTo(source) ? FSkin.Colors.CLR_ACTIVE : FSkin.Colors.CLR_INACTIVE;
|
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));
|
((CardPanel) evt.getSource()).setBorder(new LineBorder(FSkin.getColor(brdrColor), 2));
|
||||||
@@ -149,7 +146,6 @@ public class VAssignDamage {
|
|||||||
this.attackerHasDeathtouch = attacker0.hasKeyword("Deathtouch");
|
this.attackerHasDeathtouch = attacker0.hasKeyword("Deathtouch");
|
||||||
this.attackerHasInfect = attacker0.hasKeyword("Infect");
|
this.attackerHasInfect = attacker0.hasKeyword("Infect");
|
||||||
this.attackerHasTrample = defender != null && attacker0.hasKeyword("Trample");
|
this.attackerHasTrample = defender != null && attacker0.hasKeyword("Trample");
|
||||||
this.attacker = attacker0;
|
|
||||||
|
|
||||||
// Top-level UI stuff
|
// Top-level UI stuff
|
||||||
final JPanel overlay = SOverlayUtils.genericOverlay();
|
final JPanel overlay = SOverlayUtils.genericOverlay();
|
||||||
@@ -257,7 +253,7 @@ public class VAssignDamage {
|
|||||||
cp.setCardBounds(0, 0, 105, 150);
|
cp.setCardBounds(0, 0, 105, 150);
|
||||||
cp.setOpaque(true);
|
cp.setOpaque(true);
|
||||||
pnlDefenders.add(cp, "w 145px!, h 170px!, gap 5px 5px 3px 3px, ax center");
|
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 )
|
if ( getRemainingDamage() > 0 )
|
||||||
return;
|
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();
|
dlg.dispose();
|
||||||
SOverlayUtils.hideOverlay();
|
SOverlayUtils.hideOverlay();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user