mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 02:38:02 +00:00
- 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:
@@ -394,7 +394,7 @@ public class AiAttackController {
|
||||
}
|
||||
|
||||
for (Card attacker : oppList) {
|
||||
if (!CombatUtil.canAttackNextTurn(attacker)) {
|
||||
if (!ComputerUtil.canAttackNextTurn(attacker)) {
|
||||
continue;
|
||||
}
|
||||
if (blockersLeft > 0 && CombatUtil.canBeBlocked(attacker, ai)) {
|
||||
@@ -657,7 +657,7 @@ public class AiAttackController {
|
||||
for (final Card pCard : this.oppList) {
|
||||
// if the creature can attack next turn add it to counter attackers
|
||||
// list
|
||||
if (CombatUtil.canAttackNextTurn(pCard)) {
|
||||
if (ComputerUtil.canAttackNextTurn(pCard)) {
|
||||
nextTurnAttackers.add(pCard);
|
||||
if (pCard.getNetCombatDamage() > 0) {
|
||||
candidateCounterAttackDamage += pCard.getNetCombatDamage();
|
||||
@@ -684,7 +684,7 @@ public class AiAttackController {
|
||||
for (final Card pCard : this.myList) {
|
||||
// if the creature can attack then it's a potential attacker this
|
||||
// turn, assume summoning sickness creatures will be able to
|
||||
if (CombatUtil.canAttackNextTurn(pCard)) {
|
||||
if (ComputerUtil.canAttackNextTurn(pCard)) {
|
||||
candidateAttackers.add(pCard);
|
||||
if (pCard.getNetCombatDamage() > 0) {
|
||||
candidateUnblockedDamage += ComputerUtilCombat.damageIfUnblocked(pCard, opp, null);
|
||||
|
||||
@@ -879,7 +879,7 @@ public class ComputerUtil {
|
||||
playNow = false;
|
||||
break;
|
||||
}
|
||||
if (!playNow && c.isCreature() && CombatUtil.canAttackNextTurn(c) && c.canBeEquippedBy(card)) {
|
||||
if (!playNow && c.isCreature() && ComputerUtil.canAttackNextTurn(c) && c.canBeEquippedBy(card)) {
|
||||
playNow = true;
|
||||
}
|
||||
}
|
||||
@@ -1980,5 +1980,18 @@ public class ComputerUtil {
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -616,7 +616,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
prefList = CardLists.filter(prefList, new Predicate<Card>() {
|
||||
@Override
|
||||
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()) {
|
||||
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
|
||||
if (evasive) {
|
||||
if (card.getNetCombatDamage() + powerBonus <= 0
|
||||
|| !CombatUtil.canAttackNextTurn(card)
|
||||
|| !ComputerUtil.canAttackNextTurn(card)
|
||||
|| !CombatUtil.canBeBlocked(card, opponent)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1142,20 +1142,20 @@ public class AttachAi extends SpellAbilityAi {
|
||||
|| card.getNetCombatDamage() + powerBonus <= 0
|
||||
|| card.hasKeyword("CARDNAME can attack as though it had haste.")
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)
|
||||
|| !CombatUtil.canAttackNextTurn(card)) {
|
||||
|| !ComputerUtil.canAttackNextTurn(card)) {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.endsWith("Indestructible")) {
|
||||
return true;
|
||||
} else if (keyword.endsWith("Deathtouch") || keyword.endsWith("Wither")) {
|
||||
if (card.getNetCombatDamage() + powerBonus <= 0
|
||||
|| ((!CombatUtil.canBeBlocked(card, opponent) || !CombatUtil.canAttackNextTurn(card))
|
||||
|| ((!CombatUtil.canBeBlocked(card, opponent) || !ComputerUtil.canAttackNextTurn(card))
|
||||
&& !CombatUtil.canBlock(card, true))) {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.equals("Double Strike") || keyword.equals("Lifelink")) {
|
||||
if (card.getNetCombatDamage() + powerBonus <= 0
|
||||
|| (!CombatUtil.canAttackNextTurn(card) && !CombatUtil.canBlock(card, true))) {
|
||||
|| (!ComputerUtil.canAttackNextTurn(card) && !CombatUtil.canBlock(card, true))) {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.equals("First Strike")) {
|
||||
@@ -1164,29 +1164,29 @@ public class AttachAi extends SpellAbilityAi {
|
||||
}
|
||||
} else if (keyword.startsWith("Flanking")) {
|
||||
if (card.getNetCombatDamage() + powerBonus <= 0
|
||||
|| !CombatUtil.canAttackNextTurn(card)
|
||||
|| !ComputerUtil.canAttackNextTurn(card)
|
||||
|| !CombatUtil.canBeBlocked(card, opponent)) {
|
||||
return false;
|
||||
}
|
||||
} 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)) {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.equals("Trample")) {
|
||||
if (card.getNetCombatDamage() + powerBonus <= 1
|
||||
|| !CombatUtil.canBeBlocked(card, opponent)
|
||||
|| !CombatUtil.canAttackNextTurn(card)) {
|
||||
|| !ComputerUtil.canAttackNextTurn(card)) {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.equals("Infect")) {
|
||||
if (card.getNetCombatDamage() + powerBonus <= 0
|
||||
|| !CombatUtil.canAttackNextTurn(card)) {
|
||||
|| !ComputerUtil.canAttackNextTurn(card)) {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.equals("Vigilance")) {
|
||||
if (card.getNetCombatDamage() + powerBonus <= 0
|
||||
|| !CombatUtil.canAttackNextTurn(card)
|
||||
|| !ComputerUtil.canAttackNextTurn(card)
|
||||
|| !CombatUtil.canBlock(card, true)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1231,11 +1231,11 @@ public class AttachAi extends SpellAbilityAi {
|
||||
|
||||
if (keyword.endsWith("CARDNAME can't attack.") || keyword.equals("Defender")
|
||||
|| keyword.endsWith("CARDNAME can't attack or block.")) {
|
||||
if (!CombatUtil.canAttackNextTurn(card) || card.getNetCombatDamage() < 1) {
|
||||
if (!ComputerUtil.canAttackNextTurn(card) || card.getNetCombatDamage() < 1) {
|
||||
return false;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
} else if (keyword.endsWith("CARDNAME can't block.") || keyword.contains("CantBlock")) {
|
||||
@@ -1250,12 +1250,12 @@ public class AttachAi extends SpellAbilityAi {
|
||||
}
|
||||
return false;
|
||||
} 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;
|
||||
}
|
||||
} 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.")) {
|
||||
if (!CombatUtil.canAttackNextTurn(card) || card.getNetCombatDamage() < 2) {
|
||||
if (!ComputerUtil.canAttackNextTurn(card) || card.getNetCombatDamage() < 2) {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.endsWith("CARDNAME doesn't untap during your untap step.")) {
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
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>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return CombatUtil.canAttackNextTurn(c);
|
||||
return ComputerUtil.canAttackNextTurn(c);
|
||||
}
|
||||
});
|
||||
final List<Card> unblockables = CardLists.filter(attackers, new Predicate<Card>() {
|
||||
|
||||
@@ -235,7 +235,7 @@ public abstract class PumpAiBase extends SpellAbilityAi {
|
||||
|| newPower <= 0
|
||||
|| card.hasKeyword("CARDNAME can attack as though it had haste.")
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)
|
||||
|| !CombatUtil.canAttackNextTurn(card)) {
|
||||
|| !ComputerUtil.canAttackNextTurn(card)) {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.endsWith("Indestructible")) {
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
@@ -83,7 +85,7 @@ public class TapAllAi extends SpellAbilityAi {
|
||||
final boolean any = Iterables.any(validTappables, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return CombatUtil.canAttack(c) && CombatUtil.canAttackNextTurn(c);
|
||||
return CombatUtil.canAttack(c) && ComputerUtil.canAttackNextTurn(c);
|
||||
}
|
||||
});
|
||||
if(!any) {
|
||||
|
||||
@@ -731,7 +731,7 @@ public class CombatUtil {
|
||||
* @return a boolean.
|
||||
*/
|
||||
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();
|
||||
|
||||
if (cntAttackers > 0) {
|
||||
@@ -741,10 +741,6 @@ public class CombatUtil {
|
||||
if (keyword.equals("No more than two creatures can attack each combat.")) {
|
||||
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)) {
|
||||
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."))
|
||||
&& c.getController().getCreaturesInPlay().size() < 2) {
|
||||
return false;
|
||||
@@ -832,20 +840,8 @@ public class CombatUtil {
|
||||
*
|
||||
* @param c
|
||||
* a {@link forge.game.card.Card} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
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.
|
||||
* @param def
|
||||
* the defending {@link GameEntity}.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean canAttackNextTurn(final Card c, final GameEntity defender) {
|
||||
|
||||
Reference in New Issue
Block a user