This commit is contained in:
tool4ever
2023-07-26 19:21:04 +02:00
committed by GitHub
parent abb2ff3cdf
commit 3b832e02fc
16 changed files with 34 additions and 98 deletions

View File

@@ -36,14 +36,6 @@ public class SacrificeAi extends SpellAbilityAi {
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
if (sa.hasParam("AILogic")) {
if ("OpponentOnly".equals(sa.getParam("AILogic"))) {
if (sa.getActivatingPlayer() == ai) {
return false;
}
}
}
// Improve AI for triggers. If source is a creature with:
// When ETB, sacrifice a creature. Check to see if the AI has something to sacrifice

View File

@@ -89,9 +89,7 @@ public class ConniveEffect extends SpellAbilityEffect {
CardCollectionView toBeDiscarded = amt == 0 ? CardCollection.EMPTY :
p.getController().chooseCardsToDiscardFrom(p, sa, validDiscards, amt, amt);
if (toBeDiscarded.size() > 1) {
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
}
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
int numCntrs = CardLists.getValidCardCount(toBeDiscarded, "Card.nonLand", p, host, sa);

View File

@@ -87,9 +87,7 @@ public class DestroyAllEffect extends SpellAbilityEffect {
// exclude cards that can't be destroyed at this moment
list = CardLists.filter(list, CardPredicates.Presets.CAN_BE_DESTROYED);
if (list.size() > 1) {
list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard, sa);
}
list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard, sa);
CardZoneTable table = new CardZoneTable();
Map<AbilityKey, Object> params = AbilityKey.newMap();

View File

@@ -54,9 +54,7 @@ public class DestroyEffect extends SpellAbilityEffect {
CardCollectionView tgtCards = getTargetCards(sa);
CardCollectionView untargetedCards = CardUtil.getRadiance(sa);
if (tgtCards.size() > 1) {
tgtCards = GameActionUtil.orderCardsByTheirOwners(game, tgtCards, ZoneType.Graveyard, sa);
}
tgtCards = GameActionUtil.orderCardsByTheirOwners(game, tgtCards, ZoneType.Graveyard, sa);
Map<AbilityKey, Object> params = AbilityKey.newMap();
params.put(AbilityKey.LastStateBattlefield, game.copyLastStateBattlefield());
@@ -77,9 +75,7 @@ public class DestroyEffect extends SpellAbilityEffect {
internalDestroy(gameCard, sa, table, cachedMap, params);
}
if (untargetedCards.size() > 1) {
untargetedCards = GameActionUtil.orderCardsByTheirOwners(game, untargetedCards, ZoneType.Graveyard, sa);
}
untargetedCards = GameActionUtil.orderCardsByTheirOwners(game, untargetedCards, ZoneType.Graveyard, sa);
for (final Card unTgtC : untargetedCards) {
if (unTgtC.isInPlay()) {

View File

@@ -17,7 +17,6 @@ import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates.Presets;
import forge.game.card.CardZoneTable;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
@@ -157,10 +156,7 @@ public class DiscardEffect extends SpellAbilityEffect {
|| p.getController().confirmAction(sa, PlayerActionConfirmMode.Random, sa.getParam("DiscardMessage"), null);
if (runDiscard) {
toBeDiscarded = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedCards"), sa);
if (toBeDiscarded.size() > 1) {
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
}
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
}
}
@@ -172,9 +168,7 @@ public class DiscardEffect extends SpellAbilityEffect {
continue;
}
if (toBeDiscarded.size() > 1) {
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
}
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
}
if (mode.equals("NotRemembered")) {
@@ -182,9 +176,7 @@ public class DiscardEffect extends SpellAbilityEffect {
continue;
}
toBeDiscarded = CardLists.getValidCards(p.getCardsIn(ZoneType.Hand), "Card.IsNotRemembered", p, source, sa);
if (toBeDiscarded.size() > 1) {
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
}
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
}
int numCards = 1;
@@ -203,21 +195,9 @@ public class DiscardEffect extends SpellAbilityEffect {
if (runDiscard) {
final String valid = sa.getParamOrDefault("DiscardValid", "Card");
List<Card> list = CardLists.getValidCards(p.getCardsIn(ZoneType.Hand), valid, source.getController(), source, sa);
list = CardLists.filter(list, Presets.NON_TOKEN);
CardCollection toDiscard = new CardCollection();
for (int i = 0; i < numCards; i++) {
if (list.isEmpty())
break;
final Card disc = Aggregates.random(list);
toDiscard.add(disc);
list.remove(disc);
}
toBeDiscarded = toDiscard;
if (toBeDiscarded.size() > 1) {
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
}
toBeDiscarded = new CardCollection(Aggregates.random(list, numCards));
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
}
}
else if (mode.equals("TgtChoose") && sa.hasParam("UnlessType")) {
@@ -226,12 +206,8 @@ public class DiscardEffect extends SpellAbilityEffect {
}
if (numCardsInHand > 0) {
CardCollectionView hand = p.getCardsIn(ZoneType.Hand);
hand = CardLists.filter(hand, Presets.NON_TOKEN);
toBeDiscarded = p.getController().chooseCardsToDiscardUnlessType(Math.min(numCards, numCardsInHand), hand, sa.getParam("UnlessType"), sa);
if (toBeDiscarded.size() > 1) {
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game,toBeDiscarded, ZoneType.Graveyard, sa);
}
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game,toBeDiscarded, ZoneType.Graveyard, sa);
}
}
else if (mode.equals("RevealDiscardAll")) {
@@ -254,13 +230,9 @@ public class DiscardEffect extends SpellAbilityEffect {
}
toBeDiscarded = CardLists.getValidCards(dPHand, valid, source.getController(), source, sa);
toBeDiscarded = CardLists.filter(toBeDiscarded, Presets.NON_TOKEN);
if (toBeDiscarded.size() > 1) {
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
}
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
} else if (mode.endsWith("YouChoose") || mode.endsWith("TgtChoose")) {
CardCollectionView dPHand = p.getCardsIn(ZoneType.Hand);
dPHand = CardLists.filter(dPHand, Presets.NON_TOKEN);
if (dPHand.isEmpty())
continue; // for loop over players
@@ -295,9 +267,7 @@ public class DiscardEffect extends SpellAbilityEffect {
toBeDiscarded = max == 0 ? CardCollection.EMPTY : chooser.getController().chooseCardsToDiscardFrom(p, sa, validCards, min, max);
if (toBeDiscarded.size() > 1) {
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
}
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
if (mode.startsWith("Reveal") && p != chooser) {
p.getController().reveal(toBeDiscarded, ZoneType.Hand, p, Localizer.getInstance().getMessage("lblPlayerHasChosenCardsFrom", chooser.getName()));

View File

@@ -80,9 +80,7 @@ public class SacrificeAllEffect extends SpellAbilityEffect {
list = CardLists.filterControlledBy(list, AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Controller"), sa));
}
if (list.size() > 1) {
list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard, sa);
}
list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard, sa);
CardZoneTable table = new CardZoneTable();
Map<Integer, Card> cachedMap = Maps.newHashMap();

View File

@@ -160,9 +160,7 @@ public class SacrificeEffect extends SpellAbilityEffect {
}
}
if (choosenToSacrifice.size() > 1) {
choosenToSacrifice = GameActionUtil.orderCardsByTheirOwners(game, choosenToSacrifice, ZoneType.Graveyard, sa);
}
choosenToSacrifice = GameActionUtil.orderCardsByTheirOwners(game, choosenToSacrifice, ZoneType.Graveyard, sa);
Map<Integer, Card> cachedMap = Maps.newHashMap();
for (Card sac : choosenToSacrifice) {

View File

@@ -1633,7 +1633,7 @@ public class Player extends GameEntity implements Comparable<Player> {
CardCollectionView milledView = milled;
if (destination == ZoneType.Graveyard && milled.size() > 1) {
if (destination == ZoneType.Graveyard) {
milledView = GameActionUtil.orderCardsByTheirOwners(game, milled, ZoneType.Graveyard, sa);
}

View File

@@ -5,6 +5,6 @@ PT:3/2
K:Convoke
T:Mode$ Phase | Phase$ End of Turn | CheckSVar$ X | SVarCompare$ GE1 | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ At the beginning of each end step, if you created a token this turn, draw a card.
SVar:TrigDraw:DB$ Draw
SVar:X:Count$ThisTurnEntered_Battlefield_Card.token+YouCtrl
SVar:X:Count$ThisTurnEntered_Battlefield_Card.tokenCreated+YouCtrl
DeckHints:Ability$Token
Oracle:Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of that creature's color.)\nAt the beginning of each end step, if you created a token this turn, draw a card.

View File

@@ -1,7 +1,8 @@
Name:Incite
ManaCost:R
Types:Instant
A:SP$ Animate | ValidTgts$ Creature | Colors$ Red | OverwriteColors$ True | staticAbilities$ MustAttack | SpellDescription$ Target creature becomes red until end of turn and attacks this turn if able.
SVar:MustAttack:Mode$ MustAttack | ValidCreature$ Card.Self | Description$ This creature attacks this turn if able.
A:SP$ Animate | ValidTgts$ Creature | Colors$ Red | OverwriteColors$ True | SpellDescription$ Target creature becomes red until end of turn and attacks this turn if able.
SVar:DBEffect:DB$ Effect | StaticAbilities$ MustAttack | ExileOnMoved$ Battlefield | RememberObjects$ Targeted
SVar:MustAttack:Mode$ MustAttack | EffectZone$ Command | ValidCreature$ Creature.IsRemembered | Description$ This creature attacks this turn if able.
AI:RemoveDeck:All
Oracle:Target creature becomes red until end of turn and attacks this turn if able.

View File

@@ -5,8 +5,8 @@ PT:6/5
K:Trample
T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | Execute$ TrigChoose | TriggerZones$ Battlefield | TriggerDescription$ Frenzied Rampage — At the beginning of combat on your turn, choose an opponent at random. CARDNAME attacks that player this combat if able.
SVar:TrigChoose:DB$ ChoosePlayer | Defined$ You | Choices$ Opponent | Random$ True | SubAbility$ DBPump
SVar:DBPump:DB$ Animate | Defined$ Self | staticAbilities$ AttackChosen | Duration$ UntilEndOfCombat
SVar:AttackChosen:Mode$ MustAttack | ValidCreature$ Card.Self | MustAttack$ ChosenPlayer
SVar:DBPump:DB$ Effect | RememberObjects$ Self | ExileOnMoved$ Battlefield | StaticAbilities$ AttackChosen | Duration$ UntilEndOfCombat
SVar:AttackChosen:Mode$ MustAttack | ValidCreature$ Card.IsRemembered | MustAttack$ ChosenPlayer | Description$ EFFECTSOURCE attacks that player this combat if able.
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigChooseBis | TriggerDescription$ When CARDNAME dies, it deals 4 damage to target opponent chosen at random.
SVar:TrigChooseBis:DB$ ChoosePlayer | Defined$ You | Choices$ Opponent | Random$ True | SubAbility$ DBDealDamage
SVar:DBDealDamage:DB$ DealDamage | Defined$ ChosenPlayer | NumDmg$ 4 | SubAbility$ DBCleanup

View File

@@ -5,9 +5,9 @@ PT:3/5
K:Trample
A:AB$ Pump | Cost$ R | NumAtt$ +1 | SpellDescription$ CARDNAME gets +1/+0 until end of turn.
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | IsPresent$ Creature.YouCtrl+namedKeeper of Kookus | PresentCompare$ EQ0 | Execute$ TrigNoKeeper | TriggerDescription$ At the beginning of your upkeep, if you don't control a creature named Keeper of Kookus, CARDNAME deals 3 damage to you and attacks this turn if able.
SVar:TrigNoKeeper:DB$ DealDamage | NumDmg$ 3 | Defined$ You | SubAbility$ DBMustAttack
SVar:DBMustAttack:DB$ Animate | staticAbilities$ MustAttack | Defined$ Self
SVar:MustAttack:Mode$ MustAttack | ValidCreature$ Card.Self | Secondary$ True
SVar:TrigNoKeeper:DB$ DealDamage | NumDmg$ 3 | Defined$ You | SubAbility$ DBEffect
SVar:DBEffect:DB$ Effect | StaticAbilities$ MustAttack | ExileOnMoved$ Battlefield | RememberObjects$ Self
SVar:MustAttack:Mode$ MustAttack | EffectZone$ Command | ValidCreature$ Creature.IsRemembered | Description$ This creature attacks this turn if able.
AI:RemoveDeck:Random
DeckNeeds:Name$Keeper of Kookus
Oracle:Trample\nAt the beginning of your upkeep, if you don't control a creature named Keeper of Kookus, Kookus deals 3 damage to you and attacks this turn if able.\n{R}: Kookus gets +1/+0 until end of turn.

View File

@@ -3,8 +3,8 @@ ManaCost:2 B
Types:Enchantment Aura
K:Enchant creature
A:SP$ Attach | ValidTgts$ Creature | AILogic$ Curse
A:AB$ Animate | Cost$ 1 R | Defined$ Enchanted | staticAbilities$ MustAttack | IsCurse$ True | SpellDescription$ Enchanted creature attacks this turn if able.
SVar:MustAttack:Mode$ MustAttack | ValidCreature$ Card.Self | Description$ This creature attacks this turn if able.
A:AB$ Effect | Cost$ 1 R | IsCurse$ True | StaticAbilities$ MustAttack | ExileOnMoved$ Battlefield | RememberObjects$ Enchanted | SpellDescription$ Enchanted creature attacks this turn if able.
SVar:MustAttack:Mode$ MustAttack | EffectZone$ Command | ValidCreature$ Creature.IsRemembered | Description$ This creature attacks this turn if able.
T:Mode$ Attacks | ValidCard$ Card.AttachedBy | TriggerZones$ Battlefield | Execute$ TrigLoseLifeAttack | TriggerDescription$ Whenever enchanted creature attacks or blocks, its controller loses 3 life.
T:Mode$ Blocks | ValidCard$ Card.AttachedBy | TriggerZones$ Battlefield | Execute$ TrigLoseLifeBlock | Secondary$ True | TriggerDescription$ Whenever enchanted creature attacks or blocks, its controller loses 3 life.
SVar:TrigLoseLifeAttack:DB$ LoseLife | LifeAmount$ 3 | Defined$ TriggeredAttackerController

View File

@@ -4,7 +4,7 @@ Types:Legendary Creature Elemental Dog
PT:3/3
K:Partner:Haldan, Avid Arcanist:Haldan
K:Haste
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigExile | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, exile the top card of each player's library and put a fetch counter on each of them. Put a +1/+1 counter on CARDNAME for each noncreature card exiled this way.
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigExile | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, exile the top card of each player's library and put a fetch counter on each of them. Put a +1/+1 counter on NICKNAME for each noncreature card exiled this way.
SVar:TrigExile:DB$ Dig | DigNum$ 1 | ChangeNum$ All | Defined$ Player | DestinationZone$ Exile | ExileWithCounter$ FETCH | RememberChanged$ True | SubAbility$ DBPutCounter
SVar:DBPutCounter:DB$ PutCounter | CounterType$ P1P1 | CounterNum$ X | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True

View File

@@ -2,10 +2,8 @@ Name:Walking Desecration
ManaCost:2 B
Types:Creature Zombie
PT:1/1
A:AB$ ChooseType | Cost$ B T | Defined$ You | Type$ Creature | SubAbility$ DBPumpAll | SpellDescription$ Creatures of the creature type of your choice attack this turn if able.
SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Creature.ChosenType | IsCurse$ True | RememberAllPumped$ True | SubAbility$ DBAnimate
SVar:DBAnimate:DB$ Animate | Defined$ Remembered | staticAbilities$ MustAttack | SubAbility$ DBCleanup | StackDescription$ None
SVar:MustAttack:Mode$ MustAttack | ValidCreature$ Card.Self | Description$ This creature attacks this turn if able.
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
A:AB$ ChooseType | Cost$ B T | Defined$ You | Type$ Creature | SubAbility$ DBEffect | SpellDescription$ Creatures of the creature type of your choice attack this turn if able.
SVar:DBEffect:DB$ Effect | StaticAbilities$ MustAttack | StackDescription$ None
SVar:MustAttack:Mode$ MustAttack | ValidCreature$ Card.ChosenType | Description$ Creatures of the chosen creature type attack this turn if able.
AI:RemoveDeck:All
Oracle:{B}, {T}: Creatures of the creature type of your choice attack this turn if able.

View File

@@ -1306,7 +1306,6 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
// occurrences of each
Map<String, Integer> typesInDeck = Maps.newHashMap();
// TODO JAVA 8 use getOrDefault
for (Card c : player.getAllCards()) {
// Changeling are all creature types, they are not interesting for
// counting creature types
@@ -1330,10 +1329,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
}
for (String type : c.getType().getCreatureTypes()) {
Integer count = typesInDeck.get(type);
if (count == null) {
count = 0;
}
Integer count = typesInDeck.getOrDefault(type, 0);
typesInDeck.put(type, count + 1);
}
// also take into account abilities that generate tokens
@@ -1346,10 +1342,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
for (String token : sa.getParam("TokenScript").split(",")) {
Card protoType = TokenInfo.getProtoType(token, sa, null);
for (String type : protoType.getType().getCreatureTypes()) {
Integer count = typesInDeck.get(type);
if (count == null) {
count = 0;
}
Integer count = typesInDeck.getOrDefault(type, 0);
typesInDeck.put(type, count + 1);
}
}
@@ -1365,10 +1358,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
for (String token : sa.getParam("TokenScript").split(",")) {
Card protoType = TokenInfo.getProtoType(token, sa, null);
for (String type : protoType.getType().getCreatureTypes()) {
Integer count = typesInDeck.get(type);
if (count == null) {
count = 0;
}
Integer count = typesInDeck.getOrDefault(type, 0);
typesInDeck.put(type, count + 1);
}
}
@@ -1377,10 +1367,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
}
// 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 + 1);
}
}