From 1ae2055f5ac87a1906e707dba9bef04a64d25470 Mon Sep 17 00:00:00 2001 From: Agetian Date: Wed, 8 Jul 2020 21:21:41 +0300 Subject: [PATCH] - Adamant AI: initial implementation, needs refining. --- .../main/java/forge/ai/ComputerUtilMana.java | 24 ++++++++++++++++--- .../res/cardsfolder/a/ardenvale_paladin.txt | 1 + .../res/cardsfolder/c/cauldrons_gift.txt | 2 +- .../res/cardsfolder/e/embereth_paladin.txt | 1 + .../res/cardsfolder/f/foreboding_fruit.txt | 2 +- .../res/cardsfolder/g/garenbrig_paladin.txt | 1 + .../res/cardsfolder/l/locthwain_paladin.txt | 1 + .../res/cardsfolder/o/once_and_future.txt | 2 +- forge-gui/res/cardsfolder/o/outmuscle.txt | 2 +- .../cardsfolder/r/rally_for_the_throne.txt | 2 +- .../res/cardsfolder/s/searing_barrage.txt | 2 +- .../res/cardsfolder/s/silverflame_ritual.txt | 2 +- forge-gui/res/cardsfolder/s/slaying_fire.txt | 2 +- .../res/cardsfolder/t/turn_into_a_pumpkin.txt | 2 +- .../res/cardsfolder/u/unexplained_vision.txt | 2 +- .../res/cardsfolder/v/vantress_paladin.txt | 1 + 16 files changed, 36 insertions(+), 13 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java index f90a554dbc6..cc5581b528a 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java @@ -118,10 +118,19 @@ public class ComputerUtilMana { return score; } - + private static void sortManaAbilities(final Multimap manaAbilityMap) { + sortManaAbilities(manaAbilityMap, null); + } + + private static void sortManaAbilities(final Multimap manaAbilityMap, final SpellAbility sa) { final Map manaCardMap = Maps.newHashMap(); final List orderedCards = Lists.newArrayList(); + + String manaPref = sa.getParamOrDefault("AIManaPref", ""); + if (manaPref.isEmpty() && sa.getHostCard() != null && sa.getHostCard().hasSVar("AIManaPref")) { + manaPref = sa.getHostCard().getSVar("AIManaPref"); + } for (final ManaCostShard shard : manaAbilityMap.keySet()) { for (SpellAbility ability : manaAbilityMap.get(shard)) { @@ -147,6 +156,8 @@ public class ComputerUtilMana { System.out.println(); } + final String preferredShard = manaPref; + for (final ManaCostShard shard : manaAbilityMap.keySet()) { final Collection abilities = manaAbilityMap.get(shard); final List newAbilities = new ArrayList<>(abilities); @@ -160,6 +171,13 @@ public class ComputerUtilMana { public int compare(final SpellAbility ability1, final SpellAbility ability2) { int preOrder = orderedCards.indexOf(ability1.getHostCard()) - orderedCards.indexOf(ability2.getHostCard()); + if (!preferredShard.isEmpty()) { + if (ability1.getManaPart().mana().contains(preferredShard)) + return -1; + else if (ability2.getManaPart().mana().contains(preferredShard)) + return 1; + } + if (preOrder == 0) { // Mana abilities on the same card String shardMana = shard.toString().replaceAll("\\{", "").replaceAll("\\}", ""); @@ -310,7 +328,7 @@ public class ComputerUtilMana { // select which abilities may be used for each shard Multimap sourcesForShards = ComputerUtilMana.groupAndOrderToPayShards(ai, manaAbilityMap, cost); - sortManaAbilities(sourcesForShards); + sortManaAbilities(sourcesForShards, sa); ManaCostShard toPay; // Loop over mana needed @@ -621,7 +639,7 @@ public class ComputerUtilMana { } } } - sortManaAbilities(sourcesForShards); + sortManaAbilities(sourcesForShards, sa); if (DEBUG_MANA_PAYMENT) { System.out.println("DEBUG_MANA_PAYMENT: sourcesForShards = " + sourcesForShards); } diff --git a/forge-gui/res/cardsfolder/a/ardenvale_paladin.txt b/forge-gui/res/cardsfolder/a/ardenvale_paladin.txt index c2dea1ba1f8..c42d5efd188 100644 --- a/forge-gui/res/cardsfolder/a/ardenvale_paladin.txt +++ b/forge-gui/res/cardsfolder/a/ardenvale_paladin.txt @@ -3,5 +3,6 @@ ManaCost:3 W Types:Creature Human Knight PT:2/5 K:etbCounter:P1P1:1:Adamant$ White:Adamant — If at least three white mana was spent to cast this spell, CARDNAME enters the battlefield with a +1/+1 counter on it. +SVar:AIManaPref:W DeckHas:Ability$Counters Oracle:Adamant — If at least three white mana was spent to cast this spell, Ardenvale Paladin enters the battlefield with a +1/+1 counter on it. diff --git a/forge-gui/res/cardsfolder/c/cauldrons_gift.txt b/forge-gui/res/cardsfolder/c/cauldrons_gift.txt index efac5a34f90..40cd229b771 100644 --- a/forge-gui/res/cardsfolder/c/cauldrons_gift.txt +++ b/forge-gui/res/cardsfolder/c/cauldrons_gift.txt @@ -1,7 +1,7 @@ Name:Cauldron's Gift ManaCost:4 B Types:Sorcery -A:SP$ Mill | Cost$ 4 B | NumCards$ 4 | Defined$ You | SubAbility$ DBChangeZone | ConditionCheckSVar$ X | References$ X | SpellDescription$ Adamant — If at least three black mana was spent to cast this spell, mill four cards. You may choose a creature card in your graveyard. If you do, return it to the battlefield with an additional +1/+1 counter on it. +A:SP$ Mill | Cost$ 4 B | NumCards$ 4 | Defined$ You | SubAbility$ DBChangeZone | ConditionCheckSVar$ X | References$ X | AIManaPref$ B | SpellDescription$ Adamant — If at least three black mana was spent to cast this spell, mill four cards. You may choose a creature card in your graveyard. If you do, return it to the battlefield with an additional +1/+1 counter on it. SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature.YouOwn | Hidden$ True | ChangeNum$ 1 | WithCounters$ P1P1_1 SVar:X:Count$Adamant.Black.1.0 DeckHas:Ability$Counters & Ability$Graveyard diff --git a/forge-gui/res/cardsfolder/e/embereth_paladin.txt b/forge-gui/res/cardsfolder/e/embereth_paladin.txt index d96911e06cf..bf79b36a958 100644 --- a/forge-gui/res/cardsfolder/e/embereth_paladin.txt +++ b/forge-gui/res/cardsfolder/e/embereth_paladin.txt @@ -4,5 +4,6 @@ Types:Creature Human Knight PT:4/1 K:Haste K:etbCounter:P1P1:1:Adamant$ Red:Adamant — If at least three red mana was spent to cast this spell, CARDNAME enters the battlefield with a +1/+1 counter on it. +SVar:AIManaPref:R DeckHas:Ability$Counters Oracle:Haste\nAdamant — If at least three red mana was spent to cast this spell, Embereth Paladin enters the battlefield with a +1/+1 counter on it. diff --git a/forge-gui/res/cardsfolder/f/foreboding_fruit.txt b/forge-gui/res/cardsfolder/f/foreboding_fruit.txt index 5396ebf06fe..b06f90aee27 100644 --- a/forge-gui/res/cardsfolder/f/foreboding_fruit.txt +++ b/forge-gui/res/cardsfolder/f/foreboding_fruit.txt @@ -1,7 +1,7 @@ Name:Foreboding Fruit ManaCost:2 B Types:Sorcery -A:SP$ Draw | Cost$ 2 B | NumCards$ 2 | ValidTgts$ Player | TgtPrompt$ Choose a player | SubAbility$ DBLoseLife | SpellDescription$ Target player draws two cards and loses 2 life. Adamant — If at least three black mana was spent to cast this spell, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 2 life.") +A:SP$ Draw | Cost$ 2 B | NumCards$ 2 | ValidTgts$ Player | TgtPrompt$ Choose a player | SubAbility$ DBLoseLife | AIManaPref$ B | SpellDescription$ Target player draws two cards and loses 2 life. Adamant — If at least three black mana was spent to cast this spell, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 2 life.") SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ 2 | Defined$ Targeted | SubAbility$ DBToken SVar:DBToken:DB$ Token | TokenAmount$ X | TokenScript$ c_a_food_sac | TokenOwner$ You | LegacyImage$ c a food sac eld | References$ X SVar:X:Count$Adamant.Black.1.0 diff --git a/forge-gui/res/cardsfolder/g/garenbrig_paladin.txt b/forge-gui/res/cardsfolder/g/garenbrig_paladin.txt index 913a14caef0..d302fe81796 100644 --- a/forge-gui/res/cardsfolder/g/garenbrig_paladin.txt +++ b/forge-gui/res/cardsfolder/g/garenbrig_paladin.txt @@ -4,5 +4,6 @@ Types:Creature Giant Knight PT:4/4 K:etbCounter:P1P1:1:Adamant$ Green:Adamant — If at least three green mana was spent to cast this spell, CARDNAME enters the battlefield with a +1/+1 counter on it. K:CantBeBlockedBy Creature.powerLE2 +SVar:AIManaPref:G DeckHas:Ability$Counters Oracle:Adamant — If at least three green mana was spent to cast this spell, Garenbrig Paladin enters the battlefield with a +1/+1 counter on it.\nGarenbrig Paladin can't be blocked by creatures with power 2 or less. diff --git a/forge-gui/res/cardsfolder/l/locthwain_paladin.txt b/forge-gui/res/cardsfolder/l/locthwain_paladin.txt index afb980e762e..d9993643a16 100644 --- a/forge-gui/res/cardsfolder/l/locthwain_paladin.txt +++ b/forge-gui/res/cardsfolder/l/locthwain_paladin.txt @@ -4,5 +4,6 @@ Types:Creature Human Knight PT:3/2 K:Menace K:etbCounter:P1P1:1:Adamant$ Black:Adamant — If at least three black mana was spent to cast this spell, CARDNAME enters the battlefield with a +1/+1 counter on it. +SVar:AIManaPref:B DeckHas:Ability$Counters Oracle:Menace (This creature can't be blocked except by two or more creatures.)\nAdamant — If at least three black mana was spent to cast this spell, Locthwain Paladin enters the battlefield with a +1/+1 counter on it. diff --git a/forge-gui/res/cardsfolder/o/once_and_future.txt b/forge-gui/res/cardsfolder/o/once_and_future.txt index f822a30f5cb..6aa3b03f15f 100644 --- a/forge-gui/res/cardsfolder/o/once_and_future.txt +++ b/forge-gui/res/cardsfolder/o/once_and_future.txt @@ -1,7 +1,7 @@ Name:Once and Future ManaCost:3 G Types:Instant -A:SP$ ChangeZone | Cost$ 3 G | Origin$ Graveyard | Destination$ Hand | TgtPrompt$ Select target card in your graveyard to return to your hand | ValidTgts$ Card.YouOwn | SubAbility$ DBPump | StackDescription$ SpellDescription | SpellDescription$ Return target card from your graveyard to your hand. Put up to one other target card from your graveyard on top of your library. Exile CARDNAME. Adamant — If at least three green mana was spent to cast this spell, instead return those cards to your hand and exile CARDNAME. +A:SP$ ChangeZone | Cost$ 3 G | Origin$ Graveyard | Destination$ Hand | TgtPrompt$ Select target card in your graveyard to return to your hand | ValidTgts$ Card.YouOwn | SubAbility$ DBPump | AIManaPref$ G | StackDescription$ SpellDescription | SpellDescription$ Return target card from your graveyard to your hand. Put up to one other target card from your graveyard on top of your library. Exile CARDNAME. Adamant — If at least three green mana was spent to cast this spell, instead return those cards to your hand and exile CARDNAME. SVar:DBPump:DB$ Pump | TargetMin$ 0 | TargetMax$ 1 | TgtZone$ Graveyard | TgtPrompt$ Select up to one target card in your graveyard to put on top of your library | ValidTgts$ Card.YouOwn | TargetUnique$ True | RememberObjects$ ThisTargetedCard | SubAbility$ DBReturn | StackDescription$ None SVar:DBReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Library | Hidden$ True | Defined$ Remembered | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ0 | References$ X | SubAbility$ DBReturn2 SVar:DBReturn2:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | Hidden$ True | Defined$ Remembered | ConditionCheckSVar$ X | References$ X | SubAbility$ DBExile diff --git a/forge-gui/res/cardsfolder/o/outmuscle.txt b/forge-gui/res/cardsfolder/o/outmuscle.txt index 6a9a28753c0..ee3459a144d 100644 --- a/forge-gui/res/cardsfolder/o/outmuscle.txt +++ b/forge-gui/res/cardsfolder/o/outmuscle.txt @@ -1,7 +1,7 @@ Name:Outmuscle ManaCost:3 G Types:Sorcery -A:SP$ PutCounter | Cost$ 3 G | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Choose target creature you control | RememberTargets$ True | CounterType$ P1P1 | CounterNum$ 1 | AILogic$ Fight | SubAbility$ DBFight | SpellDescription$ Put a +1/+1 counter on target creature you control, then it fights with a creature you don't control. Adamant — If at least three green mana was spent to cast this spell, the creature you control gets indestructible until end of turn. +A:SP$ PutCounter | Cost$ 3 G | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Choose target creature you control | RememberTargets$ True | CounterType$ P1P1 | CounterNum$ 1 | AILogic$ Fight | AIManaPref$ G | SubAbility$ DBFight | SpellDescription$ Put a +1/+1 counter on target creature you control, then it fights with a creature you don't control. Adamant — If at least three green mana was spent to cast this spell, the creature you control gets indestructible until end of turn. SVar:DBFight:DB$ Fight | Defined$ ParentTarget | ValidTgts$ Creature.YouDontCtrl | AILogic$ Always | TgtPrompt$ Choose target creature you don't control | SubAbility$ DBPump SVar:DBPump:DB$ Pump | Defined$ Remembered | KW$ Indestructible | ConditionCheckSVar$ X | References$ X | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True diff --git a/forge-gui/res/cardsfolder/r/rally_for_the_throne.txt b/forge-gui/res/cardsfolder/r/rally_for_the_throne.txt index ef8df94ada4..c3a3e799f0a 100644 --- a/forge-gui/res/cardsfolder/r/rally_for_the_throne.txt +++ b/forge-gui/res/cardsfolder/r/rally_for_the_throne.txt @@ -1,7 +1,7 @@ Name:Rally for the Throne ManaCost:2 W Types:Instant -A:SP$ Token | Cost$ 2 W | TokenAmount$ 2 | TokenScript$ w_1_1_human | TokenOwner$ You | LegacyImage$ w 1 1 human eld | SubAbility$ DBGainLife | SpellDescription$ Create two 1/1 white Human creature tokens. Adamant — If at least three white mana was spent to cast this spell, you gain 1 life for each creature you control. +A:SP$ Token | Cost$ 2 W | TokenAmount$ 2 | TokenScript$ w_1_1_human | TokenOwner$ You | LegacyImage$ w 1 1 human eld | AIManaPref$ W | SubAbility$ DBGainLife | SpellDescription$ Create two 1/1 white Human creature tokens. Adamant — If at least three white mana was spent to cast this spell, you gain 1 life for each creature you control. SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ Y | ConditionCheckSVar$ X | References$ X,Y SVar:X:Count$Adamant.White.1.0 SVar:Y:Count$Valid Creature.YouCtrl diff --git a/forge-gui/res/cardsfolder/s/searing_barrage.txt b/forge-gui/res/cardsfolder/s/searing_barrage.txt index dbed71c499e..113ef435517 100644 --- a/forge-gui/res/cardsfolder/s/searing_barrage.txt +++ b/forge-gui/res/cardsfolder/s/searing_barrage.txt @@ -1,7 +1,7 @@ Name:Searing Barrage ManaCost:4 R Types:Instant -A:SP$ DealDamage | Cost$ 4 R | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 5 | SpellDescription$ CARDNAME deals 5 damage to target creature. Adamant — If at least three red mana was spent to cast this spell, CARDNAME deals 3 damage to that creature's controller. | SubAbility$ DBDmg +A:SP$ DealDamage | Cost$ 4 R | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 5 | AIManaPref$ R | SpellDescription$ CARDNAME deals 5 damage to target creature. Adamant — If at least three red mana was spent to cast this spell, CARDNAME deals 3 damage to that creature's controller. | SubAbility$ DBDmg SVar:DBDmg:DB$ DealDamage | Defined$ TargetedController | NumDmg$ 3 | ConditionCheckSVar$ X | References$ X SVar:X:Count$Adamant.Red.1.0 Oracle:Searing Barrage deals 5 damage to target creature.\nAdamant — If at least three red mana was spent to cast this spell, Searing Barrage deals 3 damage to that creature's controller. diff --git a/forge-gui/res/cardsfolder/s/silverflame_ritual.txt b/forge-gui/res/cardsfolder/s/silverflame_ritual.txt index cf112031338..b985cd8024c 100644 --- a/forge-gui/res/cardsfolder/s/silverflame_ritual.txt +++ b/forge-gui/res/cardsfolder/s/silverflame_ritual.txt @@ -1,7 +1,7 @@ Name:Silverflame Ritual ManaCost:3 W Types:Sorcery -A:SP$ PutCounterAll | Cost$ 3 W | ValidCards$ Creature.YouCtrl | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBPumpAll | SpellDescription$ Put a +1/+1 counter on each creature you control. Adamant — If at least three white mana was spent to cast this spell, creatures you control gain vigilance until end of turn. +A:SP$ PutCounterAll | Cost$ 3 W | ValidCards$ Creature.YouCtrl | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBPumpAll | AIManaPref$ W | SpellDescription$ Put a +1/+1 counter on each creature you control. Adamant — If at least three white mana was spent to cast this spell, creatures you control gain vigilance until end of turn. SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Creature.YouCtrl | KW$ Vigilance | ConditionCheckSVar$ X | References$ X SVar:X:Count$Adamant.White.1.0 DeckHas:Ability$Counters diff --git a/forge-gui/res/cardsfolder/s/slaying_fire.txt b/forge-gui/res/cardsfolder/s/slaying_fire.txt index 8476797dfaa..ec408a25870 100644 --- a/forge-gui/res/cardsfolder/s/slaying_fire.txt +++ b/forge-gui/res/cardsfolder/s/slaying_fire.txt @@ -1,6 +1,6 @@ Name:Slaying Fire ManaCost:2 R Types:Instant -A:SP$ DealDamage | Cost$ 2 R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | References$ X | SpellDescription$ CARDNAME deals 3 damage to any target. Adamant — If at least three red mana was spent to cast this spell, it deals 4 damage instead. +A:SP$ DealDamage | Cost$ 2 R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | References$ X | AIManaPref$ R | SpellDescription$ CARDNAME deals 3 damage to any target. Adamant — If at least three red mana was spent to cast this spell, it deals 4 damage instead. SVar:X:Count$Adamant.Red.4.3 Oracle:Slaying Fire deals 3 damage to any target.\nAdamant — If at least three red mana was spent to cast this spell, it deals 4 damage instead. diff --git a/forge-gui/res/cardsfolder/t/turn_into_a_pumpkin.txt b/forge-gui/res/cardsfolder/t/turn_into_a_pumpkin.txt index d2f75afce76..e183042a334 100644 --- a/forge-gui/res/cardsfolder/t/turn_into_a_pumpkin.txt +++ b/forge-gui/res/cardsfolder/t/turn_into_a_pumpkin.txt @@ -1,7 +1,7 @@ Name:Turn into a Pumpkin ManaCost:3 U Types:Instant -A:SP$ ChangeZone | Cost$ 3 U | ValidTgts$ Permanent.nonLand | TgtPrompt$ Select target nonland permanent | Origin$ Battlefield | Destination$ Hand | SubAbility$ DBDraw | SpellDescription$ Return target nonland permanent to its owner's hand. Draw a card. Adamant — If at least three blue mana was spent to cast this spell, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 3 life.") +A:SP$ ChangeZone | Cost$ 3 U | ValidTgts$ Permanent.nonLand | TgtPrompt$ Select target nonland permanent | Origin$ Battlefield | Destination$ Hand | SubAbility$ DBDraw | AIManaPref$ U | SpellDescription$ Return target nonland permanent to its owner's hand. Draw a card. Adamant — If at least three blue mana was spent to cast this spell, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 3 life.") SVar:DBDraw:DB$ Draw | NumCards$ 1 | SubAbility$ DBToken SVar:DBToken:DB$ Token | TokenAmount$ X | TokenScript$ c_a_food_sac | TokenOwner$ You | LegacyImage$ c a food sac eld | References$ X SVar:X:Count$Adamant.Blue.1.0 diff --git a/forge-gui/res/cardsfolder/u/unexplained_vision.txt b/forge-gui/res/cardsfolder/u/unexplained_vision.txt index 7f484b8a997..491cf90a569 100644 --- a/forge-gui/res/cardsfolder/u/unexplained_vision.txt +++ b/forge-gui/res/cardsfolder/u/unexplained_vision.txt @@ -1,7 +1,7 @@ Name:Unexplained Vision ManaCost:4 U Types:Sorcery -A:SP$ Draw | Cost$ 4 U | NumCards$ 3 | SubAbility$ DBScry | SpellDescription$ Draw three cards. Adamant — If at least three blue mana was spent to cast this spell, scry 3. +A:SP$ Draw | Cost$ 4 U | NumCards$ 3 | SubAbility$ DBScry | AIManaPref$ U | SpellDescription$ Draw three cards. Adamant — If at least three blue mana was spent to cast this spell, scry 3. SVar:DBScry:DB$ Scry | ScryNum$ 3 | ConditionCheckSVar$ X | References$ X SVar:X:Count$Adamant.Blue.1.0 Oracle:Draw three cards.\nAdamant — If at least three blue mana was spent to cast this spell, scry 3. diff --git a/forge-gui/res/cardsfolder/v/vantress_paladin.txt b/forge-gui/res/cardsfolder/v/vantress_paladin.txt index e0a22bb61dc..652337cc6af 100644 --- a/forge-gui/res/cardsfolder/v/vantress_paladin.txt +++ b/forge-gui/res/cardsfolder/v/vantress_paladin.txt @@ -5,4 +5,5 @@ PT:2/2 K:Flying K:etbCounter:P1P1:1:Adamant$ Blue:Adamant — If at least three blue mana was spent to cast this spell, CARDNAME enters the battlefield with a +1/+1 counter on it. DeckHas:Ability$Counters +SVar:AIManaPref:U Oracle:Flying\nAdamant — If at least three blue mana was spent to cast this spell, Vantress Paladin enters the battlefield with a +1/+1 counter on it.