use of mage.abilities.mana.ManaOptions in project mage by magefree.
the class PlayerImpl method getPlayable.
/**
* Returns a list of all available spells and abilities the player can
* currently cast/activate with his available resources.
* Without target validation.
*
* @param game
* @param hidden also from hidden objects (e.g. turned face down cards ?)
* @param fromZone of objects from which zone (ALL = from all zones)
* @param hideDuplicatedAbilities if equal abilities exist return only the
* first instance
* @return
*/
public List<ActivatedAbility> getPlayable(Game game, boolean hidden, Zone fromZone, boolean hideDuplicatedAbilities) {
List<ActivatedAbility> playable = new ArrayList<>();
if (shouldSkipGettingPlayable(game)) {
return playable;
}
boolean previousState = game.inCheckPlayableState();
game.setCheckPlayableState(true);
try {
// get available mana options (mana pool and conditional mana added (but conditional still lose condition))
ManaOptions availableMana = getManaAvailable(game);
boolean fromAll = fromZone.equals(Zone.ALL);
if (hidden && (fromAll || fromZone == Zone.HAND)) {
for (Card card : hand.getCards(game)) {
for (Ability ability : card.getAbilities(game)) {
// gets this activated ability from hand? (Morph?)
if (ability.getZone().match(Zone.HAND)) {
boolean isPlaySpell = (ability instanceof SpellAbility);
boolean isPlayLand = (ability instanceof PlayLandAbility);
// play land restrictions
if (isPlayLand && game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, ability.getSourceId(), ability, this.getId()), ability, game, true)) {
continue;
}
// cast spell restrictions 1
GameEvent castEvent = GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, ability.getId(), ability, this.getId());
castEvent.setZone(fromZone);
if (isPlaySpell && game.getContinuousEffects().preventedByRuleModification(castEvent, ability, game, true)) {
continue;
}
// cast spell restrictions 2
GameEvent castLateEvent = GameEvent.getEvent(GameEvent.EventType.CAST_SPELL_LATE, ability.getId(), ability, this.getId());
castLateEvent.setZone(fromZone);
if (isPlaySpell && game.getContinuousEffects().preventedByRuleModification(castLateEvent, ability, game, true)) {
continue;
}
ActivatedAbility playAbility = findActivatedAbilityFromPlayable(card, availableMana, ability, game);
if (playAbility != null && !playable.contains(playAbility)) {
playable.add(playAbility);
}
}
}
}
}
if (fromAll || fromZone == Zone.GRAVEYARD) {
for (UUID playerId : game.getState().getPlayersInRange(getId(), game)) {
Player player = game.getPlayer(playerId);
if (player == null) {
continue;
}
for (Card card : player.getGraveyard().getCards(game)) {
getPlayableFromObjectAll(game, Zone.GRAVEYARD, card, availableMana, playable);
}
}
}
if (fromAll || fromZone == Zone.EXILED) {
for (ExileZone exile : game.getExile().getExileZones()) {
for (Card card : exile.getCards(game)) {
getPlayableFromObjectAll(game, Zone.EXILED, card, availableMana, playable);
}
}
}
// check to play revealed cards
if (fromAll) {
for (Cards revealedCards : game.getState().getRevealed().values()) {
for (Card card : revealedCards.getCards(game)) {
// revealed cards can be from any zones
getPlayableFromObjectAll(game, game.getState().getZone(card.getId()), card, availableMana, playable);
}
}
}
// outside cards
if (fromAll || fromZone == Zone.OUTSIDE) {
// companion cards
for (Cards companionCards : game.getState().getCompanion().values()) {
for (Card card : companionCards.getCards(game)) {
getPlayableFromObjectAll(game, Zone.OUTSIDE, card, availableMana, playable);
}
}
// sideboard cards (example: Wish)
for (UUID sideboardCardId : this.getSideboard()) {
Card sideboardCard = game.getCard(sideboardCardId);
if (sideboardCard != null) {
getPlayableFromObjectAll(game, Zone.OUTSIDE, sideboardCard, availableMana, playable);
}
}
}
// check if it's possible to play the top card of a library
if (fromAll || fromZone == Zone.LIBRARY) {
for (UUID playerInRangeId : game.getState().getPlayersInRange(getId(), game)) {
Player player = game.getPlayer(playerInRangeId);
if (player != null && player.getLibrary().hasCards()) {
Card card = player.getLibrary().getFromTop(game);
if (card != null) {
getPlayableFromObjectAll(game, Zone.LIBRARY, card, availableMana, playable);
}
}
}
}
// AI games: computer can see and play cards from opponent's hand without reveal
if (fromAll || fromZone == Zone.HAND) {
for (UUID playerInRangeId : game.getState().getPlayersInRange(getId(), game)) {
Player player = game.getPlayer(playerInRangeId);
if (player != null && !player.getHand().isEmpty()) {
for (Card card : player.getHand().getCards(game)) {
if (card != null) {
getPlayableFromObjectAll(game, Zone.HAND, card, availableMana, playable);
}
}
}
}
}
// eliminate duplicate activated abilities (uses for AI plays)
Map<String, ActivatedAbility> activatedUnique = new HashMap<>();
List<ActivatedAbility> activatedAll = new ArrayList<>();
// activated abilities from battlefield objects
if (fromAll || fromZone == Zone.BATTLEFIELD) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents()) {
boolean canUseActivated = permanent.canUseActivatedAbilities(game);
List<ActivatedAbility> currentPlayable = new ArrayList<>();
getPlayableFromObjectAll(game, Zone.BATTLEFIELD, permanent, availableMana, currentPlayable);
for (ActivatedAbility ability : currentPlayable) {
if (ability instanceof SpecialAction || canUseActivated) {
activatedUnique.putIfAbsent(ability.toString(), ability);
activatedAll.add(ability);
}
}
}
}
// activated abilities from stack objects
if (fromAll || fromZone == Zone.STACK) {
for (StackObject stackObject : game.getState().getStack()) {
List<ActivatedAbility> currentPlayable = new ArrayList<>();
getPlayableFromObjectAll(game, Zone.STACK, stackObject, availableMana, currentPlayable);
for (ActivatedAbility ability : currentPlayable) {
activatedUnique.put(ability.toString(), ability);
activatedAll.add(ability);
}
}
}
// activated abilities from objects in the command zone (emblems or commanders)
if (fromAll || fromZone == Zone.COMMAND) {
for (CommandObject commandObject : game.getState().getCommand()) {
List<ActivatedAbility> currentPlayable = new ArrayList<>();
getPlayableFromObjectAll(game, Zone.COMMAND, commandObject, availableMana, currentPlayable);
for (ActivatedAbility ability : currentPlayable) {
activatedUnique.put(ability.toString(), ability);
activatedAll.add(ability);
}
}
}
if (hideDuplicatedAbilities) {
playable.addAll(activatedUnique.values());
} else {
playable.addAll(activatedAll);
}
} finally {
game.setCheckPlayableState(previousState);
}
return playable;
}
use of mage.abilities.mana.ManaOptions in project mage by magefree.
the class ManaOptionsTest method testSungrassPrairie.
@Test
public void testSungrassPrairie() {
// {1}, {T}: Add {G}{W}.
addCard(Zone.BATTLEFIELD, playerA, "Sungrass Prairie", 1);
// {T}: Add one mana of any color to your mana pool.
addCard(Zone.BATTLEFIELD, playerA, "Alloy Myr", 2);
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
execute();
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
assertDuplicatedManaOptions(manaOptions);
Assert.assertEquals("mana variations don't fit", 2, manaOptions.size());
assertManaOptions("{G}{W}{Any}", manaOptions);
assertManaOptions("{Any}{Any}", manaOptions);
}
use of mage.abilities.mana.ManaOptions in project mage by magefree.
the class ManaOptionsTest method testOrochiLeafcaller.
// Orochi Leafcaller
// {G}: Add one mana of any color.
@Test
public void testOrochiLeafcaller() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
addCard(Zone.BATTLEFIELD, playerA, "Orochi Leafcaller", 1);
setStopAt(1, PhaseStep.UPKEEP);
execute();
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
assertDuplicatedManaOptions(manaOptions);
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
assertManaOptions("{W}{W}{Any}{Any}", manaOptions);
}
use of mage.abilities.mana.ManaOptions in project mage by magefree.
the class ManaOptionsTest method testNykthos4b.
// Nykthos, Shrine to Nyx
// {T}: Add {C}.
// {2}, {T}: Choose a color. Add an amount of mana of that color equal to your devotion to that color. (Your devotion to a color is the number of mana symbols of that color in the mana costs of permanents you control.)
@Test
public void testNykthos4b() {
// If a land is tapped for two or more mana, it produces {C} instead of any other type and amount.
// Each spell a player casts costs {1} more to cast for each other spell that player has cast this turn.
addCard(Zone.BATTLEFIELD, playerA, "Damping Sphere", 1);
addCard(Zone.BATTLEFIELD, playerA, "Sedge Scorpion", 4);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
addCard(Zone.BATTLEFIELD, playerA, "Nykthos, Shrine to Nyx", 1);
setStopAt(1, PhaseStep.UPKEEP);
execute();
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
assertDuplicatedManaOptions(manaOptions);
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
assertManaOptions("{C}{G}{G}{G}", manaOptions);
}
use of mage.abilities.mana.ManaOptions in project mage by magefree.
the class ManaOptionsTest method testNykthos5.
@Test
public void testNykthos5() {
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 2);
addCard(Zone.BATTLEFIELD, playerA, "Sedge Scorpion", 4);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
addCard(Zone.BATTLEFIELD, playerA, "Nykthos, Shrine to Nyx", 1);
setStopAt(1, PhaseStep.UPKEEP);
execute();
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
assertDuplicatedManaOptions(manaOptions);
Assert.assertEquals("mana variations don't fit", 3, manaOptions.size());
assertManaOptions("{G}{W}{W}", manaOptions);
assertManaOptions("{C}{G}{G}{G}", manaOptions);
assertManaOptions("{G}{G}{G}{G}{G}", manaOptions);
}
Aggregations