Combat: removed getDefendingPlayer (there may be multiple defenders per combat)

This commit is contained in:
Maxmtg
2012-10-23 05:57:36 +00:00
parent a0043c5415
commit 4739492a12
9 changed files with 71 additions and 92 deletions

View File

@@ -25,6 +25,7 @@ import forge.Card;
import forge.Singletons; import forge.Singletons;
import forge.game.phase.CombatUtil; import forge.game.phase.CombatUtil;
import forge.game.player.Player;
import forge.game.zone.PlayerZone; import forge.game.zone.PlayerZone;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.framework.SDisplayUtil; import forge.gui.framework.SDisplayUtil;
@@ -46,6 +47,15 @@ public class InputBlock extends Input {
private Card currentAttacker = null; private Card currentAttacker = null;
private final HashMap<Card,List<Card>> allBlocking = new HashMap<Card, List<Card>>(); 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> * <p>
@@ -86,7 +96,7 @@ public class InputBlock extends Input {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void selectButtonOK() { public final void selectButtonOK() {
if (CombatUtil.finishedMandatoryBlocks(Singletons.getModel().getGame().getCombat())) { if (CombatUtil.finishedMandatoryBlocks(Singletons.getModel().getGame().getCombat(), defender)) {
// Done blocking // Done blocking
ButtonUtil.reset(); ButtonUtil.reset();
CombatUtil.orderMultipleCombatants(Singletons.getModel().getGame().getCombat()); CombatUtil.orderMultipleCombatants(Singletons.getModel().getGame().getCombat());
@@ -106,8 +116,8 @@ public class InputBlock extends Input {
reminder = false; reminder = false;
} else { } else {
// Make sure this card is valid to even be a blocker // Make sure this card is valid to even be a blocker
if (this.currentAttacker != null && card.isCreature() && card.getController().isHuman() if (this.currentAttacker != null && card.isCreature() && card.getController().equals(defender)
&& zone.is(ZoneType.Battlefield, Singletons.getControl().getPlayer())) { && zone.is(ZoneType.Battlefield, defender)) {
// Create a new blockedBy list if it doesn't exist // Create a new blockedBy list if it doesn't exist
if (!this.allBlocking.containsKey(card)) { if (!this.allBlocking.containsKey(card)) {
this.allBlocking.put(card, new ArrayList<Card>()); this.allBlocking.put(card, new ArrayList<Card>());

View File

@@ -212,7 +212,7 @@ public class InputControl extends MyObservable implements java.io.Serializable {
} }
if ( priority.isHuman() ) if ( priority.isHuman() )
return new InputBlock(); return new InputBlock(priority);
// ai is under attack // ai is under attack
priority.getController().getAiInput().getComputer().declareBlockers(); priority.getController().getAiInput().getComputer().declareBlockers();

View File

@@ -66,7 +66,6 @@ public class Combat {
private final HashMap<Card, GameEntity> attackerToDefender = new HashMap<Card, GameEntity>(); private final HashMap<Card, GameEntity> attackerToDefender = new HashMap<Card, GameEntity>();
private Player attackingPlayer = null; private Player attackingPlayer = null;
private Player defendingPlayer = null;
/** /**
* <p> * <p>
@@ -90,7 +89,6 @@ public class Combat {
this.defendingDamageMap.clear(); this.defendingDamageMap.clear();
this.attackingPlayer = null; this.attackingPlayer = null;
this.defendingPlayer = null;
this.currentDefender = 0; this.currentDefender = 0;
this.nextDefender = 0; this.nextDefender = 0;
@@ -250,18 +248,6 @@ public class Combat {
this.attackingPlayer = player; 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> * <p>
* Getter for the field <code>attackingPlayer</code>. * 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> * <p>
@@ -410,6 +382,19 @@ public class Combat {
return this.attackerToDefender.get(c); 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) { public final GameEntity getDefendingEntity(final Card c) {
GameEntity defender = this.attackerToDefender.get(c); GameEntity defender = this.attackerToDefender.get(c);
@@ -561,7 +546,7 @@ public class Combat {
*/ */
public Player getDefendingPlayerRelatedTo(final Card source) { public Player getDefendingPlayerRelatedTo(final Card source) {
Player defender = this.getDefendingPlayer(); Player defender = getDefenderPlayerByAttacker(source);
Card attacker = source; Card attacker = source;
if (source.isAura()) { if (source.isAura()) {
attacker = source.getEnchantingCard(); attacker = source.getEnchantingCard();
@@ -1002,16 +987,7 @@ public class Combat {
// System.out.println("\nWho attacks attacks " + priority.toString() + "?"); // System.out.println("\nWho attacks attacks " + priority.toString() + "?");
for(Card c : getAttackers()) for(Card c : getAttackers())
{ {
GameEntity defender = getDefenderByAttacker(c); if ( priority.equals(getDefenderPlayerByAttacker(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) ) {
return true; return true;
} }
} }

View File

@@ -377,7 +377,7 @@ public class CombatUtil {
* a {@link forge.game.phase.Combat} object. * a {@link forge.game.phase.Combat} object.
* @return a boolean. * @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> blockers = Singletons.getControl().getPlayer().getCreaturesInPlay();
final List<Card> attackers = combat.getAttackerList(); final List<Card> attackers = combat.getAttackerList();
@@ -395,7 +395,7 @@ public class CombatUtil {
if (CombatUtil.canBlock(attacker, blocker, combat)) { if (CombatUtil.canBlock(attacker, blocker, combat)) {
boolean must = true; boolean must = true;
if (attacker.hasKeyword("CARDNAME can't be blocked except by two or more creatures.")) { 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); possibleBlockers.remove(blocker);
if (!CombatUtil.canBeBlocked(attacker, possibleBlockers)) { if (!CombatUtil.canBeBlocked(attacker, possibleBlockers)) {
must = false; must = false;
@@ -455,16 +455,14 @@ public class CombatUtil {
private static void orderBlockingMultipleAttackers(final Combat combat) { private static void orderBlockingMultipleAttackers(final Combat combat) {
// If there are multiple blockers, the Attacker declares the Assignment Order // If there are multiple blockers, the Attacker declares the Assignment Order
final Player player = combat.getDefendingPlayer(); for (final Card blocker : combat.getAllBlockers()) {
final List<Card> blockers = combat.getAllBlockers();
for (final Card blocker : blockers) {
List<Card> attackers = combat.getAttackersBlockedBy(blocker); List<Card> attackers = combat.getAttackersBlockedBy(blocker);
if (attackers.size() <= 1) { if (attackers.size() <= 1) {
continue; continue;
} }
List<Card> orderedAttacker = null; 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); List<Card> ordered = GuiChoose.getOrderChoices("Choose Blocking Order", "Damaged First", 0, attackers, null, blocker);
orderedAttacker = new ArrayList<Card>(); orderedAttacker = new ArrayList<Card>();
@@ -518,7 +516,7 @@ public class CombatUtil {
if (CombatUtil.canBeBlocked(attacker, combat) && CombatUtil.canBlock(attacker, blocker)) { if (CombatUtil.canBeBlocked(attacker, combat) && CombatUtil.canBlock(attacker, blocker)) {
boolean canBe = true; boolean canBe = true;
if (attacker.hasKeyword("CARDNAME can't be blocked except by two or more creatures.")) { 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); blockers.remove(blocker);
if (!CombatUtil.canBeBlocked(attacker, blockers)) { if (!CombatUtil.canBeBlocked(attacker, blockers)) {
canBe = false; canBe = false;
@@ -535,7 +533,7 @@ public class CombatUtil {
if (CombatUtil.canBeBlocked(attacker, combat) && CombatUtil.canBlock(attacker, blocker)) { if (CombatUtil.canBeBlocked(attacker, combat) && CombatUtil.canBlock(attacker, blocker)) {
boolean canBe = true; boolean canBe = true;
if (attacker.hasKeyword("CARDNAME can't be blocked except by two or more creatures.")) { 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); blockers.remove(blocker);
if (!CombatUtil.canBeBlocked(attacker, blockers)) { if (!CombatUtil.canBeBlocked(attacker, blockers)) {
canBe = false; canBe = false;
@@ -2523,9 +2521,10 @@ public class CombatUtil {
final List<Card> list = attackers.get(def); final List<Card> list = attackers.get(def);
for (final Card attacker : list) { for (final Card attacker : list) {
sb.append(combat.getDefendingPlayer()).append(" assigned ");
defend = Singletons.getModel().getGame().getCombat().getBlockers(attacker); defend = Singletons.getModel().getGame().getCombat().getBlockers(attacker);
sb.append(combat.getDefenderByAttacker(attacker)).append(" assigned ");
if (!defend.isEmpty()) { if (!defend.isEmpty()) {
// loop through blockers // loop through blockers

View File

@@ -26,7 +26,6 @@ import com.esotericsoftware.minlog.Log;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.CardPredicates; import forge.CardPredicates;
import forge.GameActionUtil;
import forge.Singletons; import forge.Singletons;
import forge.card.trigger.TriggerType; import forge.card.trigger.TriggerType;
import forge.game.GameState; 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 // that give extra combat can do it like ExtraTurn stack ExtraPhases
if (this.extraCombats > 0) { if (this.extraCombats > 0) {
final Player player = this.getPlayerTurn(); final Player player = this.getPlayerTurn();
final Player opp = player.getOpponent();
this.bCombat = true; this.bCombat = true;
this.extraCombats--; this.extraCombats--;
game.getCombat().reset(); game.getCombat().reset();
game.getCombat().setAttackingPlayer(player); game.getCombat().setAttackingPlayer(player);
game.getCombat().setDefendingPlayer(opp);
this.phase = PhaseType.COMBAT_BEGIN; this.phase = PhaseType.COMBAT_BEGIN;
} }
break; break;
@@ -539,7 +536,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
if (!this.extraTurns.isEmpty()) { if (!this.extraTurns.isEmpty()) {
ExtraTurn extraTurn = this.extraTurns.pop(); ExtraTurn extraTurn = this.extraTurns.pop();
nextTurn = extraTurn.getPlayer(); nextTurn = extraTurn.getPlayer();
if (skipTurnTimeVault(nextTurn)) { if (nextTurn.skipTurnTimeVault()) {
return getNextActivePlayer(); return getNextActivePlayer();
} }
if (extraTurn.isLoseAtEndStep()) { if (extraTurn.isLoseAtEndStep()) {
@@ -550,42 +547,13 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
} }
return nextTurn; return nextTurn;
} }
if (skipTurnTimeVault(nextTurn)) { if (nextTurn.skipTurnTimeVault()) {
this.setPlayerTurn(nextTurn); this.setPlayerTurn(nextTurn);
return getNextActivePlayer(); return getNextActivePlayer();
} }
return nextTurn; 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> * <p>
* is. * is.

View File

@@ -81,7 +81,6 @@ public class PhaseUtil {
game.getCombat().reset(); game.getCombat().reset();
game.getCombat().setAttackingPlayer(turn); game.getCombat().setAttackingPlayer(turn);
game.getCombat().setDefendingPlayer(turn.getOpponent());
// Tokens starting game in play now actually suffer from Sum. Sickness // Tokens starting game in play now actually suffer from Sum. Sickness
// again // again

View File

@@ -1771,7 +1771,7 @@ public class ComputerUtil {
final ComputerUtilAttack att = new ComputerUtilAttack(ai.getCardsIn(ZoneType.Battlefield), final ComputerUtilAttack att = new ComputerUtilAttack(ai.getCardsIn(ZoneType.Battlefield),
opp.getCardsIn(ZoneType.Battlefield)); opp.getCardsIn(ZoneType.Battlefield));
return att.getAttackers(ai); return att.getAttackers(ai, opp);
} }
/** /**

View File

@@ -493,7 +493,7 @@ public class ComputerUtilAttack {
* *
* @return a {@link forge.game.phase.Combat} object. * @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, // if this method is called multiple times during a turn,
// it will always return the same value // it will always return the same value
// randomInt is used so that the computer doesn't always // randomInt is used so that the computer doesn't always
@@ -505,9 +505,9 @@ public class ComputerUtilAttack {
final Combat combat = new Combat(); final Combat combat = new Combat();
combat.setAttackingPlayer(game.getCombat().getAttackingPlayer()); 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()); combat.setDefenders(game.getCombat().getDefenders());
if (this.attackers.isEmpty()) { if (this.attackers.isEmpty()) {

View File

@@ -2866,4 +2866,31 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
return false; 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;
}
} }