mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
changes to support multiplayer
This commit is contained in:
parent
d6989797ba
commit
2d5af63cba
41 changed files with 586 additions and 204 deletions
|
@ -256,6 +256,39 @@ public final class Constants {
|
|||
ANY, YOU, NOT_YOU, OPPONENT
|
||||
}
|
||||
|
||||
public enum RangeOfInfluence {
|
||||
ONE(1),
|
||||
TWO(2),
|
||||
ALL(0);
|
||||
|
||||
private int range;
|
||||
|
||||
RangeOfInfluence(int range) {
|
||||
this.range = range;
|
||||
}
|
||||
|
||||
public int getRange() {
|
||||
return range;
|
||||
}
|
||||
}
|
||||
|
||||
public enum MultiplayerAttackOption {
|
||||
MULITPLE("Attack Multiple Players"),
|
||||
LEFT("Attack Left"),
|
||||
RIGHT("Attack Right");
|
||||
|
||||
private String text;
|
||||
|
||||
MultiplayerAttackOption(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> PlaneswalkerTypes = new ArrayList<String>()
|
||||
{{add("Ajani"); add("Bolas"); add("Chandra"); add("Elspeth");add("Garruk"); add("Jace"); add("Liliana"); add("Nissa"); add("Sarkhan"); add("Sorin"); add("Tezzeret");}};
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
|
|||
if (!controlsAbility(playerId, game))
|
||||
return false;
|
||||
//20091005 - 602.5d/602.5e
|
||||
if ((timing == TimingRule.INSTANT || game.canPlaySorcery(playerId)) && costs.canPay(playerId, game) && targets.canChoose(sourceId, game)) {
|
||||
if ((timing == TimingRule.INSTANT || game.canPlaySorcery(playerId)) && costs.canPay(playerId, game) && targets.canChoose(sourceId, playerId, game)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -49,7 +49,7 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
|||
@Override
|
||||
public boolean canActivate(UUID playerId, Game game) {
|
||||
if ((game.getObject(sourceId).getCardType().contains(CardType.INSTANT) || game.canPlaySorcery(playerId)) &&
|
||||
costs.canPay(playerId, game) && targets.canChoose(sourceId, game)) {
|
||||
costs.canPay(playerId, game) && targets.canChoose(sourceId, playerId, game)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -30,11 +30,9 @@ package mage.abilities.costs.common;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.Constants.Outcome;
|
||||
import mage.Constants.TargetController;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetSacrificePermanent;
|
||||
|
||||
/**
|
||||
|
@ -64,7 +62,7 @@ public class SacrificeTargetCost extends CostImpl {
|
|||
|
||||
@Override
|
||||
public boolean canPay(UUID playerId, Game game) {
|
||||
return target.canChoose(playerId, game);
|
||||
return target.canChoose(playerId, playerId, game);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,8 +41,8 @@ import mage.game.Game;
|
|||
public interface ContinuousEffect extends Effect {
|
||||
|
||||
public Duration getDuration();
|
||||
// public Layer getLayer();
|
||||
// public SubLayer getSubLayer();
|
||||
public Date getTimestamp();
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Game game);
|
||||
public boolean hasLayer(Layer layer);
|
||||
|
||||
}
|
||||
|
|
|
@ -76,5 +76,9 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
return timestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLayer(Layer layer) {
|
||||
return this.layer == layer;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -92,47 +92,6 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
|
||||
|
||||
// private List<ContinuousEffect> getLayer(Layer layer, SubLayer sublayer) {
|
||||
// List<ContinuousEffect> layerEffects = new ArrayList<ContinuousEffect>();
|
||||
// for (ContinuousEffect effect: effects) {
|
||||
// if (effect.getLayer() == layer && effect.getSubLayer() == sublayer) {
|
||||
// layerEffects.add(effect);
|
||||
// }
|
||||
// }
|
||||
// Collections.sort(layerEffects, new TimestampSorter());
|
||||
// return layerEffects;
|
||||
// }
|
||||
|
||||
// private List<PreventionEffect> GetApplicablePreventionEffects(GameEvent event, Game game) {
|
||||
// List<PreventionEffect> effects = new ArrayList<PreventionEffect>();
|
||||
// for (IEffect effect: this) {
|
||||
// if (effect instanceof PreventionEffect && ((PreventionEffect)effect).Applies(event, game)) {
|
||||
// effects.add((PreventionEffect)effect);
|
||||
// }
|
||||
// }
|
||||
// return effects;
|
||||
// }
|
||||
|
||||
// public List<PreventionEffect> GetApplicablePreventionEffects(IMageObject source, IPermanent target, Game game) {
|
||||
// List<PreventionEffect> effects = new ArrayList<PreventionEffect>();
|
||||
// for (IEffect effect: this) {
|
||||
// if (effect instanceof PreventionEffect && ((PreventionEffect)effect).Applies(source, target, game)) {
|
||||
// effects.add((PreventionEffect)effect);
|
||||
// }
|
||||
// }
|
||||
// return effects;
|
||||
// }
|
||||
//
|
||||
// public List<PreventionEffect> GetApplicablePreventionEffects(IMageObject source, IPlayer target, Game game) {
|
||||
// List<PreventionEffect> effects = new ArrayList<PreventionEffect>();
|
||||
// for (IEffect effect: this) {
|
||||
// if (effect instanceof PreventionEffect && ((PreventionEffect)effect).Applies(source, target, game)) {
|
||||
// effects.add((PreventionEffect)effect);
|
||||
// }
|
||||
// }
|
||||
// return effects;
|
||||
// }
|
||||
|
||||
private List<ReplacementEffect> getApplicableReplacementEffects(GameEvent event, Game game) {
|
||||
List<ReplacementEffect> replacementEffects = new ArrayList<ReplacementEffect>();
|
||||
for (Effect effect: effects) {
|
||||
|
@ -180,18 +139,6 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
// if (!caught) {
|
||||
// List<PreventionEffect> pEffects = GetApplicablePreventionEffects(event, game);
|
||||
// if (pEffects.size() > 0) {
|
||||
// if (pEffects.size() == 1) {
|
||||
// caught = pEffects.get(0).ReplaceEvent(event, game);
|
||||
// }
|
||||
// else {
|
||||
// //TODO: handle multiple
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return caught;
|
||||
}
|
||||
|
||||
|
@ -260,7 +207,7 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
|
||||
protected void applyCounters(Game game) {
|
||||
for (Permanent permanent: game.getBattlefield().getActivePermanents(CardType.CREATURE)) {
|
||||
for (Permanent permanent: game.getBattlefield().getAllActivePermanents(CardType.CREATURE)) {
|
||||
for (BoostCounter counter: permanent.getCounters().getBoostCounters()) {
|
||||
permanent.addPower(counter.getPower() * counter.getCount());
|
||||
permanent.addToughness(counter.getToughness() * counter.getCount());
|
||||
|
|
|
@ -32,7 +32,6 @@ import mage.Constants.Duration;
|
|||
import mage.Constants.Layer;
|
||||
import mage.Constants.Outcome;
|
||||
import mage.Constants.SubLayer;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
|
||||
|
@ -53,9 +52,7 @@ public abstract class WhileControlsContinuousEffect extends ContinuousEffectImpl
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game) {
|
||||
filter.getControllerId().clear();
|
||||
filter.getControllerId().add(this.source.getControllerId());
|
||||
if (game.getBattlefield().count(filter) > 0) {
|
||||
if (game.getBattlefield().countAll(filter, this.source.getControllerId()) > 0) {
|
||||
return applyEffect(game);
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -100,4 +100,9 @@ public class BecomesCreatureSourceEOTEffect extends ContinuousEffectImpl {
|
|||
return "Until end of turn {this} becomes a " + token.getDescription() + ". It's still a land";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLayer(Layer layer) {
|
||||
return layer == Layer.PTChangingEffects_7 || layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.ColorChangingEffects_5 || layer == layer.TypeChangingEffects_4;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -61,9 +61,7 @@ public class BoostControlledEffect extends ContinuousEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game) {
|
||||
filter.getControllerId().clear();
|
||||
filter.getControllerId().add(this.source.getControllerId());
|
||||
for (Permanent perm: game.getBattlefield().getActivePermanents(filter)) {
|
||||
for (Permanent perm: game.getBattlefield().getAllActivePermanents(filter, this.source.getControllerId())) {
|
||||
perm.addPower(power);
|
||||
perm.addToughness(toughness);
|
||||
}
|
||||
|
|
|
@ -47,11 +47,9 @@ public class DestroyAllControlledTargetEffect extends OneShotEffect {
|
|||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game) {
|
||||
filter.getControllerId().clear();
|
||||
filter.getControllerId().add(this.source.getFirstTarget());
|
||||
filter.setNotController(false);
|
||||
for (Permanent permanent: game.getBattlefield().getActivePermanents(filter)) {
|
||||
for (Permanent permanent: game.getBattlefield().getAllActivePermanents(filter, this.source.getFirstTarget())) {
|
||||
permanent.destroy(this.source.getSourceId(), game, false);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -47,8 +47,9 @@ public class DestroyAllEffect extends OneShotEffect {
|
|||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game) {
|
||||
for (Permanent permanent: game.getBattlefield().getActivePermanents(filter)) {
|
||||
for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, this.source.getControllerId(), game)) {
|
||||
permanent.destroy(this.source.getSourceId(), game, false);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -49,7 +49,7 @@ public class DestroyAllNamedPermanentsEffect extends OneShotEffect {
|
|||
String name = permanent.getName();
|
||||
|
||||
permanent.destroy(this.source.getSourceId(), game, false);
|
||||
for (Permanent perm: game.getBattlefield().getActivePermanents()) {
|
||||
for (Permanent perm: game.getBattlefield().getActivePermanents(this.source.getControllerId(), game)) {
|
||||
if (perm.getName().equals(name))
|
||||
perm.destroy(this.source.getSourceId(), game, false);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class EntersBattlefieldTappedUnlessControlsEffect extends EntersBattlefieldTappedEffect {
|
||||
|
||||
FilterPermanent filter;
|
||||
|
||||
public EntersBattlefieldTappedUnlessControlsEffect(FilterPermanent filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Game game) {
|
||||
if (game.getBattlefield().countAll(filter, this.source.getControllerId()) == 0)
|
||||
return apply(game);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return super.getText() + " unless you control a " + filter.getMessage();
|
||||
}
|
||||
|
||||
}
|
|
@ -59,9 +59,7 @@ public class GainAbilityControlledEffect extends ContinuousEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game) {
|
||||
permanentFilter.getControllerId().clear();
|
||||
permanentFilter.getControllerId().add(this.source.getControllerId());
|
||||
for (Permanent perm: game.getBattlefield().getActivePermanents(permanentFilter)) {
|
||||
for (Permanent perm: game.getBattlefield().getAllActivePermanents(permanentFilter, this.source.getControllerId())) {
|
||||
perm.addAbility(ability);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -50,8 +50,7 @@ public class GainControlTargetEOTEffect extends ContinuousEffectImpl {
|
|||
public boolean apply(Game game) {
|
||||
Permanent permanent = game.getPermanent(this.source.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
permanent.setControllerId(this.source.getControllerId());
|
||||
return true;
|
||||
return permanent.changeControllerId(this.source.getControllerId(), game);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
package mage.filter.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.Constants.CardType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
package mage.filter.common;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterImpl;
|
||||
|
@ -45,7 +46,7 @@ public class FilterPlaneswalkerOrPlayer extends FilterImpl<Object> implements Fi
|
|||
protected FilterPlaneswalkerPermanent planeswalkerFilter = new FilterPlaneswalkerPermanent();
|
||||
protected FilterPlayer playerFilter = new FilterPlayer();
|
||||
|
||||
public FilterPlaneswalkerOrPlayer(List<UUID> defenders) {
|
||||
public FilterPlaneswalkerOrPlayer(Set<UUID> defenders) {
|
||||
super("planeswalker or player");
|
||||
planeswalkerFilter.getControllerId().addAll(defenders);
|
||||
playerFilter.getPlayerId().addAll(defenders);
|
||||
|
|
|
@ -32,8 +32,10 @@ import mage.game.stack.SpellStack;
|
|||
import mage.MageObject;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.Constants.MultiplayerAttackOption;
|
||||
import mage.Constants.RangeOfInfluence;
|
||||
import mage.MageItem;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.TriggeredAbilities;
|
||||
|
@ -56,9 +58,11 @@ import mage.players.Players;
|
|||
|
||||
public interface Game extends MageItem, Serializable {
|
||||
|
||||
public String getGameType();
|
||||
public GameType getGameType();
|
||||
public int getNumPlayers();
|
||||
public int getLife();
|
||||
public RangeOfInfluence getRangeOfInfluence();
|
||||
public MultiplayerAttackOption getAttackOption();
|
||||
|
||||
//game data methods
|
||||
public MageObject getObject(UUID objectId);
|
||||
|
@ -67,7 +71,7 @@ public interface Game extends MageItem, Serializable {
|
|||
public Player getPlayer(UUID playerId);
|
||||
public Players getPlayers();
|
||||
public PlayerList getPlayerList(UUID playerId);
|
||||
public List<UUID> getOpponents(UUID controllerId);
|
||||
public Set<UUID> getOpponents(UUID controllerId);
|
||||
public Turn getTurn();
|
||||
public int getTurnNum();
|
||||
public boolean isMainPhase();
|
||||
|
|
|
@ -31,13 +31,15 @@ package mage.game;
|
|||
import mage.game.stack.SpellStack;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Stack;
|
||||
import java.util.UUID;
|
||||
import mage.Constants;
|
||||
import mage.Constants.CardType;
|
||||
import mage.Constants.MultiplayerAttackOption;
|
||||
import mage.Constants.Outcome;
|
||||
import mage.Constants.PhaseStep;
|
||||
import mage.Constants.RangeOfInfluence;
|
||||
import mage.Constants.Zone;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
|
@ -83,9 +85,13 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
protected UUID choosingPlayerId;
|
||||
protected Player winner;
|
||||
protected GameStates gameStates;
|
||||
protected RangeOfInfluence range;
|
||||
protected MultiplayerAttackOption attackOption;
|
||||
|
||||
public GameImpl() {
|
||||
public GameImpl(MultiplayerAttackOption attackOption, RangeOfInfluence range) {
|
||||
id = UUID.randomUUID();
|
||||
this.range = range;
|
||||
this.attackOption = attackOption;
|
||||
state = new GameState();
|
||||
gameStates = new GameStates();
|
||||
}
|
||||
|
@ -100,6 +106,16 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
state.addPlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RangeOfInfluence getRangeOfInfluence() {
|
||||
return range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiplayerAttackOption getAttackOption() {
|
||||
return attackOption;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer(UUID playerId) {
|
||||
return state.getPlayer(playerId);
|
||||
|
@ -279,22 +295,20 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void quit(UUID playerId) {
|
||||
public synchronized void quit(UUID playerId) {
|
||||
Player player = state.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
player.leaveGame();
|
||||
player.leaveGame(this);
|
||||
fireInformEvent(player.getName() + " has left the game.");
|
||||
player.abort();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void concede(UUID playerId) {
|
||||
public synchronized void concede(UUID playerId) {
|
||||
Player player = state.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
player.concede();
|
||||
player.concede(this);
|
||||
fireInformEvent(player.getName() + " has conceded.");
|
||||
player.abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,7 +318,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
while (!isGameOver()) {
|
||||
for (Player player: getPlayerList(activePlayerId)) {
|
||||
state.setPriorityPlayerId(player.getId());
|
||||
while (!player.isPassed() && !isGameOver()) {
|
||||
while (!player.isPassed() && !player.hasLost() && !player.hasLeft()&& !isGameOver()) {
|
||||
checkStateAndTriggered();
|
||||
if (isGameOver()) return;
|
||||
// resetPassed should be called if player performs any action
|
||||
|
@ -320,6 +334,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
state.getStack().resolve(this);
|
||||
applyEffects();
|
||||
state.getPlayers().resetPassed();
|
||||
fireUpdatePlayersEvent();
|
||||
saveState();
|
||||
break;
|
||||
}
|
||||
|
@ -331,7 +346,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
|
||||
protected boolean allPassed() {
|
||||
for (Player player: state.getPlayers().values()) {
|
||||
if (!player.isPassed())
|
||||
if (!player.isPassed() && !player.hasLost() && !player.hasLeft())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -347,7 +362,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void applyEffects() {
|
||||
public synchronized void applyEffects() {
|
||||
state.applyEffects(this);
|
||||
}
|
||||
|
||||
|
@ -406,7 +421,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
somethingHappened = true;
|
||||
}
|
||||
}
|
||||
for (Permanent perm: getBattlefield().getActivePermanents(CardType.CREATURE)) {
|
||||
for (Permanent perm: getBattlefield().getAllActivePermanents(CardType.CREATURE)) {
|
||||
//20091005 - 704.5f
|
||||
if (perm.getToughness().getValue() == 0) {
|
||||
perm.moveToZone(Zone.GRAVEYARD, this, false);
|
||||
|
@ -419,35 +434,37 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
//20091005 - 704.5i
|
||||
for (Permanent perm: getBattlefield().getActivePermanents(CardType.PLANESWALKER)) {
|
||||
for (Permanent perm: getBattlefield().getAllActivePermanents(CardType.PLANESWALKER)) {
|
||||
if (perm.getLoyalty().getValue() == 0) {
|
||||
perm.moveToZone(Zone.GRAVEYARD, this, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//20091005 - 704.5j
|
||||
//20091005 - 704.5j, 801.14
|
||||
FilterPlaneswalkerPermanent filterPlaneswalker = new FilterPlaneswalkerPermanent();
|
||||
if (getBattlefield().count(filterPlaneswalker) > 1) { //don't bother checking if less than 2 planeswalkers in play
|
||||
for (String planeswalkerType: Constants.PlaneswalkerTypes) {
|
||||
filterPlaneswalker.getSubtype().clear();
|
||||
filterPlaneswalker.getSubtype().add(planeswalkerType);
|
||||
filterPlaneswalker.setScopeSubtype(ComparisonScope.Any);
|
||||
if (getBattlefield().count(filterPlaneswalker) > 1) {
|
||||
for (Permanent perm: getBattlefield().getActivePermanents(filterPlaneswalker)) {
|
||||
perm.moveToZone(Zone.GRAVEYARD, this, false);
|
||||
if (getBattlefield().countAll(filterPlaneswalker) > 1) { //don't bother checking if less than 2 planeswalkers in play
|
||||
for (Permanent planeswalker: getBattlefield().getAllActivePermanents(CardType.PLANESWALKER)) {
|
||||
for (String planeswalkertype: planeswalker.getSubtype()) {
|
||||
filterPlaneswalker.getSubtype().clear();
|
||||
filterPlaneswalker.getSubtype().add(planeswalkertype);
|
||||
filterPlaneswalker.setScopeSubtype(ComparisonScope.Any);
|
||||
if (getBattlefield().count(filterPlaneswalker, planeswalker.getControllerId(), this) > 1) {
|
||||
for (Permanent perm: getBattlefield().getActivePermanents(filterPlaneswalker, planeswalker.getControllerId(), this)) {
|
||||
perm.moveToZone(Zone.GRAVEYARD, this, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
somethingHappened = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//20091005 - 704.5k
|
||||
//20091005 - 704.5k, 801.12
|
||||
FilterLegendaryPermanent filterLegendary = new FilterLegendaryPermanent();
|
||||
if (getBattlefield().count(filterPlaneswalker) > 1) { //don't bother checking if less than 2 legends in play
|
||||
for (Permanent legend: getBattlefield().getActivePermanents(filterLegendary)) {
|
||||
if (getBattlefield().countAll(filterLegendary) > 1) { //don't bother checking if less than 2 legends in play
|
||||
for (Permanent legend: getBattlefield().getAllActivePermanents(filterLegendary)) {
|
||||
FilterLegendaryPermanent filterLegendName = new FilterLegendaryPermanent();
|
||||
filterLegendName.getName().add(legend.getName());
|
||||
if (getBattlefield().count(filterLegendName) > 1) {
|
||||
for (Permanent dupLegend: getBattlefield().getActivePermanents(filterLegendName)) {
|
||||
if (getBattlefield().count(filterLegendName, legend.getControllerId(), this) > 1) {
|
||||
for (Permanent dupLegend: getBattlefield().getActivePermanents(filterLegendName, legend.getControllerId(), this)) {
|
||||
dupLegend.moveToZone(Zone.GRAVEYARD, this, false);
|
||||
}
|
||||
return true;
|
||||
|
@ -455,7 +472,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
//20091005 - 704.5p
|
||||
for (Permanent perm: getBattlefield().getActivePermanents(new FilterEquipment())) {
|
||||
for (Permanent perm: getBattlefield().getAllActivePermanents(new FilterEquipment())) {
|
||||
if (perm.getAttachedTo() != null) {
|
||||
Permanent creature = getPermanent(perm.getAttachedTo());
|
||||
if (creature == null) {
|
||||
|
@ -467,7 +484,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (Permanent perm: getBattlefield().getActivePermanents(new FilterFortification())) {
|
||||
for (Permanent perm: getBattlefield().getAllActivePermanents(new FilterFortification())) {
|
||||
if (perm.getAttachedTo() != null) {
|
||||
Permanent land = getPermanent(perm.getAttachedTo());
|
||||
if (land == null) {
|
||||
|
@ -480,7 +497,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
//20091005 - 704.5q
|
||||
for (Permanent perm: getBattlefield().getActivePermanents()) {
|
||||
for (Permanent perm: getBattlefield().getAllActivePermanents()) {
|
||||
if (perm.getAttachments().size() > 0) {
|
||||
for (UUID attachmentId: perm.getAttachments()) {
|
||||
Permanent attachment = getPermanent(attachmentId);
|
||||
|
@ -556,10 +573,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
//20091005 - 507.1
|
||||
state.getCombat().clear();
|
||||
state.getCombat().setAttacker(activePlayerId);
|
||||
for (Player player: state.getPlayers().values()) {
|
||||
if (!player.getId().equals(state.getActivePlayerId()))
|
||||
state.getCombat().getDefenders().add(player.getId());
|
||||
}
|
||||
state.getCombat().setDefenders(this);
|
||||
fireEvent(new GameEvent(GameEvent.EventType.BEGIN_COMBAT_STEP_PRE, null, null, activePlayerId));
|
||||
playPriority(activePlayerId);
|
||||
fireEvent(new GameEvent(GameEvent.EventType.PRECOMBAT_MAIN_STEP_POST, null, null, activePlayerId));
|
||||
|
@ -647,7 +661,8 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
fireEvent(new GameEvent(GameEvent.EventType.CLEANUP_STEP_PRE, null, null, activePlayerId));
|
||||
//20091005 - 514.1
|
||||
Player player = getPlayer(activePlayerId);
|
||||
player.discardToMax(this);
|
||||
if (!player.hasLeft() && !player.hasLost())
|
||||
player.discardToMax(this);
|
||||
state.getBattlefield().endOfTurn(activePlayerId, this);
|
||||
state.removeEotEffects(this);
|
||||
if (checkStateAndTriggered()) {
|
||||
|
|
|
@ -184,7 +184,7 @@ public class GameState implements Serializable {
|
|||
public PlayerList getPlayerList(UUID playerId) {
|
||||
PlayerList playerList = new PlayerList();
|
||||
for (Player player: players.values()) {
|
||||
if (!player.hasLeft())
|
||||
if (!player.hasLeft() && !player.hasLost())
|
||||
playerList.add(player);
|
||||
}
|
||||
playerList.setCurrent(playerId);
|
||||
|
|
80
Mage/src/mage/game/GameType.java
Normal file
80
Mage/src/mage/game/GameType.java
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package mage.game;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public abstract class GameType implements Serializable {
|
||||
|
||||
protected String name;
|
||||
protected int minPlayers;
|
||||
protected int maxPlayers;
|
||||
protected int numTeams;
|
||||
protected int playersPerTeam;
|
||||
protected boolean useRange;
|
||||
protected boolean useAttackOption;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getMinPlayers() {
|
||||
return minPlayers;
|
||||
}
|
||||
|
||||
public int getMaxPlayers() {
|
||||
return maxPlayers;
|
||||
}
|
||||
|
||||
public int getNumTeams() {
|
||||
return numTeams;
|
||||
}
|
||||
|
||||
public int getPlayersPerTeam() {
|
||||
return playersPerTeam;
|
||||
}
|
||||
|
||||
public boolean isUseRange() {
|
||||
return useRange;
|
||||
}
|
||||
|
||||
public boolean isUseAttackOption() {
|
||||
return useAttackOption;
|
||||
}
|
||||
|
||||
}
|
|
@ -70,10 +70,6 @@ public class Table implements Serializable {
|
|||
return tableId;
|
||||
}
|
||||
|
||||
// public void setGame(Game game) {
|
||||
// this.game = game;
|
||||
// }
|
||||
|
||||
public void initGame(Game game) throws GameException {
|
||||
for (int i = 0; i < numSeats; i++ ) {
|
||||
game.addPlayer(seats[i].getPlayer());
|
||||
|
|
|
@ -30,12 +30,16 @@ package mage.game.combat;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.players.PlayerList;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -45,14 +49,14 @@ import mage.game.permanent.Permanent;
|
|||
public class Combat implements Serializable {
|
||||
|
||||
protected List<CombatGroup> groups = new ArrayList<CombatGroup>();
|
||||
protected List<UUID> defenders = new ArrayList<UUID>();
|
||||
protected Set<UUID> defenders = new HashSet<UUID>();
|
||||
protected UUID attackerId;
|
||||
|
||||
public List<CombatGroup> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
public List<UUID> getDefenders() {
|
||||
public Set<UUID> getDefenders() {
|
||||
return defenders;
|
||||
}
|
||||
|
||||
|
@ -86,19 +90,55 @@ public class Combat implements Serializable {
|
|||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, attackerId, attackerId))) {
|
||||
game.getPlayer(attackerId).selectAttackers(game);
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_ATTACKERS, attackerId, attackerId));
|
||||
game.fireInformEvent(game.getPlayer(attackerId).getName() + " attacks with " + groups.size() + " creatures");
|
||||
}
|
||||
}
|
||||
|
||||
public void selectBlockers(Game game) {
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_BLOCKERS, attackerId, attackerId))) {
|
||||
for (UUID defenderId: defenders) {
|
||||
game.getPlayer(defenderId).selectBlockers(game);
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, defenderId, defenderId));
|
||||
//check if defender is being attacked
|
||||
if (isAttacked(defenderId, game)) {
|
||||
game.getPlayer(defenderId).selectBlockers(game);
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, defenderId, defenderId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setDefenders(Game game) {
|
||||
Set<UUID> opponents = game.getOpponents(attackerId);
|
||||
PlayerList players;
|
||||
switch (game.getAttackOption()) {
|
||||
case LEFT:
|
||||
players = game.getPlayerList(attackerId);
|
||||
while (true) {
|
||||
Player opponent = players.getNext();
|
||||
if (opponents.contains(opponent.getId())) {
|
||||
defenders.add(opponent.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RIGHT:
|
||||
players = game.getPlayerList(attackerId);
|
||||
while (true) {
|
||||
Player opponent = players.getPrevious();
|
||||
if (opponents.contains(opponent.getId())) {
|
||||
defenders.add(opponent.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MULITPLE:
|
||||
defenders.addAll(game.getOpponents(attackerId));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void declareAttacker(UUID attackerId, UUID defenderId, Game game) {
|
||||
if (!defenders.contains(defenderId))
|
||||
return;
|
||||
Permanent defender = game.getPermanent(defenderId);
|
||||
CombatGroup newGroup = new CombatGroup(defenderId, defender != null);
|
||||
newGroup.attackers.add(attackerId);
|
||||
|
@ -177,5 +217,17 @@ public class Combat implements Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected boolean isAttacked(UUID defenderId, Game game) {
|
||||
for (CombatGroup group: groups) {
|
||||
if (group.getDefenderId().equals(defenderId))
|
||||
return true;
|
||||
if (group.defenderIsPlaneswalker) {
|
||||
Permanent permanent = game.getPermanent(group.getDefenderId());
|
||||
if (permanent.getControllerId().equals(defenderId))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ public class GameEvent {
|
|||
PLAY_LAND, LAND_PLAYED,
|
||||
CAST_SPELL, SPELL_CAST,
|
||||
ACTIVATE_ABILITY, ACTIVATED_ABILITY,
|
||||
LOSES, WINS,
|
||||
LOSES, LOST, WINS,
|
||||
TARGET, TARGETED,
|
||||
COUNTER, COUNTERED,
|
||||
DECLARING_ATTACKERS, DECLARED_ATTACKERS,
|
||||
|
|
|
@ -34,9 +34,10 @@ import java.util.Collection;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.Constants.CardType;
|
||||
import mage.Constants.Zone;
|
||||
import mage.Constants.RangeOfInfluence;
|
||||
import mage.abilities.keyword.PhasingAbility;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
|
@ -60,7 +61,7 @@ public class Battlefield implements Serializable {
|
|||
field.clear();
|
||||
}
|
||||
|
||||
public int count(FilterPermanent filter) {
|
||||
public int countAll(FilterPermanent filter) {
|
||||
int count = 0;
|
||||
for (Permanent permanent: field.values()) {
|
||||
if (filter.match(permanent)) {
|
||||
|
@ -70,6 +71,37 @@ public class Battlefield implements Serializable {
|
|||
return count;
|
||||
}
|
||||
|
||||
public int countAll(FilterPermanent filter, UUID controllerId) {
|
||||
int count = 0;
|
||||
for (Permanent permanent: field.values()) {
|
||||
if (permanent.getControllerId().equals(controllerId) && filter.match(permanent)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
public int count(FilterPermanent filter, UUID sourcePlayerId, Game game) {
|
||||
int count = 0;
|
||||
if (game.getRangeOfInfluence() == RangeOfInfluence.ALL) {
|
||||
for (Permanent permanent: field.values()) {
|
||||
if (filter.match(permanent)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Set<UUID> range = game.getPlayer(sourcePlayerId).getInRange();
|
||||
for (Permanent permanent: field.values()) {
|
||||
if (range.contains(permanent.getControllerId()) && filter.match(permanent)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public void addPermanent(Permanent permanent) {
|
||||
field.put(permanent.getId(), permanent);
|
||||
}
|
||||
|
@ -87,9 +119,19 @@ public class Battlefield implements Serializable {
|
|||
}
|
||||
|
||||
public void checkTriggers(GameEvent event, Game game) {
|
||||
for (Permanent perm: field.values()) {
|
||||
if (perm.isPhasedIn())
|
||||
perm.checkTriggers(event, game);
|
||||
if (game.getRangeOfInfluence() == RangeOfInfluence.ALL) {
|
||||
for (Permanent perm: field.values()) {
|
||||
if (perm.isPhasedIn())
|
||||
perm.checkTriggers(event, game);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//20100423 - 801.7
|
||||
Set<UUID> range = game.getPlayer(event.getPlayerId()).getInRange();
|
||||
for (Permanent perm: field.values()) {
|
||||
if (range.contains(perm.getControllerId()) && perm.isPhasedIn())
|
||||
perm.checkTriggers(event, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +155,7 @@ public class Battlefield implements Serializable {
|
|||
return perms;
|
||||
}
|
||||
|
||||
public List<Permanent> getActivePermanents() {
|
||||
public List<Permanent> getAllActivePermanents() {
|
||||
List<Permanent> active = new ArrayList<Permanent>();
|
||||
for (Permanent perm: field.values()) {
|
||||
if (perm.isPhasedIn())
|
||||
|
@ -122,7 +164,7 @@ public class Battlefield implements Serializable {
|
|||
return active;
|
||||
}
|
||||
|
||||
public List<Permanent> getActivePermanents(UUID controllerId) {
|
||||
public List<Permanent> getAllActivePermanents(UUID controllerId) {
|
||||
List<Permanent> active = new ArrayList<Permanent>();
|
||||
for (Permanent perm: field.values()) {
|
||||
if (perm.isPhasedIn() && perm.getControllerId().equals(controllerId))
|
||||
|
@ -131,7 +173,7 @@ public class Battlefield implements Serializable {
|
|||
return active;
|
||||
}
|
||||
|
||||
public List<Permanent> getActivePermanents(CardType type) {
|
||||
public List<Permanent> getAllActivePermanents(CardType type) {
|
||||
List<Permanent> active = new ArrayList<Permanent>();
|
||||
for (Permanent perm: field.values()) {
|
||||
if (perm.isPhasedIn() && perm.getCardType().contains(type))
|
||||
|
@ -140,7 +182,7 @@ public class Battlefield implements Serializable {
|
|||
return active;
|
||||
}
|
||||
|
||||
public List<Permanent> getActivePermanents(FilterPermanent filter) {
|
||||
public List<Permanent> getAllActivePermanents(FilterPermanent filter) {
|
||||
List<Permanent> active = new ArrayList<Permanent>();
|
||||
for (Permanent perm: field.values()) {
|
||||
if (perm.isPhasedIn() && filter.match(perm))
|
||||
|
@ -149,15 +191,45 @@ public class Battlefield implements Serializable {
|
|||
return active;
|
||||
}
|
||||
|
||||
public List<Permanent> getActivePermanents(UUID controllerId, CardType type) {
|
||||
public List<Permanent> getAllActivePermanents(FilterPermanent filter, UUID controllerId) {
|
||||
List<Permanent> active = new ArrayList<Permanent>();
|
||||
for (Permanent perm: field.values()) {
|
||||
if (perm.isPhasedIn() && perm.getCardType().contains(type) && perm.getControllerId().equals(controllerId))
|
||||
if (perm.isPhasedIn() && perm.getControllerId().equals(controllerId) && filter.match(perm))
|
||||
active.add(perm);
|
||||
}
|
||||
return active;
|
||||
}
|
||||
|
||||
public List<Permanent> getActivePermanents(FilterPermanent filter, UUID sourcePlayerId, Game game) {
|
||||
if (game.getRangeOfInfluence() == RangeOfInfluence.ALL) {
|
||||
return getAllActivePermanents(filter);
|
||||
}
|
||||
else {
|
||||
List<Permanent> active = new ArrayList<Permanent>();
|
||||
Set<UUID> range = game.getPlayer(sourcePlayerId).getInRange();
|
||||
for (Permanent perm: field.values()) {
|
||||
if (perm.isPhasedIn() && range.contains(perm.getControllerId()) && filter.match(perm))
|
||||
active.add(perm);
|
||||
}
|
||||
return active;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Permanent> getActivePermanents(UUID sourcePlayerId, Game game) {
|
||||
if (game.getRangeOfInfluence() == RangeOfInfluence.ALL) {
|
||||
return getAllActivePermanents();
|
||||
}
|
||||
else {
|
||||
List<Permanent> active = new ArrayList<Permanent>();
|
||||
Set<UUID> range = game.getPlayer(sourcePlayerId).getInRange();
|
||||
for (Permanent perm: field.values()) {
|
||||
if (perm.isPhasedIn() && range.contains(perm.getControllerId()))
|
||||
active.add(perm);
|
||||
}
|
||||
return active;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Permanent> getPhasedIn(UUID controllerId) {
|
||||
List<Permanent> phasedIn = new ArrayList<Permanent>();
|
||||
for (Permanent perm: field.values()) {
|
||||
|
|
|
@ -65,8 +65,8 @@ public interface Permanent extends Card {
|
|||
public boolean removeAttachment(UUID permanentId, Game game);
|
||||
|
||||
public UUID getControllerId();
|
||||
public void changeControllerId(UUID controllerId, Game game);
|
||||
public boolean canTarget(MageObject source);
|
||||
public boolean changeControllerId(UUID controllerId, Game game);
|
||||
public boolean canBeTargetedBy(MageObject source);
|
||||
public int getDamage();
|
||||
public int damage(int damage, UUID sourceId, Game game);
|
||||
public Counters getCounters();
|
||||
|
|
|
@ -267,12 +267,17 @@ public abstract class PermanentImpl extends CardImpl implements Permanent
|
|||
}
|
||||
|
||||
@Override
|
||||
public void changeControllerId(UUID controllerId, Game game) {
|
||||
public boolean changeControllerId(UUID controllerId, Game game) {
|
||||
if (!controllerId.equals(this.controllerId)) {
|
||||
this.removeFromCombat(game);
|
||||
this.controlledFromStartOfTurn = false;
|
||||
this.controllerId = controllerId;
|
||||
Player newController = game.getPlayer(controllerId);
|
||||
if (newController != null && (!newController.hasLeft() || !newController.hasLost())) {
|
||||
this.removeFromCombat(game);
|
||||
this.controlledFromStartOfTurn = false;
|
||||
this.controllerId = controllerId;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -389,7 +394,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(MageObject source) {
|
||||
public boolean canBeTargetedBy(MageObject source) {
|
||||
if (source != null) {
|
||||
if (abilities.containsKey(ShroudAbility.getInstance().getId()))
|
||||
return false;
|
||||
|
|
|
@ -81,7 +81,7 @@ public class Turn implements Serializable {
|
|||
|
||||
this.activePlayerId = activePlayerId;
|
||||
resetCounts();
|
||||
game.getPlayer(activePlayerId).beginTurn();
|
||||
game.getPlayer(activePlayerId).beginTurn(game);
|
||||
for (Phase phase: phases) {
|
||||
if (game.isGameOver())
|
||||
return;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
package mage.players;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.Constants.Outcome;
|
||||
import mage.MageItem;
|
||||
|
@ -77,6 +78,7 @@ public interface Player extends MageItem {
|
|||
public boolean hasWon();
|
||||
public boolean hasLeft();
|
||||
public ManaPool getManaPool();
|
||||
public Set<UUID> getInRange();
|
||||
|
||||
public void init(Game game);
|
||||
public void reset();
|
||||
|
@ -102,8 +104,8 @@ public interface Player extends MageItem {
|
|||
public boolean discard(Card card, Game game);
|
||||
public void lost(Game game);
|
||||
public void won(Game game);
|
||||
public void leaveGame();
|
||||
public void concede();
|
||||
public void leaveGame(Game game);
|
||||
public void concede(Game game);
|
||||
public void abort();
|
||||
|
||||
public void revealCards(Cards cards, Game game);
|
||||
|
@ -135,7 +137,7 @@ public interface Player extends MageItem {
|
|||
public void declareBlocker(UUID blockerId, UUID attackerId, Game game);
|
||||
public boolean hasAvailableAttackers(Game game);
|
||||
|
||||
public void beginTurn();
|
||||
public void beginTurn(Game game);
|
||||
public void endOfTurn(Game game);
|
||||
public void phasing(Game game);
|
||||
public void untap(Game game);
|
||||
|
|
|
@ -29,11 +29,16 @@
|
|||
package mage.players;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.Constants.Outcome;
|
||||
import mage.Constants.RangeOfInfluence;
|
||||
import mage.Constants.Zone;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Abilities;
|
||||
|
@ -63,6 +68,7 @@ import mage.game.permanent.PermanentToken;
|
|||
import mage.game.permanent.token.Token;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackAbility;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.target.common.TargetDiscard;
|
||||
import mage.util.Copier;
|
||||
|
@ -88,10 +94,13 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
protected boolean passed;
|
||||
protected boolean passedTurn;
|
||||
protected boolean left;
|
||||
protected RangeOfInfluence range;
|
||||
protected Set<UUID> inRange = new HashSet<UUID>();
|
||||
|
||||
public PlayerImpl(String name, Deck deck) {
|
||||
public PlayerImpl(String name, Deck deck, RangeOfInfluence range) {
|
||||
this.playerId = UUID.randomUUID();
|
||||
this.name = name;
|
||||
this.range = range;
|
||||
deck.setOwnerId(playerId);
|
||||
library = new Library(playerId);
|
||||
library.addAll(deck.getCards());
|
||||
|
@ -113,6 +122,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
game.getState().getWatchers().add(watcher);
|
||||
}
|
||||
}
|
||||
findRange(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -128,8 +138,50 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void beginTurn() {
|
||||
public void beginTurn(Game game) {
|
||||
this.landsPlayed = 0;
|
||||
findRange(game);
|
||||
}
|
||||
|
||||
protected void findRange(Game game) {
|
||||
//20100423 - 801.2c
|
||||
inRange.clear();
|
||||
if (range == RangeOfInfluence.ALL) {
|
||||
for (Player player: game.getPlayers().values()) {
|
||||
if (!player.hasLeft())
|
||||
inRange.add(player.getId());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((range.getRange() * 2) + 1 >= game.getPlayers().size()) {
|
||||
for (Player player: game.getPlayers().values()) {
|
||||
if (!player.hasLeft())
|
||||
inRange.add(player.getId());
|
||||
}
|
||||
}
|
||||
else {
|
||||
inRange.add(playerId);
|
||||
PlayerList players = game.getPlayerList(playerId);
|
||||
for (int i = 0; i < range.getRange(); i++) {
|
||||
Player player = players.getNext();
|
||||
while (player.hasLeft())
|
||||
player = players.getNext();
|
||||
inRange.add(player.getId());
|
||||
}
|
||||
players = game.getPlayerList(playerId);
|
||||
for (int i = 0; i < range.getRange(); i++) {
|
||||
Player player = players.getPrevious();
|
||||
while (player.hasLeft())
|
||||
player = players.getPrevious();
|
||||
inRange.add(player.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getInRange() {
|
||||
return inRange;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -145,6 +197,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
|
||||
@Override
|
||||
public boolean canTarget(MageObject source) {
|
||||
if (this.hasLost() || this.hasLeft())
|
||||
return false;
|
||||
if (source != null) {
|
||||
if (abilities.containsKey(ShroudAbility.getInstance().getId()))
|
||||
return false;
|
||||
|
@ -296,6 +350,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
ability.copy().activate(game, false);
|
||||
}
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.SPELL_CAST, card.getId(), playerId));
|
||||
game.fireInformEvent(name + " casts " + card.getName());
|
||||
game.removeLastBookmark();
|
||||
return true;
|
||||
}
|
||||
|
@ -452,7 +507,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
@Override
|
||||
public void untap(Game game) {
|
||||
//20091005 - 502.2
|
||||
for (Permanent permanent: game.getBattlefield().getAllPermanents(playerId)) {
|
||||
for (Permanent permanent: game.getBattlefield().getAllActivePermanents(playerId)) {
|
||||
permanent.untap(game);
|
||||
}
|
||||
}
|
||||
|
@ -569,7 +624,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
@Override
|
||||
public void restore(Player player) {
|
||||
this.library = player.getLibrary();
|
||||
// this.deck = player.getDeck();
|
||||
this.hand = player.getHand();
|
||||
this.graveyard = player.getGraveyard();
|
||||
this.abilities = player.getAbilities();
|
||||
|
@ -590,18 +644,45 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
|
||||
@Override
|
||||
public void resetPassed() {
|
||||
passed = false;
|
||||
if (!this.loses && !this.left)
|
||||
passed = false;
|
||||
else
|
||||
passed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void concede() {
|
||||
this.loses = true;
|
||||
public void concede(Game game) {
|
||||
leaveGame(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leaveGame() {
|
||||
public void leaveGame(Game game) {
|
||||
this.passed = true;
|
||||
this.abort();
|
||||
this.loses = true;
|
||||
this.left = true;
|
||||
//20100423 - 800.4a
|
||||
this.hand.clear();
|
||||
this.graveyard.clear();
|
||||
this.library.clear();
|
||||
for (Iterator<Permanent> it = game.getBattlefield().getAllPermanents().iterator(); it.hasNext();) {
|
||||
Permanent perm = it.next();
|
||||
if (perm.getOwnerId().equals(playerId)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
for (Iterator<StackObject> it = game.getStack().iterator(); it.hasNext();) {
|
||||
StackObject object = it.next();
|
||||
if (object.getControllerId().equals(playerId)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
for (Iterator<Permanent> it = game.getBattlefield().getAllPermanents().iterator(); it.hasNext();) {
|
||||
Permanent perm = it.next();
|
||||
if (perm.getControllerId().equals(playerId)) {
|
||||
perm.moveToExile(null, "", game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -613,6 +694,10 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
public void lost(Game game) {
|
||||
if (!game.replaceEvent(new GameEvent(GameEvent.EventType.LOSES, null, null, playerId))) {
|
||||
this.loses = true;
|
||||
//20100423 - 603.9
|
||||
if (!this.wins)
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LOST, null, null, playerId));
|
||||
leaveGame(game);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,8 +705,16 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
public void won(Game game) {
|
||||
if (!game.replaceEvent(new GameEvent(GameEvent.EventType.WINS, null, null, playerId))) {
|
||||
if (!this.loses) {
|
||||
this.wins = true;
|
||||
game.end();
|
||||
//20100423 - 800.6, 801.16
|
||||
if (game.getPlayers().size() > 2) {
|
||||
for (UUID opponentId: game.getOpponents(playerId)) {
|
||||
game.getPlayer(opponentId).lost(game);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.wins = true;
|
||||
game.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -684,7 +777,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
protected List<Permanent> getAvailableAttackers(Game game) {
|
||||
FilterCreatureForAttack attackFilter = new FilterCreatureForAttack();
|
||||
attackFilter.getControllerId().add(playerId);
|
||||
List<Permanent> attackers = game.getBattlefield().getActivePermanents(attackFilter);
|
||||
List<Permanent> attackers = game.getBattlefield().getAllActivePermanents(attackFilter);
|
||||
return attackers;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ public interface Target extends Serializable {
|
|||
public boolean isChosen();
|
||||
public boolean doneChosing();
|
||||
public void clearChosen();
|
||||
public boolean canChoose(UUID sourceId, Game game);
|
||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game);
|
||||
public boolean choose(Outcome outcome, Game game);
|
||||
public String getMessage();
|
||||
public String getTargetName();
|
||||
|
|
|
@ -70,18 +70,21 @@ public class TargetCard extends TargetObject {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceId, Game game) {
|
||||
for (Player player: game.getPlayers().values()) {
|
||||
if (filter.matchOwner(player.getId())) {
|
||||
switch (zone) {
|
||||
case HAND:
|
||||
if (player.getHand().getCards(filter).size() > this.minNumberOfTargets)
|
||||
return true;
|
||||
break;
|
||||
case GRAVEYARD:
|
||||
if (player.getGraveyard().getCards(filter).size() > this.minNumberOfTargets)
|
||||
return true;
|
||||
break;
|
||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) {
|
||||
if (filter.matchOwner(playerId)) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
switch (zone) {
|
||||
case HAND:
|
||||
if (player.getHand().getCards(filter).size() > this.minNumberOfTargets)
|
||||
return true;
|
||||
break;
|
||||
case GRAVEYARD:
|
||||
if (player.getGraveyard().getCards(filter).size() > this.minNumberOfTargets)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ public class TargetPermanent extends TargetObject {
|
|||
setController(controllerId, game);
|
||||
if (permanent != null) {
|
||||
if (this.source != null)
|
||||
return permanent.canTarget(game.getObject(this.source.getSourceId())) && filter.match(permanent);
|
||||
return permanent.canBeTargetedBy(game.getObject(this.source.getSourceId())) && filter.match(permanent);
|
||||
else
|
||||
return filter.match(permanent);
|
||||
}
|
||||
|
@ -115,12 +115,12 @@ public class TargetPermanent extends TargetObject {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceId, Game game) {
|
||||
List<Permanent> permanents = game.getBattlefield().getActivePermanents(filter);
|
||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
List<Permanent> permanents = game.getBattlefield().getActivePermanents(filter, sourceControllerId, game);
|
||||
Iterator<Permanent> it = permanents.iterator();
|
||||
while(it.hasNext()) {
|
||||
Permanent permanent = it.next();
|
||||
if (!permanent.canTarget(game.getObject(sourceId))) {
|
||||
if (!permanent.canBeTargetedBy(game.getObject(sourceId))) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,10 +63,11 @@ public class TargetPlayer extends TargetImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceId, Game game) {
|
||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
int count = 0;
|
||||
for (Player player: game.getPlayers().values()) {
|
||||
if (filter.match(player)) {
|
||||
for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null && !player.hasLeft() && filter.match(player)) {
|
||||
if (player.canTarget(game.getObject(sourceId)))
|
||||
count++;
|
||||
}
|
||||
|
|
|
@ -77,10 +77,11 @@ public class TargetSpell extends TargetObject {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean canChoose(UUID sourceId, Game game) {
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
int count = 0;
|
||||
for (StackObject stackObject: game.getStack()) {
|
||||
if (stackObject instanceof Spell && filter.match((Spell)stackObject)) {
|
||||
if (stackObject instanceof Spell && game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getControllerId()) && filter.match((Spell)stackObject)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,9 +101,9 @@ public class Targets extends ArrayList<Target> {
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean canChoose(UUID sourceId, Game game) {
|
||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
for (Target target: this) {
|
||||
if (!target.canChoose(sourceId, game))
|
||||
if (!target.canChoose(sourceId, sourceControllerId, game))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -33,6 +33,7 @@ import mage.Constants.CardType;
|
|||
import mage.Constants.Zone;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.common.FilterCreatureOrPlayer;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
@ -72,7 +73,7 @@ public class TargetCreatureOrPlayer extends TargetImpl {
|
|||
Permanent permanent = game.getPermanent(id);
|
||||
if (permanent != null) {
|
||||
if (this.source != null)
|
||||
return permanent.canTarget(game.getObject(this.source.getSourceId())) && filter.match(permanent);
|
||||
return permanent.canBeTargetedBy(game.getObject(this.source.getSourceId())) && filter.match(permanent);
|
||||
else
|
||||
return filter.match(permanent);
|
||||
}
|
||||
|
@ -86,16 +87,17 @@ public class TargetCreatureOrPlayer extends TargetImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceId, Game game) {
|
||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
int count = 0;
|
||||
for (Player player: game.getPlayers().values()) {
|
||||
if (player.canTarget(game.getObject(this.source.getSourceId())) && filter.match(player))
|
||||
for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null && player.canTarget(game.getObject(this.source.getSourceId())) && filter.match(player))
|
||||
count++;
|
||||
}
|
||||
if (count >= this.minNumberOfTargets)
|
||||
return true;
|
||||
for (Permanent permanent: game.getBattlefield().getActivePermanents(CardType.CREATURE)) {
|
||||
if (permanent.canTarget(game.getObject(this.source.getSourceId())) && filter.match(permanent))
|
||||
for (Permanent permanent: game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), sourceControllerId, game)) {
|
||||
if (permanent.canBeTargetedBy(game.getObject(this.source.getSourceId())) && filter.match(permanent))
|
||||
count++;
|
||||
}
|
||||
return count >= this.minNumberOfTargets;
|
||||
|
|
|
@ -29,11 +29,13 @@
|
|||
package mage.target.common;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.Constants.CardType;
|
||||
import mage.Constants.Zone;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.common.FilterPlaneswalkerOrPlayer;
|
||||
import mage.filter.common.FilterPlaneswalkerPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
@ -48,15 +50,15 @@ public class TargetDefender extends TargetImpl {
|
|||
protected FilterPlaneswalkerOrPlayer filter;
|
||||
protected UUID attackerId;
|
||||
|
||||
public TargetDefender(List<UUID> defenders, UUID attackerId) {
|
||||
public TargetDefender(Set<UUID> defenders, UUID attackerId) {
|
||||
this(1, 1, defenders, attackerId);
|
||||
}
|
||||
|
||||
public TargetDefender(int numTargets, List<UUID> defenders, UUID attackerId) {
|
||||
public TargetDefender(int numTargets, Set<UUID> defenders, UUID attackerId) {
|
||||
this(numTargets, numTargets, defenders, attackerId);
|
||||
}
|
||||
|
||||
public TargetDefender(int minNumTargets, int maxNumTargets, List<UUID> defenders, UUID attackerId) {
|
||||
public TargetDefender(int minNumTargets, int maxNumTargets, Set<UUID> defenders, UUID attackerId) {
|
||||
this.minNumberOfTargets = minNumTargets;
|
||||
this.maxNumberOfTargets = maxNumTargets;
|
||||
this.zone = Zone.ALL;
|
||||
|
@ -71,16 +73,17 @@ public class TargetDefender extends TargetImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceId, Game game) {
|
||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
int count = 0;
|
||||
for (Player player: game.getPlayers().values()) {
|
||||
if (player.canTarget(game.getObject(this.source.getSourceId())) && filter.match(player))
|
||||
for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null && player.canTarget(game.getObject(this.source.getSourceId())) && filter.match(player))
|
||||
count++;
|
||||
}
|
||||
if (count >= this.minNumberOfTargets)
|
||||
return true;
|
||||
for (Permanent permanent: game.getBattlefield().getActivePermanents(CardType.PLANESWALKER)) {
|
||||
if (permanent.canTarget(game.getObject(this.source.getSourceId())) && filter.match(permanent))
|
||||
for (Permanent permanent: game.getBattlefield().getActivePermanents(new FilterPlaneswalkerPermanent(), sourceControllerId, game)) {
|
||||
if (permanent.canBeTargetedBy(game.getObject(this.source.getSourceId())) && filter.match(permanent))
|
||||
count++;
|
||||
}
|
||||
return count >= this.minNumberOfTargets;
|
||||
|
@ -110,7 +113,7 @@ public class TargetDefender extends TargetImpl {
|
|||
}
|
||||
Permanent permanent = game.getPermanent(id);
|
||||
if (permanent != null) {
|
||||
return permanent.canTarget(game.getObject(attackerId)) && filter.match(permanent);
|
||||
return permanent.canBeTargetedBy(game.getObject(attackerId)) && filter.match(permanent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -44,10 +44,10 @@ public class TargetOpponent extends TargetPlayer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceId, Game game) {
|
||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
filter.getPlayerId().clear();
|
||||
filter.getPlayerId().addAll(game.getOpponents(this.getAbility().getControllerId()));
|
||||
return super.canChoose(sourceId, game);
|
||||
return super.canChoose(sourceId, sourceControllerId, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -38,6 +38,7 @@ import java.util.ListIterator;
|
|||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* a thread-safe circular list
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
@ -96,14 +97,29 @@ public class CircularList<E> implements List<E>, Iterable<E>, Serializable {
|
|||
return list.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next element in the list
|
||||
*
|
||||
* @return the next element in the list
|
||||
*/
|
||||
public E getNext() {
|
||||
return list.get(incrementPointer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the previous element in the list
|
||||
*
|
||||
* @return the previous element in the list
|
||||
*/
|
||||
public E getPrevious() {
|
||||
return list.get(decrementPointer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the current element from the list
|
||||
*
|
||||
* @return <tt>true</tt> is the item was successfully removed
|
||||
*/
|
||||
public boolean remove() {
|
||||
return this.remove(get());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue