Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package org.mage.test.cards.single.mat;

import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;

/**
* @author jimga150
*/
public class TyvarTheBellicoseTest extends CardTestPlayerBase {

/**
* {@link mage.cards.t.TyvarTheBellicose}
* Tyvar the Bellicose
* {2}{B}{G}
* Legendary Creature — Elf Warrior
* Whenever one or more Elves you control attack, they gain deathtouch until end of turn.
* Each creature you control has “Whenever a mana ability of this creature resolves, put a number of +1/+1
* counters on it equal to the amount of mana this creature produced. This ability triggers only once each turn.”
* 5/4
*/
private static final String tyvar = "Tyvar the Bellicose";

/**
* {@link mage.cards.e.EnduringVitality}
* <p>
* Creatures you control have “{T}: Add one mana of any color.”
* 3/3
*/
private static final String enduringvitality = "Enduring Vitality";

/**
* {@link mage.cards.l.LlanowarElves}
* <p>
* {T}: Add {G}.
* 1/1
*/
private static final String llanowarelves = "Llanowar Elves";

/**
* {@link mage.cards.a.AkkiDrillmaster}
* <p>
* {T}: Target creature gains haste until end of turn.
* 2/2
*/
private static final String akkidrillmaster = "Akki Drillmaster";

private static final String memnite = "Memnite"; // vanilla 1/1

@Test
public void testPrintedAbility() {

addCard(Zone.BATTLEFIELD, playerA, llanowarelves);
addCard(Zone.BATTLEFIELD, playerA, tyvar);

activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}");

setStrictChooseMode(true);
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();

assertPowerToughness(playerA, llanowarelves, 2, 2);
}

@Test
public void testNonManaAbility() {

addCard(Zone.BATTLEFIELD, playerA, akkidrillmaster);
addCard(Zone.BATTLEFIELD, playerA, tyvar);

activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}");
addTarget(playerA, tyvar);

setStrictChooseMode(true);
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();

assertPowerToughness(playerA, akkidrillmaster, 2, 2);
}

@Test
public void testGainedAbility() {

addCard(Zone.BATTLEFIELD, playerA, enduringvitality);
addCard(Zone.BATTLEFIELD, playerA, memnite);
addCard(Zone.BATTLEFIELD, playerA, tyvar);

activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}");
setChoice(playerA, "Green");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}");
setChoice(playerA, "Green");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}");
setChoice(playerA, "Green");

setStrictChooseMode(true);
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();

assertPowerToughness(playerA, enduringvitality, 4, 4);
assertPowerToughness(playerA, memnite, 2, 2);
assertPowerToughness(playerA, tyvar, 6, 5);
}
}
5 changes: 5 additions & 0 deletions Mage/src/main/java/mage/abilities/Ability.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public interface Ability extends Controllable, Serializable {
*/
void newId();

/**
* Assigns a new {@link java.util.UUID} based on the input String. Will always generate the same UUID from a given String.
*/
void newDeterministicId(String string);

/**
* Assigns a new {@link java.util.UUID}
*/
Expand Down
12 changes: 12 additions & 0 deletions Mage/src/main/java/mage/abilities/AbilityImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,18 @@ public void newId() {
}
}

@Override
public void newDeterministicId(String string) {
if (!(this instanceof MageSingleton)) {
this.id = UUID.nameUUIDFromBytes(string.getBytes());
}
getEffects().newId();

for (Ability sub : getSubAbilities()) {
sub.newId();
}
}

@Override
public void newOriginalId() {
this.id = UUID.randomUUID();
Expand Down
14 changes: 13 additions & 1 deletion Mage/src/main/java/mage/game/permanent/PermanentImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,19 @@ public Ability addAbility(Ability ability, UUID sourceId, Game game, boolean fro
// other abilities -- any amount of instances
if (!abilities.containsKey(ability.getId())) {
Ability copyAbility = ability.copy();
copyAbility.newId(); // needed so that source can get an ability multiple times (e.g. Raging Ravine)

// needed so that source can get an ability multiple times (e.g. Raging Ravine)
// Generate deterministically from sourceId, ability ID, and Permanent's ID
// so that future calls to addAbility will always give the resulting ability the same ID
String seedString = getId().toString();
if (sourceId != null) {
seedString += sourceId.toString();
}
if (ability.getId() != null) {
seedString += ability.getId().toString();
}
copyAbility.newDeterministicId(seedString);

copyAbility.setControllerId(controllerId);
copyAbility.setSourceId(objectId);
// triggered abilities must be added to the state().triggers
Expand Down
7 changes: 7 additions & 0 deletions Mage/src/main/java/mage/game/stack/StackAbility.java
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,13 @@ public void newId() {
}
}

@Override
public void newDeterministicId(String string) {
if (!(this instanceof MageSingleton)) {
this.ability.newDeterministicId(string);
}
}

@Override
public void newOriginalId() {
}
Expand Down