mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Combat: removed getDefendingPlayer (there may be multiple defenders per combat)
This commit is contained in:
@@ -25,6 +25,7 @@ import forge.Card;
|
||||
|
||||
import forge.Singletons;
|
||||
import forge.game.phase.CombatUtil;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.PlayerZone;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.framework.SDisplayUtil;
|
||||
@@ -46,6 +47,15 @@ public class InputBlock extends Input {
|
||||
|
||||
private Card currentAttacker = null;
|
||||
private final HashMap<Card,List<Card>> allBlocking = new HashMap<Card, List<Card>>();
|
||||
private final Player defender;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param priority
|
||||
*/
|
||||
public InputBlock(Player priority) {
|
||||
defender = priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -86,7 +96,7 @@ public class InputBlock extends Input {
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final void selectButtonOK() {
|
||||
if (CombatUtil.finishedMandatoryBlocks(Singletons.getModel().getGame().getCombat())) {
|
||||
if (CombatUtil.finishedMandatoryBlocks(Singletons.getModel().getGame().getCombat(), defender)) {
|
||||
// Done blocking
|
||||
ButtonUtil.reset();
|
||||
CombatUtil.orderMultipleCombatants(Singletons.getModel().getGame().getCombat());
|
||||
@@ -106,8 +116,8 @@ public class InputBlock extends Input {
|
||||
reminder = false;
|
||||
} else {
|
||||
// Make sure this card is valid to even be a blocker
|
||||
if (this.currentAttacker != null && card.isCreature() && card.getController().isHuman()
|
||||
&& zone.is(ZoneType.Battlefield, Singletons.getControl().getPlayer())) {
|
||||
if (this.currentAttacker != null && card.isCreature() && card.getController().equals(defender)
|
||||
&& zone.is(ZoneType.Battlefield, defender)) {
|
||||
// Create a new blockedBy list if it doesn't exist
|
||||
if (!this.allBlocking.containsKey(card)) {
|
||||
this.allBlocking.put(card, new ArrayList<Card>());
|
||||
|
||||
@@ -212,7 +212,7 @@ public class InputControl extends MyObservable implements java.io.Serializable {
|
||||
}
|
||||
|
||||
if ( priority.isHuman() )
|
||||
return new InputBlock();
|
||||
return new InputBlock(priority);
|
||||
|
||||
// ai is under attack
|
||||
priority.getController().getAiInput().getComputer().declareBlockers();
|
||||
|
||||
@@ -66,7 +66,6 @@ public class Combat {
|
||||
private final HashMap<Card, GameEntity> attackerToDefender = new HashMap<Card, GameEntity>();
|
||||
|
||||
private Player attackingPlayer = null;
|
||||
private Player defendingPlayer = null;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -90,7 +89,6 @@ public class Combat {
|
||||
this.defendingDamageMap.clear();
|
||||
|
||||
this.attackingPlayer = null;
|
||||
this.defendingPlayer = null;
|
||||
this.currentDefender = 0;
|
||||
this.nextDefender = 0;
|
||||
|
||||
@@ -250,18 +248,6 @@ public class Combat {
|
||||
this.attackingPlayer = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Setter for the field <code>defendingPlayer</code>.
|
||||
* </p>
|
||||
*
|
||||
* @param player
|
||||
* a {@link forge.game.player.Player} object.
|
||||
*/
|
||||
public final void setDefendingPlayer(final Player player) {
|
||||
this.defendingPlayer = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Getter for the field <code>attackingPlayer</code>.
|
||||
@@ -277,20 +263,6 @@ public class Combat {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Getter for the field <code>defendingPlayer</code>.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link forge.game.player.Player} object.
|
||||
*/
|
||||
public final Player getDefendingPlayer() {
|
||||
if (this.attackingPlayer != null) {
|
||||
return this.defendingPlayer;
|
||||
} else {
|
||||
return Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn().getOpponent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -410,6 +382,19 @@ public class Combat {
|
||||
return this.attackerToDefender.get(c);
|
||||
}
|
||||
|
||||
public final Player getDefenderPlayerByAttacker(final Card c) {
|
||||
GameEntity defender = getDefenderByAttacker(c);
|
||||
|
||||
// System.out.println(c.toString() + " attacks " + defender.toString());
|
||||
if ( defender instanceof Player)
|
||||
return (Player) defender;
|
||||
|
||||
// maybe attack on a controlled planeswalker?
|
||||
if ( defender instanceof Card )
|
||||
return ((Card)defender).getController();
|
||||
return null;
|
||||
}
|
||||
|
||||
public final GameEntity getDefendingEntity(final Card c) {
|
||||
GameEntity defender = this.attackerToDefender.get(c);
|
||||
|
||||
@@ -561,7 +546,7 @@ public class Combat {
|
||||
*/
|
||||
public Player getDefendingPlayerRelatedTo(final Card source) {
|
||||
|
||||
Player defender = this.getDefendingPlayer();
|
||||
Player defender = getDefenderPlayerByAttacker(source);
|
||||
Card attacker = source;
|
||||
if (source.isAura()) {
|
||||
attacker = source.getEnchantingCard();
|
||||
@@ -1002,16 +987,7 @@ public class Combat {
|
||||
// System.out.println("\nWho attacks attacks " + priority.toString() + "?");
|
||||
for(Card c : getAttackers())
|
||||
{
|
||||
GameEntity defender = getDefenderByAttacker(c);
|
||||
// System.out.println(c.toString() + " attacks " + defender.toString());
|
||||
|
||||
if ( defender.equals(priority) ) {
|
||||
return true;
|
||||
}
|
||||
// maybe attack on a controlled planeswalker?
|
||||
if (!(defender instanceof Card)) continue;
|
||||
Card pw = (Card)defender;
|
||||
if( pw.getController().equals(priority) ) {
|
||||
if ( priority.equals(getDefenderPlayerByAttacker(c)) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ public class CombatUtil {
|
||||
* a {@link forge.game.phase.Combat} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean finishedMandatoryBlocks(final Combat combat) {
|
||||
public static boolean finishedMandatoryBlocks(final Combat combat, final Player defending) {
|
||||
|
||||
final List<Card> blockers = Singletons.getControl().getPlayer().getCreaturesInPlay();
|
||||
final List<Card> attackers = combat.getAttackerList();
|
||||
@@ -395,7 +395,7 @@ public class CombatUtil {
|
||||
if (CombatUtil.canBlock(attacker, blocker, combat)) {
|
||||
boolean must = true;
|
||||
if (attacker.hasKeyword("CARDNAME can't be blocked except by two or more creatures.")) {
|
||||
final List<Card> possibleBlockers = CardLists.filter(combat.getDefendingPlayer().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
|
||||
final List<Card> possibleBlockers = CardLists.filter(defending.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
|
||||
possibleBlockers.remove(blocker);
|
||||
if (!CombatUtil.canBeBlocked(attacker, possibleBlockers)) {
|
||||
must = false;
|
||||
@@ -455,16 +455,14 @@ public class CombatUtil {
|
||||
|
||||
private static void orderBlockingMultipleAttackers(final Combat combat) {
|
||||
// If there are multiple blockers, the Attacker declares the Assignment Order
|
||||
final Player player = combat.getDefendingPlayer();
|
||||
final List<Card> blockers = combat.getAllBlockers();
|
||||
for (final Card blocker : blockers) {
|
||||
for (final Card blocker : combat.getAllBlockers()) {
|
||||
List<Card> attackers = combat.getAttackersBlockedBy(blocker);
|
||||
if (attackers.size() <= 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<Card> orderedAttacker = null;
|
||||
if (player.isHuman()) {
|
||||
if (blocker.getController().isHuman()) {
|
||||
List<Card> ordered = GuiChoose.getOrderChoices("Choose Blocking Order", "Damaged First", 0, attackers, null, blocker);
|
||||
|
||||
orderedAttacker = new ArrayList<Card>();
|
||||
@@ -518,7 +516,7 @@ public class CombatUtil {
|
||||
if (CombatUtil.canBeBlocked(attacker, combat) && CombatUtil.canBlock(attacker, blocker)) {
|
||||
boolean canBe = true;
|
||||
if (attacker.hasKeyword("CARDNAME can't be blocked except by two or more creatures.")) {
|
||||
final List<Card> blockers = CardLists.filter(combat.getDefendingPlayer().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
|
||||
final List<Card> blockers = combat.getDefenderPlayerByAttacker(attacker).getCreaturesInPlay();
|
||||
blockers.remove(blocker);
|
||||
if (!CombatUtil.canBeBlocked(attacker, blockers)) {
|
||||
canBe = false;
|
||||
@@ -535,7 +533,7 @@ public class CombatUtil {
|
||||
if (CombatUtil.canBeBlocked(attacker, combat) && CombatUtil.canBlock(attacker, blocker)) {
|
||||
boolean canBe = true;
|
||||
if (attacker.hasKeyword("CARDNAME can't be blocked except by two or more creatures.")) {
|
||||
final List<Card> blockers = CardLists.filter(combat.getDefendingPlayer().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
|
||||
final List<Card> blockers = combat.getDefenderPlayerByAttacker(attacker).getCreaturesInPlay();
|
||||
blockers.remove(blocker);
|
||||
if (!CombatUtil.canBeBlocked(attacker, blockers)) {
|
||||
canBe = false;
|
||||
@@ -2523,9 +2521,10 @@ public class CombatUtil {
|
||||
final List<Card> list = attackers.get(def);
|
||||
|
||||
for (final Card attacker : list) {
|
||||
sb.append(combat.getDefendingPlayer()).append(" assigned ");
|
||||
|
||||
|
||||
defend = Singletons.getModel().getGame().getCombat().getBlockers(attacker);
|
||||
sb.append(combat.getDefenderByAttacker(attacker)).append(" assigned ");
|
||||
|
||||
if (!defend.isEmpty()) {
|
||||
// loop through blockers
|
||||
|
||||
@@ -26,7 +26,6 @@ import com.esotericsoftware.minlog.Log;
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
import forge.CardPredicates;
|
||||
import forge.GameActionUtil;
|
||||
import forge.Singletons;
|
||||
import forge.card.trigger.TriggerType;
|
||||
import forge.game.GameState;
|
||||
@@ -455,13 +454,11 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
|
||||
// that give extra combat can do it like ExtraTurn stack ExtraPhases
|
||||
if (this.extraCombats > 0) {
|
||||
final Player player = this.getPlayerTurn();
|
||||
final Player opp = player.getOpponent();
|
||||
|
||||
this.bCombat = true;
|
||||
this.extraCombats--;
|
||||
game.getCombat().reset();
|
||||
game.getCombat().setAttackingPlayer(player);
|
||||
game.getCombat().setDefendingPlayer(opp);
|
||||
this.phase = PhaseType.COMBAT_BEGIN;
|
||||
}
|
||||
break;
|
||||
@@ -539,7 +536,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
|
||||
if (!this.extraTurns.isEmpty()) {
|
||||
ExtraTurn extraTurn = this.extraTurns.pop();
|
||||
nextTurn = extraTurn.getPlayer();
|
||||
if (skipTurnTimeVault(nextTurn)) {
|
||||
if (nextTurn.skipTurnTimeVault()) {
|
||||
return getNextActivePlayer();
|
||||
}
|
||||
if (extraTurn.isLoseAtEndStep()) {
|
||||
@@ -550,42 +547,13 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
|
||||
}
|
||||
return nextTurn;
|
||||
}
|
||||
if (skipTurnTimeVault(nextTurn)) {
|
||||
if (nextTurn.skipTurnTimeVault()) {
|
||||
this.setPlayerTurn(nextTurn);
|
||||
return getNextActivePlayer();
|
||||
}
|
||||
return nextTurn;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* skipTurnTimeVault.
|
||||
* </p>
|
||||
*
|
||||
* @param turn
|
||||
* a {@link forge.game.player.Player} object.
|
||||
* @return a {@link forge.game.player.Player} object.
|
||||
*/
|
||||
private boolean skipTurnTimeVault(Player turn) {
|
||||
// time vault:
|
||||
List<Card> vaults = turn.getCardsIn(ZoneType.Battlefield, "Time Vault");
|
||||
vaults = CardLists.filter(vaults, CardPredicates.Presets.TAPPED);
|
||||
|
||||
if (vaults.size() > 0) {
|
||||
final Card crd = vaults.get(0);
|
||||
|
||||
if (turn.isHuman()) {
|
||||
if (GameActionUtil.showYesNoDialog(crd, "Untap " + crd + "?")) {
|
||||
crd.untap();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// TODO Should AI skip his turn for time vault?
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* is.
|
||||
|
||||
@@ -81,7 +81,6 @@ public class PhaseUtil {
|
||||
|
||||
game.getCombat().reset();
|
||||
game.getCombat().setAttackingPlayer(turn);
|
||||
game.getCombat().setDefendingPlayer(turn.getOpponent());
|
||||
|
||||
// Tokens starting game in play now actually suffer from Sum. Sickness
|
||||
// again
|
||||
|
||||
@@ -1771,7 +1771,7 @@ public class ComputerUtil {
|
||||
final ComputerUtilAttack att = new ComputerUtilAttack(ai.getCardsIn(ZoneType.Battlefield),
|
||||
opp.getCardsIn(ZoneType.Battlefield));
|
||||
|
||||
return att.getAttackers(ai);
|
||||
return att.getAttackers(ai, opp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -493,7 +493,7 @@ public class ComputerUtilAttack {
|
||||
*
|
||||
* @return a {@link forge.game.phase.Combat} object.
|
||||
*/
|
||||
public final Combat getAttackers(final Player ai) {
|
||||
public final Combat getAttackers(final Player ai, final Player opponent) {
|
||||
// if this method is called multiple times during a turn,
|
||||
// it will always return the same value
|
||||
// randomInt is used so that the computer doesn't always
|
||||
@@ -505,9 +505,9 @@ public class ComputerUtilAttack {
|
||||
|
||||
final Combat combat = new Combat();
|
||||
combat.setAttackingPlayer(game.getCombat().getAttackingPlayer());
|
||||
combat.setDefendingPlayer(game.getCombat().getDefendingPlayer());
|
||||
|
||||
game.getCombat().initiatePossibleDefenders(game.getCombat().getDefendingPlayer());
|
||||
|
||||
game.getCombat().initiatePossibleDefenders(opponent);
|
||||
combat.setDefenders(game.getCombat().getDefenders());
|
||||
|
||||
if (this.attackers.isEmpty()) {
|
||||
|
||||
@@ -2866,4 +2866,31 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* skipTurnTimeVault.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link forge.game.player.Player} object.
|
||||
*/
|
||||
public boolean skipTurnTimeVault() {
|
||||
// time vault:
|
||||
List<Card> vaults = getCardsIn(ZoneType.Battlefield, "Time Vault");
|
||||
vaults = CardLists.filter(vaults, Presets.TAPPED);
|
||||
|
||||
if (vaults.size() > 0) {
|
||||
final Card crd = vaults.get(0);
|
||||
|
||||
if (isHuman()) {
|
||||
if (GameActionUtil.showYesNoDialog(crd, "Untap " + crd + "?")) {
|
||||
crd.untap();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// TODO Should AI skip his turn for time vault?
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user