- Fix Crawlspace in multiplayer

- Move a method using getOpponent() to AI (only place it's used, to group the methods using this deprecated function in the AI code)
This commit is contained in:
elcnesh
2014-07-29 22:22:14 +00:00
parent ed496dbc10
commit ecc4620dda
7 changed files with 54 additions and 41 deletions

View File

@@ -394,7 +394,7 @@ public class AiAttackController {
} }
for (Card attacker : oppList) { for (Card attacker : oppList) {
if (!CombatUtil.canAttackNextTurn(attacker)) { if (!ComputerUtil.canAttackNextTurn(attacker)) {
continue; continue;
} }
if (blockersLeft > 0 && CombatUtil.canBeBlocked(attacker, ai)) { if (blockersLeft > 0 && CombatUtil.canBeBlocked(attacker, ai)) {
@@ -657,7 +657,7 @@ public class AiAttackController {
for (final Card pCard : this.oppList) { for (final Card pCard : this.oppList) {
// if the creature can attack next turn add it to counter attackers // if the creature can attack next turn add it to counter attackers
// list // list
if (CombatUtil.canAttackNextTurn(pCard)) { if (ComputerUtil.canAttackNextTurn(pCard)) {
nextTurnAttackers.add(pCard); nextTurnAttackers.add(pCard);
if (pCard.getNetCombatDamage() > 0) { if (pCard.getNetCombatDamage() > 0) {
candidateCounterAttackDamage += pCard.getNetCombatDamage(); candidateCounterAttackDamage += pCard.getNetCombatDamage();
@@ -684,7 +684,7 @@ public class AiAttackController {
for (final Card pCard : this.myList) { for (final Card pCard : this.myList) {
// if the creature can attack then it's a potential attacker this // if the creature can attack then it's a potential attacker this
// turn, assume summoning sickness creatures will be able to // turn, assume summoning sickness creatures will be able to
if (CombatUtil.canAttackNextTurn(pCard)) { if (ComputerUtil.canAttackNextTurn(pCard)) {
candidateAttackers.add(pCard); candidateAttackers.add(pCard);
if (pCard.getNetCombatDamage() > 0) { if (pCard.getNetCombatDamage() > 0) {
candidateUnblockedDamage += ComputerUtilCombat.damageIfUnblocked(pCard, opp, null); candidateUnblockedDamage += ComputerUtilCombat.damageIfUnblocked(pCard, opp, null);

View File

@@ -879,7 +879,7 @@ public class ComputerUtil {
playNow = false; playNow = false;
break; break;
} }
if (!playNow && c.isCreature() && CombatUtil.canAttackNextTurn(c) && c.canBeEquippedBy(card)) { if (!playNow && c.isCreature() && ComputerUtil.canAttackNextTurn(c) && c.canBeEquippedBy(card)) {
playNow = true; playNow = true;
} }
} }
@@ -1981,4 +1981,17 @@ public class ComputerUtil {
return bestBoardPosition; return bestBoardPosition;
} }
/**
* <p>
* canAttackNextTurn.
* </p>
*
* @param c
* a {@link forge.game.card.Card} object.
* @return a boolean.
*/
public static boolean canAttackNextTurn(final Card c) {
return CombatUtil.canAttackNextTurn(c, c.getController().getOpponent());
}
} }

View File

@@ -616,7 +616,7 @@ public class AttachAi extends SpellAbilityAi {
prefList = CardLists.filter(prefList, new Predicate<Card>() { prefList = CardLists.filter(prefList, new Predicate<Card>() {
@Override @Override
public boolean apply(final Card c) { public boolean apply(final Card c) {
return CombatUtil.canAttackNextTurn(c) && c.getNetAttack() > 0; return ComputerUtil.canAttackNextTurn(c) && c.getNetAttack() > 0;
} }
}); });
} }
@@ -945,7 +945,7 @@ public class AttachAi extends SpellAbilityAi {
if (!c.isCreature()) { if (!c.isCreature()) {
return true; return true;
} }
return CombatUtil.canAttackNextTurn(c) && powerBonus + c.getNetAttack() > 0; return ComputerUtil.canAttackNextTurn(c) && powerBonus + c.getNetAttack() > 0;
} }
}); });
} }
@@ -1133,7 +1133,7 @@ public class AttachAi extends SpellAbilityAi {
// give evasive keywords to creatures that can attack and deal damage // give evasive keywords to creatures that can attack and deal damage
if (evasive) { if (evasive) {
if (card.getNetCombatDamage() + powerBonus <= 0 if (card.getNetCombatDamage() + powerBonus <= 0
|| !CombatUtil.canAttackNextTurn(card) || !ComputerUtil.canAttackNextTurn(card)
|| !CombatUtil.canBeBlocked(card, opponent)) { || !CombatUtil.canBeBlocked(card, opponent)) {
return false; return false;
} }
@@ -1142,20 +1142,20 @@ public class AttachAi extends SpellAbilityAi {
|| card.getNetCombatDamage() + powerBonus <= 0 || card.getNetCombatDamage() + powerBonus <= 0
|| card.hasKeyword("CARDNAME can attack as though it had haste.") || card.hasKeyword("CARDNAME can attack as though it had haste.")
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)
|| !CombatUtil.canAttackNextTurn(card)) { || !ComputerUtil.canAttackNextTurn(card)) {
return false; return false;
} }
} else if (keyword.endsWith("Indestructible")) { } else if (keyword.endsWith("Indestructible")) {
return true; return true;
} else if (keyword.endsWith("Deathtouch") || keyword.endsWith("Wither")) { } else if (keyword.endsWith("Deathtouch") || keyword.endsWith("Wither")) {
if (card.getNetCombatDamage() + powerBonus <= 0 if (card.getNetCombatDamage() + powerBonus <= 0
|| ((!CombatUtil.canBeBlocked(card, opponent) || !CombatUtil.canAttackNextTurn(card)) || ((!CombatUtil.canBeBlocked(card, opponent) || !ComputerUtil.canAttackNextTurn(card))
&& !CombatUtil.canBlock(card, true))) { && !CombatUtil.canBlock(card, true))) {
return false; return false;
} }
} else if (keyword.equals("Double Strike") || keyword.equals("Lifelink")) { } else if (keyword.equals("Double Strike") || keyword.equals("Lifelink")) {
if (card.getNetCombatDamage() + powerBonus <= 0 if (card.getNetCombatDamage() + powerBonus <= 0
|| (!CombatUtil.canAttackNextTurn(card) && !CombatUtil.canBlock(card, true))) { || (!ComputerUtil.canAttackNextTurn(card) && !CombatUtil.canBlock(card, true))) {
return false; return false;
} }
} else if (keyword.equals("First Strike")) { } else if (keyword.equals("First Strike")) {
@@ -1164,29 +1164,29 @@ public class AttachAi extends SpellAbilityAi {
} }
} else if (keyword.startsWith("Flanking")) { } else if (keyword.startsWith("Flanking")) {
if (card.getNetCombatDamage() + powerBonus <= 0 if (card.getNetCombatDamage() + powerBonus <= 0
|| !CombatUtil.canAttackNextTurn(card) || !ComputerUtil.canAttackNextTurn(card)
|| !CombatUtil.canBeBlocked(card, opponent)) { || !CombatUtil.canBeBlocked(card, opponent)) {
return false; return false;
} }
} else if (keyword.startsWith("Bushido")) { } else if (keyword.startsWith("Bushido")) {
if ((!CombatUtil.canBeBlocked(card, opponent) || !CombatUtil.canAttackNextTurn(card)) if ((!CombatUtil.canBeBlocked(card, opponent) || !ComputerUtil.canAttackNextTurn(card))
&& !CombatUtil.canBlock(card, true)) { && !CombatUtil.canBlock(card, true)) {
return false; return false;
} }
} else if (keyword.equals("Trample")) { } else if (keyword.equals("Trample")) {
if (card.getNetCombatDamage() + powerBonus <= 1 if (card.getNetCombatDamage() + powerBonus <= 1
|| !CombatUtil.canBeBlocked(card, opponent) || !CombatUtil.canBeBlocked(card, opponent)
|| !CombatUtil.canAttackNextTurn(card)) { || !ComputerUtil.canAttackNextTurn(card)) {
return false; return false;
} }
} else if (keyword.equals("Infect")) { } else if (keyword.equals("Infect")) {
if (card.getNetCombatDamage() + powerBonus <= 0 if (card.getNetCombatDamage() + powerBonus <= 0
|| !CombatUtil.canAttackNextTurn(card)) { || !ComputerUtil.canAttackNextTurn(card)) {
return false; return false;
} }
} else if (keyword.equals("Vigilance")) { } else if (keyword.equals("Vigilance")) {
if (card.getNetCombatDamage() + powerBonus <= 0 if (card.getNetCombatDamage() + powerBonus <= 0
|| !CombatUtil.canAttackNextTurn(card) || !ComputerUtil.canAttackNextTurn(card)
|| !CombatUtil.canBlock(card, true)) { || !CombatUtil.canBlock(card, true)) {
return false; return false;
} }
@@ -1231,11 +1231,11 @@ public class AttachAi extends SpellAbilityAi {
if (keyword.endsWith("CARDNAME can't attack.") || keyword.equals("Defender") if (keyword.endsWith("CARDNAME can't attack.") || keyword.equals("Defender")
|| keyword.endsWith("CARDNAME can't attack or block.")) { || keyword.endsWith("CARDNAME can't attack or block.")) {
if (!CombatUtil.canAttackNextTurn(card) || card.getNetCombatDamage() < 1) { if (!ComputerUtil.canAttackNextTurn(card) || card.getNetCombatDamage() < 1) {
return false; return false;
} }
} else if (keyword.endsWith("CARDNAME attacks each turn if able.") || keyword.endsWith("CARDNAME attacks each combat if able.")) { } else if (keyword.endsWith("CARDNAME attacks each turn if able.") || keyword.endsWith("CARDNAME attacks each combat if able.")) {
if (!CombatUtil.canAttackNextTurn(card) || !CombatUtil.canBlock(card, true) || ai.getCreaturesInPlay().isEmpty()) { if (!ComputerUtil.canAttackNextTurn(card) || !CombatUtil.canBlock(card, true) || ai.getCreaturesInPlay().isEmpty()) {
return false; return false;
} }
} else if (keyword.endsWith("CARDNAME can't block.") || keyword.contains("CantBlock")) { } else if (keyword.endsWith("CARDNAME can't block.") || keyword.contains("CantBlock")) {
@@ -1250,12 +1250,12 @@ public class AttachAi extends SpellAbilityAi {
} }
return false; return false;
} else if (keyword.endsWith("Prevent all combat damage that would be dealt by CARDNAME.")) { } else if (keyword.endsWith("Prevent all combat damage that would be dealt by CARDNAME.")) {
if (!CombatUtil.canAttackNextTurn(card) || card.getNetCombatDamage() < 1) { if (!ComputerUtil.canAttackNextTurn(card) || card.getNetCombatDamage() < 1) {
return false; return false;
} }
} else if (keyword.endsWith("Prevent all combat damage that would be dealt to and dealt by CARDNAME.") } else if (keyword.endsWith("Prevent all combat damage that would be dealt to and dealt by CARDNAME.")
|| keyword.endsWith("Prevent all damage that would be dealt to and dealt by CARDNAME.")) { || keyword.endsWith("Prevent all damage that would be dealt to and dealt by CARDNAME.")) {
if (!CombatUtil.canAttackNextTurn(card) || card.getNetCombatDamage() < 2) { if (!ComputerUtil.canAttackNextTurn(card) || card.getNetCombatDamage() < 2) {
return false; return false;
} }
} else if (keyword.endsWith("CARDNAME doesn't untap during your untap step.")) { } else if (keyword.endsWith("CARDNAME doesn't untap during your untap step.")) {

View File

@@ -18,6 +18,8 @@
package forge.ai.ability; package forge.ai.ability;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilCard; import forge.ai.ComputerUtilCard;
import forge.ai.SpellAbilityAi; import forge.ai.SpellAbilityAi;
import forge.game.card.Card; import forge.game.card.Card;
@@ -78,7 +80,7 @@ public final class EncodeAi extends SpellAbilityAi {
final List<Card> attackers = CardLists.filter(options, new Predicate<Card>() { final List<Card> attackers = CardLists.filter(options, new Predicate<Card>() {
@Override @Override
public boolean apply(final Card c) { public boolean apply(final Card c) {
return CombatUtil.canAttackNextTurn(c); return ComputerUtil.canAttackNextTurn(c);
} }
}); });
final List<Card> unblockables = CardLists.filter(attackers, new Predicate<Card>() { final List<Card> unblockables = CardLists.filter(attackers, new Predicate<Card>() {

View File

@@ -235,7 +235,7 @@ public abstract class PumpAiBase extends SpellAbilityAi {
|| newPower <= 0 || newPower <= 0
|| card.hasKeyword("CARDNAME can attack as though it had haste.") || card.hasKeyword("CARDNAME can attack as though it had haste.")
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)
|| !CombatUtil.canAttackNextTurn(card)) { || !ComputerUtil.canAttackNextTurn(card)) {
return false; return false;
} }
} else if (keyword.endsWith("Indestructible")) { } else if (keyword.endsWith("Indestructible")) {

View File

@@ -2,6 +2,8 @@ package forge.ai.ability;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import forge.ai.ComputerUtil;
import forge.ai.SpellAbilityAi; import forge.ai.SpellAbilityAi;
import forge.game.Game; import forge.game.Game;
import forge.game.card.Card; import forge.game.card.Card;
@@ -83,7 +85,7 @@ public class TapAllAi extends SpellAbilityAi {
final boolean any = Iterables.any(validTappables, new Predicate<Card>() { final boolean any = Iterables.any(validTappables, new Predicate<Card>() {
@Override @Override
public boolean apply(final Card c) { public boolean apply(final Card c) {
return CombatUtil.canAttack(c) && CombatUtil.canAttackNextTurn(c); return CombatUtil.canAttack(c) && ComputerUtil.canAttackNextTurn(c);
} }
}); });
if(!any) { if(!any) {

View File

@@ -731,7 +731,7 @@ public class CombatUtil {
* @return a boolean. * @return a boolean.
*/ */
public static boolean canAttack(final Card c, final GameEntity def, final Combat combat) { public static boolean canAttack(final Card c, final GameEntity def, final Combat combat) {
int cntAttackers = combat.getAttackers().size(); final int cntAttackers = combat.getAttackers().size();
final Game game = c.getGame(); final Game game = c.getGame();
if (cntAttackers > 0) { if (cntAttackers > 0) {
@@ -741,10 +741,6 @@ public class CombatUtil {
if (keyword.equals("No more than two creatures can attack each combat.")) { if (keyword.equals("No more than two creatures can attack each combat.")) {
return false; return false;
} }
if (keyword.equals("No more than two creatures can attack you each combat.") &&
card.getController().getOpponent().equals(c.getController())) {
return false;
}
} }
if (keyword.equals("CARDNAME can only attack alone.") && combat.isAttacking(card)) { if (keyword.equals("CARDNAME can only attack alone.") && combat.isAttacking(card)) {
return false; return false;
@@ -761,6 +757,18 @@ public class CombatUtil {
} }
} }
final int cntAttackersToDef = combat.getAttackersOf(def).size();
if (cntAttackersToDef > 1) {
for (final Card card : game.getCardsIn(ZoneType.Battlefield)) {
for (final String keyword : card.getKeyword()) {
if (keyword.equals("No more than two creatures can attack you each combat.") &&
card.getController().equals(def)) {
return false;
}
}
}
}
if ((c.hasKeyword("CARDNAME can't attack or block alone.") || c.hasKeyword("CARDNAME can't attack alone.")) if ((c.hasKeyword("CARDNAME can't attack or block alone.") || c.hasKeyword("CARDNAME can't attack alone."))
&& c.getController().getCreaturesInPlay().size() < 2) { && c.getController().getCreaturesInPlay().size() < 2) {
return false; return false;
@@ -832,20 +840,8 @@ public class CombatUtil {
* *
* @param c * @param c
* a {@link forge.game.card.Card} object. * a {@link forge.game.card.Card} object.
* @return a boolean. * @param def
*/ * the defending {@link GameEntity}.
public static boolean canAttackNextTurn(final Card c) {
return canAttackNextTurn(c, c.getController().getOpponent());
}
// can a creature attack if untapped and without summoning sickness?
/**
* <p>
* canAttackNextTurn.
* </p>
*
* @param c
* a {@link forge.game.card.Card} object.
* @return a boolean. * @return a boolean.
*/ */
public static boolean canAttackNextTurn(final Card c, final GameEntity defender) { public static boolean canAttackNextTurn(final Card c, final GameEntity defender) {