Merge main repo.

master
Lodici 2014-09-24 11:01:24 +01:00
commit e16eeb8882
37 changed files with 588 additions and 209 deletions

View File

@ -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));
}
}
}
}
]

View File

@ -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.

View File

@ -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+")");
}
}
]

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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));
})
}
}
]

View File

@ -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.

View File

@ -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+")");
}
}
]

View File

@ -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.

View File

@ -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.

View File

@ -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+")");
}
}
]

View File

@ -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.

View File

@ -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;
}
}
]

View File

@ -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}

View File

@ -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;
}
}
]

View File

@ -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}

View File

@ -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;

View File

@ -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));
}
}
]

View File

@ -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.

View File

@ -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;
}
}
]

View File

@ -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.

View File

@ -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));
});
}
}
]

View File

@ -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.

View File

@ -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
!Bragos 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
!Muzzios 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

View File

@ -43,6 +43,7 @@ THS
BNG
JOU
M15
KTK
# banned: prefix with !
!Ancestral Vision

View File

@ -1,8 +1,5 @@
RTR
GTC
DGM
M14
THS
BNG
JOU
M15
KTK

View File

@ -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
!Bragos 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
!Muzzios Preparations
!Power Play
!Rebirth
!Secret Summoning
!Secrets of Paradise
!Sentinel Dispatch
!Shahrazad
!Tempest Efreet
!Timmerian Fiends
!Unexpected Potential
!Worldknit

View File

@ -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");
}
}

View File

@ -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))

View File

@ -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());

View File

@ -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);

View File

@ -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);