Merge branch 'master' into 'master'

Fix a variety of Roll Dice card- and AI-related issues, improve AI for AF RollDice

See merge request core-developers/forge!4138
This commit is contained in:
Michael Kamensky
2021-03-07 17:08:33 +00:00
14 changed files with 31 additions and 15 deletions

View File

@@ -375,7 +375,9 @@ public class AiController {
@Override @Override
public boolean apply(final Card c) { public boolean apply(final Card c) {
CardCollectionView battlefield = player.getCardsIn(ZoneType.Battlefield); CardCollectionView battlefield = player.getCardsIn(ZoneType.Battlefield);
canPlaySpellBasic(c, null); if (canPlaySpellBasic(c, null) != AiPlayDecision.WillPlay) {
return false;
}
String name = c.getName(); String name = c.getName();
if (c.getType().isLegendary() && !name.equals("Flagstones of Trokair")) { if (c.getType().isLegendary() && !name.equals("Flagstones of Trokair")) {
if (Iterables.any(battlefield, CardPredicates.nameEquals(name))) { if (Iterables.any(battlefield, CardPredicates.nameEquals(name))) {

View File

@@ -2,6 +2,8 @@ package forge.ai.ability;
import forge.ai.SpellAbilityAi; import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.cost.Cost; import forge.game.cost.Cost;
import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
@@ -12,8 +14,19 @@ import forge.game.spellability.SpellAbility;
public class RollDiceAi extends SpellAbilityAi { public class RollDiceAi extends SpellAbilityAi {
@Override @Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) { protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
PhaseHandler ph = aiPlayer.getGame().getPhaseHandler(); Card source = sa.getHostCard();
Game game = aiPlayer.getGame();
PhaseHandler ph = game.getPhaseHandler();
Cost cost = sa.getPayCosts(); Cost cost = sa.getPayCosts();
String logic = sa.getParamOrDefault("AILogic", "");
if (logic.equals("Combat")) {
return game.getCombat() != null && ((game.getCombat().isAttacking(source) && game.getCombat().isUnblocked(source)) || game.getCombat().isBlocking(source));
} else if (logic.equals("CombatEarly")) {
return game.getCombat() != null && (game.getCombat().isAttacking(source) || game.getCombat().isBlocking(source));
} else if (logic.equals("Main2")) {
return ph.is(PhaseType.MAIN2, aiPlayer);
}
if (cost != null && (sa.getPayCosts().hasManaCost() || sa.getPayCosts().hasTapCost())) { if (cost != null && (sa.getPayCosts().hasManaCost() || sa.getPayCosts().hasTapCost())) {
return ph.getNextTurn() == aiPlayer && ph.is(PhaseType.END_OF_TURN); return ph.getNextTurn() == aiPlayer && ph.is(PhaseType.END_OF_TURN);

View File

@@ -2,7 +2,7 @@ Name:As Luck Would Have It
ManaCost:G ManaCost:G
Types:Enchantment Types:Enchantment
K:Hexproof K:Hexproof
T:Mode$ RolledDie | Execute$ TrigCounters | ValidPlayer$ You | TriggerDescription$ Whenever you roll a die, put a number of luck counters on As Luck Would Have It equal to the result. Then if there are 100 or more luck counters on As Luck Would Have It, you win the game. T:Mode$ RolledDie | Execute$ TrigCounters | ValidPlayer$ You | TriggerZones$ Battlefield | TriggerDescription$ Whenever you roll a die, put a number of luck counters on As Luck Would Have It equal to the result. Then if there are 100 or more luck counters on As Luck Would Have It, you win the game.
SVar:TrigCounters:DB$ PutCounter | Defined$ Self | CounterType$ LUCK | CounterNum$ X | SubAbility$ DBWin SVar:TrigCounters:DB$ PutCounter | Defined$ Self | CounterType$ LUCK | CounterNum$ X | SubAbility$ DBWin
SVar:DBWin:DB$ WinsGame | Defined$ You | ConditionPresent$ Card.Self+counters_GE100_LUCK SVar:DBWin:DB$ WinsGame | Defined$ You | ConditionPresent$ Card.Self+counters_GE100_LUCK
SVar:X:TriggerCount$Result SVar:X:TriggerCount$Result

View File

@@ -2,7 +2,7 @@ Name:Chicken à la King
ManaCost:1 U U ManaCost:1 U U
Types:Creature Bird Noble Types:Creature Bird Noble
PT:2/2 PT:2/2
T:Mode$ RolledDie | Execute$ TrigCounters | ValidResult$ 6 | TriggerDescription$ Whenever a 6 is rolled on a six-sided die, put a +1/+1 counter on each Bird. T:Mode$ RolledDie | TriggerZones$ Battlefield | Execute$ TrigCounters | ValidResult$ 6 | TriggerDescription$ Whenever a 6 is rolled on a six-sided die, put a +1/+1 counter on each Bird.
SVar:TrigCounters:DB$ PutCounterAll | ValidCards$ Bird | CounterType$ P1P1 | CounterNum$ 1 SVar:TrigCounters:DB$ PutCounterAll | ValidCards$ Bird | CounterType$ P1P1 | CounterNum$ 1
A:AB$ RollDice | Cost$ tapXType<1/Bird> | SpellDescription$ Roll a six-sided die. A:AB$ RollDice | Cost$ tapXType<1/Bird> | SpellDescription$ Roll a six-sided die.
DeckHas:Ability$Counters DeckHas:Ability$Counters

View File

@@ -1,7 +1,7 @@
Name:Chittering Doom Name:Chittering Doom
ManaCost:3 G ManaCost:3 G
Types:Enchantment Types:Enchantment
T:Mode$ RolledDie | Execute$ TrigToken | ValidPlayer$ You | ValidResult$ GE4 | TriggerDescription$ Whenever you roll a 4 or higher on a die, create a 1/1 green Squirrel creature token. T:Mode$ RolledDie | TriggerZones$ Battlefield | Execute$ TrigToken | ValidPlayer$ You | ValidResult$ GE4 | TriggerDescription$ Whenever you roll a 4 or higher on a die, create a 1/1 green Squirrel creature token.
SVar:TrigToken:DB$ Token | TokenScript$ g_1_1_squirrel SVar:TrigToken:DB$ Token | TokenScript$ g_1_1_squirrel
DeckHas:Ability$Token DeckHas:Ability$Token
Oracle:Whenever you roll a 4 or higher on a die, create a 1/1 green Squirrel creature token. Oracle:Whenever you roll a 4 or higher on a die, create a 1/1 green Squirrel creature token.

View File

@@ -6,10 +6,10 @@ K:ETBReplacement:Other:RollLoyal
SVar:RollLoyal:DB$ RollDice | Sides$ 4 | ResultSVar$ Result | SubAbility$ DBLoyalty | SpellDescription$ Add 1d4 loyalty counters to CARDNAME SVar:RollLoyal:DB$ RollDice | Sides$ 4 | ResultSVar$ Result | SubAbility$ DBLoyalty | SpellDescription$ Add 1d4 loyalty counters to CARDNAME
SVar:DBLoyalty:DB$ PutCounter | Defined$ Self | CounterType$ LOYALTY | CounterNum$ Result | ETB$ True SVar:DBLoyalty:DB$ PutCounter | Defined$ Self | CounterType$ LOYALTY | CounterNum$ Result | ETB$ True
A:AB$ Token | Cost$ AddCounter<1/LOYALTY> | ValidTgts$ Opponent | TokenOwner$ Targeted | TokenScript$ b_1_1_skeleton_opp_life | Planeswalker$ True | SpellDescription$ Target opponent creates a 1/1 black Skeleton creature token with "When this creature dies, each opponent gains 2 life."" A:AB$ Token | Cost$ AddCounter<1/LOYALTY> | ValidTgts$ Opponent | TokenOwner$ Targeted | TokenScript$ b_1_1_skeleton_opp_life | Planeswalker$ True | SpellDescription$ Target opponent creates a 1/1 black Skeleton creature token with "When this creature dies, each opponent gains 2 life.""
A:AB$ RollDice | Cost$ AddCounter<1/LOYALTY> | Sides$ 2 | On1$ DBSkipTurn | ResultSVar$ Result | SubAbility$ DBDraw | SpellDescription$ Roll a d20. If you roll a 1, skip your next turn. If you roll a 12 or higher, draw a card. A:AB$ RollDice | Cost$ AddCounter<1/LOYALTY> | Sides$ 2 | On1$ DBSkipTurn | ResultSVar$ Result | Planeswalker$ True | SubAbility$ DBDraw | SpellDescription$ Roll a d20. If you roll a 1, skip your next turn. If you roll a 12 or higher, draw a card.
SVar:DBSkipTurn:DB$ SkipTurn | Defined$ You | NumTurns$ 1 SVar:DBSkipTurn:DB$ SkipTurn | Defined$ You | NumTurns$ 1
SVar:DBDraw:DB$ Draw | ConditionCheckSVar$ Result | ConditionSVarCompare$ GE12 SVar:DBDraw:DB$ Draw | ConditionCheckSVar$ Result | ConditionSVarCompare$ GE12
A:AB$ Token | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | TokenScript$ r_3_3_fighter_first_strike | SubAbility$ DBCleric | SpellDescription$ You get an adventuring party. (Your party is a 3/3 red Fighter with first strike, a 1/1 white Cleric with lifelink, a 2/2 black Rogue with hexproof, and a 1/1 blue Wizard with flying.) A:AB$ Token | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | TokenScript$ r_3_3_fighter_first_strike | SubAbility$ DBCleric | SpellDescription$ You get an adventuring party. (Your party is a 3/3 red Fighter with first strike, a 1/1 white Cleric with lifelink, a 2/2 black Rogue with hexproof, and a 1/1 blue Wizard with flying.)
SVar:DBCleric:DB$ Token | TokenScript$ w_1_1_cleric_lifelink | SubAbility$ DBRogue SVar:DBCleric:DB$ Token | TokenScript$ w_1_1_cleric_lifelink | SubAbility$ DBRogue
SVar:DBRogue:DB$ Token | TokenScript$ b_2_2_rogue_hexproof | SubAbility$ DBWizard SVar:DBRogue:DB$ Token | TokenScript$ b_2_2_rogue_hexproof | SubAbility$ DBWizard
SVar:DBWizard:DB$ Token | TokenScript$ u_1_1_wizard_flying SVar:DBWizard:DB$ Token | TokenScript$ u_1_1_wizard_flying

View File

@@ -2,7 +2,7 @@ Name:Ground Pounder
ManaCost:1 G ManaCost:1 G
Types:Creature Goblin Warrior Types:Creature Goblin Warrior
PT:2/2 PT:2/2
A:AB$ RollDice | Cost$ 3 G | ResultSVar$ X | SubAbility$ DBPump | SpellDescription$ Roll a six-sided die. A:AB$ RollDice | Cost$ 3 G | ResultSVar$ X | SubAbility$ DBPump | AILogic$ Combat | SpellDescription$ Roll a six-sided die.
SVar:DBPump:DB$ Pump | Defined$ Self | NumAtt$ X | NumDef$ X | SpellDescription$ CARDNAME gets +X/+X until end of turn, where X is the result. SVar:DBPump:DB$ Pump | Defined$ Self | NumAtt$ X | NumDef$ X | SpellDescription$ CARDNAME gets +X/+X until end of turn, where X is the result.
T:Mode$ RolledDie | Execute$ TrigTrample | ValidPlayer$ You | ValidResult$ GE5 | TriggerDescription$ Whenever you roll a 5 or higher on a die, CARDNAME gains trample until end of turn. T:Mode$ RolledDie | Execute$ TrigTrample | ValidPlayer$ You | ValidResult$ GE5 | TriggerDescription$ Whenever you roll a 5 or higher on a die, CARDNAME gains trample until end of turn.
SVar:TrigTrample:DB$ Pump | Defined$ Self | KW$ Trample SVar:TrigTrample:DB$ Pump | Defined$ Self | KW$ Trample

View File

@@ -1,6 +1,6 @@
Name:Growth Spurt Name:Growth Spurt
ManaCost:1 G ManaCost:1 G
Types:Instant Types:Instant
A:SP$ RollDice | Cost$ 1 G | ResultSVar$ X | SubAbility$ DBPump A:SP$ RollDice | Cost$ 1 G | ResultSVar$ X | AILogic$ Combat | SubAbility$ DBPump
SVar:DBPump:DB$ Pump | ValidTgts$ Creature | NumAtt$ X | NumDef$ X | SpellDescription$ Target creature gets +X/+X until end of turn, where X is the result. SVar:DBPump:DB$ Pump | ValidTgts$ Creature | NumAtt$ X | NumDef$ X | SpellDescription$ Target creature gets +X/+X until end of turn, where X is the result.
Oracle:Roll a six-sided die. Target creature gets +X/+X until end of turn, where X is the result. Oracle:Roll a six-sided die. Target creature gets +X/+X until end of turn, where X is the result.

View File

@@ -5,7 +5,7 @@ PT:0/0
K:ETBReplacement:Other:RollCounters K:ETBReplacement:Other:RollCounters
SVar:RollCounters:DB$ RollDice | ResultSVar$ Result | SubAbility$ DBCounters | SpellDescription$ As CARDNAME enters the battlefield, roll a six-sided die. CARDNAME enters the battlefield with a number of +1/+1 counters on it equal to the total of those results. SVar:RollCounters:DB$ RollDice | ResultSVar$ Result | SubAbility$ DBCounters | SpellDescription$ As CARDNAME enters the battlefield, roll a six-sided die. CARDNAME enters the battlefield with a number of +1/+1 counters on it equal to the total of those results.
SVar:DBCounters:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ Result | ETB$ True SVar:DBCounters:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ Result | ETB$ True
T:Mode$ RolledDie | Execute$ TrigRemove | ValidPlayer$ You | TriggerDescription$ Whenever you roll a die, remove all +1/+1 counters from CARDNAME, then put a number of +1/+1 counters on it equal to the result. T:Mode$ RolledDie | Execute$ TrigRemove | ValidPlayer$ You | TriggerZones$ Battlefield | TriggerDescription$ Whenever you roll a die, remove all +1/+1 counters from CARDNAME, then put a number of +1/+1 counters on it equal to the result.
SVar:TrigRemove:DB$ RemoveCounterAll | ValidCards$ Card.Self | CounterType$ P1P1 | AllCounters$ True | SubAbility$ TrigCounters SVar:TrigRemove:DB$ RemoveCounterAll | ValidCards$ Card.Self | CounterType$ P1P1 | AllCounters$ True | SubAbility$ TrigCounters
SVar:X:TriggerCount$Result SVar:X:TriggerCount$Result
SVar:TrigCounters:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ X SVar:TrigCounters:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ X

View File

@@ -2,7 +2,7 @@ Name:Mad Science Fair Project
ManaCost:3 ManaCost:3
Types:Artifact Types:Artifact
A:AB$ Pump | Cost$ T | ValidTgts$ Player | SubAbility$ DBRoll A:AB$ Pump | Cost$ T | ValidTgts$ Player | SubAbility$ DBRoll
SVar:DBRoll:DB$ RollDice | On1$ AddC | On2$ AddC | On3$ AddC | Else$ AddAny | SpellDescription$ {T}: Roll a six-sided die. On a 3 or lower, target player adds {C}. Otherwise, that player adds one mana of any color they choose. SVar:DBRoll:DB$ RollDice | On1$ AddC | On2$ AddC | On3$ AddC | Else$ AddAny | AILogic$ Main2 | SpellDescription$ {T}: Roll a six-sided die. On a 3 or lower, target player adds {C}. Otherwise, that player adds one mana of any color they choose.
SVar:AddC:DB$ Mana | Produced$ C | Defined$ Targeted SVar:AddC:DB$ Mana | Produced$ C | Defined$ Targeted
SVar:AddAny:DB$ Mana | Produced$ Any | Defined$ Targeted SVar:AddAny:DB$ Mana | Produced$ Any | Defined$ Targeted
SVar:PlayMain1:TRUE SVar:PlayMain1:TRUE

View File

@@ -5,5 +5,5 @@ PT:1/1
T:Mode$ RolledDie | Execute$ TrigPump | ValidPlayer$ You | ValidResult$ GE5 | TriggerDescription$ Whenever you roll a 5 or higher on a die, CARDNAME gets +X/+X until end of turn, where X is the result. T:Mode$ RolledDie | Execute$ TrigPump | ValidPlayer$ You | ValidResult$ GE5 | TriggerDescription$ Whenever you roll a 5 or higher on a die, CARDNAME gets +X/+X until end of turn, where X is the result.
SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ X | NumDef$ X SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ X | NumDef$ X
SVar:X:TriggerCount$Result SVar:X:TriggerCount$Result
A:AB$ RollDice | Cost$ 6 | SpellDescription$ Roll a six-sided die. A:AB$ RollDice | Cost$ 6 | AILogic$ Combat | SpellDescription$ Roll a six-sided die.
Oracle:{3}{G}: Roll a six-sided die. Ground Pounder gets +X/+X until end of turn, where X is the result.\nWhenever you roll a 5 or higher on a die, Ground Pounder gains trample until end of turn. Oracle:Whenever you roll a 5 or higher on a die, Steel Squirrel gets +X/+X until end of turn, where X is the result.\n{6}: Roll a six-sided die.

View File

@@ -2,7 +2,7 @@ Name:Urza's Science Fair Project
ManaCost:6 ManaCost:6
Types:Artifact Creature Construct Types:Artifact Creature Construct
PT:4/4 PT:4/4
A:AB$ RollDice | Cost$ 2 | On1$ M2 | On2$ Fog | On3$ Vig | On4$ FS | On5$ Fly | On6$ P2 | SpellDescription$ Roll a six-sided die. CARDNAME gets the indicated result: 1-It gets -2/-2 until end of turn. 2-Prevent all combat damage it would deal this turn. 3-It gains vigilance until end of turn. 4-It gains first strike until end of turn. 5-It gains flying until end of turn. 6-It gets +2/+2 until end of turn. A:AB$ RollDice | Cost$ 2 | On1$ M2 | On2$ Fog | On3$ Vig | On4$ FS | On5$ Fly | On6$ P2 | AILogic$ CombatEarly | SpellDescription$ Roll a six-sided die. CARDNAME gets the indicated result: 1-It gets -2/-2 until end of turn. 2-Prevent all combat damage it would deal this turn. 3-It gains vigilance until end of turn. 4-It gains first strike until end of turn. 5-It gains flying until end of turn. 6-It gets +2/+2 until end of turn.
SVar:M2:DB$ Pump | Defined$ Self | NumAtt$ -2 | NumDef$ -2 SVar:M2:DB$ Pump | Defined$ Self | NumAtt$ -2 | NumDef$ -2
SVar:Fog:DB$ Pump | Defined$ Self | KW$ Prevent all combat damage that would be dealt by CARDNAME. SVar:Fog:DB$ Pump | Defined$ Self | KW$ Prevent all combat damage that would be dealt by CARDNAME.
SVar:Vig:DB$ Pump | Defined$ Self | KW$ Vigilance SVar:Vig:DB$ Pump | Defined$ Self | KW$ Vigilance

View File

@@ -3,7 +3,7 @@ ManaCost:2 G
Types:Creature Spider Monkey Scientist Types:Creature Spider Monkey Scientist
PT:2/2 PT:2/2
K:Reach K:Reach
T:Mode$ RolledDie | Execute$ TrigCounter | ValidPlayer$ You | ValidResult$ GE4 | TriggerDescription$ Whenever you roll a 4 or higher on a die, put a +1/+1 counter on CARDNAME. T:Mode$ RolledDie | TriggerZones$ Battlefield | Execute$ TrigCounter | ValidPlayer$ You | ValidResult$ GE4 | TriggerDescription$ Whenever you roll a 4 or higher on a die, put a +1/+1 counter on CARDNAME.
SVar:TrigCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 SVar:TrigCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
A:AB$ RollDice | Cost$ 6 | SpellDescription$ Roll a six-sided die. A:AB$ RollDice | Cost$ 6 | SpellDescription$ Roll a six-sided die.
DeckHas:Ability$Counters DeckHas:Ability$Counters

View File

@@ -42,6 +42,7 @@ Domri, City Smasher|Domri's Overrun|You may feel a slight sensation of burning r
Dovin Baan|Dovin's Static|Have you tried to turn it off and on again? Dovin Baan|Dovin's Static|Have you tried to turn it off and on again?
Dovin, Architect of Law|Dovin's Freeze|With one gear out of place, the whole machine grinds to halt. Dovin, Architect of Law|Dovin's Freeze|With one gear out of place, the whole machine grinds to halt.
Dovin, Grand Arbiter|Dovin's Modern Recall|The best solutions for the worst problems. Dovin, Grand Arbiter|Dovin's Modern Recall|The best solutions for the worst problems.
Dungeon Master|Dungeons and Dragons|A fighter, a wizard, a rogue, and a cleric walk into a dungeon...
Elspeth Tirel|Elspeth's Solitude|Tokens are my only friends... Elspeth Tirel|Elspeth's Solitude|Tokens are my only friends...
Elspeth, Knight-Errant|Elspeth's Endurance|Bant will prevail! Elspeth, Knight-Errant|Elspeth's Endurance|Bant will prevail!
Elspeth, Sun's Champion|Elspeth's Crusade|With Heliod on my side, I'm invincible! Elspeth, Sun's Champion|Elspeth's Crusade|With Heliod on my side, I'm invincible!