mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
- The AI can now use spellAbilities giving shroud to creatures to protect them from spellAbilities on the stack.
This commit is contained in:
@@ -1929,11 +1929,11 @@ public class ComputerUtil {
|
|||||||
*/
|
*/
|
||||||
public static boolean containsUsefulKeyword(final ArrayList<String> keywords, final Card card) {
|
public static boolean containsUsefulKeyword(final ArrayList<String> keywords, final Card card) {
|
||||||
for (final String keyword : keywords) {
|
for (final String keyword : keywords) {
|
||||||
if (ComputerUtil.isUsefulKeyword(keyword, card)) {
|
if (!ComputerUtil.isUsefulKeyword(keyword, card)) {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1978,9 +1978,6 @@ public class ComputerUtil {
|
|||||||
if (ph.isPlayerTurn(human) || !CombatUtil.canAttack(card) || !CombatUtil.canBeBlocked(card)) {
|
if (ph.isPlayerTurn(human) || !CombatUtil.canAttack(card) || !CombatUtil.canBeBlocked(card)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (keyword.endsWith("Shroud")) {
|
|
||||||
// TODO: check stack for spells and abilities
|
|
||||||
return false;
|
|
||||||
} else if (keyword.startsWith("Rampage")) {
|
} else if (keyword.startsWith("Rampage")) {
|
||||||
if (ph.isPlayerTurn(human) || !CombatUtil.canAttack(card) || !CombatUtil.canBeBlocked(card)
|
if (ph.isPlayerTurn(human) || !CombatUtil.canAttack(card) || !CombatUtil.canBeBlocked(card)
|
||||||
|| (AllZoneUtil.getCreaturesInPlay(human).size() < 2)) {
|
|| (AllZoneUtil.getCreaturesInPlay(human).size() < 2)) {
|
||||||
|
|||||||
@@ -2272,8 +2272,10 @@ public class AbilityFactory {
|
|||||||
ArrayList<Object> objects = new ArrayList<Object>();
|
ArrayList<Object> objects = new ArrayList<Object>();
|
||||||
final ArrayList<Object> threatened = new ArrayList<Object>();
|
final ArrayList<Object> threatened = new ArrayList<Object>();
|
||||||
String saviourApi = "";
|
String saviourApi = "";
|
||||||
|
HashMap<String, String> saviourParams = null;
|
||||||
if (saviourAf != null) {
|
if (saviourAf != null) {
|
||||||
saviourApi = saviourAf.getAPI();
|
saviourApi = saviourAf.getAPI();
|
||||||
|
saviourParams = saviourAf.getMapParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (topStack == null) {
|
if (topStack == null) {
|
||||||
@@ -2299,7 +2301,7 @@ public class AbilityFactory {
|
|||||||
final String threatApi = topAf.getAPI();
|
final String threatApi = topAf.getAPI();
|
||||||
final HashMap<String, String> threatParams = topAf.getMapParams();
|
final HashMap<String, String> threatParams = topAf.getMapParams();
|
||||||
|
|
||||||
// Lethal Damage => prevent damage/regeneration/bounce
|
// Lethal Damage => prevent damage/regeneration/bounce/shroud
|
||||||
if (threatApi.equals("DealDamage") || threatApi.equals("DamageAll")) {
|
if (threatApi.equals("DealDamage") || threatApi.equals("DamageAll")) {
|
||||||
// If PredictDamage is >= Lethal Damage
|
// If PredictDamage is >= Lethal Damage
|
||||||
final int dmg = AbilityFactory.calculateAmount(topStack.getSourceCard(),
|
final int dmg = AbilityFactory.calculateAmount(topStack.getSourceCard(),
|
||||||
@@ -2323,6 +2325,13 @@ public class AbilityFactory {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// give Shroud to targeted creatures
|
||||||
|
if (saviourApi.equals("Pump") && tgt == null && saviourParams.containsKey("KW")
|
||||||
|
&& (saviourParams.get("KW").endsWith("Shroud")
|
||||||
|
|| saviourParams.get("KW").endsWith("Hexproof"))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// don't bounce or blink a permanent that the human
|
// don't bounce or blink a permanent that the human
|
||||||
// player owns or is a token
|
// player owns or is a token
|
||||||
if (saviourApi.equals("ChangeZone") && (c.getOwner().isHuman() || c.isToken())) {
|
if (saviourApi.equals("ChangeZone") && (c.getOwner().isHuman() || c.isToken())) {
|
||||||
@@ -2345,10 +2354,10 @@ public class AbilityFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Destroy => regeneration/bounce
|
// Destroy => regeneration/bounce/shroud
|
||||||
else if ((threatApi.equals("Destroy") || threatApi.equals("DestroyAll"))
|
else if ((threatApi.equals("Destroy") || threatApi.equals("DestroyAll"))
|
||||||
&& ((saviourApi.equals("Regenerate") && !threatParams.containsKey("NoRegen")) || saviourApi
|
&& ((saviourApi.equals("Regenerate") && !threatParams.containsKey("NoRegen")) || saviourApi
|
||||||
.equals("ChangeZone"))) {
|
.equals("ChangeZone") || saviourApi.equals("Pump"))) {
|
||||||
for (final Object o : objects) {
|
for (final Object o : objects) {
|
||||||
if (o instanceof Card) {
|
if (o instanceof Card) {
|
||||||
final Card c = (Card) o;
|
final Card c = (Card) o;
|
||||||
@@ -2362,6 +2371,13 @@ public class AbilityFactory {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// give Shroud to targeted creatures
|
||||||
|
if (saviourApi.equals("Pump") && tgt == null && saviourParams.containsKey("KW")
|
||||||
|
&& (saviourParams.get("KW").endsWith("Shroud")
|
||||||
|
|| saviourParams.get("KW").endsWith("Hexproof"))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// don't bounce or blink a permanent that the human
|
// don't bounce or blink a permanent that the human
|
||||||
// player owns or is a token
|
// player owns or is a token
|
||||||
if (saviourApi.equals("ChangeZone") && (c.getOwner().isHuman() || c.isToken())) {
|
if (saviourApi.equals("ChangeZone") && (c.getOwner().isHuman() || c.isToken())) {
|
||||||
@@ -2376,13 +2392,21 @@ public class AbilityFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Exiling => bounce
|
// Exiling => bounce/shroud
|
||||||
else if ((threatApi.equals("ChangeZone") || threatApi.equals("ChangeZoneAll"))
|
else if ((threatApi.equals("ChangeZone") || threatApi.equals("ChangeZoneAll"))
|
||||||
&& saviourApi.equals("ChangeZone") && threatParams.containsKey("Destination")
|
&& (saviourApi.equals("ChangeZone") || saviourApi.equals("Pump"))
|
||||||
|
&& threatParams.containsKey("Destination")
|
||||||
&& threatParams.get("Destination").equals("Exile")) {
|
&& threatParams.get("Destination").equals("Exile")) {
|
||||||
for (final Object o : objects) {
|
for (final Object o : objects) {
|
||||||
if (o instanceof Card) {
|
if (o instanceof Card) {
|
||||||
final Card c = (Card) o;
|
final Card c = (Card) o;
|
||||||
|
// give Shroud to targeted creatures
|
||||||
|
if (saviourApi.equals("Pump") && tgt == null && saviourParams.containsKey("KW")
|
||||||
|
&& (saviourParams.get("KW").endsWith("Shroud")
|
||||||
|
|| saviourParams.get("KW").endsWith("Hexproof"))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// don't bounce or blink a permanent that the human
|
// don't bounce or blink a permanent that the human
|
||||||
// player owns or is a token
|
// player owns or is a token
|
||||||
if (saviourApi.equals("ChangeZone") && (c.getOwner().isHuman() || c.isToken())) {
|
if (saviourApi.equals("ChangeZone") && (c.getOwner().isHuman() || c.isToken())) {
|
||||||
|
|||||||
@@ -278,6 +278,11 @@ public class AbilityFactoryPump {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((keywords.contains("Shroud") || keywords.contains("Hexproof"))
|
||||||
|
&& AbilityFactory.predictThreatenedObjects(sa.getAbilityFactory()).contains(this)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// will the creature attack (only relevant for sorcery speed)?
|
// will the creature attack (only relevant for sorcery speed)?
|
||||||
if (CardFactoryUtil.doesCreatureAttackAI(c)
|
if (CardFactoryUtil.doesCreatureAttackAI(c)
|
||||||
&& AllZone.getPhaseHandler().isBefore(Constant.Phase.COMBAT_DECLARE_ATTACKERS)
|
&& AllZone.getPhaseHandler().isBefore(Constant.Phase.COMBAT_DECLARE_ATTACKERS)
|
||||||
@@ -372,15 +377,16 @@ public class AbilityFactoryPump {
|
|||||||
} // getCurseCreatures()
|
} // getCurseCreatures()
|
||||||
|
|
||||||
private boolean containsCombatRelevantKeyword(final ArrayList<String> keywords) {
|
private boolean containsCombatRelevantKeyword(final ArrayList<String> keywords) {
|
||||||
boolean flag = false;
|
|
||||||
for (final String keyword : keywords) {
|
for (final String keyword : keywords) {
|
||||||
// since most keywords are combat relevant check for those that are
|
// since most keywords are combat relevant check for those that are
|
||||||
// not
|
// not
|
||||||
if (!keyword.equals("HIDDEN This card doesn't untap during your next untap step.")) {
|
if (keyword.equals("HIDDEN This card doesn't untap during your next untap step.")
|
||||||
flag = true;
|
|| keyword.endsWith("Shroud") || keyword.endsWith("Hexproof")) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return flag;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -426,11 +432,9 @@ public class AbilityFactoryPump {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (AllZone.getStack().size() > 0) {
|
} else if (AllZone.getStack().size() > 0) {
|
||||||
// TODO: pump something only if the top thing on the stack will kill
|
if (!this.keywords.contains("Shroud") && !this.keywords.contains("Hexproof")) {
|
||||||
// it via damage
|
return false;
|
||||||
// or if top thing on stack will pump it/enchant it and I want to
|
}
|
||||||
// kill it
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final int activations = restrict.getNumberTurnActivations();
|
final int activations = restrict.getNumberTurnActivations();
|
||||||
@@ -479,21 +483,12 @@ public class AbilityFactoryPump {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean givesKws = !this.keywords.get(0).equals("none");
|
|
||||||
String[] kwPump = { "none" };
|
|
||||||
if (givesKws) {
|
|
||||||
kwPump = this.keywords.toArray(new String[this.keywords.size()]);
|
|
||||||
}
|
|
||||||
final String[] keywords = kwPump;
|
|
||||||
|
|
||||||
// when this happens we need to expand AI to consider if its ok for
|
// when this happens we need to expand AI to consider if its ok for
|
||||||
// everything?
|
// everything?
|
||||||
for (final Card card : cards) {
|
for (final Card card : cards) {
|
||||||
final Random r = MyRandom.getRandom();
|
final Random r = MyRandom.getRandom();
|
||||||
|
|
||||||
// Don't add duplicate keywords
|
if (!ComputerUtil.containsUsefulKeyword(this.keywords, card)) {
|
||||||
final boolean hKW = card.hasAnyKeyword(keywords);
|
|
||||||
if (givesKws && hKW) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,18 +496,14 @@ public class AbilityFactoryPump {
|
|||||||
if (card.getController().isComputer()) {
|
if (card.getController().isComputer()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!ComputerUtil.containsUsefulKeyword(this.keywords, card)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (r.nextFloat() <= Math.pow(.6667, activations));
|
return (r.nextFloat() <= Math.pow(.6667, activations));
|
||||||
}
|
}
|
||||||
if (((card.getNetDefense() + defense) > 0) && (!card.hasAnyKeyword(this.keywords))) {
|
if (((card.getNetDefense() + defense) > 0) && (!card.hasAnyKeyword(this.keywords))) {
|
||||||
if (card.hasSickness() && this.keywords.contains("Haste")) {
|
if ((keywords.contains("Shroud") || keywords.contains("Hexproof"))
|
||||||
return true;
|
&& AbilityFactory.predictThreatenedObjects(sa.getAbilityFactory()).contains(card)) {
|
||||||
} else if (card.hasSickness() ^ this.keywords.contains("Haste")) {
|
return (r.nextFloat() <= Math.pow(.6667, activations));
|
||||||
return false;
|
} else if (this.hostCard.equals(card) && !this.keywords.contains("Haste")) {
|
||||||
} else if (this.hostCard.equals(card)) {
|
|
||||||
if (r.nextFloat() <= Math.pow(.6667, activations)) {
|
if (r.nextFloat() <= Math.pow(.6667, activations)) {
|
||||||
return CardFactoryUtil.doesCreatureAttackAI(card) && !sa.getPayCosts().getTap();
|
return CardFactoryUtil.doesCreatureAttackAI(card) && !sa.getPayCosts().getTap();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user