Merge google-code.

master
Lodici 2013-11-02 08:13:39 +00:00
commit f3ae0c14fb
69 changed files with 722 additions and 929 deletions

View File

@ -110,7 +110,10 @@ cards/existing_tokens_%.txt: $(wildcard release/Magarena/scripts/*.txt)
cards/existing_%.txt: cards/existing_scripts_%.txt cards/existing_tokens_%.txt
join -v1 -t"|" <(sort $(word 1,$^)) <(sort $(word 2,$^)) > $@
%_full.txt: scripts/extract_candidates.awk %.txt cards/mtg-data.txt
cards/groovy.txt:
grep -ho "name=.*" `grep requires_groovy_code -lr release/Magarena/scripts` | sed 's/name=//' | sort > $@
%_full.txt: scripts/extract_candidates.awk %.txt cards/groovy.txt cards/mtg-data.txt
awk -f $^ | sed 's/\t/\n/g' > $@
cards/candidates_full.txt: scripts/extract_candidates.awk cards/scored_by_dec.tsv cards/unimplementable.tsv cards/mtg-data.txt
@ -635,4 +638,4 @@ common_actions:
src/magic/MurmurHash3.java:
curl https://raw.github.com/infinispan/infinispan/master/commons/src/main/java/org/infinispan/commons/hash/MurmurHash3.java > $@
patch $@ MurmurHash3.diff
patch $@ src/magic/MurmurHash3.diff

View File

@ -1,129 +0,0 @@
--- MurmurHash3.java 2013-10-29 22:40:32.510685131 +0800
+++ src/magic/MurmurHash3.java 2013-10-29 22:42:12.150687043 +0800
@@ -1,11 +1,4 @@
-package org.infinispan.commons.hash;
-
-import net.jcip.annotations.Immutable;
-import net.jcip.annotations.ThreadSafe;
-
-import org.infinispan.commons.marshall.exts.NoStateExternalizer;
-import org.infinispan.commons.util.Util;
-import org.infinispan.commons.marshall.Ids;
+package magic;
import java.io.ObjectInput;
import java.nio.charset.Charset;
@@ -25,9 +18,7 @@
* @see <a href="http://en.wikipedia.org/wiki/MurmurHash">MurmurHash entry on Wikipedia</a>
* @since 5.0
*/
-@ThreadSafe
-@Immutable
-public class MurmurHash3 implements Hash {
+public class MurmurHash3 {
private static final Charset UTF8 = Charset.forName("UTF-8");
static class State {
@@ -92,6 +83,7 @@
* @param seed random value
* @return 128 bit hashed key, in an array containing two longs
*/
+ @SuppressWarnings("fallthrough")
public static long[] MurmurHash3_x64_128(final byte[] key, final int seed) {
State state = new State();
@@ -154,6 +146,7 @@
* @param seed random value
* @return 64 bit hashed key
*/
+ @SuppressWarnings("fallthrough")
public static long MurmurHash3_x64_64(final byte[] key, final int seed) {
// Exactly the same as MurmurHash3_x64_128, except it only returns state.h1
State state = new State();
@@ -244,7 +237,7 @@
bmix(state);
}
- long tail = key[key.length - 1];
+ final long tail = key.length > 0 ? key[key.length - 1] : 0;
// Key length is odd
if ((key.length & 1) == 1) {
@@ -290,7 +283,7 @@
bmix(state);
}
- long tail = key[key.length - 1];
+ final long tail = key.length > 0 ? key[key.length - 1] : 0;
if (key.length % 2 != 0) {
state.k1 ^= tail;
@@ -322,7 +315,7 @@
return (int) (MurmurHash3_x64_64(key, seed) >>> 32);
}
- @Override
+
public int hash(byte[] payload) {
return MurmurHash3_x64_32(payload, 9001);
}
@@ -333,11 +326,11 @@
* @param payload a byte array to hash
* @return a hash code for the byte array
*/
- public static int hash(long[] payload) {
- return MurmurHash3_x64_32(payload, 9001);
+ public static long hash(long[] payload) {
+ return MurmurHash3_x64_64(payload, 9001);
}
- @Override
+
public int hash(int hashcode) {
// Obtained by inlining MurmurHash3_x64_32(byte[], 9001) and removing all the unused code
// (since we know the input is always 4 bytes and we only need 4 bytes of output)
@@ -375,44 +368,4 @@
return (int) (state.h1 >>> 32);
}
-
- @Override
- public int hash(Object o) {
- if (o instanceof byte[])
- return hash((byte[]) o);
- else if (o instanceof long[])
- return hash((long[]) o);
- else if (o instanceof String)
- return hash(((String) o).getBytes(UTF8));
- else
- return hash(o.hashCode());
- }
-
- @Override
- public boolean equals(Object other) {
- return other != null && other.getClass() == getClass();
- }
-
- @Override
- public String toString() {
- return "MurmurHash3";
- }
-
- public static class Externalizer extends NoStateExternalizer<MurmurHash3> {
- @Override
- @SuppressWarnings("unchecked")
- public Set<Class<? extends MurmurHash3>> getTypeClasses() {
- return Util.<Class<? extends MurmurHash3>>asSet(MurmurHash3.class);
- }
-
- @Override
- public MurmurHash3 readObject(ObjectInput input) {
- return new MurmurHash3();
- }
-
- @Override
- public Integer getId() {
- return Ids.MURMURHASH_3;
- }
- }
}

View File

@ -188,13 +188,8 @@ Fact or Fiction separate into piles
Simic Growth Chamber mana pool
Golgari Rot Farm mana pool
Nykthos, Shrine to Nyx mana pool
Temple of Deceit scry 1
Magma Jet scry 2
Temple of Silence scry 1
Omenspeaker scry 2
Temple of Abandon scry 1
Read the Bones scry 2
Dissolve scry 1
Xenagos, the Reveler mana pool
Temple of Triumph scry 1
Condescend scry 2

1 Gravecrawler from graveyard
188 Simic Growth Chamber mana pool
189 Golgari Rot Farm mana pool
190 Nykthos, Shrine to Nyx mana pool
Temple of Deceit scry 1
191 Magma Jet scry 2
Temple of Silence scry 1
192 Omenspeaker scry 2
Temple of Abandon scry 1
193 Read the Bones scry 2
Dissolve scry 1
194 Xenagos, the Reveler mana pool
Temple of Triumph scry 1
195 Condescend scry 2

View File

@ -1,23 +0,0 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.POS_TARGET_CREATURE,
MagicFlyingTargetPicker.create(),
this,
"Target creature\$ gets +3/+3 and gains flying until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicChangeTurnPTAction(creature,3,3));
game.doAction(new MagicGainAbilityAction(creature,MagicAbility.Flying));
}
});
}
}
]

View File

@ -5,5 +5,5 @@ value=2.727
rarity=C
type=Sorcery
cost={2}{W}
effect=Target creature gets +3/+3 and gains flying until end of turn.
timing=pump
requires_groovy_code

View File

@ -7,5 +7,5 @@ type=Creature
subtype=Insect
cost={1}{B}{R}
pt=1/1
timing=main
ability=pay {T},Sacrifice a land: Destroy target land.
timing=main

View File

@ -5,5 +5,5 @@ value=4.256
rarity=U
type=Sorcery
cost={3}{W}
effect=Return target creature card from your graveyard to the battlefield.
timing=main
requires_groovy_code=Zombify

View File

@ -1,23 +0,0 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.POS_TARGET_CREATURE,
MagicPumpTargetPicker.create(),
this,
"Target creature\$ gets +4/+2 and gains trample until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicChangeTurnPTAction(creature,4,2));
game.doAction(new MagicGainAbilityAction(creature,MagicAbility.Trample));
}
});
}
}
]

View File

@ -5,5 +5,5 @@ value=2.786
rarity=C
type=Instant
cost={R}{G}
effect=Target creature gets +4/+2 and gains trample until end of turn.
timing=pump
requires_groovy_code

View File

@ -1,6 +1,6 @@
name=Dark Depths
url=http://magiccards.info/csp/en/145.html
image=http://magiccards.info/scans/en/csp/145.jpg
url=http://magiccards.info/cs/en/145.html
image=http://magiccards.info/scans/en/cs/145.jpg
value=2.500
rarity=R
type=Legendary,Snow,Land

View File

@ -7,5 +7,5 @@ type=Creature
subtype=Human,Wizard
cost={2}{U}
pt=1/1
timing=main
ability=pay {T}: Counter target spell unless its controller pays {1}.
timing=main

View File

@ -1,36 +0,0 @@
[
new MagicWhenDiesTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game, final MagicPermanent permanent, final MagicMoveCardAction data) {
final MagicTargetChoice targetChoice = new MagicTargetChoice(
new MagicTargetFilter.MagicCMCCardFilter(
MagicTargetFilter.TARGET_CREATURE_CARD_FROM_GRAVEYARD,
MagicTargetFilter.Operator.LESS_THAN_OR_EQUAL,
2
),
MagicTargetHint.None,
"target creature card from your graveyard)"
);
return new MagicEvent(
permanent,
targetChoice,
MagicGraveyardTargetPicker.PutOntoBattlefield,
this,
"PN returns target creature card\$ with " +
"converted mana cost 2 or less " +
"from his or her graveyard to the battlefield."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetCard(game,new MagicCardAction() {
public void doAction(final MagicCard card) {
game.doAction(new MagicReanimateAction(
card,
event.getPlayer()
));
}
});
}
}
]

View File

@ -7,5 +7,5 @@ type=Creature
subtype=Vampire
cost={3}{B}
pt=3/2
ability=dies effect Return target creature card with converted mana cost 2 or less from your graveyard to the battlefield.
timing=main
requires_groovy_code

View File

@ -7,5 +7,5 @@ type=Creature
subtype=Dwarf
cost={1}{R}
pt=1/2
timing=main
ability=pay {2}{R},{T}: Destroy target nonbasic land.
timing=main

View File

@ -5,5 +5,5 @@ value=4.133
rarity=U
type=Sorcery
cost={3}{W}
effect=Return target creature card from your graveyard to the battlefield.
timing=main
requires_groovy_code=Zombify

View File

@ -7,5 +7,5 @@ type=Creature
subtype=Bird
cost={W/U}
pt=1/1
timing=main
ability=flying;pay {S}: Counter target instant or sorcery spell unless its controller pays {1}.
timing=main

View File

@ -1,30 +0,0 @@
[
new MagicWhenComesIntoPlayTrigger() {
@Override
public MagicEvent executeTrigger(
final MagicGame game,
final MagicPermanent permanent,
final MagicPayedCost payedCost) {
return new MagicEvent(
permanent,
MagicTargetChoice.TARGET_CREATURE_CARD_FROM_GRAVEYARD,
MagicGraveyardTargetPicker.PutOntoBattlefield,
this,
"Return target creature card\$ from " +
"your graveyard to the battlefield."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetCard(game,new MagicCardAction() {
public void doAction(final MagicCard targetCard) {
game.doAction(new MagicReanimateAction(
targetCard,
event.getPlayer()
));
}
});
}
}
]

View File

@ -7,6 +7,6 @@ type=Creature
subtype=Angel,Spirit
cost={3}{W}{W}
pt=2/2
ability=flying;protection from black;echo {3}{W}{W}
ability=flying;protection from black;echo {3}{W}{W};\
enters effect Return target creature card from your graveyard to the battlefield.
timing=main
requires_groovy_code

View File

@ -1,23 +0,0 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.POS_TARGET_CREATURE,
MagicFirstStrikeTargetPicker.create(),
this,
"Target creature\$ gets +1/+0 and gains first strike until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicChangeTurnPTAction(creature,1,0));
game.doAction(new MagicGainAbilityAction(creature,MagicAbility.FirstStrike));
}
});
}
}
]

View File

@ -5,5 +5,5 @@ value=2.265
rarity=C
type=Instant
cost={R}
effect=Target creature gets +1/+0 and gains first strike until end of turn.
timing=pump
requires_groovy_code

View File

@ -1,23 +0,0 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.POS_TARGET_CREATURE,
MagicFlyingTargetPicker.create(),
this,
"Target creature\$ gets +2/+2 and gains flying until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicChangeTurnPTAction(creature,2,2));
game.doAction(new MagicGainAbilityAction(creature,MagicAbility.Flying));
}
});
}
}
]

View File

@ -5,5 +5,5 @@ value=2.932
rarity=C
type=Instant
cost={1}{W}
effect=Target creature gets +2/+2 and gains flying until end of turn.
timing=pump
requires_groovy_code

View File

@ -1,25 +1,4 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.TARGET_CREATURE_YOU_CONTROL,
MagicShroudTargetPicker.create(),
this,
"Target creature\$ you control gets +0/+1 and gains hexproof until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicChangeTurnPTAction(creature, 0, 1));
game.doAction(new MagicGainAbilityAction(creature, MagicAbility.Hexproof));
}
});
}
},
new MagicOverloadActivation(MagicTiming.Pump) {
@Override
public Iterable<MagicEvent> getCostEvent(final MagicCard source) {

View File

@ -5,5 +5,6 @@ value=3.325
rarity=C
type=Instant
cost={U}
effect=Target creature you control gets +0/+1 and gains hexproof until end of turn.
timing=pump
requires_groovy_code

View File

@ -1,23 +0,0 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.POS_TARGET_CREATURE,
MagicLifelinkTargetPicker.create(),
this,
"Target creature\$ gets +2/+2 and gains lifelink until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicChangeTurnPTAction(creature,2,2));
game.doAction(new MagicGainAbilityAction(creature,MagicAbility.Lifelink));
}
});
}
}
]

View File

@ -5,5 +5,5 @@ value=3.438
rarity=C
type=Instant
cost={1}{W}
effect=Target creature gets +2/+2 and gains lifelink until end of turn.
timing=pump
requires_groovy_code

View File

@ -1,26 +0,0 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.TARGET_PERMANENT_CARD_FROM_GRAVEYARD,
MagicGraveyardTargetPicker.PutOntoBattlefield,
this,
"Return target permanent card\$ from your graveyard to the battlefield."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetCard(game,new MagicCardAction() {
public void doAction(final MagicCard targetCard) {
game.doAction(new MagicReanimateAction(
targetCard,
event.getPlayer()
));
}
});
}
}
]

View File

@ -5,5 +5,5 @@ value=4.092
rarity=R
type=Sorcery
cost={3}{W}{B}
effect=Return target permanent card from your graveyard to the battlefield.
timing=main
requires_groovy_code

View File

@ -5,5 +5,5 @@ value=4.057
rarity=U
type=Sorcery
cost={2}{W}{W}
effect=Return target creature card from your graveyard to the battlefield.
timing=main
requires_groovy_code=Zombify

View File

@ -1,32 +0,0 @@
[
new MagicAtUpkeepTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPlayer upkeepPlayer) {
return permanent.isController(upkeepPlayer) ?
new MagicEvent(
permanent,
new MagicMayChoice(
MagicTargetChoice.TARGET_CREATURE_CARD_FROM_GRAVEYARD
),
MagicGraveyardTargetPicker.PutOntoBattlefield,
this,
"PN may\$ return target creature card\$ from " +
"his or her graveyard to the battlefield."
):
MagicEvent.NONE;
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
if (event.isYes()) {
event.processTargetCard(game,new MagicCardAction() {
public void doAction(final MagicCard card) {
game.doAction(new MagicReanimateAction(
card,
event.getPlayer()
));
}
});
}
}
}
]

View File

@ -7,6 +7,6 @@ type=Legendary,Creature
subtype=Angel
cost={6}{W}{W}{W}
pt=4/6
ability=flying
ability=flying;\
your upkeep effect PN may return target creature card from your graveyard to the battlefield.
timing=main
requires_groovy_code

View File

@ -1,29 +0,0 @@
[
new MagicWhenComesIntoPlayTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent, final MagicPayedCost payedCost) {
return new MagicEvent(
permanent,
new MagicMayChoice(
MagicTargetChoice.TARGET_ARTIFACT_CARD_FROM_GRAVEYARD,
),
MagicGraveyardTargetPicker.PutOntoBattlefield,
this,
"PN may\$ return target artifact card\$ from your graveyard to the battlefield."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
if (event.isYes()) {
event.processTargetCard(game,new MagicCardAction() {
public void doAction(final MagicCard card) {
game.doAction(new MagicReanimateAction(
card,
event.getPlayer()
));
}
});
}
}
}
]

View File

@ -7,6 +7,6 @@ type=Legendary,Artifact,Creature
subtype=Sphinx
cost={3}{W}{U}{B}
pt=5/5
ability=flying
ability=flying;\
enters effect PN may return target artifact card from your graveyard to the battlefield.
timing=main
requires_groovy_code

View File

@ -1,29 +1,4 @@
[
new MagicAtUpkeepTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPlayer upkeepPlayer) {
return permanent.isController(upkeepPlayer) ?
new MagicEvent(
permanent,
MagicTargetChoice.TARGET_CREATURE_CARD_FROM_GRAVEYARD,
MagicGraveyardTargetPicker.PutOntoBattlefield,
this,
"Return target creature card\$ from your graveyard to the battlefield."
):
MagicEvent.NONE;
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetCard(game,new MagicCardAction() {
public void doAction(final MagicCard card) {
game.doAction(new MagicReanimateAction(
card,
event.getPlayer()
));
}
});
}
},
new MagicAtUpkeepTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPlayer upkeepPlayer) {

View File

@ -7,6 +7,7 @@ type=Legendary,Creature
subtype=Praetor
cost={5}{B}{B}
pt=6/6
ability=swampwalk
timing=smain
ability=swampwalk;\
your upkeep effect Return target creature card from your graveyard to the battlefield.
timing=main
requires_groovy_code

View File

@ -1,35 +0,0 @@
[
new MagicPermanentActivation(
new MagicActivationHints(MagicTiming.Pump),
"Pump"
) {
@Override
public Iterable<MagicEvent> getCostEvent(final MagicPermanent source) {
return [
new MagicTapEvent(source), new MagicPayManaCostEvent(source, "{R}{G}")
];
}
@Override
public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
return new MagicEvent(
source,
MagicTargetChoice.POS_TARGET_CREATURE,
MagicPumpTargetPicker.create(),
this,
"Target creature\$ gets +1/+1 and gains trample until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicChangeTurnPTAction(creature,1,1));
game.doAction(new MagicGainAbilityAction(creature,MagicAbility.Trample));
}
});
}
}
]

View File

@ -4,6 +4,6 @@ image=http://magiccards.info/scans/en/gp/163.jpg
value=4.182
rarity=U
type=Land
ability=tap add mana {1}
ability=tap add mana {1};\
pay {R}{G}, {T}: Target creature gets +1/+1 and gains trample until end of turn.
timing=land
requires_groovy_code

View File

@ -1,27 +0,0 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack, final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.POS_TARGET_CREATURE,
MagicFirstStrikeTargetPicker.create(),
this,
"Target creature\$ gets +2/+0 and gains " +
"first strike until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicChangeTurnPTAction(creature,2,0));
game.doAction(new MagicGainAbilityAction(
creature,
MagicAbility.FirstStrike
));
}
});
}
}
]

View File

@ -5,5 +5,5 @@ value=2.512
rarity=C
type=Instant
cost={1}{W}
effect=Target creature gets +2/+0 and gains first strike until end of turn.
timing=pump
requires_groovy_code

View File

@ -1,23 +0,0 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.POS_TARGET_CREATURE,
MagicFirstStrikeTargetPicker.create(),
this,
"Target creature\$ gets +3/+0 and gains first strike until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicChangeTurnPTAction(creature,3,0));
game.doAction(new MagicGainAbilityAction(creature,MagicAbility.FirstStrike));
}
});
}
}
]

View File

@ -5,5 +5,5 @@ value=2.238
rarity=C
type=Instant
cost={2}{R}
effect=Target creature gets +3/+0 and gains first strike until end of turn.
timing=pump
requires_groovy_code

View File

@ -0,0 +1,26 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.NEG_TARGET_CREATURE_OR_PLAYER,
new MagicDamageTargetPicker(1),
this,
"SN deals 1 damage to target creature or player\$. " +
"Scry 1."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game, {
final MagicPermanent target ->
game.doAction(new MagicDealDamageAction(
new MagicDamage(event.getSource(),target,2)
));
game.doAction(new MagicGainAbilityAction(target, MagicAbility.CannotBlock));
game.addEvent(new MagicScryEvent(event));
} as MagicPermanentAction);
}
}
]

View File

@ -0,0 +1,10 @@
name=Spark Jolt
url=http://magiccards.info/ths/en/140.html
image=http://magiccards.info/scans/en/ths/140.jpg
value=4.641
removal=1
rarity=C
type=Instant
cost={R}
timing=removal
requires_groovy_code

View File

@ -1,38 +0,0 @@
def action = {
final MagicGame game, final MagicEvent event ->
event.processTargetCard(game,new MagicCardAction() {
public void doAction(final MagicCard card) {
game.doAction(new MagicReanimateAction(
card,
event.getPlayer()
));
}
});
} as MagicEventAction
def event = {
final MagicPermanent permanent ->
return new MagicEvent(
permanent,
MagicTargetChoice.TARGET_PERMANENT_CARD_CMC_LEQ_3_FROM_GRAVEYARD,
MagicGraveyardTargetPicker.PutOntoBattlefield,
action,
"Return target permanent card\$ with converted mana cost 3 or less " +
"from your graveyard to the battlefield."
);
}
[
new MagicWhenComesIntoPlayTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent, final MagicPayedCost payedCost) {
return event(permanent);
}
},
new MagicWhenAttacksTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPermanent attacker) {
return (permanent==attacker) ? event(permanent) : MagicEvent.NONE;
}
}
]

View File

@ -7,6 +7,7 @@ type=Creature
subtype=Giant
cost={4}{W}{W}
pt=6/6
ability=vigilance
timing=fmain
requires_groovy_code
ability=vigilance;\
enters effect PN may return target permanent card with converted mana cost 3 or less from your graveyard to the battlefield.;\
attacks effect PN may return target permanent card with converted mana cost 3 or less from your graveyard to the battlefield.
timing=main

View File

@ -80,7 +80,7 @@
act.card,
new MagicMayChoice(),
this,
"PN may return SN to your hand."
"PN may\$ return SN to your hand."
):
MagicEvent.NONE
}

View File

@ -0,0 +1,17 @@
[
new MagicWhenComesIntoPlayTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent, final MagicPayedCost payedCost) {
return new MagicEvent(
permanent,
this,
"Look at the top card of your library. You may put that card on the bottom of your library."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
game.addEvent(new MagicScryEvent(event));
}
}
]

View File

@ -0,0 +1,11 @@
name=Temple of Silence
url=http://magiccards.info/ths/en/227.html
image=http://magiccards.info/scans/en/ths/227.jpg
value=3.792
rarity=R
type=Land
mana=w3b3
ability=tap add mana {W} or {B};\
enters tapped
timing=tapland
requires_groovy_code

View File

@ -1,23 +0,0 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.POS_TARGET_CREATURE,
MagicFirstStrikeTargetPicker.create(),
this,
"Target creature\$ gets +2/+0 and gains first strike until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicChangeTurnPTAction(creature,2,0));
game.doAction(new MagicGainAbilityAction(creature,MagicAbility.FirstStrike));
}
});
}
}
]

View File

@ -5,5 +5,5 @@ value=3.139
rarity=C
type=Instant
cost={1}{R}
effect=Target creature gets +2/+0 and gains first strike until end of turn.
timing=pump
requires_groovy_code

View File

@ -1,24 +0,0 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack, final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.POS_TARGET_CREATURE,
MagicPumpTargetPicker.create(),
this,
"Target creature\$ gets +3/+0 and " +
"gains haste until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicChangeTurnPTAction(creature,3,0));
game.doAction(new MagicGainAbilityAction(creature,MagicAbility.Haste));
}
});
}
}
]

View File

@ -5,5 +5,5 @@ value=2.220
rarity=C
type=Instant
cost={1}{R}
effect=Target creature gets +3/+0 and gains haste until end of turn.
timing=fmain
requires_groovy_code

View File

@ -1,27 +0,0 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack, final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.POS_TARGET_CREATURE,
MagicFirstStrikeTargetPicker.create(),
this,
"Target creature\$ gets +2/+2 and " +
"gains first strike until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicChangeTurnPTAction(creature,2,2));
game.doAction(new MagicGainAbilityAction(
creature,
MagicAbility.FirstStrike
));
}
});
}
}
]

View File

@ -5,5 +5,5 @@ value=2.705
rarity=C
type=Instant
cost={1}{W}
effect=Target creature gets +2/+2 and gains first strike until end of turn.
timing=pump
requires_groovy_code

View File

@ -1,26 +0,0 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.TARGET_CREATURE_CARD_FROM_GRAVEYARD,
MagicGraveyardTargetPicker.PutOntoBattlefield,
this,
"Return target creature card\$ from your graveyard to the battlefield."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetCard(game,new MagicCardAction() {
public void doAction(final MagicCard targetCard) {
game.doAction(new MagicReanimateAction(
targetCard,
event.getPlayer()
));
}
});
}
}
]

View File

@ -5,5 +5,5 @@ value=4.330
rarity=U
type=Sorcery
cost={3}{B}
effect=Return target creature card from your graveyard to the battlefield.
timing=main
requires_groovy_code

View File

@ -34,6 +34,11 @@ FILENAME ~ /unimplementable/ {
next
}
FILENAME ~ /groovy/ {
comment[$1] = "groovy"
next
}
{
if (NF == 1) {
score[$1] = 1

331
src/magic/MurmurHash3.diff Normal file
View File

@ -0,0 +1,331 @@
--- MurmurHash3.java 2013-11-02 09:43:10.120309279 +0800
+++ src/magic/MurmurHash3.java 2013-11-02 09:46:15.064312827 +0800
@@ -1,11 +1,4 @@
-package org.infinispan.commons.hash;
-
-import net.jcip.annotations.Immutable;
-import net.jcip.annotations.ThreadSafe;
-
-import org.infinispan.commons.marshall.exts.NoStateExternalizer;
-import org.infinispan.commons.util.Util;
-import org.infinispan.commons.marshall.Ids;
+package magic;
import java.io.ObjectInput;
import java.nio.charset.Charset;
@@ -25,9 +18,7 @@
* @see <a href="http://en.wikipedia.org/wiki/MurmurHash">MurmurHash entry on Wikipedia</a>
* @since 5.0
*/
-@ThreadSafe
-@Immutable
-public class MurmurHash3 implements Hash {
+public class MurmurHash3 {
private static final Charset UTF8 = Charset.forName("UTF-8");
static class State {
@@ -92,143 +83,7 @@
* @param seed random value
* @return 128 bit hashed key, in an array containing two longs
*/
- public static long[] MurmurHash3_x64_128(final byte[] key, final int seed) {
- State state = new State();
-
- state.h1 = 0x9368e53c2f6af274L ^ seed;
- state.h2 = 0x586dcd208f7cd3fdL ^ seed;
-
- state.c1 = 0x87c37b91114253d5L;
- state.c2 = 0x4cf5ad432745937fL;
-
- for (int i = 0; i < key.length / 16; i++) {
- state.k1 = getblock(key, i * 2 * 8);
- state.k2 = getblock(key, (i * 2 + 1) * 8);
-
- bmix(state);
- }
-
- state.k1 = 0;
- state.k2 = 0;
-
- int tail = (key.length >>> 4) << 4;
-
- switch (key.length & 15) {
- case 15: state.k2 ^= (long) key[tail + 14] << 48;
- case 14: state.k2 ^= (long) key[tail + 13] << 40;
- case 13: state.k2 ^= (long) key[tail + 12] << 32;
- case 12: state.k2 ^= (long) key[tail + 11] << 24;
- case 11: state.k2 ^= (long) key[tail + 10] << 16;
- case 10: state.k2 ^= (long) key[tail + 9] << 8;
- case 9: state.k2 ^= key[tail + 8];
-
- case 8: state.k1 ^= (long) key[tail + 7] << 56;
- case 7: state.k1 ^= (long) key[tail + 6] << 48;
- case 6: state.k1 ^= (long) key[tail + 5] << 40;
- case 5: state.k1 ^= (long) key[tail + 4] << 32;
- case 4: state.k1 ^= (long) key[tail + 3] << 24;
- case 3: state.k1 ^= (long) key[tail + 2] << 16;
- case 2: state.k1 ^= (long) key[tail + 1] << 8;
- case 1: state.k1 ^= key[tail + 0];
- bmix(state);
- }
-
- state.h2 ^= key.length;
-
- state.h1 += state.h2;
- state.h2 += state.h1;
-
- state.h1 = fmix(state.h1);
- state.h2 = fmix(state.h2);
-
- state.h1 += state.h2;
- state.h2 += state.h1;
-
- return new long[] { state.h1, state.h2 };
- }
-
- /**
- * Hash a value using the x64 64 bit variant of MurmurHash3
- *
- * @param key value to hash
- * @param seed random value
- * @return 64 bit hashed key
- */
- public static long MurmurHash3_x64_64(final byte[] key, final int seed) {
- // Exactly the same as MurmurHash3_x64_128, except it only returns state.h1
- State state = new State();
-
- state.h1 = 0x9368e53c2f6af274L ^ seed;
- state.h2 = 0x586dcd208f7cd3fdL ^ seed;
-
- state.c1 = 0x87c37b91114253d5L;
- state.c2 = 0x4cf5ad432745937fL;
-
- for (int i = 0; i < key.length / 16; i++) {
- state.k1 = getblock(key, i * 2 * 8);
- state.k2 = getblock(key, (i * 2 + 1) * 8);
-
- bmix(state);
- }
-
- state.k1 = 0;
- state.k2 = 0;
-
- int tail = (key.length >>> 4) << 4;
-
- switch (key.length & 15) {
- case 15: state.k2 ^= (long) key[tail + 14] << 48;
- case 14: state.k2 ^= (long) key[tail + 13] << 40;
- case 13: state.k2 ^= (long) key[tail + 12] << 32;
- case 12: state.k2 ^= (long) key[tail + 11] << 24;
- case 11: state.k2 ^= (long) key[tail + 10] << 16;
- case 10: state.k2 ^= (long) key[tail + 9] << 8;
- case 9: state.k2 ^= key[tail + 8];
-
- case 8: state.k1 ^= (long) key[tail + 7] << 56;
- case 7: state.k1 ^= (long) key[tail + 6] << 48;
- case 6: state.k1 ^= (long) key[tail + 5] << 40;
- case 5: state.k1 ^= (long) key[tail + 4] << 32;
- case 4: state.k1 ^= (long) key[tail + 3] << 24;
- case 3: state.k1 ^= (long) key[tail + 2] << 16;
- case 2: state.k1 ^= (long) key[tail + 1] << 8;
- case 1: state.k1 ^= key[tail + 0];
- bmix(state);
- }
-
- state.h2 ^= key.length;
-
- state.h1 += state.h2;
- state.h2 += state.h1;
-
- state.h1 = fmix(state.h1);
- state.h2 = fmix(state.h2);
-
- state.h1 += state.h2;
- state.h2 += state.h1;
-
- return state.h1;
- }
-
- /**
- * Hash a value using the x64 32 bit variant of MurmurHash3
- *
- * @param key value to hash
- * @param seed random value
- * @return 32 bit hashed key
- */
- public static int MurmurHash3_x64_32(final byte[] key, final int seed) {
- return (int) (MurmurHash3_x64_64(key, seed) >>> 32);
- }
-
- /**
- * Hash a value using the x64 128 bit variant of MurmurHash3
- *
- * @param key value to hash
- * @param seed random value
- * @return 128 bit hashed key, in an array containing two longs
- */
- public static long[] MurmurHash3_x64_128(final long[] key, final int seed) {
+ private static State MurmurHash3_x64_128(final long[] key, final int seed) {
State state = new State();
state.h1 = 0x9368e53c2f6af274L ^ seed;
@@ -244,7 +99,7 @@
bmix(state);
}
- long tail = key[key.length - 1];
+ final long tail = key.length > 0 ? key[key.length - 1] : 0;
// Key length is odd
if ((key.length & 1) == 1) {
@@ -263,7 +118,7 @@
state.h1 += state.h2;
state.h2 += state.h1;
- return new long[] { state.h1, state.h2 };
+ return state;
}
/**
@@ -275,40 +130,7 @@
*/
public static long MurmurHash3_x64_64(final long[] key, final int seed) {
// Exactly the same as MurmurHash3_x64_128, except it only returns state.h1
- State state = new State();
-
- state.h1 = 0x9368e53c2f6af274L ^ seed;
- state.h2 = 0x586dcd208f7cd3fdL ^ seed;
-
- state.c1 = 0x87c37b91114253d5L;
- state.c2 = 0x4cf5ad432745937fL;
-
- for (int i = 0; i < key.length / 2; i++) {
- state.k1 = key[i * 2];
- state.k2 = key[i * 2 + 1];
-
- bmix(state);
- }
-
- long tail = key[key.length - 1];
-
- if (key.length % 2 != 0) {
- state.k1 ^= tail;
- bmix(state);
- }
-
- state.h2 ^= key.length * 8;
-
- state.h1 += state.h2;
- state.h2 += state.h1;
-
- state.h1 = fmix(state.h1);
- state.h2 = fmix(state.h2);
-
- state.h1 += state.h2;
- state.h2 += state.h1;
-
- return state.h1;
+ return MurmurHash3_x64_128(key, seed).h1;
}
/**
@@ -322,97 +144,13 @@
return (int) (MurmurHash3_x64_64(key, seed) >>> 32);
}
- @Override
- public int hash(byte[] payload) {
- return MurmurHash3_x64_32(payload, 9001);
- }
-
/**
* Hashes a byte array efficiently.
*
* @param payload a byte array to hash
* @return a hash code for the byte array
*/
- public static int hash(long[] payload) {
- return MurmurHash3_x64_32(payload, 9001);
- }
-
- @Override
- public int hash(int hashcode) {
- // Obtained by inlining MurmurHash3_x64_32(byte[], 9001) and removing all the unused code
- // (since we know the input is always 4 bytes and we only need 4 bytes of output)
- byte b0 = (byte) hashcode;
- byte b1 = (byte) (hashcode >>> 8);
- byte b2 = (byte) (hashcode >>> 16);
- byte b3 = (byte) (hashcode >>> 24);
- State state = new State();
-
- state.h1 = 0x9368e53c2f6af274L ^ 9001;
- state.h2 = 0x586dcd208f7cd3fdL ^ 9001;
-
- state.c1 = 0x87c37b91114253d5L;
- state.c2 = 0x4cf5ad432745937fL;
-
- state.k1 = 0;
- state.k2 = 0;
-
- state.k1 ^= (long) b3 << 24;
- state.k1 ^= (long) b2 << 16;
- state.k1 ^= (long) b1 << 8;
- state.k1 ^= b0;
- bmix(state);
-
- state.h2 ^= 4;
-
- state.h1 += state.h2;
- state.h2 += state.h1;
-
- state.h1 = fmix(state.h1);
- state.h2 = fmix(state.h2);
-
- state.h1 += state.h2;
- state.h2 += state.h1;
-
- return (int) (state.h1 >>> 32);
- }
-
- @Override
- public int hash(Object o) {
- if (o instanceof byte[])
- return hash((byte[]) o);
- else if (o instanceof long[])
- return hash((long[]) o);
- else if (o instanceof String)
- return hash(((String) o).getBytes(UTF8));
- else
- return hash(o.hashCode());
- }
-
- @Override
- public boolean equals(Object other) {
- return other != null && other.getClass() == getClass();
- }
-
- @Override
- public String toString() {
- return "MurmurHash3";
- }
-
- public static class Externalizer extends NoStateExternalizer<MurmurHash3> {
- @Override
- @SuppressWarnings("unchecked")
- public Set<Class<? extends MurmurHash3>> getTypeClasses() {
- return Util.<Class<? extends MurmurHash3>>asSet(MurmurHash3.class);
- }
-
- @Override
- public MurmurHash3 readObject(ObjectInput input) {
- return new MurmurHash3();
- }
-
- @Override
- public Integer getId() {
- return Ids.MURMURHASH_3;
- }
+ public static long hash(long[] payload) {
+ return MurmurHash3_x64_64(payload, 9001);
}
}

View File

@ -83,145 +83,7 @@ public class MurmurHash3 {
* @param seed random value
* @return 128 bit hashed key, in an array containing two longs
*/
@SuppressWarnings("fallthrough")
public static long[] MurmurHash3_x64_128(final byte[] key, final int seed) {
State state = new State();
state.h1 = 0x9368e53c2f6af274L ^ seed;
state.h2 = 0x586dcd208f7cd3fdL ^ seed;
state.c1 = 0x87c37b91114253d5L;
state.c2 = 0x4cf5ad432745937fL;
for (int i = 0; i < key.length / 16; i++) {
state.k1 = getblock(key, i * 2 * 8);
state.k2 = getblock(key, (i * 2 + 1) * 8);
bmix(state);
}
state.k1 = 0;
state.k2 = 0;
int tail = (key.length >>> 4) << 4;
switch (key.length & 15) {
case 15: state.k2 ^= (long) key[tail + 14] << 48;
case 14: state.k2 ^= (long) key[tail + 13] << 40;
case 13: state.k2 ^= (long) key[tail + 12] << 32;
case 12: state.k2 ^= (long) key[tail + 11] << 24;
case 11: state.k2 ^= (long) key[tail + 10] << 16;
case 10: state.k2 ^= (long) key[tail + 9] << 8;
case 9: state.k2 ^= key[tail + 8];
case 8: state.k1 ^= (long) key[tail + 7] << 56;
case 7: state.k1 ^= (long) key[tail + 6] << 48;
case 6: state.k1 ^= (long) key[tail + 5] << 40;
case 5: state.k1 ^= (long) key[tail + 4] << 32;
case 4: state.k1 ^= (long) key[tail + 3] << 24;
case 3: state.k1 ^= (long) key[tail + 2] << 16;
case 2: state.k1 ^= (long) key[tail + 1] << 8;
case 1: state.k1 ^= key[tail + 0];
bmix(state);
}
state.h2 ^= key.length;
state.h1 += state.h2;
state.h2 += state.h1;
state.h1 = fmix(state.h1);
state.h2 = fmix(state.h2);
state.h1 += state.h2;
state.h2 += state.h1;
return new long[] { state.h1, state.h2 };
}
/**
* Hash a value using the x64 64 bit variant of MurmurHash3
*
* @param key value to hash
* @param seed random value
* @return 64 bit hashed key
*/
@SuppressWarnings("fallthrough")
public static long MurmurHash3_x64_64(final byte[] key, final int seed) {
// Exactly the same as MurmurHash3_x64_128, except it only returns state.h1
State state = new State();
state.h1 = 0x9368e53c2f6af274L ^ seed;
state.h2 = 0x586dcd208f7cd3fdL ^ seed;
state.c1 = 0x87c37b91114253d5L;
state.c2 = 0x4cf5ad432745937fL;
for (int i = 0; i < key.length / 16; i++) {
state.k1 = getblock(key, i * 2 * 8);
state.k2 = getblock(key, (i * 2 + 1) * 8);
bmix(state);
}
state.k1 = 0;
state.k2 = 0;
int tail = (key.length >>> 4) << 4;
switch (key.length & 15) {
case 15: state.k2 ^= (long) key[tail + 14] << 48;
case 14: state.k2 ^= (long) key[tail + 13] << 40;
case 13: state.k2 ^= (long) key[tail + 12] << 32;
case 12: state.k2 ^= (long) key[tail + 11] << 24;
case 11: state.k2 ^= (long) key[tail + 10] << 16;
case 10: state.k2 ^= (long) key[tail + 9] << 8;
case 9: state.k2 ^= key[tail + 8];
case 8: state.k1 ^= (long) key[tail + 7] << 56;
case 7: state.k1 ^= (long) key[tail + 6] << 48;
case 6: state.k1 ^= (long) key[tail + 5] << 40;
case 5: state.k1 ^= (long) key[tail + 4] << 32;
case 4: state.k1 ^= (long) key[tail + 3] << 24;
case 3: state.k1 ^= (long) key[tail + 2] << 16;
case 2: state.k1 ^= (long) key[tail + 1] << 8;
case 1: state.k1 ^= key[tail + 0];
bmix(state);
}
state.h2 ^= key.length;
state.h1 += state.h2;
state.h2 += state.h1;
state.h1 = fmix(state.h1);
state.h2 = fmix(state.h2);
state.h1 += state.h2;
state.h2 += state.h1;
return state.h1;
}
/**
* Hash a value using the x64 32 bit variant of MurmurHash3
*
* @param key value to hash
* @param seed random value
* @return 32 bit hashed key
*/
public static int MurmurHash3_x64_32(final byte[] key, final int seed) {
return (int) (MurmurHash3_x64_64(key, seed) >>> 32);
}
/**
* Hash a value using the x64 128 bit variant of MurmurHash3
*
* @param key value to hash
* @param seed random value
* @return 128 bit hashed key, in an array containing two longs
*/
public static long[] MurmurHash3_x64_128(final long[] key, final int seed) {
private static State MurmurHash3_x64_128(final long[] key, final int seed) {
State state = new State();
state.h1 = 0x9368e53c2f6af274L ^ seed;
@ -256,7 +118,7 @@ public class MurmurHash3 {
state.h1 += state.h2;
state.h2 += state.h1;
return new long[] { state.h1, state.h2 };
return state;
}
/**
@ -268,40 +130,7 @@ public class MurmurHash3 {
*/
public static long MurmurHash3_x64_64(final long[] key, final int seed) {
// Exactly the same as MurmurHash3_x64_128, except it only returns state.h1
State state = new State();
state.h1 = 0x9368e53c2f6af274L ^ seed;
state.h2 = 0x586dcd208f7cd3fdL ^ seed;
state.c1 = 0x87c37b91114253d5L;
state.c2 = 0x4cf5ad432745937fL;
for (int i = 0; i < key.length / 2; i++) {
state.k1 = key[i * 2];
state.k2 = key[i * 2 + 1];
bmix(state);
}
final long tail = key.length > 0 ? key[key.length - 1] : 0;
if (key.length % 2 != 0) {
state.k1 ^= tail;
bmix(state);
}
state.h2 ^= key.length * 8;
state.h1 += state.h2;
state.h2 += state.h1;
state.h1 = fmix(state.h1);
state.h2 = fmix(state.h2);
state.h1 += state.h2;
state.h2 += state.h1;
return state.h1;
return MurmurHash3_x64_128(key, seed).h1;
}
/**
@ -315,11 +144,6 @@ public class MurmurHash3 {
return (int) (MurmurHash3_x64_64(key, seed) >>> 32);
}
public int hash(byte[] payload) {
return MurmurHash3_x64_32(payload, 9001);
}
/**
* Hashes a byte array efficiently.
*
@ -329,43 +153,4 @@ public class MurmurHash3 {
public static long hash(long[] payload) {
return MurmurHash3_x64_64(payload, 9001);
}
public int hash(int hashcode) {
// Obtained by inlining MurmurHash3_x64_32(byte[], 9001) and removing all the unused code
// (since we know the input is always 4 bytes and we only need 4 bytes of output)
byte b0 = (byte) hashcode;
byte b1 = (byte) (hashcode >>> 8);
byte b2 = (byte) (hashcode >>> 16);
byte b3 = (byte) (hashcode >>> 24);
State state = new State();
state.h1 = 0x9368e53c2f6af274L ^ 9001;
state.h2 = 0x586dcd208f7cd3fdL ^ 9001;
state.c1 = 0x87c37b91114253d5L;
state.c2 = 0x4cf5ad432745937fL;
state.k1 = 0;
state.k2 = 0;
state.k1 ^= (long) b3 << 24;
state.k1 ^= (long) b2 << 16;
state.k1 ^= (long) b1 << 8;
state.k1 ^= b0;
bmix(state);
state.h2 ^= 4;
state.h1 += state.h2;
state.h2 += state.h1;
state.h1 = fmix(state.h1);
state.h2 = fmix(state.h2);
state.h1 += state.h2;
state.h2 += state.h1;
return (int) (state.h1 >>> 32);
}
}

View File

@ -71,6 +71,12 @@ public class MagicCardList extends ArrayList<MagicCard> implements MagicCopyable
remove(index);
return card;
}
public MagicCard removeCardAtBottom() {
final MagicCard card=get(0);
remove(0);
return card;
}
public int removeCard(final MagicCard card) {
final int index=indexOf(card);

View File

@ -0,0 +1,29 @@
package magic.model.action;
import magic.model.MagicCard;
import magic.model.MagicCardList;
import magic.model.MagicGame;
import magic.model.MagicPlayer;
public class MagicScryAction extends MagicAction {
private final MagicPlayer player;
private MagicCard card;
public MagicScryAction(final MagicPlayer aPlayer) {
player = aPlayer;
}
@Override
public void doAction(final MagicGame game) {
card = player.getLibrary().removeCardAtTop();
player.getLibrary().addToBottom(card);
}
@Override
public void undoAction(final MagicGame game) {
player.getLibrary().removeCardAtBottom();
player.getLibrary().addToTop(card);
}
}

View File

@ -0,0 +1,55 @@
package magic.model.choice;
import magic.data.GeneralConfig;
import magic.model.MagicGame;
import magic.model.MagicCard;
import magic.model.MagicCardList;
import magic.model.MagicPlayer;
import magic.model.MagicSource;
import magic.model.event.MagicEvent;
import magic.ui.GameController;
import magic.ui.UndoClickedException;
import magic.ui.choice.MayChoicePanel;
import java.util.concurrent.Callable;
public class MagicScryChoice extends MagicMayChoice {
public MagicScryChoice() {
super("Put this card on the bottom of your library?");
}
@Override
public Object[] getPlayerChoiceResults(
final GameController controller,
final MagicGame game,
final MagicPlayer player,
final MagicSource source) throws UndoClickedException {
final Object[] choiceResults=new Object[1];
choiceResults[0]=NO_CHOICE;
final MagicCard topCard = player.getLibrary().getCardAtTop();
if (topCard == MagicCard.NONE) {
return choiceResults;
}
final MagicCardList cards = new MagicCardList();
cards.add(topCard);
controller.showCards(cards);
controller.disableActionButton(false);
final MayChoicePanel choicePanel = controller.waitForInput(new Callable<MayChoicePanel>() {
public MayChoicePanel call() {
return new MayChoicePanel(controller,source,getDescription());
}
});
controller.showCards(new MagicCardList());
if (choicePanel.isYesClicked()) {
choiceResults[0]=YES_CHOICE;
}
return choiceResults;
}
}

View File

@ -37,6 +37,7 @@ import magic.model.action.MagicGainAbilityAction;
import magic.model.action.MagicMillLibraryAction;
import magic.model.action.MagicRemoveCardAction;
import magic.model.action.MagicMoveCardAction;
import magic.model.action.MagicReanimateAction;
import magic.model.stack.MagicCardOnStack;
import magic.model.target.MagicTarget;
import magic.model.target.MagicTargetFilter;
@ -382,6 +383,66 @@ public enum MagicRuleEventAction {
};
}
},
GainPumpChosen(
"(?<choice>[^\\.]*) gets (?<pt>[0-9+]+/[0-9+]+) and gains (?<ability>[^\\.]*) until end of turn.",
MagicTargetHint.Positive
) {
public MagicEventAction getAction(final String rule) {
final Matcher matcher = matched(rule);
final MagicAbility ability = MagicAbility.getAbility(matcher.group("ability"));
final String[] pt = matcher.group("pt").replace("+","").split("/");
final int power = Integer.parseInt(pt[0]);
final int toughness = Integer.parseInt(pt[1]);
return new MagicEventAction() {
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicChangeTurnPTAction(creature,power,toughness));
game.doAction(new MagicGainAbilityAction(creature,ability));
}
});
}
};
}
public MagicTiming getTiming(final String rule) {
final Matcher matcher = matched(rule);
final MagicAbility ability = MagicAbility.getAbility(matcher.group("ability"));
switch (ability) {
case Haste:
case Vigilance:
return MagicTiming.FirstMain;
case FirstStrike:
case DoubleStrike:
return MagicTiming.Block;
default:
return MagicTiming.Pump;
}
}
public MagicTargetPicker<?> getPicker(final String rule) {
final Matcher matcher = matched(rule);
final MagicAbility ability = MagicAbility.getAbility(matcher.group("ability"));
switch (ability) {
case Deathtouch:
return MagicDeathtouchTargetPicker.getInstance();
case Lifelink:
return MagicLifelinkTargetPicker.create();
case FirstStrike:
case DoubleStrike:
return MagicFirstStrikeTargetPicker.create();
case Haste:
return MagicHasteTargetPicker.create();
case Indestructible:
return MagicIndestructibleTargetPicker.create();
case Trample:
return MagicTrampleTargetPicker.create();
case Flying:
return MagicFlyingTargetPicker.create();
default:
return MagicPumpTargetPicker.create();
}
}
},
PumpGroup(
"(?<group>[^\\.]*) get (?<pt>[0-9+]+/[0-9+]+) until end of turn.",
MagicTiming.Pump,
@ -749,6 +810,26 @@ public enum MagicRuleEventAction {
}
}
),
Reanimate(
"return (?<choice>[^\\.]*) to the battlefield.",
MagicTargetHint.None,
MagicGraveyardTargetPicker.PutOntoBattlefield,
MagicTiming.Pump,
"Return",
new MagicEventAction() {
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetCard(game,new MagicCardAction() {
public void doAction(final MagicCard card) {
game.doAction(new MagicReanimateAction(
card,
event.getPlayer()
));
}
});
}
}
),
Tap(
"tap (?<choice>[^\\.]*).",
MagicTargetHint.Negative,

View File

@ -0,0 +1,38 @@
package magic.model.event;
import magic.model.MagicGame;
import magic.model.MagicPlayer;
import magic.model.MagicSource;
import magic.model.MagicLocationType;
import magic.model.MagicPermanent;
import magic.model.MagicCard;
import magic.model.choice.MagicScryChoice;
import magic.model.action.MagicScryAction;
public class MagicScryEvent extends MagicEvent {
public MagicScryEvent(final MagicEvent event) {
this(event.getSource(), event.getPlayer());
}
public MagicScryEvent(final MagicSource source, final MagicPlayer player) {
super(
source,
player,
new MagicScryChoice(),
EventAction,
""
);
}
private static final MagicEventAction EventAction = new MagicEventAction() {
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
if (event.isYes()) {
final MagicPlayer p = event.getPlayer();
game.logAppendMessage(p, p + " moves a card from top of his or her library to the bottom.");
game.doAction(new MagicScryAction(p));
}
}
};
}

View File

@ -907,6 +907,15 @@ public interface MagicTargetFilter<T extends MagicTarget> {
return targetType==MagicTargetType.Graveyard;
}
};
MagicCardFilterImpl TARGET_CREATURE_CARD_CMC_LEQ_2_FROM_GRAVEYARD=new MagicCardFilterImpl() {
public boolean accept(final MagicGame game,final MagicPlayer player,final MagicCard target) {
return target.getConvertedCost() <= 2 && target.hasType(MagicType.Creature);
}
public boolean acceptType(final MagicTargetType targetType) {
return targetType==MagicTargetType.Graveyard;
}
};
MagicPermanentFilterImpl TARGET_NONLAND_PERMANENT_CMC_LEQ_3 = new MagicTargetFilter.MagicCMCPermanentFilter(
MagicTargetFilter.TARGET_NONLAND_PERMANENT,

View File

@ -144,6 +144,7 @@ public class MagicTargetFilterFactory {
single.put("non-Vampire creature you control", TARGET_NON_VAMPIRE_YOU_CONTROL);
single.put("permanent card from your graveyard", TARGET_PERMANENT_CARD_FROM_GRAVEYARD);
single.put("permanent card with converted mana cost 3 or less from your graveyard", TARGET_PERMANENT_CARD_CMC_LEQ_3_FROM_GRAVEYARD);
single.put("creature card with converted mana cost 2 or less from your graveyard", TARGET_CREATURE_CARD_CMC_LEQ_2_FROM_GRAVEYARD);
single.put("unblocked attacking creature you control", UNBLOCKED_ATTACKING_CREATURE_YOU_CONTROL);
single.put("attacking creature you control", TARGET_ATTACKING_CREATURE_YOU_CONTROL);
single.put("Vampire, Werewolf, or Zombie", TARGET_VAMPIRE_WEREWOLF_OR_ZOMBIE);

View File

@ -29,11 +29,12 @@ class TestPlaneswalker extends TestGameBuilder {
P.setLife(20);
addToLibrary(P, "Plains", 10);
createPermanent(game,P,"Rupture Spire",false,8);
createPermanent(game,P,"Rupture Spire",false,10);
createPermanent(game,P,"Grizzly Bears",false,1);
addToHand(P, "Ajani, Caller of the Pride", 1);
addToHand(P, "Sarkhan Vol", 1);
addToHand(P, "Tamiyo, the Moon Sage", 1);
addToHand(P, "Burst Lightning", 1);
addToHand(P, "Elspeth Tirel", 1);
addToHand(P, "Venser, the Sojourner", 1);
addToHand(P, "Vraska the Unseen", 1);

View File

@ -0,0 +1,49 @@
package magic.test;
import magic.model.MagicDuel;
import magic.model.MagicGame;
import magic.model.MagicPlayer;
import magic.model.MagicPlayerDefinition;
import magic.model.MagicPlayerProfile;
import magic.model.phase.MagicMainPhase;
class TestScry extends TestGameBuilder {
public MagicGame getGame() {
final MagicDuel duel=new MagicDuel();
duel.setDifficulty(6);
final MagicPlayerProfile profile=new MagicPlayerProfile("bgruw");
final MagicPlayerDefinition player1=new MagicPlayerDefinition("Player",false,profile,15);
final MagicPlayerDefinition player2=new MagicPlayerDefinition("Computer",true,profile,14);
duel.setPlayers(new MagicPlayerDefinition[]{player1,player2});
duel.setStartPlayer(0);
final MagicGame game=duel.nextGame(true);
game.setPhase(MagicMainPhase.getFirstInstance());
final MagicPlayer player=game.getPlayer(0);
final MagicPlayer opponent=game.getPlayer(1);
MagicPlayer P = player;
P.setLife(6);
addToLibrary(P, "Forest", 20);
addToLibrary(P, "Island", 20);
addToLibrary(P, "Entreat the Angels", 20);
addToLibrary(P, "Sliver Overlord", 1);
addToGraveyard(P, "Ink-Eyes, Servant of Oni", 3);
createPermanent(game,P, "Rupture Spire", false, 10);
addToHand(P, "Spark Jolt", 1);
addToHand(P, "Temple of Silence", 1);
P = opponent;
P.setLife(6);
addToLibrary(P, "Mountain", 20);
createPermanent(game,P,"Rupture Spire",false,9);
createPermanent(game,P, "Grizzly Bears", false, 1);
addToHand(P, "Trained Jackal", 1);
addToGraveyard(P, "Ink-Eyes, Servant of Oni", 1);
return game;
}
}

View File

@ -475,7 +475,11 @@ public class GameController implements ILogBookListener {
} else {
game.gotoLastUndoPoint();
}
gamePanel.getLogBookViewer().update();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
gamePanel.getLogBookViewer().update();
}
});
}
public void haltGame() {