use of mage.game.stack.StackObject 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.game.stack.StackObject in project mage by magefree.
the class EmissaryOfGrudgesEffect method apply.
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget());
if (controller == null || stackObject == null || !stackObject.isControlledBy(ChooseSecretOpponentEffect.getChosenPlayer(source, game))) {
return false;
}
// find if it targets you or a permanent you control
boolean targetsYouOrAPermanentYouControl = false;
for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) {
Mode mode = stackObject.getStackAbility().getModes().get(modeId);
for (Target target : mode.getTargets()) {
for (UUID targetId : target.getTargets()) {
if (source.isControlledBy(targetId)) {
targetsYouOrAPermanentYouControl = true;
}
Permanent permanent = game.getPermanent(targetId);
if (permanent != null && source.isControlledBy(permanent.getControllerId())) {
targetsYouOrAPermanentYouControl = true;
}
}
}
}
if (targetsYouOrAPermanentYouControl) {
return stackObject.chooseNewTargets(game, source.getControllerId(), false, false, null);
}
return false;
}
use of mage.game.stack.StackObject in project mage by magefree.
the class EnchantmentAlterationEffect method apply.
@Override
public boolean apply(ObjectSourcePlayer<MageItem> input, Game game) {
StackObject source = game.getStack().getStackObject(input.getSourceId());
Permanent auraIsAttachedToThisPermanent = null;
Permanent newPermanentToAttachAuraTo;
if (source != null) {
if (source.getStackAbility().getTargets().isEmpty() || source.getStackAbility().getTargets().get(0).getTargets().isEmpty()) {
return true;
}
Permanent auraPermanent = game.getPermanent(// targeted aura enchanting land or creature
source.getStackAbility().getTargets().get(0).getTargets().get(0));
if (auraPermanent != null) {
auraIsAttachedToThisPermanent = game.getPermanent(auraPermanent.getAttachedTo());
}
if (auraIsAttachedToThisPermanent == null) {
// the original permanent the aura is attached to
return false;
}
// the new target creature or land to enchant
newPermanentToAttachAuraTo = game.getPermanent(input.getObject().getId());
if (newPermanentToAttachAuraTo == auraIsAttachedToThisPermanent) {
// must be another permanent
return false;
}
if (auraIsAttachedToThisPermanent.isCreature(game) && newPermanentToAttachAuraTo.isCreature(game)) {
return true;
}
if (auraIsAttachedToThisPermanent.isLand(game) && newPermanentToAttachAuraTo.isLand(game)) {
return true;
}
return false;
}
return true;
}
use of mage.game.stack.StackObject in project mage by magefree.
the class GuardianBeastConditionalEffect method applies.
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
Permanent targetPermanent = game.getPermanent(event.getTargetId());
if (permanent == null || permanent.isTapped() || targetPermanent == null) {
return false;
}
if (!Objects.equals(targetPermanent.getControllerId(), permanent.getControllerId())) {
return false;
}
StackObject spell = game.getStack().getStackObject(event.getSourceId());
if (event.getType() == GameEvent.EventType.GAIN_CONTROL || ((event.getType() == GameEvent.EventType.ATTACH || event.getType() == GameEvent.EventType.TARGET) && spell != null && spell.isEnchantment(game) && spell.hasSubtype(SubType.AURA, game))) {
for (Permanent perm : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_ARTIFACTS_NON_CREATURE, source.getControllerId(), game)) {
if (perm != null && Objects.equals(perm.getId(), targetPermanent.getId()) && !perm.isCreature(game)) {
return true;
}
}
}
return false;
}
use of mage.game.stack.StackObject in project mage by magefree.
the class InvasiveSurgeryEffect method apply.
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
String cardName = "";
UUID spellController = null;
if (source.getTargets().get(0) instanceof TargetSpell) {
UUID objectId = source.getFirstTarget();
StackObject stackObject = game.getStack().getStackObject(objectId);
if (stackObject != null) {
MageObject targetObject = game.getObject(stackObject.getSourceId());
if (targetObject instanceof Card) {
cardName = targetObject.getName();
}
spellController = stackObject.getControllerId();
game.getStack().counter(objectId, source, game);
}
}
// Check the Delirium condition
if (!DeliriumCondition.instance.apply(game, source)) {
return true;
}
return this.applySearchAndExile(game, source, cardName, spellController);
}
Aggregations