mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 10:18:01 +00:00
- AI: added an experimental option to actively prioritize destroying creatures that are not immediately blockable and thus pose a recurring threat (currently in testing, disabled in all default profiles).
This commit is contained in:
@@ -69,6 +69,10 @@ public enum AiProps { /** */
|
||||
ALWAYS_COUNTER_AURAS ("true"), /** */
|
||||
ALWAYS_COUNTER_SPELLS_FROM_NAMED_CARDS (""), /** */
|
||||
ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS ("true"), /** */
|
||||
ACTIVELY_DESTROY_IMMEDIATELY_UNBLOCKABLE ("false"), /** */
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_THRESHOLD ("2"), /** */
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_ONLY_IN_DNGR ("true"), /** */
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_LIFE_IN_DNGR ("5"), /** */
|
||||
PRIORITY_REDUCTION_FOR_STORM_SPELLS ("0"), /** */
|
||||
USE_BERSERK_AGGRESSIVELY ("false"), /** */
|
||||
MIN_COUNT_FOR_STORM_SPELLS ("0"), /** */
|
||||
|
||||
@@ -5,6 +5,7 @@ import forge.ai.*;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.cost.CostSacrifice;
|
||||
@@ -115,6 +116,9 @@ public class DestroyAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
list = CardLists.getNotKeyword(list, "Indestructible");
|
||||
if (CardLists.getNotType(list, "Creature").isEmpty()) {
|
||||
list = prioritizeCreaturesWorthDestroyingNow(ai, list);
|
||||
}
|
||||
if (!SpellAbilityAi.playReusable(ai, sa)) {
|
||||
list = CardLists.filter(list, new Predicate<Card>() {
|
||||
@Override
|
||||
@@ -291,6 +295,9 @@ public class DestroyAi extends SpellAbilityAi {
|
||||
|
||||
CardCollection preferred = CardLists.getNotKeyword(list, "Indestructible");
|
||||
preferred = CardLists.filterControlledBy(preferred, ai.getOpponents());
|
||||
if (CardLists.getNotType(preferred, "Creature").isEmpty()) {
|
||||
preferred = prioritizeCreaturesWorthDestroyingNow(ai, preferred);
|
||||
}
|
||||
|
||||
// If NoRegen is not set, filter out creatures that have a
|
||||
// regeneration shield
|
||||
@@ -444,4 +451,51 @@ public class DestroyAi extends SpellAbilityAi {
|
||||
return tempoCheck;
|
||||
}
|
||||
}
|
||||
|
||||
public static CardCollection prioritizeCreaturesWorthDestroyingNow(final Player ai, final CardCollection oppCards) {
|
||||
if (!CardLists.getNotType(oppCards, "Creature").isEmpty()) {
|
||||
// non-creatures were passed, nothing to do here
|
||||
return oppCards;
|
||||
}
|
||||
|
||||
boolean enablePriorityRemoval = false;
|
||||
boolean priorityRemovalOnlyInDanger = false;
|
||||
int priorityRemovalThreshold = 0;
|
||||
int lifeInDanger = 5;
|
||||
if (ai.getController().isAI()) {
|
||||
AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
|
||||
enablePriorityRemoval = aic.getBooleanProperty(AiProps.ACTIVELY_DESTROY_IMMEDIATELY_UNBLOCKABLE);
|
||||
priorityRemovalThreshold = aic.getIntProperty(AiProps.DESTROY_IMMEDIATELY_UNBLOCKABLE_THRESHOLD);
|
||||
priorityRemovalOnlyInDanger = aic.getBooleanProperty(AiProps.DESTROY_IMMEDIATELY_UNBLOCKABLE_ONLY_IN_DNGR);
|
||||
lifeInDanger = aic.getIntProperty(AiProps.DESTROY_IMMEDIATELY_UNBLOCKABLE_LIFE_IN_DNGR);
|
||||
}
|
||||
|
||||
if (!enablePriorityRemoval) {
|
||||
// Nothing to do here, the profile does not allow prioritizing
|
||||
return oppCards;
|
||||
}
|
||||
|
||||
CardCollection aiCreats = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
|
||||
|
||||
CardCollection priorityCards = new CardCollection();
|
||||
for (Card atk : oppCards) {
|
||||
if (ComputerUtilCard.isUselessCreature(atk.getController(), atk)) {
|
||||
continue;
|
||||
}
|
||||
for (Card blk : aiCreats) {
|
||||
if (!CombatUtil.canBlock(atk, blk, true)) {
|
||||
boolean threat = atk.getNetCombatDamage() >= ai.getLife() - lifeInDanger;
|
||||
if (!priorityRemovalOnlyInDanger || threat) {
|
||||
priorityCards.add(atk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!priorityCards.isEmpty() && priorityCards.size() <= priorityRemovalThreshold) {
|
||||
return priorityCards;
|
||||
}
|
||||
|
||||
return oppCards;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,18 @@ RESERVE_MANA_FOR_MAIN2_CHANCE=100
|
||||
# If enabled, the AI will target artifacts and non-aura enchantments with removal aggressively
|
||||
ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=true
|
||||
|
||||
# If enabled, the AI will prioritize removing creatures that it can't block at all (e.g. Flying in absence of flying
|
||||
# blockers). This is a master toggle. If disabled, the following three options do nothing.
|
||||
ACTIVELY_DESTROY_IMMEDIATELY_UNBLOCKABLE=false
|
||||
# How many unblockable creatures can there be when the AI should still consider prioritizing something (when there are
|
||||
# too many, probably it's just worth going for the biggest threat overall instead)
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_THRESHOLD=2
|
||||
# Only consider prioritizing the destruction of immediately unblockable creatures if life is in danger
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_ONLY_IN_DNGR=true
|
||||
# How much life can there remain after a swing of the immediately unblockable creature for it to be considered dangerous
|
||||
# for the purpose of previous option
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_LIFE_IN_DNGR=5
|
||||
|
||||
# Permission timings
|
||||
MIN_SPELL_CMC_TO_COUNTER=2
|
||||
CHANCE_TO_COUNTER_CMC_1=0
|
||||
|
||||
@@ -91,6 +91,18 @@ RESERVE_MANA_FOR_MAIN2_CHANCE=100
|
||||
# If enabled, the AI will target artifacts and non-aura enchantments with removal aggressively
|
||||
ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=true
|
||||
|
||||
# If enabled, the AI will prioritize removing creatures that it can't block at all (e.g. Flying in absence of flying
|
||||
# blockers). This is a master toggle. If disabled, the following three options do nothing.
|
||||
ACTIVELY_DESTROY_IMMEDIATELY_UNBLOCKABLE=false
|
||||
# How many unblockable creatures can there be when the AI should still consider prioritizing something (when there are
|
||||
# too many, probably it's just worth going for the biggest threat overall instead)
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_THRESHOLD=2
|
||||
# Only consider prioritizing the destruction of immediately unblockable creatures if life is in danger
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_ONLY_IN_DNGR=true
|
||||
# How much life can there remain after a swing of the immediately unblockable creature for it to be considered dangerous
|
||||
# for the purpose of previous option
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_LIFE_IN_DNGR=5
|
||||
|
||||
# Permission timings
|
||||
MIN_SPELL_CMC_TO_COUNTER=0
|
||||
CHANCE_TO_COUNTER_CMC_1=30
|
||||
|
||||
@@ -29,7 +29,7 @@ USE_BERSERK_AGGRESSIVELY=true
|
||||
TRY_TO_HOLD_COMBAT_TRICKS_UNTIL_BLOCK=true
|
||||
# Chance to hold combat tricks until blockers are declared. If -1 is specified, this chance is not used, and the standard
|
||||
# evaluation for offensive pump buff is used instead.
|
||||
CHANCE_TO_HOLD_COMBAT_TRICKS_UNTIL_BLOCK=65
|
||||
CHANCE_TO_HOLD_COMBAT_TRICKS_UNTIL_BLOCK=75
|
||||
|
||||
# Trade blocking preferences (enabling these will make the AI trade more aggressively when considering blocks,
|
||||
# but only with creatures that are worse in abilities and have lower or the same power as the attacker). Note
|
||||
@@ -91,6 +91,18 @@ RESERVE_MANA_FOR_MAIN2_CHANCE=100
|
||||
# If enabled, the AI will target artifacts and non-aura enchantments with removal aggressively
|
||||
ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=true
|
||||
|
||||
# If enabled, the AI will prioritize removing creatures that it can't block at all (e.g. Flying in absence of flying
|
||||
# blockers). This is a master toggle. If disabled, the following three options do nothing.
|
||||
ACTIVELY_DESTROY_IMMEDIATELY_UNBLOCKABLE=true
|
||||
# How many unblockable creatures can there be when the AI should still consider prioritizing something (when there are
|
||||
# too many, probably it's just worth going for the biggest threat overall instead)
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_THRESHOLD=3
|
||||
# Only consider prioritizing the destruction of immediately unblockable creatures if life is in danger
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_ONLY_IN_DNGR=false
|
||||
# How much life can there remain after a swing of the immediately unblockable creature for it to be considered dangerous
|
||||
# for the purpose of previous option
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_LIFE_IN_DNGR=5
|
||||
|
||||
# Permission timings
|
||||
MIN_SPELL_CMC_TO_COUNTER=2
|
||||
CHANCE_TO_COUNTER_CMC_1=30
|
||||
|
||||
@@ -91,6 +91,18 @@ RESERVE_MANA_FOR_MAIN2_CHANCE=100
|
||||
# If enabled, the AI will target artifacts and non-aura enchantments with removal aggressively
|
||||
ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=true
|
||||
|
||||
# If enabled, the AI will prioritize removing creatures that it can't block at all (e.g. Flying in absence of flying
|
||||
# blockers). This is a master toggle. If disabled, the following three options do nothing.
|
||||
ACTIVELY_DESTROY_IMMEDIATELY_UNBLOCKABLE=false
|
||||
# How many unblockable creatures can there be when the AI should still consider prioritizing something (when there are
|
||||
# too many, probably it's just worth going for the biggest threat overall instead)
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_THRESHOLD=2
|
||||
# Only consider prioritizing the destruction of immediately unblockable creatures if life is in danger
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_ONLY_IN_DNGR=true
|
||||
# How much life can there remain after a swing of the immediately unblockable creature for it to be considered dangerous
|
||||
# for the purpose of previous option
|
||||
DESTROY_IMMEDIATELY_UNBLOCKABLE_LIFE_IN_DNGR=5
|
||||
|
||||
# Permission timings
|
||||
MIN_SPELL_CMC_TO_COUNTER=0
|
||||
CHANCE_TO_COUNTER_CMC_1=80
|
||||
|
||||
Reference in New Issue
Block a user