- 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:
Agetian
2017-09-30 06:57:17 +00:00
parent 345f6fc2af
commit 8108bdc91b
6 changed files with 107 additions and 1 deletions

View File

@@ -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"), /** */

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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