Merge main repo.
commit
e16eeb8882
|
@ -0,0 +1,35 @@
|
|||
[
|
||||
new MagicPermanentActivation(
|
||||
new MagicActivationHints(MagicTiming.Token),
|
||||
"Reanimate"
|
||||
) {
|
||||
@Override
|
||||
public Iterable<MagicEvent> getCostEvent(final MagicPermanent source) {
|
||||
return [
|
||||
new MagicExileEvent(source),
|
||||
new MagicPayManaCostEvent(source,"{B}{B}{B}")
|
||||
|
||||
];
|
||||
}
|
||||
@Override
|
||||
public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
|
||||
return new MagicEvent(
|
||||
source,
|
||||
this,
|
||||
"Each player returns all black and all red creature cards from his or her graveyard to the battlefield."
|
||||
);
|
||||
}
|
||||
@Override
|
||||
public void executeEvent(final MagicGame game, final MagicEvent event) {
|
||||
for (final MagicPlayer player : game.getAPNAP()) {
|
||||
final Collection<MagicCard> targets = game.filterCards(
|
||||
player,
|
||||
MagicTargetFilterFactory.BLACK_OR_RED_CREATURE_CARD_FROM_GRAVEYARD
|
||||
);
|
||||
for (final MagicCard card : targets) {
|
||||
game.doAction(new MagicReanimateAction(card, player));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
|
@ -6,7 +6,7 @@ type=Legendary,Creature
|
|||
subtype=Zombie,Dwarf
|
||||
cost={2}{B}{B}
|
||||
pt=2/2
|
||||
ability=Minion creatures get +1/+1.;\
|
||||
{B}{B}{B}, Exile SN: Each player returns all black and all red creature cards from his or her graveyard to the battlefield.
|
||||
ability=Minion creatures get +1/+1.
|
||||
timing=main
|
||||
requires_groovy_code
|
||||
oracle=Minion creatures get +1/+1. {B}{B}{B}, Exile Balthor the Defiled: Each player returns all black and all red creature cards from his or her graveyard to the battlefield.
|
|
@ -24,8 +24,10 @@
|
|||
}
|
||||
@Override
|
||||
public void executeEvent(final MagicGame game, final MagicEvent event) {
|
||||
final int sacrificed = event.getRefPermanent().getToughness();
|
||||
game.doAction(new MagicChangeLifeAction(event.getPlayer(),sacrificed));
|
||||
final int amount = event.getRefPermanent().getToughness();
|
||||
final MagicPlayer player = event.getPlayer();
|
||||
game.doAction(new MagicChangeLifeAction(event.getPlayer(),amount));
|
||||
game.logAppendMessage(event.getPlayer(),"("+amount+")");
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -6,7 +6,7 @@ type=Creature
|
|||
subtype=Zombie
|
||||
cost={4}{B}
|
||||
pt=0/0
|
||||
ability=SN enters the battlefield with X +1/+1 counters on it, where X is the number of creature cards in all graveyards.;\
|
||||
{2}{B}, Remove a +1/+1 counter from SN: Target creature gets -1/-1 until end of turn.
|
||||
ability={2}{B}, Remove a +1/+1 counter from SN: Target creature gets -1/-1 until end of turn.
|
||||
timing=main
|
||||
requires_groovy_code=Undergrowth Scavenger
|
||||
oracle=Drakestown Forgotten enters the battlefield with X +1/+1 counters on it, where X is the number of creature cards in all graveyards. {2}{B}, Remove a +1/+1 counter from Drakestown Forgotten: Target creature gets -1/-1 until end of turn.
|
|
@ -4,6 +4,7 @@ value=2.296
|
|||
rarity=U
|
||||
type=Instant
|
||||
cost={X}{R}
|
||||
ability=Cast SN with AI only if an opponent controls a creature.
|
||||
timing=removal
|
||||
requires_groovy_code
|
||||
oracle=Dwarven Catapult deals X damage divided evenly, rounded down, among all creatures target opponent controls.
|
||||
|
|
|
@ -5,7 +5,7 @@ rarity=U
|
|||
type=Enchantment
|
||||
subtype=Aura
|
||||
cost={1}{G}
|
||||
ability=Enchant creature;\
|
||||
Enchanted creature gets +X/+X, where X is the number of creature cards in all graveyards.
|
||||
timing=main
|
||||
enchant=pump,pos creature
|
||||
requires_groovy_code=Bonehoard
|
||||
oracle=Enchant creature. Enchanted creature gets +X/+X, where X is the number of creature cards in all graveyards.
|
|
@ -0,0 +1,27 @@
|
|||
[
|
||||
new MagicSpellCardEvent() {
|
||||
@Override
|
||||
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
|
||||
return new MagicEvent(
|
||||
cardOnStack,
|
||||
MagicTargetChoice.TARGET_CREATURE,
|
||||
MagicBounceTargetPicker.create(),
|
||||
this,
|
||||
"Return target creature\$ and all Auras attached to it to their owners' hands."
|
||||
);
|
||||
}
|
||||
@Override
|
||||
public void executeEvent(final MagicGame game, final MagicEvent event) {
|
||||
event.processTargetPermanent(game, {
|
||||
if (it.isEnchanted()) {
|
||||
final MagicPermanentList auras = new MagicPermanentList();
|
||||
auras.addAll(it.getAuraPermanents())
|
||||
for (final MagicPermanent aura : auras) {
|
||||
game.doAction(new MagicRemoveFromPlayAction(aura,MagicLocationType.OwnersHand));
|
||||
}
|
||||
}
|
||||
game.doAction(new MagicRemoveFromPlayAction(it,MagicLocationType.OwnersHand));
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
|
@ -4,6 +4,6 @@ value=2.500
|
|||
rarity=C
|
||||
type=Instant
|
||||
cost={1}{U}
|
||||
effect=Return target creature and all Auras attached to it to their owners' hands.
|
||||
timing=removal
|
||||
requires_groovy_code
|
||||
oracle=Return target creature and all Auras attached to it to their owners' hands.
|
|
@ -0,0 +1,19 @@
|
|||
[
|
||||
new MagicSpellCardEvent() {
|
||||
@Override
|
||||
public MagicEvent getEvent(final MagicCardOnStack cardOnStack, final MagicPayedCost payedCost) {
|
||||
return new MagicEvent(
|
||||
cardOnStack,
|
||||
this,
|
||||
"PN gains life equal to the number of creature cards in all graveyards."
|
||||
);
|
||||
}
|
||||
@Override
|
||||
public void executeEvent(final MagicGame game, final MagicEvent event) {
|
||||
final MagicPlayer player = event.getPlayer();
|
||||
final int amount = game.filterCards(player,MagicTargetFilterFactory.CREATURE_CARD_FROM_ALL_GRAVEYARDS).size();
|
||||
game.doAction(new MagicChangeLifeAction(player,amount));
|
||||
game.logAppendMessage(player," ("+amount+")");
|
||||
}
|
||||
}
|
||||
]
|
|
@ -4,6 +4,6 @@ value=2.500
|
|||
rarity=C
|
||||
type=Sorcery
|
||||
cost={2}{G}{G}
|
||||
effect=You gain life equal to the number of creature cards in all graveyards.
|
||||
timing=main
|
||||
requires_groovy_code
|
||||
oracle=You gain life equal to the number of creature cards in all graveyards.
|
|
@ -7,6 +7,6 @@ subtype=Giant,Cleric
|
|||
cost={4}{W}{W}
|
||||
pt=3/3
|
||||
ability=Protection from red;\
|
||||
Creatures named SN get +1/+1 as long as an opponent controls a nontoken red permanent.
|
||||
Creatures named Ivory Guardians get +1/+1 as long as an opponent controls a nontoken red permanent.
|
||||
timing=main
|
||||
oracle=Protection from red. Creatures named Ivory Guardians get +1/+1 as long as an opponent controls a nontoken red permanent.
|
|
@ -0,0 +1,33 @@
|
|||
[
|
||||
new MagicPermanentActivation(
|
||||
[MagicCondition.YOUR_UPKEEP_CONDITION],
|
||||
new MagicActivationHints(MagicTiming.Removal),
|
||||
"Gain Life"
|
||||
) {
|
||||
@Override
|
||||
public Iterable<MagicEvent> getCostEvent(final MagicPermanent source) {
|
||||
return [
|
||||
new MagicSacrificePermanentEvent(
|
||||
source,
|
||||
MagicTargetChoice.SACRIFICE_CREATURE
|
||||
)
|
||||
];
|
||||
}
|
||||
@Override
|
||||
public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
|
||||
return new MagicEvent(
|
||||
source,
|
||||
payedCost.getTarget(),
|
||||
this,
|
||||
"PN gains life equal to RN's toughness."
|
||||
);
|
||||
}
|
||||
@Override
|
||||
public void executeEvent(final MagicGame game, final MagicEvent event) {
|
||||
final int amount = event.getRefPermanent().getToughness();
|
||||
final MagicPlayer player = event.getPlayer();
|
||||
game.doAction(new MagicChangeLifeAction(player,amount));
|
||||
game.logAppendMessage(event.getPlayer(),"("+amount+")");
|
||||
}
|
||||
}
|
||||
]
|
|
@ -4,6 +4,6 @@ value=2.500
|
|||
rarity=U
|
||||
type=Artifact
|
||||
cost={4}
|
||||
ability=Sacrifice a creature: You gain life equal to the sacrificed creature's toughness. Activate this ability only during your upkeep.
|
||||
timing=main
|
||||
requires_groovy_code
|
||||
oracle=Sacrifice a creature: You gain life equal to the sacrificed creature's toughness. Activate this ability only during your upkeep.
|
|
@ -0,0 +1,25 @@
|
|||
[
|
||||
new MagicStatic(MagicLayer.Ability) {
|
||||
@Override
|
||||
public void modAbilityFlags(final MagicPermanent source,final MagicPermanent permanent,final Set<MagicAbility> flags) {
|
||||
flags.remove(MagicAbility.Flying);
|
||||
}
|
||||
@Override
|
||||
public boolean accept(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
|
||||
return MagicStatic.acceptLinked(game, source, target);
|
||||
}
|
||||
},
|
||||
|
||||
new MagicIfDamageWouldBeDealtTrigger(MagicTrigger.PREVENT_DAMAGE) {
|
||||
@Override
|
||||
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicDamage damage) {
|
||||
if (!damage.isCombat() && damage.isTargetCreature()) {
|
||||
if (damage.getTargetPermanent() == permanent.getEquippedCreature()) {
|
||||
// Prevention effect.
|
||||
damage.prevent();
|
||||
}
|
||||
}
|
||||
return MagicEvent.NONE;
|
||||
}
|
||||
}
|
||||
]
|
|
@ -5,8 +5,8 @@ rarity=R
|
|||
type=Artifact
|
||||
subtype=Equipment
|
||||
cost={3}
|
||||
ability=Equipped creature gets +2/+4 and loses flying.;\
|
||||
Prevent all noncombat damage that would be dealt to equipped creature.;\
|
||||
ability=Equipped creature gets +2/+4;\
|
||||
Equip {2}
|
||||
timing=main
|
||||
requires_groovy_code
|
||||
oracle=Equipped creature gets +2/+4 and loses flying. Prevent all noncombat damage that would be dealt to equipped creature. Equip {2}
|
|
@ -5,25 +5,22 @@ def MUTANT = new MagicStatic(MagicLayer.Type) {
|
|||
}
|
||||
};
|
||||
[
|
||||
new MagicWhenOtherComesIntoPlayTrigger() {
|
||||
new MagicWhenOtherComesIntoPlayTrigger(MagicTrigger.REPLACEMENT) {
|
||||
@Override
|
||||
public MagicEvent executeTrigger(final MagicGame game, final MagicPermanent permanent, final MagicPermanent otherPermanent) {
|
||||
return(otherPermanent != permanent &&
|
||||
if (otherPermanent != permanent &&
|
||||
otherPermanent.isCreature() &&
|
||||
otherPermanent.isFriend(permanent))?
|
||||
new MagicEvent(
|
||||
permanent,
|
||||
otherPermanent,
|
||||
this,
|
||||
"RN enters the battelfied with a number of +1/+1 counters equal to the power of PN," +
|
||||
"and a Mutant in adddition to its other types."
|
||||
) :
|
||||
MagicEvent.NONE;
|
||||
}
|
||||
@Override
|
||||
public void executeEvent(final MagicGame game, final MagicEvent event) {
|
||||
game.doAction(new MagicChangeCountersAction(event.getRefPermanent(),MagicCounterType.PlusOne,event.getPermanent().getPower()));
|
||||
game.doAction(new MagicAddStaticAction(event.getRefPermanent(),MUTANT));
|
||||
otherPermanent.isFriend(permanent)) {
|
||||
final int amount = permanent.getPower();
|
||||
game.doAction(new MagicChangeCountersAction(otherPermanent,MagicCounterType.PlusOne,amount));
|
||||
game.doAction(new MagicAddStaticAction(otherPermanent,MUTANT));
|
||||
game.logAppendMessage(
|
||||
permanent.getController(),
|
||||
""+otherPermanent.getName()+" enters the battlefield with an additional "+amount+
|
||||
" +1/+1 counters on it, and as a Mutant in addition to its other types."
|
||||
);
|
||||
}
|
||||
return MagicEvent.NONE;
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -5,7 +5,7 @@ rarity=U
|
|||
type=Artifact
|
||||
subtype=Equipment
|
||||
cost={2}
|
||||
ability=Whenever equipped creature deals combat damage to a player, you may draw a card.;\
|
||||
Equip {2}
|
||||
ability=Equip {2}
|
||||
timing=main
|
||||
requires_groovy_code=Mask of Riddles
|
||||
oracle=Whenever equipped creature deals combat damage to a player, you may draw a card. Equip {2}
|
|
@ -1,5 +1,5 @@
|
|||
[
|
||||
new MagicWhenComesIntoPlayTrigger() {
|
||||
new MagicWhenComesIntoPlayTrigger(MagicTrigger.REPLACEMENT) {
|
||||
@Override
|
||||
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPayedCost payedCost) {
|
||||
final int X = game.getNrOfPermanents(MagicType.Creature) - 1;
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
[
|
||||
new MagicSpellCardEvent() {
|
||||
@Override
|
||||
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
|
||||
return new MagicEvent(
|
||||
cardOnStack,
|
||||
this,
|
||||
"SN deals damage to each opponent equal to the number of Islands that player controls."
|
||||
);
|
||||
}
|
||||
@Override
|
||||
public void executeEvent(final MagicGame game, final MagicEvent event) {
|
||||
final MagicSource source=event.getSource();
|
||||
final MagicPlayer opponent=event.getPlayer().getOpponent();
|
||||
final int amount = opponent.getNrOfPermanents(MagicSubType.Island);
|
||||
final MagicDamage damage=new MagicDamage(source,opponent,amount);
|
||||
game.doAction(new MagicDealDamageAction(damage));
|
||||
}
|
||||
}
|
||||
]
|
|
@ -4,6 +4,6 @@ value=2.500
|
|||
rarity=R
|
||||
type=Sorcery
|
||||
cost={2}{G}
|
||||
effect=SN deals damage to each opponent equal to the number of Islands that player controls.
|
||||
timing=main
|
||||
requires_groovy_code
|
||||
oracle=Typhoon deals damage to each opponent equal to the number of Islands that player controls.
|
|
@ -0,0 +1,10 @@
|
|||
[
|
||||
new MagicWhenComesIntoPlayTrigger(MagicTrigger.REPLACEMENT) {
|
||||
@Override
|
||||
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPayedCost payedCost) {
|
||||
final int amount = game.filterCards(permanent.getController(), MagicTargetFilterFactory.CREATURE_CARD_FROM_ALL_GRAVEYARDS).size();
|
||||
game.doAction(MagicChangeCountersAction.Enters(permanent,MagicCounterType.PlusOne,amount));
|
||||
return MagicEvent.NONE;
|
||||
}
|
||||
}
|
||||
]
|
|
@ -6,6 +6,6 @@ type=Creature
|
|||
subtype=Fungus,Horror
|
||||
cost={3}{G}
|
||||
pt=0/0
|
||||
ability=SN enters the battlefield with a number of +1/+1 counters on it equal to the number of creature cards in all graveyards.
|
||||
timing=main
|
||||
requires_groovy_code
|
||||
oracle=Undergrowth Scavenger enters the battlefield with a number of +1/+1 counters on it equal to the number of creature cards in all graveyards.
|
|
@ -0,0 +1,32 @@
|
|||
[
|
||||
new MagicPermanentActivation(
|
||||
new MagicActivationHints(MagicTiming.Removal),
|
||||
"Damage"
|
||||
) {
|
||||
|
||||
@Override
|
||||
public Iterable<MagicEvent> getCostEvent(final MagicPermanent source) {
|
||||
return [
|
||||
new MagicSacrificeEvent(source), new MagicPayManaCostEvent(source, "{5}{B}{B}")
|
||||
];
|
||||
}
|
||||
|
||||
@Override
|
||||
public MagicEvent getPermanentEvent(final MagicPermanent source, final MagicPayedCost payedCost) {
|
||||
return new MagicEvent(
|
||||
source,
|
||||
MagicTargetChoice.NEG_TARGET_PLAYER,
|
||||
this,
|
||||
"Target player\$ loses X life, where X is SN's power. (X="+source.getPower()+")"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeEvent(final MagicGame game, final MagicEvent event) {
|
||||
event.processTargetPlayer(game, {
|
||||
final int amount=event.getPermanent().getPower();
|
||||
game.doAction(new MagicChangeLifeAction(it, -amount));
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
|
@ -7,7 +7,7 @@ subtype=Zombie,Wall
|
|||
cost={2}{B}
|
||||
pt=0/3
|
||||
ability=Defender;\
|
||||
Whenever you gain life, put a +1/+1 counter on SN.;\
|
||||
{5}{B}{B}, Sacrifice SN: Target player loses X life, where X is SN's power.
|
||||
Whenever you gain life, put a +1/+1 counter on SN.
|
||||
timing=main
|
||||
requires_groovy_code
|
||||
oracle=Defender. Whenever you gain life, put a +1/+1 counter on Wall of Limbs. {5}{B}{B}, Sacrifice Wall of Limbs: Target player loses X life, where X is Wall of Limbs's power.
|
|
@ -41,6 +41,7 @@ INV
|
|||
ISD
|
||||
JOU
|
||||
JUD
|
||||
KTK
|
||||
LEA
|
||||
LEB
|
||||
LEG
|
||||
|
@ -92,12 +93,15 @@ WWK
|
|||
ZEN
|
||||
|
||||
# banned: prefix with !
|
||||
!Advantageous Proclamation
|
||||
!Amulet of Quoz
|
||||
!Ancestral Recall
|
||||
!Backup Plan
|
||||
!Balance
|
||||
!Bazaar of Baghdad
|
||||
!Black Lotus
|
||||
!Black Vise
|
||||
!Brago’s Favor
|
||||
!Bronze Tablet
|
||||
!Channel
|
||||
!Chaos Orb
|
||||
|
@ -106,6 +110,7 @@ ZEN
|
|||
!Demonic Attorney
|
||||
!Demonic Consultation
|
||||
!Demonic Tutor
|
||||
!Double Stroke
|
||||
!Earthcraft
|
||||
!Falling Star
|
||||
!Fastbond
|
||||
|
@ -114,7 +119,9 @@ ZEN
|
|||
!Goblin Recruiter
|
||||
!Gush
|
||||
!Hermit Druid
|
||||
!Immediate Action
|
||||
!Imperial Seal
|
||||
!Iterative Analysis
|
||||
!Jeweled Bird
|
||||
!Library of Alexandria
|
||||
!Mana Crypt
|
||||
|
@ -130,10 +137,15 @@ ZEN
|
|||
!Mox Pearl
|
||||
!Mox Ruby
|
||||
!Mox Sapphire
|
||||
!Muzzio’s Preparations
|
||||
!Mystical Tutor
|
||||
!Necropotence
|
||||
!Oath of Druids
|
||||
!Power Play
|
||||
!Rebirth
|
||||
!Secret Summoning
|
||||
!Secrets of Paradise
|
||||
!Sentinel Dispatch
|
||||
!Shahrazad
|
||||
!Skullclamp
|
||||
!Sol Ring
|
||||
|
@ -146,22 +158,11 @@ ZEN
|
|||
!Timmerian Fiends
|
||||
!Tinker
|
||||
!Tolarian Academy
|
||||
!Unexpected Potential
|
||||
!Vampiric Tutor
|
||||
!Wheel of Fortune
|
||||
!Windfall
|
||||
!Worldgorger Dragon
|
||||
!Worldknit
|
||||
!Yawgmoth's Bargain
|
||||
!Yawgmoth's Will
|
||||
!Advantageous Proclamation
|
||||
!Backup Plan
|
||||
!Brago's Favor
|
||||
!Double Stroke
|
||||
!Immediate Action
|
||||
!Iterative Analysis
|
||||
!Muzzio's Preparations
|
||||
!Power Play
|
||||
!Secret Summoning
|
||||
!Secrets of Paradise
|
||||
!Sentinel Dispatch
|
||||
!Unexpected Potential
|
||||
!Worldknit
|
||||
|
|
|
@ -43,6 +43,7 @@ THS
|
|||
BNG
|
||||
JOU
|
||||
M15
|
||||
KTK
|
||||
|
||||
# banned: prefix with !
|
||||
!Ancestral Vision
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
RTR
|
||||
GTC
|
||||
DGM
|
||||
M14
|
||||
THS
|
||||
BNG
|
||||
JOU
|
||||
M15
|
||||
KTK
|
||||
|
|
|
@ -41,6 +41,7 @@ INV
|
|||
ISD
|
||||
JOU
|
||||
JUD
|
||||
KTK
|
||||
LEA
|
||||
LEB
|
||||
LEG
|
||||
|
@ -92,29 +93,29 @@ WWK
|
|||
ZEN
|
||||
|
||||
# banned: prefix with !
|
||||
!Advantageous Proclamation
|
||||
!Amulet of Quoz
|
||||
!Backup Plan
|
||||
!Brago’s Favor
|
||||
!Bronze Tablet
|
||||
!Chaos Orb
|
||||
!Contract from Below
|
||||
!Darkpact
|
||||
!Demonic Attorney
|
||||
!Falling Star
|
||||
!Jeweled Bird
|
||||
!Rebirth
|
||||
!Shahrazad
|
||||
!Tempest Efreet
|
||||
!Timmerian Fiends
|
||||
!Advantageous Proclamation
|
||||
!Backup Plan
|
||||
!Brago's Favor
|
||||
!Double Stroke
|
||||
!Falling Star
|
||||
!Immediate Action
|
||||
!Iterative Analysis
|
||||
!Muzzio's Preparations
|
||||
!Jeweled Bird
|
||||
!Muzzio’s Preparations
|
||||
!Power Play
|
||||
!Rebirth
|
||||
!Secret Summoning
|
||||
!Secrets of Paradise
|
||||
!Sentinel Dispatch
|
||||
!Shahrazad
|
||||
!Tempest Efreet
|
||||
!Timmerian Fiends
|
||||
!Unexpected Potential
|
||||
!Worldknit
|
||||
|
||||
|
|
|
@ -17,150 +17,163 @@ import java.io.BufferedWriter;
|
|||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Date;
|
||||
|
||||
public class FiremindQueueWorker {
|
||||
|
||||
private static int games;
|
||||
private static int str1 = 2;
|
||||
private static int str2 = 2;
|
||||
private static int life = 20;
|
||||
private static int seed;
|
||||
private static String deck1 = "";
|
||||
private static String deck2 = "";
|
||||
private static MagicAIImpl ai1 = MagicAIImpl.MCTS;
|
||||
private static MagicAIImpl ai2 = MagicAIImpl.MCTS;
|
||||
private static Duel currentDuel;
|
||||
private static int gameCount = 0;
|
||||
private static int games;
|
||||
private static int str1 = 2;
|
||||
private static int str2 = 2;
|
||||
private static int life = 20;
|
||||
private static int seed;
|
||||
private static String deck1 = "";
|
||||
private static String deck2 = "";
|
||||
private static MagicAIImpl ai1 = MagicAIImpl.MCTS;
|
||||
private static MagicAIImpl ai2 = MagicAIImpl.MCTS;
|
||||
private static Duel currentDuel;
|
||||
private static int gameCount = 0;
|
||||
|
||||
private static MagicDuel setupDuel() {
|
||||
// Set the random seed
|
||||
if (seed != 0) {
|
||||
MagicRandom.setRNGState(seed);
|
||||
seed = MagicRandom.nextRNGInt(Integer.MAX_VALUE) + 1;
|
||||
}
|
||||
private static MagicDuel setupDuel() {
|
||||
// Set the random seed
|
||||
if (seed != 0) {
|
||||
MagicRandom.setRNGState(seed);
|
||||
seed = MagicRandom.nextRNGInt(Integer.MAX_VALUE) + 1;
|
||||
}
|
||||
|
||||
// Set number of games.
|
||||
final DuelConfig config = new DuelConfig();
|
||||
config.setNrOfGames(games);
|
||||
config.setStartLife(life);
|
||||
// Set number of games.
|
||||
final DuelConfig config = new DuelConfig();
|
||||
config.setNrOfGames(games);
|
||||
config.setStartLife(life);
|
||||
|
||||
// Set difficulty.
|
||||
final MagicDuel testDuel = new MagicDuel(config);
|
||||
testDuel.initialize();
|
||||
testDuel.setDifficulty(0, str1);
|
||||
testDuel.setDifficulty(1, str2);
|
||||
// Set difficulty.
|
||||
final MagicDuel testDuel = new MagicDuel(config);
|
||||
testDuel.initialize();
|
||||
testDuel.setDifficulty(0, str1);
|
||||
testDuel.setDifficulty(1, str2);
|
||||
|
||||
// Set the AI
|
||||
testDuel.setAIs(new MagicAI[] { ai1.getAI(), ai2.getAI() });
|
||||
testDuel.getPlayer(0).setArtificial(true);
|
||||
testDuel.getPlayer(1).setArtificial(true);
|
||||
// Set the AI
|
||||
testDuel.setAIs(new MagicAI[] { ai1.getAI(), ai2.getAI() });
|
||||
testDuel.getPlayer(0).setArtificial(true);
|
||||
testDuel.getPlayer(1).setArtificial(true);
|
||||
|
||||
// Set the deck.
|
||||
if (deck1.length() > 0) {
|
||||
DeckUtils.loadDeck(deck1, testDuel.getPlayer(0));
|
||||
}
|
||||
if (deck2.length() > 0) {
|
||||
DeckUtils.loadDeck(deck2, testDuel.getPlayer(1));
|
||||
}
|
||||
// Set the deck.
|
||||
if (deck1.length() > 0) {
|
||||
DeckUtils.loadDeck(deck1, testDuel.getPlayer(0));
|
||||
}
|
||||
if (deck2.length() > 0) {
|
||||
DeckUtils.loadDeck(deck2, testDuel.getPlayer(1));
|
||||
}
|
||||
|
||||
return testDuel;
|
||||
}
|
||||
return testDuel;
|
||||
}
|
||||
|
||||
public static void main(final String[] args) {
|
||||
|
||||
FiremindClient.setHostByEnvironment();
|
||||
MagicMain.initializeEngine();
|
||||
while (true) {
|
||||
Duel duel = FiremindClient.popDeckJob();
|
||||
if (duel != null) {
|
||||
final FiremindGameReport reporter = new FiremindGameReport(
|
||||
duel.id);
|
||||
Thread.setDefaultUncaughtExceptionHandler(reporter);
|
||||
System.out.println(duel.games_to_play + " Games to run");
|
||||
File theDir = new File("duels/" + duel.id);
|
||||
theDir.mkdir();
|
||||
public static void main(final String[] args) {
|
||||
|
||||
deck1 = saveDeckFile("duels/" + duel.id + "/" + "deck1",
|
||||
duel.deck1_text);
|
||||
deck2 = saveDeckFile("duels/" + duel.id + "/" + "deck2",
|
||||
duel.deck2_text);
|
||||
currentDuel = duel;
|
||||
games = duel.games_to_play;
|
||||
FiremindClient.setHostByEnvironment();
|
||||
while (true) {
|
||||
Duel duel = FiremindClient.popDeckJob();
|
||||
if (duel != null) {
|
||||
try {
|
||||
MagicMain.initializeEngine();
|
||||
final FiremindGameReport reporter = new FiremindGameReport(
|
||||
duel.id);
|
||||
Thread.setDefaultUncaughtExceptionHandler(reporter);
|
||||
System.out.println(duel.games_to_play + " Games to run");
|
||||
File theDir = new File("duels/" + duel.id);
|
||||
theDir.mkdir();
|
||||
|
||||
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
|
||||
runDuel();
|
||||
if (gameCount > 25) {
|
||||
System.out
|
||||
.println("Exceeded max number of games. Shutting down.");
|
||||
return;
|
||||
}
|
||||
deck1 = saveDeckFile("duels/" + duel.id + "/" + "deck1",
|
||||
duel.deck1_text);
|
||||
deck2 = saveDeckFile("duels/" + duel.id + "/" + "deck2",
|
||||
duel.deck2_text);
|
||||
currentDuel = duel;
|
||||
games = duel.games_to_play;
|
||||
|
||||
} else {
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Woken");
|
||||
}
|
||||
}
|
||||
}
|
||||
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
|
||||
runDuel();
|
||||
FiremindClient.postSuccess(duel.id);
|
||||
if (gameCount > 25) {
|
||||
System.out
|
||||
.println("Exceeded max number of games. Shutting down.");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
e.printStackTrace(pw);
|
||||
FiremindClient.postFailure(duel.id, sw.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
FiremindClient.resetChangedScripts();
|
||||
|
||||
} else {
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Woken");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String saveDeckFile(String name, String content) {
|
||||
try {
|
||||
File deckFile = new File(name + ".dec");
|
||||
deckFile.getParentFile().mkdirs();
|
||||
deckFile.createNewFile();
|
||||
FileWriter fw = new FileWriter(deckFile.getAbsoluteFile());
|
||||
BufferedWriter bw = new BufferedWriter(fw);
|
||||
bw.write(content);
|
||||
bw.close();
|
||||
return deckFile.getPath();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void runDuel() {
|
||||
int played = 0;
|
||||
int wins = 0;
|
||||
MagicGameLog.initialize();
|
||||
final MagicDuel testDuel = setupDuel();
|
||||
private static String saveDeckFile(String name, String content) {
|
||||
try {
|
||||
File deckFile = new File(name + ".dec");
|
||||
deckFile.getParentFile().mkdirs();
|
||||
deckFile.createNewFile();
|
||||
FileWriter fw = new FileWriter(deckFile.getAbsoluteFile());
|
||||
BufferedWriter bw = new BufferedWriter(fw);
|
||||
bw.write(content);
|
||||
bw.close();
|
||||
return deckFile.getPath();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
Date baseDate = new Date();
|
||||
baseDate.setTime(0);
|
||||
long started = System.currentTimeMillis();
|
||||
while (testDuel.getGamesPlayed() < testDuel.getGamesTotal()) {
|
||||
final MagicGame game = testDuel.nextGame(false);
|
||||
game.setArtificial(true);
|
||||
final GameController controller = new GameController(game);
|
||||
private static void runDuel() {
|
||||
int played = 0;
|
||||
int wins = 0;
|
||||
MagicGameLog.initialize();
|
||||
final MagicDuel testDuel = setupDuel();
|
||||
|
||||
// maximum duration of a game is 60 minutes
|
||||
controller.setMaxTestGameDuration(3600000);
|
||||
Date baseDate = new Date();
|
||||
baseDate.setTime(0);
|
||||
long started = System.currentTimeMillis();
|
||||
while (testDuel.getGamesPlayed() < testDuel.getGamesTotal()) {
|
||||
final MagicGame game = testDuel.nextGame(false);
|
||||
game.setArtificial(true);
|
||||
final GameController controller = new GameController(game);
|
||||
|
||||
controller.runGame();
|
||||
if (testDuel.getGamesPlayed() > played) {
|
||||
gameCount++;
|
||||
played = testDuel.getGamesPlayed();
|
||||
long diff = System.currentTimeMillis() - started;
|
||||
String[] vers = MagicMain.VERSION.split("\\.");
|
||||
String log = MagicGameLog.getLogFileName();
|
||||
FiremindClient.postGame(currentDuel.id, played, new Date(
|
||||
baseDate.getTime() + diff),
|
||||
testDuel.getGamesWon() > wins, Integer
|
||||
.parseInt(vers[0]), Integer.parseInt(vers[1]),
|
||||
log);
|
||||
// maximum duration of a game is 60 minutes
|
||||
controller.setMaxTestGameDuration(3600000);
|
||||
|
||||
wins = testDuel.getGamesWon();
|
||||
started = System.currentTimeMillis();
|
||||
MagicGameLog.initialize();
|
||||
}
|
||||
}
|
||||
System.out.println("Duel finished " + played + " of "
|
||||
+ testDuel.getGamesTotal() + " run");
|
||||
controller.runGame();
|
||||
if (testDuel.getGamesPlayed() > played) {
|
||||
gameCount++;
|
||||
played = testDuel.getGamesPlayed();
|
||||
long diff = System.currentTimeMillis() - started;
|
||||
String[] vers = MagicMain.VERSION.split("\\.");
|
||||
String log = MagicGameLog.getLogFileName();
|
||||
FiremindClient.postGame(currentDuel.id, played, new Date(
|
||||
baseDate.getTime() + diff),
|
||||
testDuel.getGamesWon() > wins, Integer
|
||||
.parseInt(vers[0]), Integer.parseInt(vers[1]),
|
||||
log);
|
||||
|
||||
}
|
||||
wins = testDuel.getGamesWon();
|
||||
started = System.currentTimeMillis();
|
||||
MagicGameLog.initialize();
|
||||
}
|
||||
}
|
||||
System.out.println("Duel finished " + played + " of "
|
||||
+ testDuel.getGamesTotal() + " run");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@ import java.io.FileNotFoundException;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.UnknownHostException;
|
||||
|
@ -13,18 +15,29 @@ import java.net.URL;
|
|||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import magic.data.CardDefinitions;
|
||||
import magic.data.GeneralConfig;
|
||||
import magic.firemind.Duel;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONArray;
|
||||
|
||||
import magic.utility.MagicFileSystem;
|
||||
import magic.utility.MagicFileSystem.DataPath;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class FiremindClient {
|
||||
|
||||
protected static final GeneralConfig CONFIG = GeneralConfig.getInstance();
|
||||
static String firemindHost ;
|
||||
|
||||
static List<String> addedScripts;
|
||||
public static Duel popDeckJob() {
|
||||
CONFIG.load();
|
||||
JSONObject obj;
|
||||
|
@ -37,6 +50,23 @@ public class FiremindClient {
|
|||
d.deck1_text = obj.getString("deck1_text");
|
||||
d.deck2_text = obj.getString("deck2_text");
|
||||
|
||||
JSONArray scripts = obj.getJSONArray("card_scripts");
|
||||
addedScripts = new ArrayList<String>();
|
||||
if(scripts != null){
|
||||
for (int i = 0; i < scripts.length(); i++) {
|
||||
JSONObject script = scripts.getJSONObject(i);
|
||||
String name = script.getString("name");
|
||||
|
||||
saveScriptFile(name, "txt", script.getString("config"));
|
||||
String groovyScript = script.getString("script");
|
||||
if(groovyScript != null && !groovyScript.equals("")){
|
||||
saveScriptFile(name, "groovy", groovyScript);
|
||||
}
|
||||
|
||||
System.out.println(name);
|
||||
}
|
||||
}
|
||||
|
||||
return d;
|
||||
} catch (JSONException e) {
|
||||
// TODO Auto-generated catch block
|
||||
|
@ -52,6 +82,43 @@ public class FiremindClient {
|
|||
}
|
||||
}
|
||||
|
||||
private static void saveScriptFile(String name, String extension, String content){
|
||||
File scriptsDirectory = MagicFileSystem.getDataPath(DataPath.SCRIPTS).toFile();
|
||||
String filename = CardDefinitions.getCanonicalName(name)+"."+extension;
|
||||
File f = new File(scriptsDirectory.getAbsolutePath()+"/"+filename);
|
||||
if (f.exists()){
|
||||
f.renameTo(new File(scriptsDirectory.getAbsolutePath()+"/"+filename+".orig"));
|
||||
}else{
|
||||
addedScripts.add(f.getAbsolutePath());
|
||||
}
|
||||
try {
|
||||
f.createNewFile();
|
||||
}catch (IOException e){
|
||||
System.err.println("Couldn't save script file");
|
||||
}
|
||||
try{
|
||||
PrintWriter writer = new PrintWriter(f.getAbsolutePath(), "UTF-8");
|
||||
writer.println(content);
|
||||
writer.close();
|
||||
System.out.println(f.getAbsolutePath());
|
||||
}catch (FileNotFoundException e){
|
||||
System.err.println("Couldn't save script file");
|
||||
}catch (UnsupportedEncodingException e){
|
||||
System.err.println("Couldn't save script file");
|
||||
}
|
||||
}
|
||||
|
||||
public static void resetChangedScripts(){
|
||||
String[] ext = new String[]{"orig"};
|
||||
List<File> files = (List<File>) FileUtils.listFiles(MagicFileSystem.getDataPath(DataPath.SCRIPTS).toFile(), ext, true);
|
||||
for(File f: files){
|
||||
f.renameTo(new File(f.getAbsolutePath().substring(0, f.getAbsolutePath().lastIndexOf("."))));
|
||||
}
|
||||
for(String path: addedScripts){
|
||||
(new File(path)).delete();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean postGame(Integer duel_id, Integer game_number,
|
||||
Date play_time, boolean win_deck1, Integer magarena_version_major,
|
||||
Integer magarena_version_minor, String logFile) {
|
||||
|
@ -99,10 +166,74 @@ public class FiremindClient {
|
|||
}
|
||||
|
||||
public static boolean postFailure(Integer duel_id, String text) {
|
||||
System.err.println("POST ERROR STUB: "+text);
|
||||
CONFIG.load();
|
||||
String url = firemindHost + "/api/v1/duel_jobs/" + duel_id + "/post_failure";
|
||||
URL object;
|
||||
try {
|
||||
object = new URL(url);
|
||||
HttpURLConnection con = (HttpURLConnection) object.openConnection();
|
||||
con.setRequestProperty("Content-Type", "application/json");
|
||||
con.setRequestProperty("Accept", "application/json");
|
||||
con.setRequestProperty("Authorization", "Token token="
|
||||
+ CONFIG.getFiremindAccessToken());
|
||||
con.setRequestMethod("POST");
|
||||
|
||||
JSONObject parent = new JSONObject();
|
||||
parent.put("failure_message", text);
|
||||
con.setDoOutput(true);
|
||||
|
||||
con.setDoInput(true);
|
||||
OutputStreamWriter wr = new OutputStreamWriter(
|
||||
con.getOutputStream());
|
||||
wr.write(parent.toString());
|
||||
wr.flush();
|
||||
int HttpResult = con.getResponseCode();
|
||||
if (HttpResult == HttpURLConnection.HTTP_OK) {
|
||||
return true;
|
||||
} else {
|
||||
System.err.println(con.getResponseMessage());
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean postSuccess(Integer duel_id) {
|
||||
CONFIG.load();
|
||||
String url = firemindHost + "/api/v1/duel_jobs/" + duel_id + "/post_failure";
|
||||
URL object;
|
||||
try {
|
||||
object = new URL(url);
|
||||
HttpURLConnection con = (HttpURLConnection) object.openConnection();
|
||||
con.setRequestProperty("Content-Type", "application/json");
|
||||
con.setRequestProperty("Accept", "application/json");
|
||||
con.setRequestProperty("Authorization", "Token token="
|
||||
+ CONFIG.getFiremindAccessToken());
|
||||
con.setRequestMethod("POST");
|
||||
|
||||
con.setDoOutput(true);
|
||||
|
||||
int HttpResult = con.getResponseCode();
|
||||
if (HttpResult == HttpURLConnection.HTTP_OK) {
|
||||
return true;
|
||||
} else {
|
||||
System.err.println(con.getResponseMessage());
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static JSONObject readJsonFromUrl(String url) throws IOException,
|
||||
JSONException {
|
||||
HttpURLConnection con = (HttpURLConnection) (new URL(url))
|
||||
|
|
|
@ -16,15 +16,15 @@ import java.text.SimpleDateFormat;
|
|||
import java.util.Date;
|
||||
|
||||
public class FiremindGameReport implements Thread.UncaughtExceptionHandler {
|
||||
Integer currentDuelId;
|
||||
private Integer currentDuelId;
|
||||
|
||||
public FiremindGameReport(Integer duel_id) {
|
||||
super();
|
||||
this.currentDuelId = duel_id;
|
||||
currentDuelId = duel_id;
|
||||
}
|
||||
|
||||
public void uncaughtException(final Thread th, final Throwable ex) {
|
||||
FiremindGameReport.buildReport(MagicGame.getInstance(), th, ex);
|
||||
buildReport(MagicGame.getInstance(), th, ex);
|
||||
ex.printStackTrace();
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
|
@ -124,8 +124,7 @@ public class FiremindGameReport implements Thread.UncaughtExceptionHandler {
|
|||
return report.toString();
|
||||
}
|
||||
|
||||
public static void buildReport(final MagicGame game, final Thread th,
|
||||
final Throwable ex) {
|
||||
public void buildReport(final MagicGame game, final Thread th, final Throwable ex) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("CRASH REPORT FOR MAGARENA THREAD " + th);
|
||||
sb.append('\n');
|
||||
|
@ -162,6 +161,8 @@ public class FiremindGameReport implements Thread.UncaughtExceptionHandler {
|
|||
ex.printStackTrace(printWriter);
|
||||
sb.append(result.toString());
|
||||
sb.append('\n');
|
||||
|
||||
FiremindClient.postFailure(currentDuelId, sb.toString());
|
||||
|
||||
// print a copy to stderr
|
||||
System.err.println(sb.toString());
|
||||
|
|
|
@ -40,6 +40,30 @@ public enum MagicCostEvent {
|
|||
return new MagicRepeatedPermanentsEvent(source, choice, amt, MagicChainEventFactory.Sac);
|
||||
}
|
||||
},
|
||||
BounceSelf("Return SN to its owner's hand") {
|
||||
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
|
||||
return new MagicBouncePermanentEvent(source, (MagicPermanent)source);
|
||||
}
|
||||
@Override
|
||||
public boolean isIndependent() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
BounceMultiple("Return (?<another>another )?(" + ARG.AMOUNT + " )?" + ARG.ANY + " to (their|its) owner's hand") {
|
||||
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
|
||||
final int amt = ARG.amount(arg);
|
||||
final String chosen = MagicTargetFilterFactory.toSingular(ARG.any(arg));
|
||||
final MagicTargetFilter<MagicPermanent> regular = MagicTargetFilterFactory.singlePermanent(chosen);
|
||||
final MagicTargetFilter<MagicPermanent> filter = arg.group("another") != null ?
|
||||
new MagicOtherPermanentTargetFilter(regular, (MagicPermanent)source) :
|
||||
regular;
|
||||
final MagicTargetChoice choice = new MagicTargetChoice(
|
||||
filter,
|
||||
("aeiou".indexOf(chosen.charAt(0)) >= 0 ? "an " : "a ") + chosen
|
||||
);
|
||||
return new MagicRepeatedPermanentsEvent(source, choice, amt, MagicChainEventFactory.Bounce);
|
||||
}
|
||||
},
|
||||
DiscardAll("Discard your hand") {
|
||||
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
|
||||
return new MagicDiscardHandEvent(source);
|
||||
|
@ -134,20 +158,6 @@ public enum MagicCostEvent {
|
|||
return new MagicPayLifeEvent(source, ARG.number(arg));
|
||||
}
|
||||
},
|
||||
BounceSelf("Return SN to its owner's hand") {
|
||||
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
|
||||
return new MagicBouncePermanentEvent(source, (MagicPermanent)source);
|
||||
}
|
||||
@Override
|
||||
public boolean isIndependent() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
BounceChosen("Return " + ARG.ANY + " to its owner's hand") {
|
||||
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
|
||||
return new MagicBounceChosenPermanentEvent(source, new MagicTargetChoice(ARG.any(arg)));
|
||||
}
|
||||
},
|
||||
RemoveCounterSelf("Remove " + ARG.AMOUNT + " " + ARG.WORD1 + " counter(s)? from SN") {
|
||||
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
|
||||
final int amount = ARG.amount(arg);
|
||||
|
|
|
@ -383,6 +383,12 @@ public class MagicTargetFilterFactory {
|
|||
}
|
||||
};
|
||||
|
||||
public static final MagicPermanentFilterImpl NONTOKEN_RED_PERMANENT=new MagicPermanentFilterImpl() {
|
||||
public boolean accept(final MagicGame game,final MagicPlayer player,final MagicPermanent target) {
|
||||
return !target.isToken() && target.hasColor(MagicColor.Red);
|
||||
}
|
||||
};
|
||||
|
||||
public static final MagicPermanentFilterImpl NONLAND_PERMANENT_YOUR_OPPONENT_CONTROLS=new MagicPermanentFilterImpl() {
|
||||
public boolean accept(final MagicGame game,final MagicPlayer player,final MagicPermanent target) {
|
||||
return !target.isLand() && target.isOpponent(player);
|
||||
|
@ -1462,7 +1468,16 @@ public class MagicTargetFilterFactory {
|
|||
(target.hasColor(MagicColor.Blue) || target.hasColor(MagicColor.Red));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static final MagicCardFilterImpl BLACK_OR_RED_CREATURE_CARD_FROM_GRAVEYARD = new MagicCardFilterImpl() {
|
||||
public boolean acceptType(final MagicTargetType targetType) {
|
||||
return targetType==MagicTargetType.Graveyard;
|
||||
}
|
||||
public boolean accept(final MagicGame game, final MagicPlayer player, final MagicCard target) {
|
||||
return target.hasType(MagicType.Creature) &&
|
||||
(target.hasColor(MagicColor.Black) || target.hasColor(MagicColor.Red));
|
||||
}
|
||||
};
|
||||
|
||||
public static final MagicCardFilterImpl INSTANT_OR_SORCERY_CARD_FROM_OPPONENTS_GRAVEYARD =
|
||||
card(MagicType.Instant).or(MagicType.Sorcery).from(MagicTargetType.OpponentsGraveyard);
|
||||
|
@ -1973,6 +1988,12 @@ public class MagicTargetFilterFactory {
|
|||
3
|
||||
);
|
||||
|
||||
public static final MagicPermanentFilterImpl CREATURE_TOUGHNESS_4_OR_GREATER = new MagicPTTargetFilter(
|
||||
MagicTargetFilterFactory.CREATURE,
|
||||
Operator.GREATER_THAN_OR_EQUAL,
|
||||
4
|
||||
);
|
||||
|
||||
public static final MagicPermanentFilterImpl CREATURE_POWER_1_OR_LESS = new MagicPTTargetFilter(
|
||||
MagicTargetFilterFactory.CREATURE,
|
||||
Operator.LESS_THAN_OR_EQUAL,
|
||||
|
@ -2269,6 +2290,7 @@ public class MagicTargetFilterFactory {
|
|||
single.put("creature with toughness 2 or less", CREATURE_TOUGHNESS_2_OR_LESS);
|
||||
single.put("creature with toughness 3 or less", CREATURE_TOUGHNESS_3_OR_LESS);
|
||||
single.put("creature with toughness 3 or greater", CREATURE_TOUGHNESS_3_OR_GREATER);
|
||||
single.put("creature with toughness 4 or greater", CREATURE_TOUGHNESS_4_OR_GREATER);
|
||||
single.put("creature with shadow", CREATURE_WITH_SHADOW);
|
||||
single.put("creature with a +1/+1 counter on it", CREATURE_PLUSONE_COUNTER);
|
||||
single.put("creature with a -1/-1 counter on it", CREATURE_MINSUONE_COUNTER);
|
||||
|
@ -2346,6 +2368,7 @@ public class MagicTargetFilterFactory {
|
|||
single.put("spell or permanent", SPELL_OR_PERMANENT);
|
||||
single.put("nonland permanent", NONLAND_PERMANENT);
|
||||
single.put("nontoken permanent", NONTOKEN_PERMANENT);
|
||||
single.put("nontoken red permanent", NONTOKEN_RED_PERMANENT);
|
||||
single.put("nonland permanent with converted mana cost 3 or less", NONLAND_PERMANENT_CMC_LEQ_3);
|
||||
single.put("black or red permanent", BLACK_RED_PERMANENT);
|
||||
single.put("multicolored permanent", MULTICOLORED_PERMANENT);
|
||||
|
|
Loading…
Reference in New Issue