Merge remote-tracking branch 'remotes/upstream/master'

This commit is contained in:
ciaccona007 2017-07-16 13:10:43 -04:00
commit 95d0fe8802
45 changed files with 702 additions and 338 deletions

View file

@ -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",
});

View file

@ -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());
}

View file

@ -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);

View file

@ -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) {

View file

@ -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

View file

@ -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));

View file

@ -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();

View file

@ -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");

View file

@ -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());
}

View file

@ -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) {

View file

@ -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)),

View file

@ -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());

View file

@ -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)) {

View file

@ -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())));
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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));
}

View file

@ -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());
}
}

View file

@ -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);
}

View file

@ -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)) {

View file

@ -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);
}

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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());

View file

@ -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;

View file

@ -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);

View file

@ -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)) {

View file

@ -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 {

View file

@ -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);

View file

@ -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);
}

View file

@ -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)) {

View file

@ -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();

View file

@ -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

View file

@ -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;

View file

@ -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.

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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()) {

View file

@ -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);
}
}

View 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);
}
}

View 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>;