Skip combat phases if player has no creatures that can attack

This commit is contained in:
drdev
2013-11-30 20:57:30 +00:00
parent cfeeda3c93
commit 2ffc18cc89
3 changed files with 105 additions and 64 deletions

View File

@@ -20,6 +20,7 @@ package forge.game.combat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
@@ -669,6 +670,45 @@ public class CombatUtil {
} }
} }
// can a player attack with one or more creatures at the moment?
/**
* <p>
* canAttack.
* </p>
*
* @param p
* a {@link forge.game.player} object.
* @return a boolean.
*/
public static boolean canAttack(Player p) {
List<Card> creatures = p.getCreaturesInPlay();
if (creatures.isEmpty()) { return false; }
List<Player> defenders = p.getOpponents();
if (defenders.isEmpty()) { return false; }
boolean foundCreatureThatCantAttackAlone = false;
for (Card c : creatures) {
if (CombatUtil.canAttack(c)) {
for (Player def : defenders) {
if (CombatUtil.canAttackNextTurn(c, def)) {
if (c.hasKeyword("CARDNAME can't attack or block alone.")) {
//ensure another possible attacker is found
//if the first one found can't attack alone
if (!foundCreatureThatCantAttackAlone) {
foundCreatureThatCantAttackAlone = true;
break;
}
}
return true;
}
}
}
}
return false;
}
// can a creature attack given the combat state // can a creature attack given the combat state
/** /**
* <p> * <p>
@@ -685,37 +725,40 @@ public class CombatUtil {
int cntAttackers = combat.getAttackers().size(); int cntAttackers = combat.getAttackers().size();
final Game game = c.getGame(); final Game game = c.getGame();
for (final Card card : game.getCardsIn(ZoneType.Battlefield)) { if (cntAttackers > 0) {
for (final String keyword : card.getKeyword()) { for (final Card card : game.getCardsIn(ZoneType.Battlefield)) {
if (keyword.equals("No more than two creatures can attack each combat.") && cntAttackers > 1) { for (final String keyword : card.getKeyword()) {
return false; if (cntAttackers > 1) {
} if (keyword.equals("No more than two creatures can attack each combat.")) {
if (keyword.equals("No more than two creatures can attack you each combat.") && cntAttackers > 1 return false;
&& card.getController().getOpponent().equals(c.getController())) { }
return false; if (keyword.equals("No more than two creatures can attack you each combat.") &&
} card.getController().getOpponent().equals(c.getController())) {
if (keyword.equals("CARDNAME can only attack alone.") && combat.isAttacking(card)) { return false;
return false; }
}
if (keyword.equals("CARDNAME can only attack alone.") && combat.isAttacking(card)) {
return false;
}
} }
} }
if (c.hasKeyword("CARDNAME can only attack alone.")) {
return false;
}
if (game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.onlyOneAttackerACombat)) {
return false;
}
} }
final List<Card> list = c.getController().getCreaturesInPlay(); if (c.hasKeyword("CARDNAME can't attack or block alone.") &&
if (list.size() < 2 && c.hasKeyword("CARDNAME can't attack or block alone.")) { c.getController().getCreaturesInPlay().size() < 2) {
return false; return false;
} }
if (cntAttackers > 0 && c.hasKeyword("CARDNAME can only attack alone.")) { if ((cntAttackers > 0 || c.getController().getAttackedWithCreatureThisTurn()) &&
return false; game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.onlyOneAttackerATurn)) {
}
if (cntAttackers > 0
&& game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.onlyOneAttackerACombat)) {
return false;
}
if ((cntAttackers > 0 || c.getController().getAttackedWithCreatureThisTurn())
&& game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.onlyOneAttackerATurn)) {
return false; return false;
} }
@@ -806,7 +849,6 @@ public class CombatUtil {
final int[] powerLimit = { 0 }; final int[] powerLimit = { 0 };
String cantAttackKw = null; String cantAttackKw = null;
for( String kw : c.getKeyword()) { for( String kw : c.getKeyword()) {
if (kw.startsWith("CARDNAME can't attack if defending player controls an untapped creature with power")) { if (kw.startsWith("CARDNAME can't attack if defending player controls an untapped creature with power")) {
cantAttackKw = kw; cantAttackKw = kw;

View File

@@ -51,6 +51,7 @@ import forge.game.card.CardLists;
import forge.game.card.CardPredicates; import forge.game.card.CardPredicates;
import forge.game.card.CounterType; import forge.game.card.CounterType;
import forge.game.card.CardPredicates.Presets; import forge.game.card.CardPredicates.Presets;
import forge.game.combat.CombatUtil;
import forge.game.event.GameEventLandPlayed; import forge.game.event.GameEventLandPlayed;
import forge.game.event.GameEventMulligan; import forge.game.event.GameEventMulligan;
import forge.game.event.GameEventPlayerControl; import forge.game.event.GameEventPlayerControl;
@@ -2947,7 +2948,6 @@ public class Player extends GameEntity implements Comparable<Player> {
* @return a boolean. * @return a boolean.
*/ */
public boolean isSkippingCombat() { public boolean isSkippingCombat() {
if (hasKeyword("Skip your next combat phase.")) { if (hasKeyword("Skip your next combat phase.")) {
return true; return true;
} }
@@ -2963,7 +2963,8 @@ public class Player extends GameEntity implements Comparable<Player> {
return true; return true;
} }
return false; //skip combat unless player has a creature that can attack
return !CombatUtil.canAttack(this);
} }
/** /**

View File

@@ -47,7 +47,6 @@ public class InputAttack extends InputSyncronizedBase {
/** Constant <code>serialVersionUID=7849903731842214245L</code>. */ /** Constant <code>serialVersionUID=7849903731842214245L</code>. */
private static final long serialVersionUID = 7849903731842214245L; private static final long serialVersionUID = 7849903731842214245L;
private final Combat combat; private final Combat combat;
private final List<GameEntity> defenders; private final List<GameEntity> defenders;
private GameEntity currentDefender; private GameEntity currentDefender;
@@ -62,7 +61,6 @@ public class InputAttack extends InputSyncronizedBase {
this.defenders = combat.getDefenders(); this.defenders = combat.getDefenders();
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void showMessage() { public final void showMessage() {