mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
Improve AI logic for cavern of souls. (#1787)
* Improve AI logic for cavern of souls. Improve AI logic for cavern of souls. - Don't count token creature types when looking for most prominent creature type, since cavern of souls doesn't help with them. - Weigh cards in hand and commanders double, as they are more likely to be cast. I tested with a Tiny Leaders deck running Geist of Saint Traft that didn't have any creature type synergy and confirmed that the changes make the AI choose Spirit for Geist, rather than Human as before. * Apply this to a few more cards. * Remove a print statement. * Address review comments.
This commit is contained in:
@@ -2378,8 +2378,9 @@ public class ComputerUtil {
|
||||
chosen = ComputerUtilCard.getMostProminentType(list, valid);
|
||||
}
|
||||
}
|
||||
else if (logic.equals("MostProminentInComputerDeck")) {
|
||||
chosen = ComputerUtilCard.getMostProminentType(ai.getAllCards(), valid);
|
||||
else if (logic.startsWith("MostProminentInComputerDeck")) {
|
||||
boolean includeTokens = !logic.endsWith("NonToken");
|
||||
chosen = ComputerUtilCard.getMostProminentType(ai.getAllCards(), valid, includeTokens);
|
||||
}
|
||||
else if (logic.equals("MostProminentInComputerGraveyard")) {
|
||||
chosen = ComputerUtilCard.getMostProminentType(ai.getCardsIn(ZoneType.Graveyard), valid);
|
||||
|
||||
@@ -762,30 +762,21 @@ public class ComputerUtilCard {
|
||||
return maxName;
|
||||
}
|
||||
|
||||
public static String getMostProminentBasicLandType(final CardCollectionView list) {
|
||||
return getMostProminentType(list, CardType.getBasicTypes());
|
||||
public static String getMostProminentType(final CardCollectionView list, final Collection<String> valid) {
|
||||
return getMostProminentType(list, valid, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getMostProminentCreatureType.
|
||||
* </p>
|
||||
*
|
||||
* @param list
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public static String getMostProminentCreatureType(final CardCollectionView list) {
|
||||
return getMostProminentType(list, CardType.getAllCreatureTypes());
|
||||
}
|
||||
public static String getMostProminentType(final CardCollectionView list, final Collection<String> valid) {
|
||||
public static String getMostProminentType(final CardCollectionView list, final Collection<String> valid, boolean includeTokens) {
|
||||
if (list.size() == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
final Map<String, Integer> typesInDeck = Maps.newHashMap();
|
||||
|
||||
// TODO JAVA 8 use getOrDefault
|
||||
for (final Card c : list) {
|
||||
if (!includeTokens && c.isToken()) {
|
||||
continue;
|
||||
}
|
||||
// Changeling are all creature types, they are not interesting for
|
||||
// counting creature types
|
||||
if (c.hasStartOfKeyword(Keyword.CHANGELING.toString())) {
|
||||
@@ -803,15 +794,20 @@ public class ComputerUtilCard {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cards in hand and commanders are worth double, as they are more likely to be played.
|
||||
int weight = 1;
|
||||
if (c.isInZone(ZoneType.Hand) || c.isRealCommander()) {
|
||||
weight = 2;
|
||||
}
|
||||
|
||||
Set<String> cardCreatureTypes = c.getType().getCreatureTypes();
|
||||
for (String type : cardCreatureTypes) {
|
||||
Integer count = typesInDeck.get(type);
|
||||
if (count == null) {
|
||||
count = 0;
|
||||
}
|
||||
typesInDeck.put(type, count + 1);
|
||||
Integer count = typesInDeck.getOrDefault(type, 0);
|
||||
typesInDeck.put(type, count + weight);
|
||||
}
|
||||
|
||||
//also take into account abilities that generate tokens
|
||||
if (includeTokens) {
|
||||
for (SpellAbility sa : c.getAllSpellAbilities()) {
|
||||
if (sa.getApi() != ApiType.Token) {
|
||||
continue;
|
||||
@@ -821,11 +817,8 @@ public class ComputerUtilCard {
|
||||
if (!CardType.isACreatureType(var)) {
|
||||
continue;
|
||||
}
|
||||
Integer count = typesInDeck.get(var);
|
||||
if (count == null) {
|
||||
count = 0;
|
||||
}
|
||||
typesInDeck.put(var, count + 1);
|
||||
Integer count = typesInDeck.getOrDefault(var, 0);
|
||||
typesInDeck.put(var, count + weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -840,21 +833,16 @@ public class ComputerUtilCard {
|
||||
if (!CardType.isACreatureType(var)) {
|
||||
continue;
|
||||
}
|
||||
Integer count = typesInDeck.get(var);
|
||||
if (count == null) {
|
||||
count = 0;
|
||||
}
|
||||
typesInDeck.put(var, count + 1);
|
||||
Integer count = typesInDeck.getOrDefault(var, 0);
|
||||
typesInDeck.put(var, count + weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
// special rule for Fabricate and Servo
|
||||
if (c.hasStartOfKeyword(Keyword.FABRICATE.toString())) {
|
||||
Integer count = typesInDeck.get("Servo");
|
||||
if (count == null) {
|
||||
count = 0;
|
||||
Integer count = typesInDeck.getOrDefault("Servo", 0);
|
||||
typesInDeck.put("Servo", count + weight);
|
||||
}
|
||||
typesInDeck.put("Servo", count + 1);
|
||||
}
|
||||
} // for
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@ Name:Belbe's Portal
|
||||
ManaCost:5
|
||||
Types:Artifact
|
||||
K:ETBReplacement:Other:ChooseCT
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type. | AILogic$ MostProminentInComputerDeck
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type. | AILogic$ MostProminentInComputerDeckNonToken
|
||||
A:AB$ ChangeZone | Cost$ 3 T | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature.ChosenType | ChangeNum$ 1 | SpellDescription$ You may put a creature card of the chosen type from your hand onto the battlefield.
|
||||
Oracle:As Belbe's Portal enters the battlefield, choose a creature type.\n{3}, {T}: You may put a creature card of the chosen type from your hand onto the battlefield.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Bloodline Shaman
|
||||
ManaCost:1 G
|
||||
Types:Creature Elf Wizard Shaman
|
||||
PT:1/1
|
||||
A:AB$ ChooseType | Cost$ T | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeck | SubAbility$ ShamanDig | SpellDescription$ Choose a creature type. Reveal the top card of your library. If that card is a creature card of the chosen type, put it into your hand. Otherwise, put it into your graveyard.
|
||||
A:AB$ ChooseType | Cost$ T | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeckNonToken | SubAbility$ ShamanDig | SpellDescription$ Choose a creature type. Reveal the top card of your library. If that card is a creature card of the chosen type, put it into your hand. Otherwise, put it into your graveyard.
|
||||
SVar:ShamanDig:DB$ Dig | DigNum$ 1 | Reveal$ True | ChangeNum$ All | ChangeValid$ Creature.ChosenType | DestinationZone$ Hand | DestinationZone2$ Graveyard
|
||||
AI:RemoveDeck:Random
|
||||
Oracle:{T}: Choose a creature type. Reveal the top card of your library. If that card is a creature card of the chosen type, put it into your hand. Otherwise, put it into your graveyard.
|
||||
|
||||
@@ -4,7 +4,7 @@ Types:Artifact Creature Golem
|
||||
PT:2/2
|
||||
S:Mode$ Continuous | Affected$ Creature.ChosenType | AddPower$ 1 | AddToughness$ 1 | Description$ Creatures of the chosen type get +1/+1.
|
||||
K:ETBReplacement:Other:ChooseCT
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type. | AILogic$ MostProminentInComputerDeck
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type. | AILogic$ MostProminentInComputerDeckNonToken
|
||||
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigDig | TriggerDescription$ When CARDNAME enters the battlefield, reveal the top four cards of your library. Put all creature cards of the chosen type revealed this way into your hand and the rest on the bottom of your library in any order.
|
||||
SVar:TrigDig:DB$ Dig | DigNum$ 4 | Reveal$ True | ChangeNum$ All | ChangeValid$ Creature.ChosenType
|
||||
SVar:PlayMain1:TRUE
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Cavern of Souls
|
||||
ManaCost:no cost
|
||||
Types:Land
|
||||
K:ETBReplacement:Other:ChooseCT
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type. | AILogic$ MostProminentInComputerDeck
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type. | AILogic$ MostProminentInComputerDeckNonToken
|
||||
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
|
||||
A:AB$ Mana | Cost$ T | Produced$ Any | RestrictValid$ Spell.Creature+ChosenType | AddsNoCounter$ True | SpellDescription$ Add one mana of any color. Spend this mana only to cast a creature spell of the chosen type, and that spell can't be countered.
|
||||
Oracle:As Cavern of Souls enters the battlefield, choose a creature type.\n{T}: Add {C}.\n{T}: Add one mana of any color. Spend this mana only to cast a creature spell of the chosen type, and that spell can't be countered.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Herald's Horn
|
||||
ManaCost:3
|
||||
Types:Artifact
|
||||
K:ETBReplacement:Other:ChooseCT
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type. | AILogic$ MostProminentInComputerDeck
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type. | AILogic$ MostProminentInComputerDeckNonToken
|
||||
S:Mode$ ReduceCost | ValidCard$ Creature.ChosenType | Type$ Spell | Activator$ You | Amount$ 1 | Description$ Creature spells you cast of the chosen type cost {1} less to cast.
|
||||
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigPeek | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, look at the top card of your library. If it's a creature card of the chosen type, you may reveal it and put it into your hand.
|
||||
SVar:TrigPeek:DB$ PeekAndReveal | PeekAmount$ 1 | RevealValid$ Creature.ChosenType | RevealOptional$ True | RememberRevealed$ True | SubAbility$ DBChangeZone
|
||||
|
||||
@@ -13,6 +13,6 @@ Name:The Ringhart Crest
|
||||
ManaCost:1 G
|
||||
Types:Legendary Artifact
|
||||
K:ETBReplacement:Other:ChooseCT
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeck | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type.
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeckNonToken | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type.
|
||||
A:AB$ Mana | Cost$ T | Produced$ G | RestrictValid$ Spell.Creature+ChosenType,Spell.Creature+Legendary | SpellDescription$ Add {G}. Spend this mana only to cast a creature spell of the chosen type or a legendary creature spell.
|
||||
Oracle:As The Ringhart Crest enters the battlefield, choose a creature type.\n{T}: Add {G}. Spend this mana only to cast a creature spell of the chosen type or a legendary creature spell.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Molten Echoes
|
||||
ManaCost:2 R R
|
||||
Types:Enchantment
|
||||
K:ETBReplacement:Other:ChooseCT
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeck | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type.
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeckNonToken | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type.
|
||||
T:Mode$ ChangesZone | ValidCard$ Creature.nonToken+ChosenType+YouCtrl | Origin$ Any | Destination$ Battlefield | Execute$ TrigCopyPermanent | TriggerZones$ Battlefield | TriggerDescription$ Whenever a nontoken creature of the chosen type enters the battlefield under your control, create a token that's a copy of that creature. That token gains haste. Exile it at the beginning of the next end step.
|
||||
SVar:TrigCopyPermanent:DB$ CopyPermanent | Defined$ TriggeredCard | NumCopies$ 1 | PumpKeywords$ Haste | AtEOT$ Exile
|
||||
Oracle:As Molten Echoes enters the battlefield, choose a creature type.\nWhenever a nontoken creature of the chosen type enters the battlefield under your control, create a token that's a copy of that creature. That token gains haste. Exile it at the beginning of the next end step.
|
||||
|
||||
@@ -4,7 +4,7 @@ Types:Creature Shapeshifter
|
||||
PT:2/3
|
||||
K:Changeling
|
||||
K:ETBReplacement:Other:ChooseCT
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeck | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type.
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeckNonToken | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type.
|
||||
S:Mode$ Continuous | Affected$ Card.TopLibrary+YouCtrl | AffectedZone$ Library | MayLookAt$ You | Description$ You may look at the top card of your library any time.
|
||||
S:Mode$ Continuous | Affected$ Creature.ChosenType+TopLibrary+YouCtrl+nonLand | AffectedZone$ Library | MayPlay$ True | Description$ You may cast creature spells of the chosen type from the top of your library.
|
||||
Oracle:Changeling (This card is every creature type.)\nAs Realmwalker enters the battlefield, choose a creature type.\nYou may look at the top card of your library any time.\nYou may cast creature spells of the chosen type from the top of your library.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Reflections of Littjara
|
||||
ManaCost:4 U
|
||||
Types:Enchantment
|
||||
K:ETBReplacement:Other:ChooseCT
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeck | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type. | StackDescription$ SpellDescription
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeckNonToken | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type. | StackDescription$ SpellDescription
|
||||
T:Mode$ SpellCast | ValidCard$ Card.ChosenType | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigCopy | TriggerDescription$ Whenever you cast a spell of the chosen type, copy that spell. (A copy of a permanent spell becomes a token.)
|
||||
SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | AILogic$ Always | MayChooseTarget$ True
|
||||
DeckHas:Ability$Token
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Unclaimed Territory
|
||||
ManaCost:no cost
|
||||
Types:Land
|
||||
K:ETBReplacement:Other:ChooseCT
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type. | AILogic$ MostProminentInComputerDeck
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type. | AILogic$ MostProminentInComputerDeckNonToken
|
||||
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
|
||||
A:AB$ Mana | Cost$ T | Produced$ Any | RestrictValid$ Spell.Creature+ChosenType | SpellDescription$ Add one mana of any color. Spend this mana only to cast a creature spell of the chosen type.
|
||||
Oracle:As Unclaimed Territory enters the battlefield, choose a creature type.\n{T}: Add {C}.\n{T}: Add one mana of any color. Spend this mana only to cast a creature spell of the chosen type.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Urza's Incubator
|
||||
ManaCost:3
|
||||
Types:Artifact
|
||||
K:ETBReplacement:Other:ChooseCT
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeck | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type.
|
||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeckNonToken | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type.
|
||||
S:Mode$ ReduceCost | ValidCard$ Creature.ChosenType | Type$ Spell | Amount$ 2 | Description$ Creature spells of the chosen type cost {2} less to cast.
|
||||
AI:RemoveDeck:Random
|
||||
Oracle:As Urza's Incubator enters the battlefield, choose a creature type.\nCreature spells of the chosen type cost {2} less to cast.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Name:Vexing Arcanix
|
||||
ManaCost:4
|
||||
Types:Artifact
|
||||
A:AB$ NameCard | Cost$ 3 T | ValidTgts$ Player | TgtPrompt$ Select target player | SubAbility$ DBDig | AILogic$ MostProminentInComputerDeck | SpellDescription$ Target player chooses a card name, then reveals the top card of their library. If that card has the chosen name, the player puts it into their hand. Otherwise, the player puts it into their graveyard and CARDNAME deals 2 damage to them.
|
||||
A:AB$ NameCard | Cost$ 3 T | ValidTgts$ Player | TgtPrompt$ Select target player | SubAbility$ DBDig | AILogic$ MostProminentInComputerDeckNonToken | SpellDescription$ Target player chooses a card name, then reveals the top card of their library. If that card has the chosen name, the player puts it into their hand. Otherwise, the player puts it into their graveyard and CARDNAME deals 2 damage to them.
|
||||
SVar:DBDig:DB$ Dig | DigNum$ 1 | Defined$ Targeted | ChangeNum$ All | ChangeValid$ Card.NamedCard | DestinationZone2$ Graveyard | Reveal$ True | RememberChanged$ True | SubAbility$ DBDamage
|
||||
SVar:DBDamage:DB$ DealDamage | NumDmg$ 2 | Defined$ Targeted | ConditionDefined$ Remembered | ConditionPresent$ Card.NamedCard | ConditionCompare$ EQ0 | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
|
||||
Reference in New Issue
Block a user