mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
- Added an experimental (and disabled by default in all profiles) AI profile option ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS, which makes the AI more willing to not hold back using removal on artifacts and global (non-aura) enchantments that have "suspicious" (potentially beneficial for the opponent/disruptive for the AI) intrinsic static or triggered abilities.
- Currently very basic and requires tweaking and expansion, from hence it's disabled by default until I experiment enough with it, see how it works in practice and tweak it to account for other cases and corner cases that may be viable (and prove that it does not make the AI take stupider decisions than without this option).
This commit is contained in:
@@ -34,7 +34,8 @@ public enum AiProps { /** */
|
|||||||
PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS ("true"),
|
PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS ("true"),
|
||||||
PREDICT_SPELLS_FOR_MAIN2 ("true"), /** */
|
PREDICT_SPELLS_FOR_MAIN2 ("true"), /** */
|
||||||
RESERVE_MANA_FOR_MAIN2_CHANCE ("0"), /** */
|
RESERVE_MANA_FOR_MAIN2_CHANCE ("0"), /** */
|
||||||
PLAY_AGGRO ("false"); /** */
|
PLAY_AGGRO ("false"), /** */
|
||||||
|
ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS ("false"); /** */
|
||||||
|
|
||||||
private final String strDefaultVal;
|
private final String strDefaultVal;
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import forge.game.phase.PhaseType;
|
|||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
|
import forge.game.trigger.Trigger;
|
||||||
import forge.game.zone.MagicStack;
|
import forge.game.zone.MagicStack;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
@@ -846,6 +847,7 @@ public class ComputerUtilCard {
|
|||||||
|
|
||||||
public static boolean useRemovalNow(final SpellAbility sa, final Card c, final int dmg, ZoneType destination) {
|
public static boolean useRemovalNow(final SpellAbility sa, final Card c, final int dmg, ZoneType destination) {
|
||||||
final Player ai = sa.getActivatingPlayer();
|
final Player ai = sa.getActivatingPlayer();
|
||||||
|
final AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
|
||||||
final Player opp = ai.getOpponent();
|
final Player opp = ai.getOpponent();
|
||||||
final Game game = ai.getGame();
|
final Game game = ai.getGame();
|
||||||
final PhaseHandler ph = game.getPhaseHandler();
|
final PhaseHandler ph = game.getPhaseHandler();
|
||||||
@@ -992,6 +994,43 @@ public class ComputerUtilCard {
|
|||||||
}
|
}
|
||||||
} else if (c.isPlaneswalker()) {
|
} else if (c.isPlaneswalker()) {
|
||||||
threat = 1;
|
threat = 1;
|
||||||
|
} else if (aic.getBooleanProperty(AiProps.ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS) && (c.isArtifact() && !c.isCreature()) || (c.isEnchantment() && !c.isAura())) {
|
||||||
|
// non-creature artifacts and global enchantments with suspicious intrinsic abilities
|
||||||
|
boolean priority = false;
|
||||||
|
if (c.getOwner().isOpponentOf(ai) && c.getController().isOpponentOf(ai)) {
|
||||||
|
// if this thing is both owned and controlled by an opponent and it has a continuous ability,
|
||||||
|
// assume it either benefits the player or disrupts the opponent
|
||||||
|
for (final StaticAbility stAb : c.getStaticAbilities()) {
|
||||||
|
final Map<String, String> params = stAb.getMapParams();
|
||||||
|
if (params.get("Mode").equals("Continuous") && stAb.isIntrinsic() && !stAb.isTemporary()) {
|
||||||
|
priority = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!priority) {
|
||||||
|
for (final Trigger t : c.getTriggers()) {
|
||||||
|
if (t.isIntrinsic() && !t.isTemporary()) {
|
||||||
|
// has a triggered ability, could be benefitting the opponent or disrupting the AI
|
||||||
|
priority = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if this thing has AILogic set to "Curse", it's probably meant as some form of disruption
|
||||||
|
if (!priority) {
|
||||||
|
for (final String sVar : c.getSVars().keySet()) {
|
||||||
|
if (c.getSVars().get(sVar).contains("AILogic$ Curse")) {
|
||||||
|
// this is a curse ability, so prioritize its removal
|
||||||
|
priority = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if it's a priority object, set its threat level to high
|
||||||
|
if (priority) {
|
||||||
|
threat = 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (final StaticAbility stAb : c.getStaticAbilities()) {
|
for (final StaticAbility stAb : c.getStaticAbilities()) {
|
||||||
final Map<String, String> params = stAb.getMapParams();
|
final Map<String, String> params = stAb.getMapParams();
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ MOVE_EQUIPMENT_TO_BETTER_CREATURES=from_useless_only
|
|||||||
PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS=true
|
PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS=true
|
||||||
PREDICT_SPELLS_FOR_MAIN2=true
|
PREDICT_SPELLS_FOR_MAIN2=true
|
||||||
RESERVE_MANA_FOR_MAIN2_CHANCE=100
|
RESERVE_MANA_FOR_MAIN2_CHANCE=100
|
||||||
|
ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=false
|
||||||
PLAY_AGGRO=false
|
PLAY_AGGRO=false
|
||||||
|
|
||||||
|
|||||||
@@ -8,4 +8,5 @@ MOVE_EQUIPMENT_TO_BETTER_CREATURES=always
|
|||||||
PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS=false
|
PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS=false
|
||||||
PREDICT_SPELLS_FOR_MAIN2=true
|
PREDICT_SPELLS_FOR_MAIN2=true
|
||||||
RESERVE_MANA_FOR_MAIN2_CHANCE=100
|
RESERVE_MANA_FOR_MAIN2_CHANCE=100
|
||||||
|
ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=false
|
||||||
PLAY_AGGRO=true
|
PLAY_AGGRO=true
|
||||||
|
|||||||
Reference in New Issue
Block a user