use of mage.game.stack.StackObject in project mage by magefree.
the class SharkTyphoonTriggeredAbility method checkTrigger.
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!event.getSourceId().equals(this.getSourceId())) {
return false;
}
StackObject object = game.getStack().getStackObject(event.getSourceId());
if (object == null || !(object.getStackAbility() instanceof CyclingAbility)) {
return false;
}
this.getEffects().clear();
this.addEffect(new CreateTokenEffect(new SharkToken(object.getStackAbility().getManaCostsToPay().getX())));
return true;
}
use of mage.game.stack.StackObject in project mage by magefree.
the class SwiftSilenceEffect method apply.
@Override
public boolean apply(Game game, Ability source) {
List<Spell> spellsToCounter = new LinkedList<>();
for (StackObject stackObject : game.getStack()) {
if (stackObject instanceof Spell && !stackObject.getId().equals(source.getSourceObject(game).getId())) {
spellsToCounter.add((Spell) stackObject);
}
}
int toDraw = 0;
for (Spell spell : spellsToCounter) {
if (game.getStack().counter(spell.getId(), source, game)) {
toDraw++;
}
}
Player controller = game.getPlayer(source.getControllerId());
if (toDraw > 0 && controller != null) {
controller.drawCards(toDraw, source, game);
}
return true;
}
use of mage.game.stack.StackObject in project mage by magefree.
the class WildMagicSorcererWatcher method apply.
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
for (StackObject stackObject : game.getStack()) {
// only spells cast, so no copies of spells
if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.isControlledBy(source.getControllerId())) {
Spell spell = (Spell) stackObject;
WildMagicSorcererWatcher watcher = game.getState().getWatcher(WildMagicSorcererWatcher.class);
if (watcher != null && FirstSpellCastFromExileEachTurnCondition.instance.apply(game, source)) {
game.getState().addOtherAbility(spell.getCard(), cascadeAbility);
}
}
}
return true;
}
return false;
}
use of mage.game.stack.StackObject in project mage by magefree.
the class TestPlayer method chooseTarget.
@Override
public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) {
UUID abilityControllerId = computerPlayer.getId();
if (target.getTargetController() != null && target.getAbilityController() != null) {
abilityControllerId = target.getAbilityController();
}
UUID sourceId = source != null ? source.getSourceId() : null;
assertAliasSupportInTargets(true);
if (!targets.isEmpty()) {
// skip targets
if (targets.get(0).equals(TARGET_SKIP)) {
Assert.assertTrue("found skip target, but it require more targets, needs " + (target.getMinNumberOfTargets() - target.getTargets().size()) + " more", target.getTargets().size() >= target.getMinNumberOfTargets());
targets.remove(0);
return true;
}
// control miss implementation
Set<Zone> targetCardZonesChecked = new HashSet<>();
// player
if (target.getOriginalTarget() instanceof TargetPlayer || target.getOriginalTarget() instanceof TargetAnyTarget || target.getOriginalTarget() instanceof TargetCreatureOrPlayer || target.getOriginalTarget() instanceof TargetPermanentOrPlayer || target.getOriginalTarget() instanceof TargetDefender) {
for (String targetDefinition : targets) {
if (!targetDefinition.startsWith("targetPlayer=")) {
continue;
}
checkTargetDefinitionMarksSupport(target, targetDefinition, "=");
String playerName = targetDefinition.substring(targetDefinition.indexOf("targetPlayer=") + 13);
for (Player player : game.getPlayers().values()) {
if (player.getName().equals(playerName) && target.canTarget(abilityControllerId, player.getId(), source, game)) {
target.addTarget(player.getId(), source, game);
targets.remove(targetDefinition);
return true;
}
}
}
}
// permanent in battlefield
if ((target.getOriginalTarget() instanceof TargetPermanent) || (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) || (target.getOriginalTarget() instanceof TargetAnyTarget) || (target.getOriginalTarget() instanceof TargetCreatureOrPlayer) || (target.getOriginalTarget() instanceof TargetDefender) || (target.getOriginalTarget() instanceof TargetPermanentOrSuspendedCard)) {
for (String targetDefinition : targets) {
if (targetDefinition.startsWith("targetPlayer=")) {
continue;
}
checkTargetDefinitionMarksSupport(target, targetDefinition, "^[]");
String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
// must have all valid targets from list
targetFound = false;
boolean originOnly = false;
boolean copyOnly = false;
if (targetName.endsWith("]")) {
if (targetName.endsWith("[no copy]")) {
originOnly = true;
targetName = targetName.substring(0, targetName.length() - 9);
}
if (targetName.endsWith("[only copy]")) {
copyOnly = true;
targetName = targetName.substring(0, targetName.length() - 11);
}
}
Filter filter = target.getOriginalTarget().getFilter();
if (filter instanceof FilterCreatureOrPlayer) {
filter = ((FilterCreatureOrPlayer) filter).getCreatureFilter();
}
if (filter instanceof FilterPermanentOrPlayer) {
filter = ((FilterPermanentOrPlayer) filter).getPermanentFilter();
}
if (filter instanceof FilterPlaneswalkerOrPlayer) {
filter = ((FilterPlaneswalkerOrPlayer) filter).getFilterPermanent();
}
if (filter instanceof FilterPermanentOrSuspendedCard) {
filter = ((FilterPermanentOrSuspendedCard) filter).getPermanentFilter();
}
for (Permanent permanent : game.getBattlefield().getActivePermanents((FilterPermanent) filter, abilityControllerId, sourceId, game)) {
if (hasObjectTargetNameOrAlias(permanent, targetName) || (permanent.getName() + '-' + permanent.getExpansionSetCode()).equals(targetName)) {
// TODO: remove exp code search?
if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.getTargets().contains(permanent.getId())) {
if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly)) {
target.addTarget(permanent.getId(), source, game);
targetFound = true;
// return to next targetName
break;
}
}
}
}
}
if (targetFound) {
targets.remove(targetDefinition);
return true;
}
}
}
// cards from non-own hand must be targeted through revealed cards
if (target.getOriginalTarget() instanceof TargetCardInHand || target.getOriginalTarget() instanceof TargetDiscard || (target.getOriginalTarget() instanceof TargetCard && target.getOriginalTarget().getZone() == Zone.HAND)) {
targetCardZonesChecked.add(Zone.HAND);
for (String targetDefinition : targets) {
checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
for (Card card : computerPlayer.getHand().getCards(((TargetCard) target.getOriginalTarget()).getFilter(), game)) {
if (hasObjectTargetNameOrAlias(card, targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
// TODO: remove set code search?
if (target.canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
target.addTarget(card.getId(), source, game);
targetFound = true;
// return to next targetName
break;
}
}
}
}
if (targetFound) {
targets.remove(targetDefinition);
return true;
}
}
}
// card in exile
if (target.getOriginalTarget() instanceof TargetCardInExile || target.getOriginalTarget() instanceof TargetPermanentOrSuspendedCard || (target.getOriginalTarget() instanceof TargetCard && target.getOriginalTarget().getZone() == Zone.EXILED)) {
targetCardZonesChecked.add(Zone.EXILED);
FilterCard filter = null;
if (target.getOriginalTarget().getFilter() instanceof FilterCard) {
filter = (FilterCard) target.getOriginalTarget().getFilter();
} else if (target.getOriginalTarget().getFilter() instanceof FilterPermanentOrSuspendedCard) {
filter = ((FilterPermanentOrSuspendedCard) target.getOriginalTarget().getFilter()).getCardFilter();
}
if (filter == null) {
Assert.fail("Unsupported exile target filter in TestPlayer: " + target.getOriginalTarget().getClass().getCanonicalName());
}
for (String targetDefinition : targets) {
checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
for (Card card : game.getExile().getCards(filter, game)) {
if (hasObjectTargetNameOrAlias(card, targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
// TODO: remove set code search?
if (target.canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
target.addTarget(card.getId(), source, game);
targetFound = true;
// return to next targetName
break;
}
}
}
}
if (targetFound) {
targets.remove(targetDefinition);
return true;
}
}
}
// card in battlefield
if (target instanceof TargetCardInGraveyardOrBattlefield) {
TargetCard targetFull = (TargetCard) target;
for (String targetDefinition : targets) {
checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
for (Card card : game.getBattlefield().getAllActivePermanents()) {
if (hasObjectTargetNameOrAlias(card, targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
// TODO: remove set code search?
if (targetFull.canTarget(abilityControllerId, card.getId(), source, game) && !targetFull.getTargets().contains(card.getId())) {
targetFull.add(card.getId(), game);
targetFound = true;
// return to next targetName
break;
}
}
}
}
if (targetFound) {
targets.remove(targetDefinition);
return true;
}
}
}
// card in graveyard
if (target.getOriginalTarget() instanceof TargetCardInOpponentsGraveyard || target.getOriginalTarget() instanceof TargetCardInYourGraveyard || target.getOriginalTarget() instanceof TargetCardInGraveyard || target.getOriginalTarget() instanceof TargetCardInGraveyardOrBattlefield || (target.getOriginalTarget() instanceof TargetCard && target.getOriginalTarget().getZone() == Zone.GRAVEYARD)) {
targetCardZonesChecked.add(Zone.GRAVEYARD);
TargetCard targetFull = (TargetCard) target.getOriginalTarget();
List<UUID> needPlayers = game.getState().getPlayersInRange(getId(), game).toList();
// fix for opponent graveyard
if (target.getOriginalTarget() instanceof TargetCardInOpponentsGraveyard) {
// current player remove
Assert.assertTrue(needPlayers.contains(getId()));
needPlayers.remove(getId());
Assert.assertFalse(needPlayers.contains(getId()));
}
// fix for your graveyard
if (target.getOriginalTarget() instanceof TargetCardInYourGraveyard) {
// only current player
Assert.assertTrue(needPlayers.contains(getId()));
needPlayers.clear();
needPlayers.add(getId());
Assert.assertEquals(1, needPlayers.size());
}
for (String targetDefinition : targets) {
checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
IterateGraveyards: for (UUID playerId : needPlayers) {
Player player = game.getPlayer(playerId);
for (Card card : player.getGraveyard().getCards(targetFull.getFilter(), game)) {
if (hasObjectTargetNameOrAlias(card, targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
// TODO: remove set code search?
if (target.canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
target.addTarget(card.getId(), source, game);
targetFound = true;
// return to next targetName
break IterateGraveyards;
}
}
}
}
}
if (targetFound) {
targets.remove(targetDefinition);
return true;
}
}
}
// stack
if (target.getOriginalTarget() instanceof TargetSpell) {
for (String targetDefinition : targets) {
checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
for (StackObject stackObject : game.getStack()) {
if (hasObjectTargetNameOrAlias(stackObject, targetName)) {
if (target.canTarget(abilityControllerId, stackObject.getId(), source, game) && !target.getTargets().contains(stackObject.getId())) {
target.addTarget(stackObject.getId(), source, game);
targetFound = true;
// return to next targetName
break;
}
}
}
}
if (targetFound) {
targets.remove(targetDefinition);
return true;
}
}
}
// library
if (target.getOriginalTarget() instanceof TargetCardInLibrary || (target.getOriginalTarget() instanceof TargetCard && target.getOriginalTarget().getZone() == Zone.LIBRARY)) {
// user don't have access to library, so it must be targeted through list/revealed cards
Assert.fail("Library zone is private, you must target through cards list, e.g. revealed: " + target.getOriginalTarget().getClass().getCanonicalName());
}
// uninplemented TargetCard's zone
if (target.getOriginalTarget() instanceof TargetCard && !targetCardZonesChecked.contains(target.getOriginalTarget().getZone())) {
Assert.fail("Found unimplemented TargetCard's zone or TargetCard's extented class: " + target.getOriginalTarget().getClass().getCanonicalName() + ", zone " + target.getOriginalTarget().getZone() + ", from " + (source == null ? "unknown source" : source.getSourceObject(game)));
}
}
// how to fix: implement target class processing above
if (!targets.isEmpty()) {
String message;
if (source != null) {
message = this.getName() + " - Targets list was setup by addTarget with " + targets + ", but not used" + "\nCard: " + source.getSourceObject(game) + "\nAbility: " + source.getClass().getSimpleName() + " (" + source.getRule() + ")" + "\nTarget: " + target.getClass().getSimpleName() + " (" + target.getMessage() + ")" + "\nYou must implement target class support in TestPlayer or setup good targets";
} else {
message = this.getName() + " - Targets list was setup by addTarget with " + targets + ", but not used" + "\nCard: unknown source" + "\nAbility: unknown source" + "\nTarget: " + target.getClass().getSimpleName() + " (" + target.getMessage() + ")" + "\nYou must implement target class support in TestPlayer or setup good targets";
}
Assert.fail(message);
}
this.chooseStrictModeFailed("target", game, getInfo(source, game) + "\n" + getInfo(target));
return computerPlayer.chooseTarget(outcome, target, source, game);
}
use of mage.game.stack.StackObject in project mage by magefree.
the class TestPlayer method choose.
@Override
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map<String, Serializable> options) {
UUID abilityControllerId = computerPlayer.getId();
if (target.getTargetController() != null && target.getAbilityController() != null) {
abilityControllerId = target.getAbilityController();
}
// ignore player select
if (target.getMessage().equals("Select a starting player")) {
return computerPlayer.choose(outcome, target, sourceId, game, options);
}
assertAliasSupportInChoices(true);
if (!choices.isEmpty()) {
// skip choices
if (choices.get(0).equals(CHOICE_SKIP)) {
Assert.assertTrue("found skip choice, but it require more choices, needs " + (target.getMinNumberOfTargets() - target.getTargets().size()) + " more", target.getTargets().size() >= target.getMinNumberOfTargets());
choices.remove(0);
return true;
}
List<Integer> usedChoices = new ArrayList<>();
List<UUID> usedTargets = new ArrayList<>();
Ability source = null;
StackObject stackObject = game.getStack().getStackObject(sourceId);
if (stackObject != null) {
source = stackObject.getStackAbility();
}
if ((target.getOriginalTarget() instanceof TargetPermanent) || (target.getOriginalTarget() instanceof TargetPermanentOrPlayer)) {
// player target not implemted yet
FilterPermanent filterPermanent;
if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) {
filterPermanent = ((TargetPermanentOrPlayer) target.getOriginalTarget()).getFilterPermanent();
} else {
filterPermanent = ((TargetPermanent) target.getOriginalTarget()).getFilter();
}
for (String choiceRecord : choices) {
String[] targetList = choiceRecord.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
boolean originOnly = false;
boolean copyOnly = false;
if (targetName.endsWith("]")) {
if (targetName.endsWith("[no copy]")) {
originOnly = true;
targetName = targetName.substring(0, targetName.length() - 9);
}
if (targetName.endsWith("[only copy]")) {
copyOnly = true;
targetName = targetName.substring(0, targetName.length() - 11);
}
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterPermanent, abilityControllerId, sourceId, game)) {
if (target.getTargets().contains(permanent.getId())) {
continue;
}
if (hasObjectTargetNameOrAlias(permanent, targetName)) {
if (target.isNotTarget() || target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly)) {
target.add(permanent.getId(), game);
targetFound = true;
break;
}
}
} else if ((permanent.getName() + '-' + permanent.getExpansionSetCode()).equals(targetName)) {
// TODO: remove search by exp code?
if (target.isNotTarget() || target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly)) {
target.add(permanent.getId(), game);
targetFound = true;
break;
}
}
}
}
}
if (targetFound) {
choices.remove(choiceRecord);
return true;
}
}
}
if (target instanceof TargetPlayer) {
for (Player player : game.getPlayers().values()) {
for (String choose2 : choices) {
if (player.getName().equals(choose2)) {
if (target.canTarget(abilityControllerId, player.getId(), null, game) && !target.getTargets().contains(player.getId())) {
target.add(player.getId(), game);
choices.remove(choose2);
return true;
}
}
}
}
}
// TODO: add same choices fixes for other target types (one choice must uses only one time for one target)
if (target.getOriginalTarget() instanceof TargetCard) {
// one choice per target
// only unique targets
// TargetCard targetFull = ((TargetCard) target);
usedChoices.clear();
usedTargets.clear();
boolean targetCompleted = false;
CheckAllChoices: for (int choiceIndex = 0; choiceIndex < choices.size(); choiceIndex++) {
String choiceRecord = choices.get(choiceIndex);
if (targetCompleted) {
break CheckAllChoices;
}
boolean targetFound = false;
String[] possibleChoices = choiceRecord.split("\\^");
CheckOneChoice: for (String possibleChoice : possibleChoices) {
Set<UUID> possibleCards = target.possibleTargets(sourceId, abilityControllerId, game);
CheckTargetsList: for (UUID targetId : possibleCards) {
MageObject targetObject = game.getCard(targetId);
if (hasObjectTargetNameOrAlias(targetObject, possibleChoice)) {
if (target.canTarget(targetObject.getId(), game)) {
// only unique targets
if (usedTargets.contains(targetObject.getId())) {
continue;
}
// OK, can use it
target.add(targetObject.getId(), game);
targetFound = true;
usedTargets.add(targetObject.getId());
// break on full targets list
if (target.getTargets().size() >= target.getMaxNumberOfTargets()) {
targetCompleted = true;
break CheckOneChoice;
}
// restart search
break CheckTargetsList;
}
}
}
}
if (targetFound) {
usedChoices.add(choiceIndex);
}
}
// apply only on ALL targets or revert
if (usedChoices.size() > 0) {
if (target.isChosen()) {
// remove all used choices
for (int i = choices.size(); i >= 0; i--) {
if (usedChoices.contains(i)) {
choices.remove(i);
}
}
return true;
} else {
Assert.fail("Not full targets list.");
target.clearChosen();
}
}
}
if (target.getOriginalTarget() instanceof TargetSource) {
Set<UUID> possibleTargets;
TargetSource t = ((TargetSource) target.getOriginalTarget());
possibleTargets = t.possibleTargets(sourceId, abilityControllerId, game);
for (String choiceRecord : choices) {
String[] targetList = choiceRecord.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
for (UUID targetId : possibleTargets) {
MageObject targetObject = game.getObject(targetId);
if (targetObject != null) {
if (hasObjectTargetNameOrAlias(targetObject, targetName)) {
List<UUID> alreadyTargetted = target.getTargets();
if (t.canTarget(targetObject.getId(), game)) {
if (alreadyTargetted != null && !alreadyTargetted.contains(targetObject.getId())) {
target.add(targetObject.getId(), game);
choices.remove(choiceRecord);
targetFound = true;
}
}
}
}
if (targetFound) {
choices.remove(choiceRecord);
return true;
}
}
}
}
}
// TODO: enable fail checks and fix tests
/*
if (!target.getTargetName().equals("starting player")) {
Assert.fail("Wrong choice");
}
*/
}
this.chooseStrictModeFailed("choice", game, getInfo(game.getObject(sourceId)) + ";\n" + getInfo(target));
return computerPlayer.choose(outcome, target, sourceId, game, options);
}
Aggregations