mirror of
https://github.com/correl/mage.git
synced 2024-12-25 11:11:16 +00:00
Merge remote-tracking branch 'remotes/upstream/master'
This commit is contained in:
commit
95d0fe8802
45 changed files with 702 additions and 338 deletions
|
@ -5,8 +5,12 @@ import java.awt.image.BufferedImage;
|
|||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.file.AccessDeniedException;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -103,7 +107,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
p0.add(jLabel1);
|
||||
p0.add(Box.createVerticalStrut(5));
|
||||
ComboBoxModel jComboBox1Model = new DefaultComboBoxModel(new String[]{
|
||||
"magiccards.info",
|
||||
// "magiccards.info",
|
||||
"wizards.com",
|
||||
"mythicspoiler.com",
|
||||
"tokens.mtg.onl", //"mtgimage.com (HQ)",
|
||||
|
@ -111,8 +115,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
"alternative.mtg.onl",
|
||||
"GrabBag",
|
||||
"magidex.com",
|
||||
"scryfall.com",
|
||||
//"mtgathering.ru HQ",
|
||||
"scryfall.com", //"mtgathering.ru HQ",
|
||||
//"mtgathering.ru MQ",
|
||||
//"mtgathering.ru LQ",
|
||||
});
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
*/
|
||||
package mage.server;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.server.exceptions.UserNotFoundException;
|
||||
|
@ -40,6 +36,11 @@ import mage.view.ChatMessage.MessageType;
|
|||
import mage.view.ChatMessage.SoundToPlay;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
@ -290,7 +291,7 @@ public enum ChatManager {
|
|||
}
|
||||
}
|
||||
|
||||
public ArrayList<ChatSession> getChatSessions() {
|
||||
public List<ChatSession> getChatSessions() {
|
||||
return new ArrayList<>(chatSessions.values());
|
||||
}
|
||||
|
||||
|
|
|
@ -36,10 +36,7 @@ import mage.view.ChatMessage.SoundToPlay;
|
|||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
|
@ -119,7 +116,7 @@ public class ChatSession {
|
|||
|
||||
public void broadcast(String userName, String message, MessageColor color, boolean withTime, MessageType messageType, SoundToPlay soundToPlay) {
|
||||
if (!message.isEmpty()) {
|
||||
HashSet<UUID> clientsToRemove = new HashSet<>();
|
||||
Set<UUID> clientsToRemove = new HashSet<>();
|
||||
ClientCallback clientCallback = new ClientCallback(ClientCallbackMethod.CHATMESSAGE, chatId, new ChatMessage(userName, message, (withTime ? timeFormatter.format(new Date()) : ""), color, messageType, soundToPlay));
|
||||
for (UUID userId : clients.keySet()) {
|
||||
Optional<User> user = UserManager.instance.getUser(userId);
|
||||
|
|
|
@ -369,7 +369,7 @@ public enum TableManager {
|
|||
+ " | " + sessionState
|
||||
+ " | " + user.getName() + " (" + user.getUserState().toString() + " - " + user.getPingInfo() + ')');
|
||||
}
|
||||
ArrayList<ChatSession> chatSessions = ChatManager.instance.getChatSessions();
|
||||
List<ChatSession> chatSessions = ChatManager.instance.getChatSessions();
|
||||
logger.debug("------- ChatSessions: " + chatSessions.size() + " ----------------------------------");
|
||||
for (ChatSession chatSession : chatSessions) {
|
||||
logger.debug(chatSession.getChatId() + " " + formatter.format(chatSession.getCreateTime()) + ' ' + chatSession.getInfo() + ' ' + chatSession.getClients().values().toString());
|
||||
|
@ -387,7 +387,7 @@ public enum TableManager {
|
|||
debugServerState();
|
||||
}
|
||||
logger.debug("TABLE HEALTH CHECK");
|
||||
ArrayList<Table> tableCopy = new ArrayList<>(tables.values());
|
||||
List<Table> tableCopy = new ArrayList<>(tables.values());
|
||||
for (Table table : tableCopy) {
|
||||
try {
|
||||
if (table.getState() != TableState.FINISHED) {
|
||||
|
|
|
@ -73,7 +73,7 @@ public class User {
|
|||
private final String host;
|
||||
private final Date connectionTime;
|
||||
private final Map<UUID, Table> tables;
|
||||
private final ArrayList<UUID> tablesToDelete;
|
||||
private final List<UUID> tablesToDelete;
|
||||
private final Map<UUID, GameSessionPlayer> gameSessions;
|
||||
private final Map<UUID, DraftSession> draftSessions;
|
||||
private final Map<UUID, UUID> userTournaments; // playerId, tournamentId
|
||||
|
|
|
@ -88,8 +88,8 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
|||
private void update() {
|
||||
List<Table> allTables = new ArrayList<>(tables.values());
|
||||
allTables.sort(new TableListSorter());
|
||||
ArrayList<MatchView> matchList = new ArrayList<>();
|
||||
ArrayList<TableView> tableList = new ArrayList<>();
|
||||
List<MatchView> matchList = new ArrayList<>();
|
||||
List<TableView> tableList = new ArrayList<>();
|
||||
for (Table table : allTables) {
|
||||
if (table.getState() != TableState.FINISHED) {
|
||||
tableList.add(new TableView(table));
|
||||
|
|
|
@ -18,6 +18,7 @@ import java.sql.SQLException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public enum UserStatsRepository {
|
||||
|
||||
|
@ -107,7 +108,7 @@ public enum UserStatsRepository {
|
|||
// updateUserStats reads tables finished after the last DB update and reflects it to the DB.
|
||||
// It returns the list of user names that are upated.
|
||||
public List<String> updateUserStats() {
|
||||
HashSet<String> updatedUsers = new HashSet<>();
|
||||
Set<String> updatedUsers = new HashSet<>();
|
||||
// Lock the DB so that no other updateUserStats runs at the same time.
|
||||
synchronized(this) {
|
||||
long latestEndTimeMs = this.getLatestEndTimeMs();
|
||||
|
|
|
@ -27,8 +27,10 @@
|
|||
*/
|
||||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DiesTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.condition.common.LastTimeCounterRemovedCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
|
@ -43,9 +45,6 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.CardType;
|
||||
import mage.counters.CounterType;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.common.DiesTriggeredAbility;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gal Lerman
|
||||
|
@ -61,14 +60,14 @@ public class Chronozoa extends CardImpl {
|
|||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Vanishing 3
|
||||
|
||||
// Vanishing 3 (This permanent enters the battlefield with three time counters on it. At the beginning of your upkeep, remove a time counter from it. When the last is removed, sacrifice it.)
|
||||
Ability ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(3)));
|
||||
ability.setRuleVisible(false);
|
||||
this.addAbility(ability);
|
||||
this.addAbility(new VanishingUpkeepAbility(3));
|
||||
this.addAbility(new VanishingSacrificeAbility());
|
||||
|
||||
|
||||
// When Chronozoa is put into a graveyard from play, if it had no time counters on it, create two tokens that are copies of it.
|
||||
Effect effect = new PutTokenOntoBattlefieldCopySourceEffect(2);
|
||||
effect.setText("create two tokens that are copies of it");
|
||||
|
|
|
@ -28,13 +28,13 @@
|
|||
package mage.cards.k;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.keyword.PersistAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -43,7 +43,7 @@ import mage.cards.CardSetInfo;
|
|||
public class KitchenFinks extends CardImpl {
|
||||
|
||||
public KitchenFinks(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G/W}{G/W}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G/W}{G/W}");
|
||||
this.subtype.add("Ouphe");
|
||||
|
||||
this.power = new MageInt(3);
|
||||
|
@ -51,7 +51,7 @@ public class KitchenFinks extends CardImpl {
|
|||
|
||||
// When Kitchen Finks enters the battlefield, you gain 2 life.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(2)));
|
||||
// Persist
|
||||
// Persist (When this creature dies, if it had no -1/-1 counters on it, return it to the battlefield under its owner's control with a -1/-1 counter on it.)
|
||||
this.addAbility(new PersistAbility());
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
package mage.cards.r;
|
||||
|
||||
import mage.Mana;
|
||||
import mage.abilities.condition.common.LandfallCondition;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.decorator.ConditionalManaEffect;
|
||||
import mage.abilities.effects.common.BasicManaEffect;
|
||||
|
@ -37,9 +36,10 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.watchers.common.LandfallWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.condition.common.PlayLandCondition;
|
||||
import mage.watchers.common.PlayLandWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -48,16 +48,16 @@ import java.util.UUID;
|
|||
public class RiverOfTears extends CardImpl {
|
||||
|
||||
public RiverOfTears(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.LAND},"");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
|
||||
|
||||
// {T}: Add {U} to your mana pool. If you played a land this turn, add {B} to your mana pool instead.
|
||||
this.addAbility(new ConditionalManaAbility(Zone.BATTLEFIELD, new ConditionalManaEffect(
|
||||
new BasicManaEffect(Mana.BlackMana(1)),
|
||||
new BasicManaEffect(Mana.BlueMana(1)),
|
||||
LandfallCondition.instance,
|
||||
PlayLandCondition.instance,
|
||||
"Add {U} to your mana pool. If you played a land this turn, add {B} to your mana pool instead"),
|
||||
new TapSourceCost()),
|
||||
new LandfallWatcher());
|
||||
new TapSourceCost()),
|
||||
new PlayLandWatcher());
|
||||
}
|
||||
|
||||
public RiverOfTears(final RiverOfTears card) {
|
||||
|
|
|
@ -68,7 +68,7 @@ public class SandStrangler extends CardImpl {
|
|||
|
||||
// When Sand Strangler enters the battlefield, if you control a Desert or there is a Desert card in your graveyard, you may have Sand Strangler deal 3 damage to target creature.
|
||||
Ability ability = new ConditionalTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3)),
|
||||
new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3), true),
|
||||
new OrCondition(
|
||||
new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(filterDesertPermanent)),
|
||||
new CardsInControllerGraveCondition(1, filterDesertCard)),
|
||||
|
|
|
@ -60,7 +60,7 @@ public class Terastodon extends CardImpl {
|
|||
}
|
||||
|
||||
public Terastodon(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{6}{G}{G}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{G}{G}");
|
||||
this.subtype.add("Elephant");
|
||||
|
||||
this.power = new MageInt(9);
|
||||
|
@ -112,6 +112,7 @@ class TerastodonEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
}
|
||||
game.applyEffects();
|
||||
ElephantToken elephantToken = new ElephantToken();
|
||||
for (Entry<UUID, Integer> entry : destroyedPermanents.entrySet()) {
|
||||
elephantToken.putOntoBattlefield(entry.getValue(), game, source.getSourceId(), entry.getKey());
|
||||
|
|
|
@ -27,9 +27,6 @@
|
|||
*/
|
||||
package mage.cards.t;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
|
@ -49,6 +46,10 @@ import mage.game.Game;
|
|||
import mage.game.combat.CombatGroup;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
|
@ -113,7 +114,7 @@ class CantBeBlockedUnlessAllEffect extends RestrictionEffect {
|
|||
return false;
|
||||
}
|
||||
// check blocker restrictions
|
||||
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry: game.getContinuousEffects().getApplicableRestrictionEffects(permanent, game).entrySet()) {
|
||||
for (Map.Entry<RestrictionEffect, Set<Ability>> entry: game.getContinuousEffects().getApplicableRestrictionEffects(permanent, game).entrySet()) {
|
||||
for (Ability ability : entry.getValue()) {
|
||||
if (!entry.getKey().canBlock(attacker, permanent, ability, game)) {
|
||||
return false;
|
||||
|
@ -121,7 +122,7 @@ class CantBeBlockedUnlessAllEffect extends RestrictionEffect {
|
|||
}
|
||||
}
|
||||
// check also attacker's restriction effects
|
||||
for (Map.Entry<RestrictionEffect, HashSet<Ability>> restrictionEntry: game.getContinuousEffects().getApplicableRestrictionEffects(attacker, game).entrySet()) {
|
||||
for (Map.Entry<RestrictionEffect, Set<Ability>> restrictionEntry: game.getContinuousEffects().getApplicableRestrictionEffects(attacker, game).entrySet()) {
|
||||
for (Ability ability : restrictionEntry.getValue()) {
|
||||
if (!(restrictionEntry.getKey() instanceof CantBeBlockedUnlessAllEffect)
|
||||
&& !restrictionEntry.getKey().canBeBlocked(attacker, permanent, ability, game)) {
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
|
@ -20,23 +20,22 @@
|
|||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.cards.v;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.effects.keyword.ScryEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
/**
|
||||
|
@ -46,13 +45,13 @@ import mage.target.common.TargetControlledCreaturePermanent;
|
|||
public class VisceraSeer extends CardImpl {
|
||||
|
||||
public VisceraSeer(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}");
|
||||
this.subtype.add("Vampire");
|
||||
this.subtype.add("Wizard");
|
||||
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
// Sacrifice a creature: Scry 1. (To scry 1, look at the top card of your library, then you may put that card on the bottom of your library.)
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScryEffect(1), new SacrificeTargetCost(new TargetControlledCreaturePermanent())));
|
||||
}
|
||||
|
||||
|
|
|
@ -153,4 +153,36 @@ public class AddingCountersToPermanentsTest extends CardTestPlayerBase {
|
|||
assertPowerToughness(playerB, "Silvercoat Lion", 2, 2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Considering rule 121.6 Persist is not working with Hapatra, Vizier of
|
||||
* Poisons and Obelisk Spider. Hapatra and Obelisk Spider do not trigger
|
||||
* their second abilities when Kitchen Finks returns with -1/-1 counter.
|
||||
*/
|
||||
@Test
|
||||
public void HapatraVizierOfPoisons() {
|
||||
|
||||
// Whenever Hapatra, Vizier of Poisons deals combat damage to a player, you may put a -1/-1 counter on target creature.
|
||||
// Whenever you put one or more -1/-1 counters on a creature, create a 1/1 green Snake creature token with deathtouch.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Hapatra, Vizier of Poisons", 1);
|
||||
|
||||
// When Kitchen Finks enters the battlefield, you gain 2 life.
|
||||
// Persist (When this creature dies, if it had no -1/-1 counters on it, return it to the battlefield under its owner's control with a -1/-1 counter on it.)
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Kitchen Finks", 1); // Creature 3/2
|
||||
|
||||
addCard(Zone.HAND, playerB, "Lightning Bolt");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "Kitchen Finks");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerB, "Lightning Bolt", 1);
|
||||
|
||||
assertPowerToughness(playerA, "Kitchen Finks", 2, 1);
|
||||
|
||||
assertPermanentCount(playerA, "Snake", 1);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package org.mage.test.cards.triggers.dies;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ChronozoaTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* Chronozoa's duplicating ability is triggering whenever any card is put
|
||||
* into a graveyard from play, not just Chronozoa itself. Here's an excerpt
|
||||
* from the log: As you can see, I sacrificed Viscera Seer and for some
|
||||
* reason that triggered Chronozoa's ability.
|
||||
*/
|
||||
@Test
|
||||
public void testTriggerOtherCreature() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
// Flying
|
||||
// Vanishing 3 (This permanent enters the battlefield with three time counters on it. At the beginning of your upkeep, remove a time counter from it. When the last is removed, sacrifice it.)
|
||||
// When Chronozoa is put into a graveyard from play, if it had no time counters on it, create two tokens that are copies of it.
|
||||
addCard(Zone.HAND, playerA, "Chronozoa"); // {3}{U}
|
||||
addCard(Zone.GRAVEYARD, playerA, "Chronozoa");
|
||||
// Sacrifice a creature: Scry 1. (To scry 1, look at the top card of your library, then you may put that card on the bottom of your library.)
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Viscera Seer", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Chronozoa");
|
||||
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Sacrifice a creature");
|
||||
addTarget(playerA, "Viscera Seer");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Viscera Seer", 1);
|
||||
assertGraveyardCount(playerA, "Chronozoa", 1);
|
||||
assertPermanentCount(playerA, "Chronozoa", 1);
|
||||
assertPermanentCount(playerA, 5);
|
||||
|
||||
assertHandCount(playerA, 0);
|
||||
}
|
||||
|
||||
}
|
|
@ -27,19 +27,9 @@
|
|||
*/
|
||||
package org.mage.test.player;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.Modes;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.costs.AlternativeSourceCosts;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.Costs;
|
||||
|
@ -52,13 +42,7 @@ import mage.cards.Card;
|
|||
import mage.cards.Cards;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.choices.Choice;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.ManaType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.Counters;
|
||||
import mage.filter.Filter;
|
||||
|
@ -83,22 +67,15 @@ import mage.players.Library;
|
|||
import mage.players.ManaPool;
|
||||
import mage.players.Player;
|
||||
import mage.players.net.UserData;
|
||||
import mage.target.Target;
|
||||
import mage.target.TargetAmount;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.target.TargetSource;
|
||||
import mage.target.TargetSpell;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.target.common.TargetCardInOpponentsGraveyard;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.target.common.TargetCreatureOrPlayer;
|
||||
import mage.target.common.TargetCreaturePermanentAmount;
|
||||
import mage.target.common.TargetPermanentOrPlayer;
|
||||
import mage.target.*;
|
||||
import mage.target.common.*;
|
||||
import org.junit.Ignore;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
* @author Simown
|
||||
|
@ -1329,7 +1306,7 @@ public class TestPlayer implements Player {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int drawCards(int num, Game game, ArrayList<UUID> appliedEffects) {
|
||||
public int drawCards(int num, Game game, List<UUID> appliedEffects) {
|
||||
return computerPlayer.drawCards(num, game, appliedEffects);
|
||||
}
|
||||
|
||||
|
@ -1619,7 +1596,7 @@ public class TestPlayer implements Player {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, ArrayList<UUID> appliedEffects) {
|
||||
public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects) {
|
||||
return computerPlayer.damage(damage, sourceId, game, combatDamage, preventable, appliedEffects);
|
||||
}
|
||||
|
||||
|
@ -2284,7 +2261,7 @@ public class TestPlayer implements Player {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects) {
|
||||
return computerPlayer.moveCards(card, toZone, source, game, tapped, faceDown, byOwner, appliedEffects);
|
||||
}
|
||||
|
||||
|
@ -2299,7 +2276,7 @@ public class TestPlayer implements Player {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects) {
|
||||
return computerPlayer.moveCards(cards, toZone, source, game, tapped, faceDown, byOwner, appliedEffects);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,21 +27,8 @@
|
|||
*/
|
||||
package org.mage.test.stub;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.Modes;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.costs.AlternativeSourceCosts;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.Costs;
|
||||
|
@ -53,12 +40,7 @@ import mage.cards.Card;
|
|||
import mage.cards.Cards;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.choices.Choice;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.ManaType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.PlayerAction;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.Counters;
|
||||
import mage.filter.FilterPermanent;
|
||||
|
@ -80,6 +62,9 @@ import mage.target.TargetAmount;
|
|||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Quercitron
|
||||
|
@ -174,7 +159,7 @@ public class PlayerStub implements Player {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, ArrayList<UUID> appliedEffects) {
|
||||
public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -563,7 +548,7 @@ public class PlayerStub implements Player {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int drawCards(int num, Game game, ArrayList<UUID> appliedEffects) {
|
||||
public int drawCards(int num, Game game, List<UUID> appliedEffects) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1098,7 +1083,7 @@ public class PlayerStub implements Player {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1113,7 +1098,7 @@ public class PlayerStub implements Player {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,6 @@
|
|||
|
||||
package mage.abilities.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.ActivatedAbilityImpl;
|
||||
import mage.abilities.costs.common.PayLifeCost;
|
||||
|
@ -48,6 +45,10 @@ import mage.filter.predicate.mageobject.CardTypePredicate;
|
|||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
@ -67,7 +68,7 @@ public class FetchLandActivatedAbility extends ActivatedAbilityImpl {
|
|||
addCost(new SacrificeSourceCost());
|
||||
FilterCard filter = new FilterCard(subTypeNames(subtypes));
|
||||
filter.add(new CardTypePredicate(CardType.LAND));
|
||||
ArrayList<Predicate<MageObject>> subtypePredicates = new ArrayList<>();
|
||||
List<Predicate<MageObject>> subtypePredicates = new ArrayList<>();
|
||||
for (SubType subtype : subtypes) {
|
||||
subtypePredicates.add(new SubtypePredicate(subtype));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package mage.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.game.Game;
|
||||
import mage.watchers.common.PlayLandWatcher;
|
||||
|
||||
/**
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public enum PlayLandCondition implements Condition {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
PlayLandWatcher watcher = (PlayLandWatcher) game.getState().getWatchers().get(PlayLandWatcher.class.getSimpleName());
|
||||
return watcher != null
|
||||
&& watcher.landPlayed(source.getControllerId());
|
||||
}
|
||||
}
|
|
@ -27,13 +27,15 @@
|
|||
*/
|
||||
package mage.abilities.condition.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.keyword.SurgeAbility;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
|
@ -46,7 +48,7 @@ public enum SurgedCondition implements Condition {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
if (source.getAbilityType() == AbilityType.TRIGGERED) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<Integer> surgeActivations = (ArrayList) game.getState().getValue(SurgeAbility.SURGE_ACTIVATION_VALUE_KEY + source.getSourceId());
|
||||
List<Integer> surgeActivations = (ArrayList) game.getState().getValue(SurgeAbility.SURGE_ACTIVATION_VALUE_KEY + source.getSourceId());
|
||||
if (surgeActivations != null) {
|
||||
return surgeActivations.contains(game.getState().getZoneChangeCounter(source.getSourceId()) - 1);
|
||||
}
|
||||
|
|
|
@ -27,11 +27,6 @@
|
|||
*/
|
||||
package mage.abilities.effects;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.keyword.SpliceOntoArcaneAbility;
|
||||
|
@ -54,6 +49,11 @@ import mage.players.Player;
|
|||
import mage.target.common.TargetCardInHand;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
@ -192,7 +192,7 @@ public class ContinuousEffects implements Serializable {
|
|||
case WhileOnBattlefield:
|
||||
case WhileOnStack:
|
||||
case WhileInGraveyard:
|
||||
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
if (!abilities.isEmpty()) {
|
||||
for (Ability ability : abilities) {
|
||||
// If e.g. triggerd abilities (non static) created the effect, the ability must not be in usable zone (e.g. Unearth giving Haste effect)
|
||||
|
@ -244,11 +244,11 @@ public class ContinuousEffects implements Serializable {
|
|||
return effects.stream().filter(effect->effect.hasLayer(layer)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public HashMap<RequirementEffect, HashSet<Ability>> getApplicableRequirementEffects(Permanent permanent, Game game) {
|
||||
HashMap<RequirementEffect, HashSet<Ability>> effects = new HashMap<>();
|
||||
public Map<RequirementEffect, Set<Ability>> getApplicableRequirementEffects(Permanent permanent, Game game) {
|
||||
Map<RequirementEffect, Set<Ability>> effects = new HashMap<>();
|
||||
for (RequirementEffect effect : requirementEffects) {
|
||||
HashSet<Ability> abilities = requirementEffects.getAbility(effect.getId());
|
||||
HashSet<Ability> applicableAbilities = new HashSet<>();
|
||||
Set<Ability> abilities = requirementEffects.getAbility(effect.getId());
|
||||
Set<Ability> applicableAbilities = new HashSet<>();
|
||||
for (Ability ability : abilities) {
|
||||
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, ability instanceof MageSingleton ? permanent : null, null)) {
|
||||
if (effect.applies(permanent, ability, game)) {
|
||||
|
@ -263,11 +263,11 @@ public class ContinuousEffects implements Serializable {
|
|||
return effects;
|
||||
}
|
||||
|
||||
public HashMap<RestrictionEffect, HashSet<Ability>> getApplicableRestrictionEffects(Permanent permanent, Game game) {
|
||||
HashMap<RestrictionEffect, HashSet<Ability>> effects = new HashMap<>();
|
||||
public Map<RestrictionEffect, Set<Ability>> getApplicableRestrictionEffects(Permanent permanent, Game game) {
|
||||
Map<RestrictionEffect, Set<Ability>> effects = new HashMap<>();
|
||||
for (RestrictionEffect effect : restrictionEffects) {
|
||||
HashSet<Ability> abilities = restrictionEffects.getAbility(effect.getId());
|
||||
HashSet<Ability> applicableAbilities = new HashSet<>();
|
||||
Set<Ability> abilities = restrictionEffects.getAbility(effect.getId());
|
||||
Set<Ability> applicableAbilities = new HashSet<>();
|
||||
for (Ability ability : abilities) {
|
||||
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, ability instanceof MageSingleton ? permanent : null, null)) {
|
||||
if (effect.applies(permanent, ability, game)) {
|
||||
|
@ -282,11 +282,11 @@ public class ContinuousEffects implements Serializable {
|
|||
return effects;
|
||||
}
|
||||
|
||||
public HashMap<RestrictionUntapNotMoreThanEffect, HashSet<Ability>> getApplicableRestrictionUntapNotMoreThanEffects(Player player, Game game) {
|
||||
HashMap<RestrictionUntapNotMoreThanEffect, HashSet<Ability>> effects = new HashMap<>();
|
||||
public Map<RestrictionUntapNotMoreThanEffect, Set<Ability>> getApplicableRestrictionUntapNotMoreThanEffects(Player player, Game game) {
|
||||
Map<RestrictionUntapNotMoreThanEffect, Set<Ability>> effects = new HashMap<>();
|
||||
for (RestrictionUntapNotMoreThanEffect effect : restrictionUntapNotMoreThanEffects) {
|
||||
HashSet<Ability> abilities = restrictionUntapNotMoreThanEffects.getAbility(effect.getId());
|
||||
HashSet<Ability> applicableAbilities = new HashSet<>();
|
||||
Set<Ability> abilities = restrictionUntapNotMoreThanEffects.getAbility(effect.getId());
|
||||
Set<Ability> applicableAbilities = new HashSet<>();
|
||||
for (Ability ability : abilities) {
|
||||
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) {
|
||||
if (effect.applies(player, ability, game)) {
|
||||
|
@ -307,7 +307,7 @@ public class ContinuousEffects implements Serializable {
|
|||
continue;
|
||||
}
|
||||
if (effect instanceof PayCostToAttackBlockEffect) {
|
||||
HashSet<Ability> abilities = replacementEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = replacementEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
// for replacment effects of static abilities do not use LKI to check if to apply
|
||||
if (ability.getAbilityType() != AbilityType.STATIC || ability.isInUseableZone(game, null, event)) {
|
||||
|
@ -332,8 +332,8 @@ public class ContinuousEffects implements Serializable {
|
|||
* @return a list of all {@link ReplacementEffect} that apply to the current
|
||||
* event
|
||||
*/
|
||||
private HashMap<ReplacementEffect, HashSet<Ability>> getApplicableReplacementEffects(GameEvent event, Game game) {
|
||||
HashMap<ReplacementEffect, HashSet<Ability>> replaceEffects = new HashMap<>();
|
||||
private Map<ReplacementEffect, Set<Ability>> getApplicableReplacementEffects(GameEvent event, Game game) {
|
||||
Map<ReplacementEffect, Set<Ability>> replaceEffects = new HashMap<>();
|
||||
if (planeswalkerRedirectionEffect.checksEventType(event, game) && planeswalkerRedirectionEffect.applies(event, null, game)) {
|
||||
replaceEffects.put(planeswalkerRedirectionEffect, null);
|
||||
}
|
||||
|
@ -351,8 +351,8 @@ public class ContinuousEffects implements Serializable {
|
|||
// TODO: Handle also gained effect that are connected to different abilities.
|
||||
continue;
|
||||
}
|
||||
HashSet<Ability> abilities = replacementEffects.getAbility(effect.getId());
|
||||
HashSet<Ability> applicableAbilities = new HashSet<>();
|
||||
Set<Ability> abilities = replacementEffects.getAbility(effect.getId());
|
||||
Set<Ability> applicableAbilities = new HashSet<>();
|
||||
for (Ability ability : abilities) {
|
||||
// for replacment effects of static abilities do not use LKI to check if to apply
|
||||
if (ability.getAbilityType() != AbilityType.STATIC || ability.isInUseableZone(game, null, event)) {
|
||||
|
@ -380,8 +380,8 @@ public class ContinuousEffects implements Serializable {
|
|||
// TODO: Handle also gained effect that are connected to different abilities.
|
||||
continue;
|
||||
}
|
||||
HashSet<Ability> abilities = preventionEffects.getAbility(effect.getId());
|
||||
HashSet<Ability> applicableAbilities = new HashSet<>();
|
||||
Set<Ability> abilities = preventionEffects.getAbility(effect.getId());
|
||||
Set<Ability> applicableAbilities = new HashSet<>();
|
||||
for (Ability ability : abilities) {
|
||||
if (ability.getAbilityType() != AbilityType.STATIC || ability.isInUseableZone(game, null, event)) {
|
||||
if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) {
|
||||
|
@ -455,7 +455,7 @@ public class ContinuousEffects implements Serializable {
|
|||
List<CostModificationEffect> costEffects = new ArrayList<>();
|
||||
|
||||
for (CostModificationEffect effect : costModificationEffects) {
|
||||
HashSet<Ability> abilities = costModificationEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = costModificationEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) {
|
||||
if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) {
|
||||
|
@ -479,7 +479,7 @@ public class ContinuousEffects implements Serializable {
|
|||
List<SpliceCardEffect> spliceEffects = new ArrayList<>();
|
||||
|
||||
for (SpliceCardEffect effect : spliceCardEffects) {
|
||||
HashSet<Ability> abilities = spliceCardEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = spliceCardEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (ability.getControllerId().equals(playerId) && (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null))) {
|
||||
if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) {
|
||||
|
@ -500,7 +500,7 @@ public class ContinuousEffects implements Serializable {
|
|||
public boolean asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) {
|
||||
List<AsThoughEffect> asThoughEffectsList = getApplicableAsThoughEffects(type, game);
|
||||
for (AsThoughEffect effect : asThoughEffectsList) {
|
||||
HashSet<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
|
||||
Set<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (affectedAbility == null) {
|
||||
if (effect.applies(objectId, ability, controllerId, game)) {
|
||||
|
@ -519,7 +519,7 @@ public class ContinuousEffects implements Serializable {
|
|||
// First check existing only effects
|
||||
List<AsThoughEffect> asThoughEffectsList = getApplicableAsThoughEffects(AsThoughEffectType.SPEND_ONLY_MANA, game);
|
||||
for (AsThoughEffect effect : asThoughEffectsList) {
|
||||
HashSet<Ability> abilities = asThoughEffectsMap.get(AsThoughEffectType.SPEND_ONLY_MANA).getAbility(effect.getId());
|
||||
Set<Ability> abilities = asThoughEffectsMap.get(AsThoughEffectType.SPEND_ONLY_MANA).getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if ((affectedAbility == null && effect.applies(objectId, ability, controllerId, game))
|
||||
|| effect.applies(objectId, affectedAbility, ability, game)) {
|
||||
|
@ -532,7 +532,7 @@ public class ContinuousEffects implements Serializable {
|
|||
// then check effects that allow to use other mana types to pay the current mana type to pay
|
||||
asThoughEffectsList = getApplicableAsThoughEffects(AsThoughEffectType.SPEND_OTHER_MANA, game);
|
||||
for (AsThoughEffect effect : asThoughEffectsList) {
|
||||
HashSet<Ability> abilities = asThoughEffectsMap.get(AsThoughEffectType.SPEND_OTHER_MANA).getAbility(effect.getId());
|
||||
Set<Ability> abilities = asThoughEffectsMap.get(AsThoughEffectType.SPEND_OTHER_MANA).getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if ((affectedAbility == null && effect.applies(objectId, ability, controllerId, game))
|
||||
|| effect.applies(objectId, affectedAbility, ability, game)) {
|
||||
|
@ -557,7 +557,7 @@ public class ContinuousEffects implements Serializable {
|
|||
List<AsThoughEffect> asThoughEffectsList = new ArrayList<>();
|
||||
if (asThoughEffectsMap.containsKey(type)) {
|
||||
for (AsThoughEffect effect : asThoughEffectsMap.get(type)) {
|
||||
HashSet<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
|
||||
Set<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) {
|
||||
if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) {
|
||||
|
@ -600,7 +600,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
for (CostModificationEffect effect : costEffects) {
|
||||
if (effect.getModificationType() == CostModificationType.INCREASE_COST) {
|
||||
HashSet<Ability> abilities = costModificationEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = costModificationEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (effect.applies(abilityToModify, ability, game)) {
|
||||
effect.apply(game, ability, abilityToModify);
|
||||
|
@ -611,7 +611,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
for (CostModificationEffect effect : costEffects) {
|
||||
if (effect.getModificationType() == CostModificationType.REDUCE_COST) {
|
||||
HashSet<Ability> abilities = costModificationEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = costModificationEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (effect.applies(abilityToModify, ability, game)) {
|
||||
effect.apply(game, ability, abilityToModify);
|
||||
|
@ -622,7 +622,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
for (CostModificationEffect effect : costEffects) {
|
||||
if (effect.getModificationType() == CostModificationType.SET_COST) {
|
||||
HashSet<Ability> abilities = costModificationEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = costModificationEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (effect.applies(abilityToModify, ability, game)) {
|
||||
effect.apply(game, ability, abilityToModify);
|
||||
|
@ -647,7 +647,7 @@ public class ContinuousEffects implements Serializable {
|
|||
// get the applyable splice abilities
|
||||
List<SpliceOntoArcaneAbility> spliceAbilities = new ArrayList<>();
|
||||
for (SpliceCardEffect effect : spliceEffects) {
|
||||
HashSet<Ability> abilities = spliceCardEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = spliceCardEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (effect.applies(abilityToModify, ability, game)) {
|
||||
spliceAbilities.add((SpliceOntoArcaneAbility) ability);
|
||||
|
@ -741,14 +741,14 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
public boolean replaceEvent(GameEvent event, Game game) {
|
||||
boolean caught = false;
|
||||
HashMap<UUID, HashSet<UUID>> consumed = new HashMap<>();
|
||||
Map<UUID, Set<UUID>> consumed = new HashMap<>();
|
||||
do {
|
||||
HashMap<ReplacementEffect, HashSet<Ability>> rEffects = getApplicableReplacementEffects(event, game);
|
||||
Map<ReplacementEffect, Set<Ability>> rEffects = getApplicableReplacementEffects(event, game);
|
||||
// Remove all consumed effects (ability dependant)
|
||||
for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext();) {
|
||||
ReplacementEffect entry = it1.next();
|
||||
if (consumed.containsKey(entry.getId())) {
|
||||
HashSet<UUID> consumedAbilitiesIds = consumed.get(entry.getId());
|
||||
Set<UUID> consumedAbilitiesIds = consumed.get(entry.getId());
|
||||
if (rEffects.get(entry) == null || consumedAbilitiesIds.size() == rEffects.get(entry).size()) {
|
||||
it1.remove();
|
||||
} else {
|
||||
|
@ -770,7 +770,7 @@ public class ContinuousEffects implements Serializable {
|
|||
boolean onlyOne = false;
|
||||
if (rEffects.size() == 1) {
|
||||
ReplacementEffect effect = rEffects.keySet().iterator().next();
|
||||
HashSet<Ability> abilities;
|
||||
Set<Ability> abilities;
|
||||
if (effect.getEffectType() == EffectType.REPLACEMENT) {
|
||||
abilities = replacementEffects.getAbility(effect.getId());
|
||||
} else {
|
||||
|
@ -791,7 +791,7 @@ public class ContinuousEffects implements Serializable {
|
|||
int checked = 0;
|
||||
ReplacementEffect rEffect = null;
|
||||
Ability rAbility = null;
|
||||
for (Map.Entry<ReplacementEffect, HashSet<Ability>> entry : rEffects.entrySet()) {
|
||||
for (Map.Entry<ReplacementEffect, Set<Ability>> entry : rEffects.entrySet()) {
|
||||
if (entry.getValue() == null) {
|
||||
if (checked == index) {
|
||||
rEffect = entry.getKey();
|
||||
|
@ -800,7 +800,7 @@ public class ContinuousEffects implements Serializable {
|
|||
checked++;
|
||||
}
|
||||
} else {
|
||||
HashSet<Ability> abilities = entry.getValue();
|
||||
Set<Ability> abilities = entry.getValue();
|
||||
int size = abilities.size();
|
||||
if (index > (checked + size - 1)) {
|
||||
checked += size;
|
||||
|
@ -831,13 +831,13 @@ public class ContinuousEffects implements Serializable {
|
|||
// add the applied effect to the consumed effects
|
||||
if (rEffect != null) {
|
||||
if (consumed.containsKey(rEffect.getId())) {
|
||||
HashSet<UUID> set = consumed.get(rEffect.getId());
|
||||
Set<UUID> set = consumed.get(rEffect.getId());
|
||||
if (rAbility != null) {
|
||||
set.add(rAbility.getId());
|
||||
|
||||
}
|
||||
} else {
|
||||
HashSet<UUID> set = new HashSet<>();
|
||||
Set<UUID> set = new HashSet<>();
|
||||
if (rAbility != null) { // in case of AuraReplacementEffect or PlaneswalkerReplacementEffect there is no Ability
|
||||
set.add(rAbility.getId());
|
||||
}
|
||||
|
@ -860,7 +860,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
List<ContinuousEffect> layer = filterLayeredEffects(activeLayerEffects, Layer.CopyEffects_1);
|
||||
for (ContinuousEffect effect : layer) {
|
||||
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
effect.apply(Layer.CopyEffects_1, SubLayer.NA, ability, game);
|
||||
}
|
||||
|
@ -876,7 +876,7 @@ public class ContinuousEffects implements Serializable {
|
|||
// e.g. Mind Control is controlled by Steal Enchantment
|
||||
while (true) {
|
||||
for (ContinuousEffect effect : layer) {
|
||||
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
effect.apply(Layer.ControlChangingEffects_2, SubLayer.NA, ability, game);
|
||||
}
|
||||
|
@ -908,7 +908,7 @@ public class ContinuousEffects implements Serializable {
|
|||
continue;
|
||||
}
|
||||
List<Ability> appliedAbilities = appliedEffectAbilities.get(effect);
|
||||
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (appliedAbilities == null || !appliedAbilities.contains(ability)) {
|
||||
if (appliedAbilities == null) {
|
||||
|
@ -955,7 +955,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
layer = filterLayeredEffects(activeLayerEffects, Layer.PTChangingEffects_7);
|
||||
for (ContinuousEffect effect : layer) {
|
||||
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (abilityActive(ability, game)) {
|
||||
effect.apply(Layer.PTChangingEffects_7, SubLayer.CharacteristicDefining_7a, ability, game);
|
||||
|
@ -963,13 +963,13 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
}
|
||||
for (ContinuousEffect effect : layer) {
|
||||
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
effect.apply(Layer.PTChangingEffects_7, SubLayer.SetPT_7b, ability, game);
|
||||
}
|
||||
}
|
||||
for (ContinuousEffect effect : layer) {
|
||||
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
effect.apply(Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, ability, game);
|
||||
}
|
||||
|
@ -978,21 +978,21 @@ public class ContinuousEffects implements Serializable {
|
|||
applyCounters.apply(Layer.PTChangingEffects_7, SubLayer.Counters_7d, null, game);
|
||||
|
||||
for (ContinuousEffect effect : layer) {
|
||||
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
effect.apply(Layer.PTChangingEffects_7, SubLayer.SwitchPT_e, ability, game);
|
||||
}
|
||||
}
|
||||
layer = filterLayeredEffects(activeLayerEffects, Layer.PlayerEffects);
|
||||
for (ContinuousEffect effect : layer) {
|
||||
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
effect.apply(Layer.PlayerEffects, SubLayer.NA, ability, game);
|
||||
}
|
||||
}
|
||||
layer = filterLayeredEffects(activeLayerEffects, Layer.RulesEffects);
|
||||
for (ContinuousEffect effect : layer) {
|
||||
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
effect.apply(Layer.RulesEffects, SubLayer.NA, ability, game);
|
||||
}
|
||||
|
@ -1034,13 +1034,13 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
|
||||
private void applyContinuousEffect(ContinuousEffect effect, Layer currentLayer, Game game) {
|
||||
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
effect.apply(currentLayer, SubLayer.NA, ability, game);
|
||||
}
|
||||
}
|
||||
|
||||
public HashSet<Ability> getLayeredEffectAbilities(ContinuousEffect effect) {
|
||||
public Set<Ability> getLayeredEffectAbilities(ContinuousEffect effect) {
|
||||
return layeredEffects.getAbility(effect.getId());
|
||||
}
|
||||
|
||||
|
@ -1135,7 +1135,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
private void setControllerForEffect(ContinuousEffectsList<?> effects, UUID sourceId, UUID controllerId) {
|
||||
for (Effect effect : effects) {
|
||||
HashSet<Ability> abilities = effects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = effects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (ability.getSourceId() != null) {
|
||||
if (ability.getSourceId().equals(sourceId)) {
|
||||
|
@ -1200,9 +1200,9 @@ public class ContinuousEffects implements Serializable {
|
|||
temporaryEffects.clear();
|
||||
}
|
||||
|
||||
public Map<String, String> getReplacementEffectsTexts(HashMap<ReplacementEffect, HashSet<Ability>> rEffects, Game game) {
|
||||
public Map<String, String> getReplacementEffectsTexts(Map<ReplacementEffect, Set<Ability>> rEffects, Game game) {
|
||||
Map<String, String> texts = new LinkedHashMap<>();
|
||||
for (Map.Entry<ReplacementEffect, HashSet<Ability>> entry : rEffects.entrySet()) {
|
||||
for (Map.Entry<ReplacementEffect, Set<Ability>> entry : rEffects.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
for (Ability ability : entry.getValue()) {
|
||||
MageObject object = game.getObject(ability.getSourceId());
|
||||
|
@ -1229,7 +1229,7 @@ public class ContinuousEffects implements Serializable {
|
|||
public UUID getControllerOfSourceId(UUID sourceId) {
|
||||
UUID controllerFound = null;
|
||||
for (PreventionEffect effect : preventionEffects) {
|
||||
HashSet<Ability> abilities = preventionEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = preventionEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (ability.getSourceId().equals(sourceId)) {
|
||||
if (controllerFound == null || controllerFound.equals(ability.getControllerId())) {
|
||||
|
@ -1242,7 +1242,7 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
}
|
||||
for (ReplacementEffect effect : replacementEffects) {
|
||||
HashSet<Ability> abilities = replacementEffects.getAbility(effect.getId());
|
||||
Set<Ability> abilities = replacementEffects.getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (ability.getSourceId() != null) {
|
||||
if (ability.getSourceId().equals(sourceId)) {
|
||||
|
|
|
@ -27,20 +27,14 @@
|
|||
*/
|
||||
package mage.abilities.effects;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.MageSingleton;
|
||||
import mage.constants.Duration;
|
||||
import mage.game.Game;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @param <T>
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
@ -50,7 +44,7 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
|
|||
private static final Logger logger = Logger.getLogger(ContinuousEffectsList.class);
|
||||
|
||||
// the effectAbilityMap holds for each effect all abilities that are connected (used) with this effect
|
||||
private final Map<UUID, HashSet<Ability>> effectAbilityMap = new HashMap<>();
|
||||
private final Map<UUID, Set<Ability>> effectAbilityMap = new HashMap<>();
|
||||
|
||||
public ContinuousEffectsList() {
|
||||
}
|
||||
|
@ -60,8 +54,8 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
|
|||
for (ContinuousEffect cost : effects) {
|
||||
this.add((T) cost.copy());
|
||||
}
|
||||
for (Map.Entry<UUID, HashSet<Ability>> entry : effects.effectAbilityMap.entrySet()) {
|
||||
HashSet<Ability> newSet = new HashSet<>();
|
||||
for (Map.Entry<UUID, Set<Ability>> entry : effects.effectAbilityMap.entrySet()) {
|
||||
Set<Ability> newSet = new HashSet<>();
|
||||
for (Ability ability : entry.getValue()) {
|
||||
newSet.add(ability.copy());
|
||||
}
|
||||
|
@ -104,7 +98,7 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
|
|||
}
|
||||
|
||||
private boolean isInactive(T effect, Game game) {
|
||||
HashSet<Ability> set = effectAbilityMap.get(effect.getId());
|
||||
Set<Ability> set = effectAbilityMap.get(effect.getId());
|
||||
if (set == null) {
|
||||
logger.debug("No abilities for effect found: " + effect.toString());
|
||||
return false;
|
||||
|
@ -153,7 +147,7 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
|
|||
*/
|
||||
public void addEffect(T effect, Ability source) {
|
||||
if (effectAbilityMap.containsKey(effect.getId())) {
|
||||
HashSet<Ability> set = effectAbilityMap.get(effect.getId());
|
||||
Set<Ability> set = effectAbilityMap.get(effect.getId());
|
||||
for (Ability ability : set) {
|
||||
if (ability.getId().equals(source.getId()) && ability.getSourceId().equals(source.getSourceId())) {
|
||||
return;
|
||||
|
@ -162,18 +156,18 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
|
|||
set.add(source);
|
||||
return;
|
||||
}
|
||||
HashSet<Ability> set = new HashSet<>();
|
||||
Set<Ability> set = new HashSet<>();
|
||||
set.add(source);
|
||||
this.effectAbilityMap.put(effect.getId(), set);
|
||||
this.add(effect);
|
||||
}
|
||||
|
||||
public HashSet<Ability> getAbility(UUID effectId) {
|
||||
public Set<Ability> getAbility(UUID effectId) {
|
||||
return effectAbilityMap.getOrDefault(effectId, new HashSet<>());
|
||||
}
|
||||
|
||||
public void removeEffects(UUID effectIdToRemove, Set<Ability> abilitiesToRemove) {
|
||||
HashSet<Ability> abilities = effectAbilityMap.get(effectIdToRemove);
|
||||
Set<Ability> abilities = effectAbilityMap.get(effectIdToRemove);
|
||||
if (abilitiesToRemove != null && abilities != null) {
|
||||
abilities.removeAll(abilitiesToRemove);
|
||||
}
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.choices.Choice;
|
||||
|
@ -38,13 +36,17 @@ import mage.game.Game;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ChooseModeEffect extends OneShotEffect {
|
||||
|
||||
protected final ArrayList<String> modes = new ArrayList();
|
||||
protected final List<String> modes = new ArrayList();
|
||||
protected final String choiceMessage;
|
||||
|
||||
public ChooseModeEffect(String choiceMessage, String... modes) {
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.effects.EntersBattlefieldEffect;
|
||||
|
@ -39,6 +37,10 @@ import mage.counters.Counter;
|
|||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Use this effect only (I guess) with EntersBattlefieldAbility like abilities
|
||||
*
|
||||
|
@ -77,7 +79,7 @@ public class EntersBattlefieldWithXCountersEffect extends OneShotEffect {
|
|||
if (amount > 0) {
|
||||
Counter counterToAdd = counter.copy();
|
||||
counterToAdd.add(amount - counter.getCount());
|
||||
ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects");
|
||||
List<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects");
|
||||
permanent.addCounters(counterToAdd, source, game, appliedEffects);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
*/
|
||||
package mage.abilities.effects.common.continuous;
|
||||
|
||||
import java.util.HashSet;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.choices.ChoiceImpl;
|
||||
|
@ -37,6 +36,9 @@ import mage.game.permanent.Permanent;
|
|||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author a
|
||||
|
@ -71,7 +73,7 @@ public class LoseAbilityOrAnotherAbilityTargetEffect extends LoseAbilityTargetEf
|
|||
ChoiceImpl chooseAbility = new ChoiceImpl();
|
||||
chooseAbility.setMessage("What ability do you wish to remove?");
|
||||
|
||||
HashSet<String> choice = new HashSet<>();
|
||||
Set<String> choice = new HashSet<>();
|
||||
|
||||
if (permanent.getAbilities().contains(ability)) {
|
||||
choice.add(ability.getRule());
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package mage.actions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.actions.impl.MageAction;
|
||||
import mage.actions.score.ArtificialScoringSystem;
|
||||
import mage.cards.Card;
|
||||
|
@ -12,6 +9,10 @@ import mage.game.events.GameEvent;
|
|||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Action for drawing cards.
|
||||
*
|
||||
|
@ -21,12 +22,12 @@ public class MageDrawAction extends MageAction {
|
|||
|
||||
private final Player player;
|
||||
private final int amount;
|
||||
private final ArrayList<UUID> appliedEffects;
|
||||
private final List<UUID> appliedEffects;
|
||||
private final List<Card> drawnCards;
|
||||
|
||||
private static final int NEGATIVE_VALUE = -1000000;
|
||||
|
||||
public MageDrawAction(Player player, int amount, ArrayList<UUID> appliedEffects) {
|
||||
public MageDrawAction(Player player, int amount, List<UUID> appliedEffects) {
|
||||
this.player = player;
|
||||
this.amount = amount;
|
||||
this.appliedEffects = appliedEffects;
|
||||
|
|
|
@ -27,16 +27,12 @@
|
|||
*/
|
||||
package mage.cards;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.Counter;
|
||||
|
@ -46,6 +42,9 @@ import mage.game.Game;
|
|||
import mage.game.GameState;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface Card extends MageObject {
|
||||
|
||||
|
||||
|
@ -127,7 +126,7 @@ public interface Card extends MageObject {
|
|||
*/
|
||||
boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag);
|
||||
|
||||
boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects);
|
||||
boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects);
|
||||
|
||||
/**
|
||||
* Moves the card to an exile zone
|
||||
|
@ -140,7 +139,7 @@ public interface Card extends MageObject {
|
|||
*/
|
||||
boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game);
|
||||
|
||||
boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects);
|
||||
boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects);
|
||||
|
||||
boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId);
|
||||
|
||||
|
@ -152,7 +151,7 @@ public interface Card extends MageObject {
|
|||
|
||||
boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown);
|
||||
|
||||
boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown, ArrayList<UUID> appliedEffects);
|
||||
boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown, List<UUID> appliedEffects);
|
||||
|
||||
void setZone(Zone zone, Game game);
|
||||
|
||||
|
@ -170,7 +169,7 @@ public interface Card extends MageObject {
|
|||
|
||||
boolean addCounters(Counter counter, Ability source, Game game);
|
||||
|
||||
boolean addCounters(Counter counter, Ability source, Game game, ArrayList<UUID> appliedEffects);
|
||||
boolean addCounters(Counter counter, Ability source, Game game, List<UUID> appliedEffects);
|
||||
|
||||
void removeCounters(String name, int amount, Game game);
|
||||
|
||||
|
|
|
@ -28,24 +28,18 @@
|
|||
package mage.cards;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectImpl;
|
||||
import mage.Mana;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.AbilitiesImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.PlayLandAbility;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.mana.ActivatedManaAbilityImpl;
|
||||
import mage.cards.repository.PluginClassloaderRegistery;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ColoredManaSymbol;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.Counters;
|
||||
import mage.game.*;
|
||||
|
@ -286,6 +280,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
|
||||
/**
|
||||
* Public in order to support adding abilities to SplitCardHalf's
|
||||
*
|
||||
* @param ability
|
||||
*/
|
||||
public void addAbility(Ability ability) {
|
||||
|
@ -358,7 +353,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
Zone fromZone = game.getState().getZone(objectId);
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, toZone, appliedEffects);
|
||||
ZoneChangeInfo zoneChangeInfo;
|
||||
|
@ -394,7 +389,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
|
||||
Zone fromZone = game.getState().getZone(objectId);
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, Zone.EXILED, appliedEffects);
|
||||
ZoneChangeInfo.Exile info = new ZoneChangeInfo.Exile(event, exileId, name);
|
||||
|
@ -417,7 +412,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean faceDown, ArrayList<UUID> appliedEffects) {
|
||||
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean faceDown, List<UUID> appliedEffects) {
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, controllerId, fromZone, Zone.BATTLEFIELD, appliedEffects);
|
||||
ZoneChangeInfo.Battlefield info = new ZoneChangeInfo.Battlefield(event, faceDown, tapped);
|
||||
return ZonesHandler.moveCard(info, game);
|
||||
|
@ -627,9 +622,9 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean addCounters(Counter counter, Ability source, Game game, ArrayList<UUID> appliedEffects) {
|
||||
public boolean addCounters(Counter counter, Ability source, Game game, List<UUID> appliedEffects) {
|
||||
boolean returnCode = true;
|
||||
UUID sourceId = (source == null ? null : source.getSourceId());
|
||||
UUID sourceId = (source == null ? getId() : source.getSourceId());
|
||||
GameEvent countersEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTERS, objectId, sourceId, getControllerOrOwner(), counter.getName(), counter.getCount());
|
||||
countersEvent.setAppliedEffects(appliedEffects);
|
||||
if (!game.replaceEvent(countersEvent)) {
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
*/
|
||||
package mage.cards;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
|
@ -37,6 +35,9 @@ import mage.game.Game;
|
|||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author emerald000
|
||||
|
@ -133,7 +134,7 @@ public abstract class MeldCard extends CardImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean addCounters(Counter counter, Ability source, Game game, ArrayList<UUID> appliedEffects) {
|
||||
public boolean addCounters(Counter counter, Ability source, Game game, List<UUID> appliedEffects) {
|
||||
if (this.isMelded()) {
|
||||
return super.addCounters(counter, source, game, appliedEffects);
|
||||
} else {
|
||||
|
|
|
@ -27,9 +27,6 @@
|
|||
*/
|
||||
package mage.cards;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.AbilitiesImpl;
|
||||
import mage.abilities.Ability;
|
||||
|
@ -39,6 +36,10 @@ import mage.constants.SpellAbilityType;
|
|||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
|
@ -91,7 +92,7 @@ public abstract class SplitCard extends CardImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
if (super.moveToZone(toZone, sourceId, game, flag, appliedEffects)) {
|
||||
game.getState().setZone(getLeftHalfCard().getId(), toZone);
|
||||
game.getState().setZone(getRightHalfCard().getId(), toZone);
|
||||
|
@ -101,7 +102,7 @@ public abstract class SplitCard extends CardImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
|
||||
if (super.moveToExile(exileId, name, sourceId, game, appliedEffects)) {
|
||||
Zone currentZone = game.getState().getZone(getId());
|
||||
game.getState().setZone(getLeftHalfCard().getId(), currentZone);
|
||||
|
|
|
@ -5,13 +5,15 @@
|
|||
*/
|
||||
package mage.cards;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
|
@ -51,12 +53,12 @@ public class SplitCardHalfImpl extends CardImpl implements SplitCardHalf {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
return splitCardParent.moveToZone(toZone, sourceId, game, flag, appliedEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
|
||||
return splitCardParent.moveToExile(exileId, name, sourceId, game, appliedEffects);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,15 +27,6 @@
|
|||
*/
|
||||
package mage.game.combat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.RequirementEffect;
|
||||
|
@ -59,6 +50,9 @@ import mage.util.Copyable;
|
|||
import mage.util.trace.TraceUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
@ -308,7 +302,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
for (Permanent creature : player.getAvailableAttackers(game)) {
|
||||
boolean mustAttack = false;
|
||||
Set<UUID> defendersForcedToAttack = new HashSet<>();
|
||||
for (Map.Entry<RequirementEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
||||
for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
||||
RequirementEffect effect = entry.getKey();
|
||||
if (effect.mustAttack(game)) {
|
||||
mustAttack = true;
|
||||
|
@ -395,7 +389,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
}
|
||||
for (UUID attackingCreatureId : this.getAttackers()) {
|
||||
Permanent attackingCreature = game.getPermanent(attackingCreatureId);
|
||||
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(attackingCreature, game).entrySet()) {
|
||||
for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(attackingCreature, game).entrySet()) {
|
||||
RestrictionEffect effect = entry.getKey();
|
||||
for (Ability ability : entry.getValue()) {
|
||||
if (!effect.canAttackCheckAfter(numberAttackers, ability, game)) {
|
||||
|
@ -581,7 +575,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
return;
|
||||
}
|
||||
for (Permanent possibleBlocker : game.getBattlefield().getActivePermanents(filterBlockers, attackingPlayer.getId(), game)) {
|
||||
for (Map.Entry<RequirementEffect, HashSet<Ability>> requirementEntry : game.getContinuousEffects().getApplicableRequirementEffects(possibleBlocker, game).entrySet()) {
|
||||
for (Map.Entry<RequirementEffect, Set<Ability>> requirementEntry : game.getContinuousEffects().getApplicableRequirementEffects(possibleBlocker, game).entrySet()) {
|
||||
if (requirementEntry.getKey().mustBlock(game)) {
|
||||
for (Ability ability : requirementEntry.getValue()) {
|
||||
UUID attackingCreatureId = requirementEntry.getKey().mustBlockAttacker(ability, game);
|
||||
|
@ -658,7 +652,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
// Creature is already blocking but not forced to do so
|
||||
if (creature.getBlocking() > 0) {
|
||||
// get all requirement effects that apply to the creature (e.g. is able to block attacker)
|
||||
for (Map.Entry<RequirementEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
||||
for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
||||
RequirementEffect effect = entry.getKey();
|
||||
// get possible mustBeBlockedByAtLeastOne blocker
|
||||
for (Ability ability : entry.getValue()) {
|
||||
|
@ -680,7 +674,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
// Creature is not blocking yet
|
||||
if (creature.getBlocking() == 0) {
|
||||
// get all requirement effects that apply to the creature
|
||||
for (Map.Entry<RequirementEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
||||
for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
||||
RequirementEffect effect = entry.getKey();
|
||||
// get possible mustBeBlockedByAtLeastOne blocker
|
||||
for (Ability ability : entry.getValue()) {
|
||||
|
@ -980,7 +974,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
for (UUID blockingCreatureId : this.getBlockers()) {
|
||||
Permanent blockingCreature = game.getPermanent(blockingCreatureId);
|
||||
if (blockingCreature != null) {
|
||||
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(blockingCreature, game).entrySet()) {
|
||||
for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(blockingCreature, game).entrySet()) {
|
||||
RestrictionEffect effect = entry.getKey();
|
||||
for (Ability ability : entry.getValue()) {
|
||||
if (!effect.canBlockCheckAfter(ability, game)) {
|
||||
|
@ -1000,7 +994,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
for (UUID attackingCreatureId : this.getAttackers()) {
|
||||
Permanent attackingCreature = game.getPermanent(attackingCreatureId);
|
||||
if (attackingCreature != null) {
|
||||
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(attackingCreature, game).entrySet()) {
|
||||
for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(attackingCreature, game).entrySet()) {
|
||||
RestrictionEffect effect = entry.getKey();
|
||||
for (Ability ability : entry.getValue()) {
|
||||
if (!effect.canBeBlockedCheckAfter(attackingCreature, ability, game)) {
|
||||
|
|
|
@ -340,7 +340,7 @@ public abstract class DraftImpl implements Draft {
|
|||
|
||||
@Override
|
||||
public void resetBufferedCards() {
|
||||
HashSet<ExpansionSet> setsDone = new HashSet<>();
|
||||
Set<ExpansionSet> setsDone = new HashSet<>();
|
||||
for(ExpansionSet set: sets) {
|
||||
if (!setsDone.contains(set)) {
|
||||
set.removeSavedCards();
|
||||
|
|
|
@ -27,10 +27,12 @@
|
|||
*/
|
||||
package mage.game.events;
|
||||
|
||||
import mage.constants.Zone;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -46,7 +48,7 @@ public class GameEvent implements Serializable {
|
|||
protected boolean flag;
|
||||
protected String data;
|
||||
protected Zone zone;
|
||||
protected ArrayList<UUID> appliedEffects = new ArrayList<>();
|
||||
protected List<UUID> appliedEffects = new ArrayList<>();
|
||||
protected UUID customEventType = null;
|
||||
|
||||
public enum EventType {
|
||||
|
@ -460,7 +462,7 @@ public class GameEvent implements Serializable {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public ArrayList<UUID> getAppliedEffects() {
|
||||
public List<UUID> getAppliedEffects() {
|
||||
return appliedEffects;
|
||||
}
|
||||
|
||||
|
@ -468,13 +470,13 @@ public class GameEvent implements Serializable {
|
|||
return type == EventType.CUSTOM_EVENT && this.customEventType.equals(customEventType);
|
||||
}
|
||||
|
||||
public void addAppliedEffects(ArrayList<UUID> appliedEffects) {
|
||||
public void addAppliedEffects(List<UUID> appliedEffects) {
|
||||
if (appliedEffects != null) {
|
||||
this.appliedEffects.addAll(appliedEffects);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAppliedEffects(ArrayList<UUID> appliedEffects) {
|
||||
public void setAppliedEffects(List<UUID> appliedEffects) {
|
||||
if (appliedEffects != null) {
|
||||
if (this.appliedEffects.isEmpty()) {
|
||||
this.appliedEffects = appliedEffects; // Use object refecence to handle that an replacement effect can only be once applied to an event
|
||||
|
|
|
@ -28,11 +28,12 @@
|
|||
|
||||
package mage.game.events;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
@ -50,7 +51,7 @@ public class ZoneChangeEvent extends GameEvent {
|
|||
this.target = target;
|
||||
}
|
||||
|
||||
public ZoneChangeEvent(Permanent target, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone, ArrayList<UUID> appliedEffects) {
|
||||
public ZoneChangeEvent(Permanent target, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone, List<UUID> appliedEffects) {
|
||||
super(EventType.ZONE_CHANGE, target.getId(), sourceId, playerId);
|
||||
this.fromZone = fromZone;
|
||||
this.toZone = toZone;
|
||||
|
@ -66,7 +67,7 @@ public class ZoneChangeEvent extends GameEvent {
|
|||
this.toZone = toZone;
|
||||
}
|
||||
|
||||
public ZoneChangeEvent(UUID targetId, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone, ArrayList<UUID> appliedEffects) {
|
||||
public ZoneChangeEvent(UUID targetId, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone, List<UUID> appliedEffects) {
|
||||
super(EventType.ZONE_CHANGE, targetId, sourceId, playerId);
|
||||
this.fromZone = fromZone;
|
||||
this.toZone = toZone;
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
*/
|
||||
package mage.game.permanent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
|
@ -41,6 +37,10 @@ import mage.game.Controllable;
|
|||
import mage.game.Game;
|
||||
import mage.game.GameState;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface Permanent extends Card, Controllable {
|
||||
|
||||
void setControllerId(UUID controllerId);
|
||||
|
@ -129,7 +129,7 @@ public interface Permanent extends Card, Controllable {
|
|||
|
||||
int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable);
|
||||
|
||||
int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, ArrayList<UUID> appliedEffects);
|
||||
int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, List<UUID> appliedEffects);
|
||||
|
||||
/**
|
||||
* used in combat only to deal damage at the same time
|
||||
|
@ -267,7 +267,7 @@ public interface Permanent extends Card, Controllable {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
HashSet<MageObjectReference> getDealtDamageByThisTurn();
|
||||
Set<MageObjectReference> getDealtDamageByThisTurn();
|
||||
|
||||
/**
|
||||
* Imprint some other card to this one.
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
*/
|
||||
package mage.game.permanent;
|
||||
|
||||
import java.util.*;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.ObjectColor;
|
||||
|
@ -56,6 +55,8 @@ import mage.players.Player;
|
|||
import mage.util.GameLog;
|
||||
import mage.util.ThreadLocalStringBuilder;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
@ -100,7 +101,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
protected boolean deathtouched;
|
||||
protected List<UUID> attachments = new ArrayList<>();
|
||||
protected Map<String, List<UUID>> connectedCards = new HashMap<>();
|
||||
protected HashSet<MageObjectReference> dealtDamageByThisTurn;
|
||||
protected Set<MageObjectReference> dealtDamageByThisTurn;
|
||||
protected UUID attachedTo;
|
||||
protected int attachedToZoneChangeCounter;
|
||||
protected MageObjectReference pairedPermanent;
|
||||
|
@ -695,7 +696,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, ArrayList<UUID> appliedEffects) {
|
||||
public int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, List<UUID> appliedEffects) {
|
||||
return damage(damage, sourceId, game, preventable, combat, false, appliedEffects);
|
||||
}
|
||||
|
||||
|
@ -709,7 +710,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
* method
|
||||
* @return
|
||||
*/
|
||||
private int damage(int damageAmount, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, ArrayList<UUID> appliedEffects) {
|
||||
private int damage(int damageAmount, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
|
||||
int damageDone = 0;
|
||||
if (damageAmount > 0 && canDamage(game.getObject(sourceId), game)) {
|
||||
if (this.isPlaneswalker()) {
|
||||
|
@ -794,7 +795,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
deathtouched = false;
|
||||
}
|
||||
|
||||
protected int damagePlaneswalker(int damage, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, ArrayList<UUID> appliedEffects) {
|
||||
protected int damagePlaneswalker(int damage, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
|
||||
GameEvent event = new DamagePlaneswalkerEvent(objectId, sourceId, controllerId, damage, preventable, combat);
|
||||
event.setAppliedEffects(appliedEffects);
|
||||
if (!game.replaceEvent(event)) {
|
||||
|
@ -812,7 +813,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
return 0;
|
||||
}
|
||||
|
||||
protected int damageCreature(int damage, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, ArrayList<UUID> appliedEffects) {
|
||||
protected int damageCreature(int damage, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
|
||||
GameEvent event = new DamageCreatureEvent(objectId, sourceId, controllerId, damage, preventable, combat);
|
||||
event.setAppliedEffects(appliedEffects);
|
||||
if (!game.replaceEvent(event)) {
|
||||
|
@ -1062,7 +1063,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
|
||||
private boolean canAttackCheckRestrictionEffects(UUID defenderId, Game game) {
|
||||
//20101001 - 508.1c
|
||||
for (Map.Entry<RestrictionEffect, HashSet<Ability>> effectEntry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
|
||||
for (Map.Entry<RestrictionEffect, Set<Ability>> effectEntry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
|
||||
if (!effectEntry.getKey().canAttack(game)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1090,7 +1091,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
//20101001 - 509.1b
|
||||
// check blocker restrictions
|
||||
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
|
||||
for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
|
||||
for (Ability ability : entry.getValue()) {
|
||||
if (!entry.getKey().canBlock(attacker, this, ability, game)) {
|
||||
return false;
|
||||
|
@ -1098,7 +1099,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
}
|
||||
// check also attacker's restriction effects
|
||||
for (Map.Entry<RestrictionEffect, HashSet<Ability>> restrictionEntry : game.getContinuousEffects().getApplicableRestrictionEffects(attacker, game).entrySet()) {
|
||||
for (Map.Entry<RestrictionEffect, Set<Ability>> restrictionEntry : game.getContinuousEffects().getApplicableRestrictionEffects(attacker, game).entrySet()) {
|
||||
for (Ability ability : restrictionEntry.getValue()) {
|
||||
if (!restrictionEntry.getKey().canBeBlocked(attacker, this, ability, game)) {
|
||||
return false;
|
||||
|
@ -1115,7 +1116,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
//20101001 - 509.1b
|
||||
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
|
||||
for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
|
||||
RestrictionEffect effect = entry.getKey();
|
||||
for (Ability ability : entry.getValue()) {
|
||||
if (!effect.canBlock(null, this, ability, game)) {
|
||||
|
@ -1136,7 +1137,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
*/
|
||||
@Override
|
||||
public boolean canUseActivatedAbilities(Game game) {
|
||||
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
|
||||
for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
|
||||
RestrictionEffect effect = entry.getKey();
|
||||
for (Ability ability : entry.getValue()) {
|
||||
if (!effect.canUseActivatedAbilities(this, ability, game)) {
|
||||
|
@ -1150,7 +1151,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
@Override
|
||||
public boolean canTransform(Ability source, Game game) {
|
||||
if (transformable) {
|
||||
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
|
||||
for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
|
||||
RestrictionEffect effect = entry.getKey();
|
||||
for (Ability ability : entry.getValue()) {
|
||||
if (!effect.canTransform(this, ability, game)) {
|
||||
|
@ -1237,7 +1238,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public HashSet<MageObjectReference> getDealtDamageByThisTurn() {
|
||||
public Set<MageObjectReference> getDealtDamageByThisTurn() {
|
||||
if (dealtDamageByThisTurn == null) {
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
@ -1376,7 +1377,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
Zone fromZone = game.getState().getZone(objectId);
|
||||
Player controller = game.getPlayer(controllerId);
|
||||
if (controller != null) {
|
||||
|
@ -1393,7 +1394,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
|
||||
Zone fromZone = game.getState().getZone(objectId);
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, ownerId, fromZone, Zone.EXILED, appliedEffects);
|
||||
ZoneChangeInfo.Exile info = new ZoneChangeInfo.Exile(event, exileId, name);
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
*/
|
||||
package mage.game.stack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
|
@ -62,6 +58,11 @@ import mage.game.permanent.PermanentCard;
|
|||
import mage.players.Player;
|
||||
import mage.util.GameLog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
@ -732,7 +733,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
// 706.10a If a copy of a spell is in a zone other than the stack, it ceases to exist.
|
||||
// If a copy of a card is in any zone other than the stack or the battlefield, it ceases to exist.
|
||||
// These are state-based actions. See rule 704.
|
||||
|
@ -748,7 +749,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
|
||||
return this.card.moveToExile(exileId, name, sourceId, game, appliedEffects);
|
||||
}
|
||||
|
||||
|
@ -768,7 +769,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown, ArrayList<UUID> appliedEffects) {
|
||||
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown, List<UUID> appliedEffects) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
|
@ -865,7 +866,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean addCounters(Counter counter, Ability source, Game game, ArrayList<UUID> appliedEffects) {
|
||||
public boolean addCounters(Counter counter, Ability source, Game game, List<UUID> appliedEffects) {
|
||||
return card.addCounters(counter, source, game, appliedEffects);
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
|
||||
int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable);
|
||||
|
||||
int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, ArrayList<UUID> appliedEffects);
|
||||
int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects);
|
||||
|
||||
// to handle rule changing effects (613.10)
|
||||
boolean isCanLoseLife();
|
||||
|
@ -350,7 +350,7 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
|
||||
int drawCards(int num, Game game);
|
||||
|
||||
int drawCards(int num, Game game, ArrayList<UUID> appliedEffects);
|
||||
int drawCards(int num, Game game, List<UUID> appliedEffects);
|
||||
|
||||
boolean cast(SpellAbility ability, Game game, boolean noMana);
|
||||
|
||||
|
@ -674,7 +674,7 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
|
||||
boolean moveCards(Card card, Zone toZone, Ability source, Game game);
|
||||
|
||||
boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects);
|
||||
boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects);
|
||||
|
||||
boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game);
|
||||
|
||||
|
@ -694,7 +694,7 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
* @param appliedEffects
|
||||
* @return
|
||||
*/
|
||||
boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects);
|
||||
boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects);
|
||||
|
||||
boolean moveCardsToExile(Card card, Ability source, Game game, boolean withName, UUID exileId, String exileZoneName);
|
||||
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
*/
|
||||
package mage.players;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import mage.ConditionalMana;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
|
@ -91,6 +87,11 @@ import mage.util.GameLog;
|
|||
import mage.util.RandomUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public abstract class PlayerImpl implements Player, Serializable {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(PlayerImpl.class);
|
||||
|
@ -621,7 +622,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int drawCards(int num, Game game, ArrayList<UUID> appliedEffects) {
|
||||
public int drawCards(int num, Game game, List<UUID> appliedEffects) {
|
||||
return game.doAction(new MageDrawAction(this, num, appliedEffects));
|
||||
}
|
||||
|
||||
|
@ -1472,8 +1473,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
@Override
|
||||
public void untap(Game game) {
|
||||
// create list of all "notMoreThan" effects to track which one are consumed
|
||||
HashMap<Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>>, Integer> notMoreThanEffectsUsage = new HashMap<>();
|
||||
for (Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>> restrictionEffect : game.getContinuousEffects().getApplicableRestrictionUntapNotMoreThanEffects(this, game).entrySet()) {
|
||||
HashMap<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffectsUsage = new HashMap<>();
|
||||
for (Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>> restrictionEffect : game.getContinuousEffects().getApplicableRestrictionUntapNotMoreThanEffects(this, game).entrySet()) {
|
||||
notMoreThanEffectsUsage.put(restrictionEffect, restrictionEffect.getKey().getNumber());
|
||||
}
|
||||
|
||||
|
@ -1497,7 +1498,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
do {
|
||||
playerCanceledSelection = false;
|
||||
// select permanents to untap to consume the "notMoreThan" effects
|
||||
for (Map.Entry<Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>>, Integer> handledEntry : notMoreThanEffectsUsage.entrySet()) {
|
||||
for (Map.Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> handledEntry : notMoreThanEffectsUsage.entrySet()) {
|
||||
// select a permanent to untap for this entry
|
||||
int numberToUntap = handledEntry.getValue();
|
||||
if (numberToUntap > 0) {
|
||||
|
@ -1535,7 +1536,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
// don't allow to select same permanent twice
|
||||
filter.add(Predicates.not(new PermanentIdPredicate(selectedPermanent.getId())));
|
||||
// reduce available untap numbers from other "UntapNotMoreThan" effects if selected permanent applies to their filter too
|
||||
for (Entry<Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) {
|
||||
for (Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) {
|
||||
if (notMoreThanEffect.getValue() > 0 && notMoreThanEffect.getKey().getKey().getFilter().match(selectedPermanent, game)) {
|
||||
notMoreThanEffect.setValue(notMoreThanEffect.getValue() - 1);
|
||||
}
|
||||
|
@ -1574,7 +1575,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
boolean doUntap = true;
|
||||
if (!selectedToUntap.contains(permanent)) {
|
||||
// if the permanent is covered by one of the restriction effects, don't untap it
|
||||
for (Entry<Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) {
|
||||
for (Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) {
|
||||
if (notMoreThanEffect.getKey().getKey().getFilter().match(permanent, game)) {
|
||||
doUntap = false;
|
||||
break;
|
||||
|
@ -1601,14 +1602,14 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
private List<Permanent> getPermanentsThatCanBeUntapped(Game game, List<Permanent> canBeUntapped, RestrictionUntapNotMoreThanEffect handledEffect, HashMap<Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>>, Integer> notMoreThanEffectsUsage) {
|
||||
private List<Permanent> getPermanentsThatCanBeUntapped(Game game, List<Permanent> canBeUntapped, RestrictionUntapNotMoreThanEffect handledEffect, Map<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffectsUsage) {
|
||||
List<Permanent> leftForUntap = new ArrayList<>();
|
||||
// select permanents that can still be untapped
|
||||
for (Permanent permanent : canBeUntapped) {
|
||||
if (handledEffect.getFilter().match(permanent, game)) { // matches the restricted permanents of handled entry
|
||||
boolean canBeSelected = true;
|
||||
// check if the permanent is restriced by another restriction that has left no permanent
|
||||
for (Entry<Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) {
|
||||
for (Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) {
|
||||
if (notMoreThanEffect.getKey().getKey().getFilter().match(permanent, game) && notMoreThanEffect.getValue() == 0) {
|
||||
canBeSelected = false;
|
||||
break;
|
||||
|
@ -1763,12 +1764,12 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, ArrayList<UUID> appliedEffects) {
|
||||
public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects) {
|
||||
return doDamage(damage, sourceId, game, combatDamage, preventable, appliedEffects);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"null", "ConstantConditions"})
|
||||
private int doDamage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, ArrayList<UUID> appliedEffects) {
|
||||
private int doDamage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects) {
|
||||
if (damage > 0 && canDamage(game.getObject(sourceId), game)) {
|
||||
GameEvent event = new DamagePlayerEvent(playerId, sourceId, playerId, damage, preventable, combatDamage);
|
||||
event.setAppliedEffects(appliedEffects);
|
||||
|
@ -3093,7 +3094,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects) {
|
||||
Set<Card> cardList = new HashSet<>();
|
||||
if (card != null) {
|
||||
cardList.add(card);
|
||||
|
@ -3112,7 +3113,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) {
|
||||
public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects) {
|
||||
if (cards.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
package mage.util.trace;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.StaticAbility;
|
||||
import mage.abilities.effects.ContinuousEffectsList;
|
||||
import mage.abilities.effects.RestrictionEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.ReachAbility;
|
||||
import mage.abilities.keyword.CantBeBlockedSourceAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.IntimidateAbility;
|
||||
import mage.abilities.keyword.ReachAbility;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.combat.Combat;
|
||||
|
@ -18,9 +16,7 @@ import mage.game.combat.CombatGroup;
|
|||
import mage.game.permanent.Permanent;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.keyword.IntimidateAbility;
|
||||
import mage.constants.CardType;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author magenoxx_at_gmail.com
|
||||
|
@ -146,8 +142,8 @@ public final class TraceUtil {
|
|||
|
||||
log.error(prefix+"Restriction effects:");
|
||||
log.error(prefix+" Applied to ATTACKER:");
|
||||
HashMap<RestrictionEffect, HashSet<Ability>> attackerResEffects = game.getContinuousEffects().getApplicableRestrictionEffects(attacker, game);
|
||||
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : attackerResEffects.entrySet()) {
|
||||
Map<RestrictionEffect, Set<Ability>> attackerResEffects = game.getContinuousEffects().getApplicableRestrictionEffects(attacker, game);
|
||||
for (Map.Entry<RestrictionEffect, Set<Ability>> entry : attackerResEffects.entrySet()) {
|
||||
log.error(prefix+" " + entry.getKey());
|
||||
log.error(prefix+" id=" + entry.getKey().getId());
|
||||
for (Ability ability: entry.getValue()) {
|
||||
|
@ -156,8 +152,8 @@ public final class TraceUtil {
|
|||
}
|
||||
log.error(prefix+" Applied to BLOCKER:");
|
||||
if (blocker != null) {
|
||||
HashMap<RestrictionEffect, HashSet<Ability>> blockerResEffects = game.getContinuousEffects().getApplicableRestrictionEffects(blocker, game);
|
||||
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : blockerResEffects.entrySet()) {
|
||||
Map<RestrictionEffect, Set<Ability>> blockerResEffects = game.getContinuousEffects().getApplicableRestrictionEffects(blocker, game);
|
||||
for (Map.Entry<RestrictionEffect, Set<Ability>> entry : blockerResEffects.entrySet()) {
|
||||
log.error(prefix+" " + entry.getKey());
|
||||
log.error(prefix+" id=" + entry.getKey().getId());
|
||||
for (Ability ability: entry.getValue()) {
|
||||
|
|
|
@ -15,8 +15,8 @@ import mage.watchers.Watcher;
|
|||
*/
|
||||
public class LandfallWatcher extends Watcher {
|
||||
|
||||
final Set<UUID> playerPlayedLand = new HashSet<>(); // player that played land
|
||||
final Set<UUID> landPlayed = new HashSet<>(); // land played
|
||||
final Set<UUID> playerPlayedLand = new HashSet<>(); // player that had a land enter the battlefield
|
||||
final Set<UUID> landEnteredBattlefield = new HashSet<>(); // land played
|
||||
|
||||
public LandfallWatcher() {
|
||||
super(LandfallWatcher.class.getSimpleName(), WatcherScope.GAME);
|
||||
|
@ -25,7 +25,7 @@ public class LandfallWatcher extends Watcher {
|
|||
public LandfallWatcher(final LandfallWatcher watcher) {
|
||||
super(watcher);
|
||||
playerPlayedLand.addAll(watcher.playerPlayedLand);
|
||||
landPlayed.addAll(watcher.landPlayed);
|
||||
landEnteredBattlefield.addAll(watcher.landEnteredBattlefield);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,13 +35,13 @@ public class LandfallWatcher extends Watcher {
|
|||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.LAND_PLAYED) {
|
||||
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
|
||||
if (permanent != null
|
||||
&& permanent.isLand()
|
||||
&& !playerPlayedLand.contains(event.getPlayerId())) {
|
||||
playerPlayedLand.add(event.getPlayerId());
|
||||
landPlayed.add(event.getTargetId());
|
||||
landEnteredBattlefield.add(event.getTargetId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public class LandfallWatcher extends Watcher {
|
|||
@Override
|
||||
public void reset() {
|
||||
playerPlayedLand.clear();
|
||||
landPlayed.clear();
|
||||
landEnteredBattlefield.clear();
|
||||
super.reset();
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ public class LandfallWatcher extends Watcher {
|
|||
return playerPlayedLand.contains(playerId);
|
||||
}
|
||||
|
||||
public boolean wasLandPlayed(UUID landId) {
|
||||
return landPlayed.contains(landId);
|
||||
public boolean landEnteredBattlefield(UUID landId) {
|
||||
return landEnteredBattlefield.contains(landId);
|
||||
}
|
||||
}
|
||||
|
|
62
Mage/src/main/java/mage/watchers/common/PlayLandWatcher.java
Normal file
62
Mage/src/main/java/mage/watchers/common/PlayLandWatcher.java
Normal file
|
@ -0,0 +1,62 @@
|
|||
package mage.watchers.common;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
/**
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public class PlayLandWatcher extends Watcher {
|
||||
|
||||
final Set<UUID> playerPlayedLand = new HashSet<>(); // player that played land
|
||||
final Set<UUID> landPlayed = new HashSet<>(); // land played
|
||||
|
||||
public PlayLandWatcher() {
|
||||
super(PlayLandWatcher.class.getSimpleName(), WatcherScope.GAME);
|
||||
}
|
||||
|
||||
public PlayLandWatcher(final PlayLandWatcher watcher) {
|
||||
super(watcher);
|
||||
playerPlayedLand.addAll(watcher.playerPlayedLand);
|
||||
landPlayed.addAll(watcher.landPlayed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayLandWatcher copy() {
|
||||
return new PlayLandWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.LAND_PLAYED) {
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
|
||||
if (permanent != null
|
||||
&& permanent.isLand()
|
||||
&& !playerPlayedLand.contains(event.getPlayerId())) {
|
||||
playerPlayedLand.add(event.getPlayerId());
|
||||
landPlayed.add(event.getTargetId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
playerPlayedLand.clear();
|
||||
landPlayed.clear();
|
||||
super.reset();
|
||||
}
|
||||
|
||||
public boolean landPlayed(UUID playerId) {
|
||||
return playerPlayedLand.contains(playerId);
|
||||
}
|
||||
|
||||
public boolean wasLandPlayed(UUID landId) {
|
||||
return landPlayed.contains(landId);
|
||||
}
|
||||
}
|
215
Utils/gen-existing-cards-by-set-author.pl
Normal file
215
Utils/gen-existing-cards-by-set-author.pl
Normal file
|
@ -0,0 +1,215 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
#author: North
|
||||
|
||||
use Text::Template;
|
||||
use strict;
|
||||
|
||||
|
||||
my $dataFile = "mtg-cards-data.txt";
|
||||
my $setsFile = "mtg-sets-data.txt";
|
||||
my $knownSetsFile = "known-sets.txt";
|
||||
|
||||
|
||||
my %cards;
|
||||
my %sets;
|
||||
my %knownSets;
|
||||
|
||||
my @setCards;
|
||||
|
||||
# gets the set name
|
||||
my $setName = $ARGV[0];
|
||||
if(!$setName) {
|
||||
print 'Enter a set name: ';
|
||||
$setName = <STDIN>;
|
||||
chomp $setName;
|
||||
}
|
||||
|
||||
sub toCamelCase {
|
||||
my $string = $_[0];
|
||||
$string =~ s/\b([\w']+)\b/ucfirst($1)/ge;
|
||||
$string =~ s/[-,\s\']//g;
|
||||
$string =~ s/[\/]//g;
|
||||
$string;
|
||||
}
|
||||
|
||||
my $cardsFound = 0;
|
||||
my %all_sets;
|
||||
|
||||
print ("Opening $dataFile\n");
|
||||
open (DATA, $dataFile) || die "can't open $dataFile";
|
||||
while(my $line = <DATA>) {
|
||||
my @data = split('\\|', $line);
|
||||
$cards{$data[0]}{$data[1]} = \@data;
|
||||
|
||||
if ($data[1] eq $setName) {
|
||||
my $cardInfo = "$data[0],,,$data[2]";
|
||||
|
||||
push(@setCards, $cardInfo);
|
||||
} else {
|
||||
$all_sets {$data[1]} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Fix up split cards
|
||||
my $potentialSideA;
|
||||
my @tempSetCards;
|
||||
|
||||
foreach $potentialSideA (sort @setCards) {
|
||||
#print (">>$potentialSideA\n");
|
||||
if ($potentialSideA =~ m/.*,,,(\d+)(a)$/) {
|
||||
my $cardNumSideB = $1 . "b";
|
||||
my $val;
|
||||
foreach $val (sort @setCards) {
|
||||
if ($val =~ m/$cardNumSideB$/) {
|
||||
$potentialSideA =~ s/,,,.*//;
|
||||
$val =~ s/,,,.*//;
|
||||
|
||||
# Add 'SideaSideb' to %cards
|
||||
my $ds = $cards{$val}{$setName};
|
||||
#print ("$potentialSideA$val,,,$cardNumSideB\n");
|
||||
my @newCard;
|
||||
push (@newCard, "$potentialSideA$val");
|
||||
push (@newCard, "$setName");
|
||||
push (@newCard, "SPLIT");
|
||||
push (@newCard, @$ds[3]);
|
||||
push (@newCard, "$potentialSideA // $val");
|
||||
$cards{$newCard[0]}{$newCard[1]} = \@newCard;
|
||||
|
||||
$cardNumSideB =~ s/.$//;
|
||||
push (@tempSetCards, "$potentialSideA$val,,,$cardNumSideB");
|
||||
|
||||
#print ("Adding in: $potentialSideA \/\/ $val,,,$cardNumSideB\n");
|
||||
$cardsFound = $cardsFound - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ($potentialSideA =~ m/.*,,,(\d+)(b)$/) {
|
||||
next;
|
||||
}
|
||||
else {
|
||||
$cardsFound = $cardsFound + 1;
|
||||
push (@tempSetCards, $potentialSideA);
|
||||
}
|
||||
}
|
||||
@setCards = @tempSetCards;
|
||||
|
||||
close(DATA);
|
||||
print "Number of cards found for set " . $setName . ": " . $cardsFound . "\n";
|
||||
|
||||
|
||||
if ($cardsFound == 0) {
|
||||
$setName =~ s/^(...).*/$1/;
|
||||
my $poss;
|
||||
my $foundPossibleSet = 0;
|
||||
my $numPossibleSets = 0;
|
||||
foreach $poss (sort keys (%all_sets)) {
|
||||
$numPossibleSets++;
|
||||
if ($poss =~ m/^$setName/i) {
|
||||
print ("Did you possibly mean: $poss ?\n");
|
||||
$foundPossibleSet = 1;
|
||||
}
|
||||
}
|
||||
if (!$foundPossibleSet) {
|
||||
print ("Couldn't find any matching set for '$setName'. \n");
|
||||
}
|
||||
|
||||
print "(Note: Looked at $numPossibleSets sets in total).\nPress the enter key to exit.";
|
||||
$setName = <STDIN>;
|
||||
exit;
|
||||
}
|
||||
|
||||
open (DATA, $setsFile) || die "can't open $setsFile";
|
||||
|
||||
while(my $line = <DATA>) {
|
||||
my @data = split('\\|', $line);
|
||||
$sets{$data[0]}= $data[1];
|
||||
}
|
||||
close(DATA);
|
||||
|
||||
open (DATA, $knownSetsFile) || die "can't open $knownSetsFile";
|
||||
while(my $line = <DATA>) {
|
||||
my @data = split('\\|', $line);
|
||||
$knownSets{$data[0]}= $data[1];
|
||||
}
|
||||
close(DATA);
|
||||
|
||||
print ("Reading in existing cards in set\n");
|
||||
open (SET_FILE, "../../mage/Mage.Sets/src/mage/sets/$knownSets{$setName}.java") || die "can't open $dataFile";
|
||||
my %alreadyIn;
|
||||
while (<SET_FILE>) {
|
||||
my $line = $_;
|
||||
if ($line =~ m/SetCardInfo.*\("(.*)", (\d+).*/)
|
||||
{
|
||||
$alreadyIn {$2} = $1;
|
||||
}
|
||||
}
|
||||
close SET_FILE;
|
||||
|
||||
my $name_collectorid;
|
||||
|
||||
|
||||
my %authors;
|
||||
my %author_counts;
|
||||
|
||||
foreach $name_collectorid (sort @setCards)
|
||||
{
|
||||
my $cardName;
|
||||
my $cardNr;
|
||||
$name_collectorid =~ m/^(.*),,,(.*)$/;
|
||||
$cardName = $1;
|
||||
$cardNr = $2;
|
||||
{
|
||||
my $ds;
|
||||
$ds = $cards{$cardName}{$setName};
|
||||
my $className = toCamelCase($cardName);
|
||||
my $setId = lc($cardName);
|
||||
$setId =~ s/^(.).*/$1/;
|
||||
my $fn = "..\\Mage.Sets\\src\\mage\\cards\\$setId\\$className.java";
|
||||
|
||||
if (@$ds[2] eq "SPLIT") {
|
||||
my $oldCardName = $cardName;
|
||||
$cardName = @$ds[4];
|
||||
}
|
||||
|
||||
my $plus_cardName = $cardName;
|
||||
$plus_cardName =~ s/ /+/img;
|
||||
$plus_cardName =~ s/,/+/img;
|
||||
$plus_cardName = "intext:\"$plus_cardName\"";
|
||||
my $cmd = "find /I \"\@author\" $fn";
|
||||
|
||||
if (!exists ($alreadyIn{$cardNr})) {
|
||||
if (-e $fn) {
|
||||
my $output = `$cmd`;
|
||||
chomp $output;
|
||||
$output =~ s/^----.*\n//img;
|
||||
$output =~ s/^.*author\s*//img;
|
||||
$authors {$fn} = $output;
|
||||
$author_counts {$output} ++;
|
||||
|
||||
}
|
||||
} else {
|
||||
if (-e $fn) {
|
||||
my $output = `$cmd`;
|
||||
chomp $output;
|
||||
$output =~ s/^----.*\n//img;
|
||||
$output =~ s/^.*.author\s*//img;
|
||||
$authors {$fn} = $output;
|
||||
$author_counts {$output} ++;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print "\n\n\nAuthor Counts:\n";
|
||||
my $author;
|
||||
foreach $author (sort (keys %author_counts)) {
|
||||
if ($author !~ m/---/img) {
|
||||
print ("$author --> $author_counts{$author}");
|
||||
}
|
||||
}
|
||||
|
||||
print ("\nData from reading: ../../mage/Mage.Sets/src/mage/sets/$knownSets{$setName}.java\n");
|
||||
print "\n\nYou are done. Press the enter key to exit.";
|
||||
$setName = <STDIN>;
|
Loading…
Reference in a new issue