mirror of
https://github.com/magefree/mage.git
synced 2025-12-26 05:22:02 -08:00
Merge branch 'master' into akh-card-frame
This commit is contained in:
commit
a2e8cedd02
272 changed files with 7641 additions and 2593 deletions
|
|
@ -4,6 +4,8 @@ import mage.abilities.Abilities;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.keyword.ChangelingAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.FrameStyle;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SuperType;
|
||||
|
|
@ -132,4 +134,52 @@ public interface MageObject extends MageItem, Serializable {
|
|||
default boolean isWorld() {
|
||||
return getSuperType().contains(SuperType.WORLD);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether two cards share card types.
|
||||
*
|
||||
*
|
||||
* @param otherCard
|
||||
* @return
|
||||
*/
|
||||
default boolean shareTypes(Card otherCard) {
|
||||
|
||||
if (otherCard == null) {
|
||||
throw new IllegalArgumentException("Params can't be null");
|
||||
}
|
||||
|
||||
for (CardType type : getCardType()) {
|
||||
if (otherCard.getCardType().contains(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
default boolean shareSubtypes(Card otherCard, Game game) {
|
||||
|
||||
if (otherCard == null) {
|
||||
throw new IllegalArgumentException("Params can't be null");
|
||||
}
|
||||
|
||||
if (this.isCreature() && otherCard.isCreature()) {
|
||||
if (this.getAbilities().contains(ChangelingAbility.getInstance())
|
||||
|| this.getSubtype(game).contains(ChangelingAbility.ALL_CREATURE_TYPE)
|
||||
|| otherCard.getAbilities().contains(ChangelingAbility.getInstance())
|
||||
|| otherCard.getSubtype(game).contains(ChangelingAbility.ALL_CREATURE_TYPE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (String subtype : this.getSubtype(game)) {
|
||||
if (otherCard.getSubtype(game).contains(subtype)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ package mage.abilities;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.keyword.ProtectionAbility;
|
||||
import mage.abilities.mana.ActivatedManaAbilityImpl;
|
||||
|
|
@ -245,7 +246,7 @@ public interface Abilities<T extends Ability> extends List<T>, Serializable {
|
|||
* @param abilityId
|
||||
* @return
|
||||
*/
|
||||
T get(UUID abilityId);
|
||||
Optional<T> get(UUID abilityId);
|
||||
|
||||
/**
|
||||
* TODO The usage of this method seems redundant to that of
|
||||
|
|
|
|||
|
|
@ -27,13 +27,6 @@
|
|||
*/
|
||||
package mage.abilities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.common.ZoneChangeTriggeredAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.keyword.ProtectionAbility;
|
||||
|
|
@ -44,6 +37,8 @@ import mage.game.Game;
|
|||
import mage.util.ThreadLocalStringBuilder;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @param <T>
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -277,12 +272,7 @@ public class AbilitiesImpl<T extends Ability> extends ArrayList<T> implements Ab
|
|||
|
||||
@Override
|
||||
public boolean containsRule(T ability) {
|
||||
for (T test : this) {
|
||||
if (ability.getRule().equals(test.getRule())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return stream().anyMatch(rule -> rule.getRule().equals(ability.getRule()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -301,32 +291,16 @@ public class AbilitiesImpl<T extends Ability> extends ArrayList<T> implements Ab
|
|||
|
||||
@Override
|
||||
public boolean containsKey(UUID abilityId) {
|
||||
for (T ability : this) {
|
||||
if (ability.getId().equals(abilityId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return stream().anyMatch(ability -> ability.getId().equals(abilityId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsClass(Class classObject) {
|
||||
for (T ability : this) {
|
||||
if (ability.getClass().equals(classObject)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return stream().anyMatch(ability -> ability.getClass().equals(classObject));
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(UUID abilityId) {
|
||||
for (T ability : this) {
|
||||
if (ability.getId().equals(abilityId)) {
|
||||
return ability;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
public Optional<T> get(UUID abilityId) {
|
||||
return stream().filter(ability -> ability.getId().equals(abilityId)).findFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@
|
|||
*/
|
||||
package mage.abilities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.Mana;
|
||||
|
|
@ -59,11 +63,6 @@ import mage.util.ThreadLocalStringBuilder;
|
|||
import mage.watchers.Watcher;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
|
@ -489,7 +488,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
protected String handleOtherXCosts(Game game, Player controller) {
|
||||
StringBuilder announceString = new StringBuilder();
|
||||
for (VariableCost variableCost : this.costs.getVariableCosts()) {
|
||||
if (!(variableCost instanceof VariableManaCost)) {
|
||||
if (!(variableCost instanceof VariableManaCost) && !((Cost) variableCost).isPaid()) {
|
||||
int xValue = variableCost.announceXValue(this, game);
|
||||
Cost fixedCost = variableCost.getFixedCostsFromAnnouncedValue(xValue);
|
||||
if (fixedCost != null) {
|
||||
|
|
@ -506,19 +505,20 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
|
||||
/**
|
||||
* 601.2b
|
||||
* If a cost that will be paid as the spell is being cast includes Phyrexian mana symbols,
|
||||
* the player announces whether he or she intends to pay 2 life or the corresponding colored mana cost for each of those symbols.
|
||||
* 601.2b If a cost that will be paid as the spell is being cast includes
|
||||
* Phyrexian mana symbols, the player announces whether he or she intends to
|
||||
* pay 2 life or the corresponding colored mana cost for each of those
|
||||
* symbols.
|
||||
*/
|
||||
private void handlePhyrexianManaCosts(Game game, UUID sourceId, Player controller) {
|
||||
Iterator<ManaCost> costIterator = manaCostsToPay.iterator();
|
||||
while(costIterator.hasNext()) {
|
||||
while (costIterator.hasNext()) {
|
||||
ManaCost cost = costIterator.next();
|
||||
if(cost instanceof PhyrexianManaCost) {
|
||||
PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost)cost;
|
||||
if (cost instanceof PhyrexianManaCost) {
|
||||
PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost) cost;
|
||||
PayLifeCost payLifeCost = new PayLifeCost(2);
|
||||
if(payLifeCost.canPay(this, sourceId, controller.getId(), game) &&
|
||||
controller.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + phyrexianManaCost.getBaseText() + '?', this, game)) {
|
||||
if (payLifeCost.canPay(this, sourceId, controller.getId(), game)
|
||||
&& controller.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + phyrexianManaCost.getBaseText() + '?', this, game)) {
|
||||
costIterator.remove();
|
||||
costs.add(payLifeCost);
|
||||
}
|
||||
|
|
@ -558,7 +558,11 @@ public abstract class AbilityImpl implements Ability {
|
|||
} else {
|
||||
String manaSymbol = null;
|
||||
if (variableManaCost.getFilter().isBlack()) {
|
||||
manaSymbol = "B";
|
||||
if (variableManaCost.getFilter().isRed()) {
|
||||
manaSymbol = "B/R";
|
||||
} else {
|
||||
manaSymbol = "B";
|
||||
}
|
||||
} else if (variableManaCost.getFilter().isRed()) {
|
||||
manaSymbol = "R";
|
||||
} else if (variableManaCost.getFilter().isBlue()) {
|
||||
|
|
|
|||
|
|
@ -28,20 +28,21 @@
|
|||
|
||||
package mage.abilities;
|
||||
|
||||
import java.util.Iterator;
|
||||
import mage.constants.Duration;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class DelayedTriggeredAbilities extends AbilitiesImpl<DelayedTriggeredAbility> {
|
||||
public class DelayedTriggeredAbilities extends AbilitiesImpl<DelayedTriggeredAbility> {
|
||||
|
||||
public DelayedTriggeredAbilities() {}
|
||||
public DelayedTriggeredAbilities() {
|
||||
}
|
||||
|
||||
public DelayedTriggeredAbilities(final DelayedTriggeredAbilities abilities) {
|
||||
public DelayedTriggeredAbilities(final DelayedTriggeredAbilities abilities) {
|
||||
super(abilities);
|
||||
}
|
||||
|
||||
|
|
@ -52,9 +53,9 @@ import mage.game.events.GameEvent;
|
|||
|
||||
public void checkTriggers(GameEvent event, Game game) {
|
||||
if (this.size() > 0) {
|
||||
for (Iterator<DelayedTriggeredAbility> it = this.iterator();it.hasNext();) {
|
||||
for (Iterator<DelayedTriggeredAbility> it = this.iterator(); it.hasNext(); ) {
|
||||
DelayedTriggeredAbility ability = it.next();
|
||||
if (ability.getDuration()== Duration.Custom){
|
||||
if (ability.getDuration() == Duration.Custom) {
|
||||
if (ability.isInactive(game)) {
|
||||
it.remove();
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ import mage.game.events.GameEvent;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -126,7 +125,7 @@ class KinshipBaseEffect extends OneShotEffect {
|
|||
if (card != null) {
|
||||
Cards cards = new CardsImpl(card);
|
||||
controller.lookAtCards(sourcePermanent.getName(), cards, game);
|
||||
if (CardUtil.shareSubtypes(sourcePermanent, card, game)) {
|
||||
if (sourcePermanent.shareSubtypes(card, game)) {
|
||||
if (controller.chooseUse(outcome,new StringBuilder("Kinship - Reveal ").append(card.getLogName()).append('?').toString(), source, game)) {
|
||||
controller.revealCards(sourcePermanent.getName(), cards, game);
|
||||
for (Effect effect: kinshipEffects) {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ package mage.abilities.costs;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.keyword.FlashbackAbility;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.Targets;
|
||||
|
|
@ -131,13 +133,15 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
|
|||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
||||
return true; /* not used */
|
||||
return true;
|
||||
/* not used */
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
return true; /* not used */
|
||||
return true;
|
||||
/* not used */
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -165,7 +169,9 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
|
|||
public int announceXValue(Ability source, Game game) {
|
||||
int xValue = 0;
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
StackObject stackObject = game.getStack().getStackObject(source.getId());
|
||||
if (controller != null
|
||||
&& (source instanceof FlashbackAbility || stackObject != null)) {
|
||||
xValue = controller.announceXCost(getMinValue(source, game), getMaxValue(source, game),
|
||||
"Announce the number of " + actionText, game, source, this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.costs.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -40,7 +39,6 @@ import mage.target.common.TargetCardInHand;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class DiscardXTargetCost extends VariableCostImpl {
|
||||
|
||||
protected FilterCard filter;
|
||||
|
|
@ -50,9 +48,8 @@ public class DiscardXTargetCost extends VariableCostImpl {
|
|||
}
|
||||
|
||||
public DiscardXTargetCost(FilterCard filter, boolean additionalCostText) {
|
||||
super(new StringBuilder(filter.getMessage()).append(" to discard").toString());
|
||||
this.text = new StringBuilder(additionalCostText ? "As an additional cost to cast {source}, discard ":"Discard ")
|
||||
.append(xText).append(' ').append(filter.getMessage()).toString();
|
||||
super(filter.getMessage() + " to discard");
|
||||
this.text = (additionalCostText ? "As an additional cost to cast {source}, discard " : "Discard ") + xText + ' ' + filter.getMessage();
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,15 @@ import mage.players.ManaPoolItem;
|
|||
public interface AsThoughManaEffect extends AsThoughEffect {
|
||||
|
||||
// return a mana type that can be used to pay a mana cost instead of the normally needed mana type
|
||||
/**
|
||||
*
|
||||
* @param manaType type of mana with which the player wants to pay the cost
|
||||
* @param mana mana pool item to pay from the cost
|
||||
* @param affectedControllerId
|
||||
* @param source
|
||||
* @param game
|
||||
* @return
|
||||
*/
|
||||
ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@
|
|||
*/
|
||||
package mage.abilities.effects;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.keyword.SpliceOntoArcaneAbility;
|
||||
|
|
@ -49,10 +52,6 @@ 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;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
|
@ -691,8 +690,7 @@ public class ContinuousEffects implements Serializable {
|
|||
spliceAbilities.remove(selectedAbility);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!spliceAbilities.isEmpty() && controller.chooseUse(Outcome.Benefit, "Splice another card?", abilityToModify, game));
|
||||
} while (!spliceAbilities.isEmpty() && controller.chooseUse(Outcome.Benefit, "Splice another card?", abilityToModify, game));
|
||||
controller.revealCards("Spliced cards", cardsToReveal, game);
|
||||
}
|
||||
}
|
||||
|
|
@ -702,10 +700,10 @@ public class ContinuousEffects implements Serializable {
|
|||
* Checks if an event won't happen because of an rule modifying effect
|
||||
*
|
||||
* @param event
|
||||
* @param targetAbility ability the event is attached to. can be null.
|
||||
* @param targetAbility ability the event is attached to. can be null.
|
||||
* @param game
|
||||
* @param checkPlayableMode true if the event does not really happen but
|
||||
* it's checked if the event would be replaced
|
||||
* it's checked if the event would be replaced
|
||||
* @return
|
||||
*/
|
||||
public boolean preventedByRuleModification(GameEvent event, Ability targetAbility, Game game, boolean checkPlayableMode) {
|
||||
|
|
@ -752,7 +750,7 @@ public class ContinuousEffects implements Serializable {
|
|||
do {
|
||||
HashMap<ReplacementEffect, HashSet<Ability>> rEffects = getApplicableReplacementEffects(event, game);
|
||||
// Remove all consumed effects (ability dependant)
|
||||
for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext(); ) {
|
||||
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());
|
||||
|
|
@ -933,7 +931,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
if (!waitingEffects.isEmpty()) {
|
||||
// check if waiting effects can be applied now
|
||||
for (Iterator<Map.Entry<ContinuousEffect, Set<UUID>>> iterator = waitingEffects.entrySet().iterator(); iterator.hasNext(); ) {
|
||||
for (Iterator<Map.Entry<ContinuousEffect, Set<UUID>>> iterator = waitingEffects.entrySet().iterator(); iterator.hasNext();) {
|
||||
Map.Entry<ContinuousEffect, Set<UUID>> entry = iterator.next();
|
||||
if (appliedEffects.containsAll(entry.getValue())) { // all dependent to effects are applied now so apply the effect itself
|
||||
appliedAbilities = appliedEffectAbilities.get(entry.getKey());
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ public class EntersBattlefieldEffect extends ReplacementEffectImpl {
|
|||
if (spell != null) {
|
||||
effect.setValue(SOURCE_CAST_SPELL_ABILITY, spell.getSpellAbility());
|
||||
}
|
||||
effect.setValue("appliedEffects", event.getAppliedEffects());
|
||||
effect.apply(game, source);
|
||||
}
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ public class EndTurnEffect extends OneShotEffect {
|
|||
if (!game.isSimulation()) {
|
||||
game.informPlayers("The current turn ends");
|
||||
}
|
||||
return game.endTurn();
|
||||
return game.endTurn(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
*/
|
||||
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;
|
||||
|
|
@ -75,7 +77,8 @@ public class EntersBattlefieldWithXCountersEffect extends OneShotEffect {
|
|||
if (amount > 0) {
|
||||
Counter counterToAdd = counter.copy();
|
||||
counterToAdd.add(amount - counter.getCount());
|
||||
permanent.addCounters(counterToAdd, source, game);
|
||||
ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects");
|
||||
permanent.addCounters(counterToAdd, source, game, appliedEffects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
*/
|
||||
package mage.abilities.effects.common.counter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
|
|
@ -103,7 +105,8 @@ public class AddCountersSourceEffect extends OneShotEffect {
|
|||
countersToAdd--;
|
||||
}
|
||||
newCounter.add(countersToAdd);
|
||||
card.addCounters(newCounter, source, game);
|
||||
ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects");
|
||||
card.addCounters(newCounter, source, game, appliedEffects);
|
||||
if (informPlayers && !game.isSimulation()) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
|
|
@ -128,7 +131,8 @@ public class AddCountersSourceEffect extends OneShotEffect {
|
|||
}
|
||||
newCounter.add(countersToAdd);
|
||||
int before = permanent.getCounters(game).getCount(newCounter.getName());
|
||||
permanent.addCounters(newCounter, source, game);
|
||||
ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects");
|
||||
permanent.addCounters(newCounter, source, game, appliedEffects); // if used from a replacement effect, the basic event determines if an effect was already applied to an event
|
||||
if (informPlayers && !game.isSimulation()) {
|
||||
int amountAdded = permanent.getCounters(game).getCount(newCounter.getName()) - before;
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
|
|
@ -150,12 +154,10 @@ public class AddCountersSourceEffect extends OneShotEffect {
|
|||
sb.append("put ");
|
||||
if (counter.getCount() > 1) {
|
||||
sb.append(CardUtil.numberToText(counter.getCount())).append(' ');
|
||||
} else if (amount.toString().equals("X") && amount.getMessage().isEmpty()) {
|
||||
sb.append("X ");
|
||||
} else {
|
||||
if (amount.toString().equals("X") && amount.getMessage().isEmpty()) {
|
||||
sb.append("X ");
|
||||
} else {
|
||||
sb.append("a ");
|
||||
}
|
||||
sb.append("a ");
|
||||
}
|
||||
sb.append(counter.getName().toLowerCase()).append(" counter on {this}");
|
||||
if (!amount.getMessage().isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
|
|
@ -71,7 +73,8 @@ class BloodthirstEffect extends OneShotEffect {
|
|||
if (watcher != null && watcher.conditionMet()) {
|
||||
Permanent permanent = game.getPermanentEntering(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game);
|
||||
ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects"); // the basic event is the EntersBattlefieldEvent, so use already applied replacement effects from that event
|
||||
permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game, appliedEffects);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
121
Mage/src/main/java/mage/abilities/keyword/EmbalmAbility.java
Normal file
121
Mage/src/main/java/mage/abilities/keyword/EmbalmAbility.java
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* 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.keyword;
|
||||
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbilityImpl;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.common.ExileSourceFromGraveCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.EmptyToken;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class EmbalmAbility extends ActivatedAbilityImpl {
|
||||
|
||||
private String rule;
|
||||
|
||||
public EmbalmAbility(Cost cost, Card card) {
|
||||
super(Zone.GRAVEYARD, new EmbalmEffect(), cost);
|
||||
addCost(new ExileSourceFromGraveCost());
|
||||
this.rule = setRule(cost, card);
|
||||
this.timing = TimingRule.SORCERY;
|
||||
setRule(cost, card);
|
||||
}
|
||||
|
||||
public EmbalmAbility(final EmbalmAbility ability) {
|
||||
super(ability);
|
||||
this.rule = ability.rule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmbalmAbility copy() {
|
||||
return new EmbalmAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return rule;
|
||||
}
|
||||
|
||||
private String setRule(Cost cost, Card card) {
|
||||
StringBuilder sb = new StringBuilder("Embalm ").append(cost.getText());
|
||||
sb.append(" <i>(").append(cost.getText());
|
||||
sb.append(", Exile this card from your graveyard: Create a token that's a copy of it, except it's a white Zombie ");
|
||||
for (String subtype : card.getSubtype(null)) {
|
||||
sb.append(subtype).append(" ");
|
||||
}
|
||||
sb.append(" with no mana cost. Embalm only as a sorcery.)</i>");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class EmbalmEffect extends OneShotEffect {
|
||||
|
||||
public EmbalmEffect() {
|
||||
super(Outcome.PutCreatureInPlay);
|
||||
}
|
||||
|
||||
public EmbalmEffect(final EmbalmEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmbalmEffect copy() {
|
||||
return new EmbalmEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null && card != null) {
|
||||
EmptyToken token = new EmptyToken();
|
||||
CardUtil.copyTo(token).from(card); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
|
||||
token.getColor(game).setColor(ObjectColor.WHITE);
|
||||
if (!token.getSubtype(game).contains("Zombie")) {
|
||||
token.getSubtype(game).add(0, "Zombie");
|
||||
}
|
||||
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId(), false, false, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
package mage.abilities.keyword;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
|
|
@ -14,7 +13,6 @@ import mage.target.targetpointer.FixedTarget;
|
|||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Plopman
|
||||
*/
|
||||
|
||||
|
|
@ -38,16 +36,12 @@ public class FlankingAbility extends TriggeredAbilityImpl {
|
|||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getTargetId().equals(this.getSourceId())) {
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if(permanent != null)
|
||||
{
|
||||
boolean hasFlankingAbility = false;
|
||||
for(Ability ability : permanent.getAbilities()){
|
||||
if(ability instanceof FlankingAbility){
|
||||
hasFlankingAbility = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!hasFlankingAbility){
|
||||
if (permanent != null) {
|
||||
boolean hasFlankingAbility =
|
||||
permanent.getAbilities().stream().anyMatch(ability -> ability instanceof FlankingAbility);
|
||||
|
||||
|
||||
if (!hasFlankingAbility) {
|
||||
for (Effect effect : this.getEffects()) {
|
||||
effect.setTargetPointer(new FixedTarget(event.getSourceId()));
|
||||
}
|
||||
|
|
@ -68,5 +62,5 @@ public class FlankingAbility extends TriggeredAbilityImpl {
|
|||
return new FlankingAbility(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,20 +27,10 @@
|
|||
*/
|
||||
package mage.abilities.keyword;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.StaticAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.Costs;
|
||||
import mage.abilities.costs.CostsImpl;
|
||||
import mage.abilities.costs.OptionalAdditionalCost;
|
||||
import mage.abilities.costs.OptionalAdditionalCostImpl;
|
||||
import mage.abilities.costs.OptionalAdditionalSourceCosts;
|
||||
import mage.abilities.costs.*;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
|
|
@ -51,8 +41,9 @@ import mage.constants.Zone;
|
|||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 20121001 702.31. Kicker 702.31a Kicker is a static ability that functions
|
||||
* while the spell with kicker is on the stack. "Kicker [cost]" means "You may
|
||||
* pay an additional [cost] as you cast this spell." Paying a spell's kicker
|
||||
|
|
@ -80,7 +71,6 @@ import mage.players.Player;
|
|||
* 601.2c.
|
||||
*
|
||||
* @author LevelX2
|
||||
*
|
||||
*/
|
||||
public class KickerAbility extends StaticAbility implements OptionalAdditionalSourceCosts {
|
||||
|
||||
|
|
@ -159,10 +149,7 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo
|
|||
|
||||
public int getKickedCounter(Game game, Ability source) {
|
||||
String key = getActivationKey(source, "", game);
|
||||
if (activations.containsKey(key)) {
|
||||
return activations.get(key);
|
||||
}
|
||||
return 0;
|
||||
return activations.getOrDefault(key, 0);
|
||||
}
|
||||
|
||||
public boolean isKicked(Game game, Ability source, String costText) {
|
||||
|
|
@ -227,10 +214,10 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo
|
|||
&& player.chooseUse(Outcome.Benefit, "Pay " + times + kickerCost.getText(false) + " ?", ability, game)) {
|
||||
this.activateKicker(kickerCost, ability, game);
|
||||
if (kickerCost instanceof Costs) {
|
||||
for (Iterator itKickerCost = ((Costs) kickerCost).iterator(); itKickerCost.hasNext();) {
|
||||
for (Iterator itKickerCost = ((Costs) kickerCost).iterator(); itKickerCost.hasNext(); ) {
|
||||
Object kickerCostObject = itKickerCost.next();
|
||||
if ((kickerCostObject instanceof Costs) || (kickerCostObject instanceof CostsImpl)) {
|
||||
for (@SuppressWarnings("unchecked") Iterator<Cost> itDetails = ((Costs) kickerCostObject).iterator(); itDetails.hasNext();) {
|
||||
for (@SuppressWarnings("unchecked") Iterator<Cost> itDetails = ((Costs) kickerCostObject).iterator(); itDetails.hasNext(); ) {
|
||||
addKickerCostsToAbility(itDetails.next(), ability, game);
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.StaticAbility;
|
||||
import mage.abilities.common.DiesTriggeredAbility;
|
||||
|
|
@ -159,7 +161,8 @@ class ModularDistributeCounterEffect extends OneShotEffect {
|
|||
if (sourcePermanent != null && targetArtifact != null && player != null) {
|
||||
int numberOfCounters = sourcePermanent.getCounters(game).getCount(CounterType.P1P1);
|
||||
if (numberOfCounters > 0) {
|
||||
targetArtifact.addCounters(CounterType.P1P1.createInstance(numberOfCounters), source, game);
|
||||
ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects"); // the basic event is the EntersBattlefieldEvent, so use already applied replacement effects from that event
|
||||
targetArtifact.addCounters(CounterType.P1P1.createInstance(numberOfCounters), source, game, appliedEffects);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import mage.constants.Zone;
|
|||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Split Second
|
||||
*
|
||||
|
|
@ -66,8 +68,8 @@ class SplitSecondEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
return true;
|
||||
}
|
||||
if (event.getType() == GameEvent.EventType.ACTIVATE_ABILITY) {
|
||||
Ability ability = game.getAbility(event.getTargetId(), event.getSourceId());
|
||||
if (ability != null && !(ability instanceof ActivatedManaAbilityImpl)) {
|
||||
Optional<Ability> ability = game.getAbility(event.getTargetId(), event.getSourceId());
|
||||
if (ability != null && !(ability.get() instanceof ActivatedManaAbilityImpl)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,13 +27,14 @@
|
|||
*/
|
||||
package mage.abilities.keyword;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.SunburstCount;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
|
|
@ -97,8 +98,8 @@ class SunburstEffect extends OneShotEffect {
|
|||
counter = CounterType.CHARGE.createInstance(amount.calculate(game, source, this));
|
||||
}
|
||||
if (counter != null) {
|
||||
|
||||
permanent.addCounters(counter, source, game);
|
||||
ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects"); // the basic event is the EntersBattlefieldEvent, so use already applied replacement effects from that event
|
||||
permanent.addCounters(counter, source, game, appliedEffects);
|
||||
if (!game.isSimulation()) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ class UnleashReplacementEffect extends ReplacementEffectImpl {
|
|||
if (!game.isSimulation()) {
|
||||
game.informPlayers(controller.getLogName() + " unleashes " + creature.getName());
|
||||
}
|
||||
creature.addCounters(CounterType.P1P1.createInstance(), source, game);
|
||||
creature.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ public class MageDrawAction extends MageAction {
|
|||
*/
|
||||
protected int drawCard(Game game) {
|
||||
GameEvent event = GameEvent.getEvent(GameEvent.EventType.DRAW_CARD, player.getId(), player.getId());
|
||||
event.setAppliedEffects(appliedEffects);
|
||||
event.addAppliedEffects(appliedEffects);
|
||||
if (!game.replaceEvent(event)) {
|
||||
Card card = player.getLibrary().removeFromTop(game);
|
||||
if (card != null) {
|
||||
|
|
|
|||
|
|
@ -27,24 +27,16 @@
|
|||
*/
|
||||
package mage.cards;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.util.RandomUtil;
|
||||
import mage.util.ThreadLocalStringBuilder;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class CardsImpl extends LinkedHashSet<UUID> implements Cards, Serializable {
|
||||
|
|
@ -118,24 +110,13 @@ public class CardsImpl extends LinkedHashSet<UUID> implements Cards, Serializabl
|
|||
|
||||
@Override
|
||||
public int count(FilterCard filter, Game game) {
|
||||
int result = 0;
|
||||
for (UUID cardId : this) {
|
||||
if (filter.match(game.getCard(cardId), game)) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return (int) stream().filter(cardId -> filter.match(game.getCard(cardId), game)).count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int count(FilterCard filter, UUID playerId, Game game) {
|
||||
int result = 0;
|
||||
for (UUID card : this) {
|
||||
if (filter.match(game.getCard(card), playerId, game)) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return (int) this.stream().filter(card -> filter.match(game.getCard(card), playerId, game)).count();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -143,13 +124,8 @@ public class CardsImpl extends LinkedHashSet<UUID> implements Cards, Serializabl
|
|||
if (sourceId == null) {
|
||||
return count(filter, playerId, game);
|
||||
}
|
||||
int result = 0;
|
||||
for (UUID card : this) {
|
||||
if (filter.match(game.getCard(card), sourceId, playerId, game)) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return (int) this.stream().filter(card -> filter.match(game.getCard(card), sourceId, playerId, game)).count();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -169,20 +145,13 @@ public class CardsImpl extends LinkedHashSet<UUID> implements Cards, Serializabl
|
|||
|
||||
@Override
|
||||
public Set<Card> getCards(FilterCard filter, Game game) {
|
||||
Set<Card> cards = new LinkedHashSet<>();
|
||||
for (UUID card : this) {
|
||||
boolean match = filter.match(game.getCard(card), game);
|
||||
if (match) {
|
||||
cards.add(game.getCard(card));
|
||||
}
|
||||
}
|
||||
return cards;
|
||||
return stream().map(game::getCard).filter(card -> filter.match(card, game)).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Card> getCards(Game game) {
|
||||
Set<Card> cards = new LinkedHashSet<>();
|
||||
for (Iterator<UUID> it = this.iterator(); it.hasNext();) { // Changed to iterator because of ConcurrentModificationException
|
||||
for (Iterator<UUID> it = this.iterator(); it.hasNext(); ) { // Changed to iterator because of ConcurrentModificationException
|
||||
UUID cardId = it.next();
|
||||
|
||||
Card card = game.getCard(cardId);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import mage.util.RandomUtil;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -160,13 +161,7 @@ public abstract class ExpansionSet implements Serializable {
|
|||
}
|
||||
|
||||
public List<SetCardInfo> findCardInfoByClass(Class<?> clazz) {
|
||||
ArrayList<SetCardInfo> result = new ArrayList<>();
|
||||
for (SetCardInfo info : cards) {
|
||||
if (info.getCardClass().equals(clazz)) {
|
||||
result.add(info);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return cards.stream().filter(info -> info.getCardClass().equals(clazz)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<Card> create15CardBooster() {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ public enum CounterType {
|
|||
BLAZE("blaze"),
|
||||
BOUNTY("bounty"),
|
||||
BRIBERY("bribery"),
|
||||
BRICK("brick"),
|
||||
CARRION("carrion"),
|
||||
CHARGE("charge"),
|
||||
CORPSE("corpse"),
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@
|
|||
package mage.counters;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -122,12 +122,9 @@ public class Counters extends HashMap<String, Counter> implements Serializable {
|
|||
}
|
||||
|
||||
public List<BoostCounter> getBoostCounters() {
|
||||
List<BoostCounter> boosters = new ArrayList<>();
|
||||
for (Counter counter : this.values()) {
|
||||
if (counter instanceof BoostCounter) {
|
||||
boosters.add((BoostCounter) counter);
|
||||
}
|
||||
}
|
||||
return boosters;
|
||||
return values().stream().
|
||||
filter(counter -> counter instanceof BoostCounter).
|
||||
map(counter -> (BoostCounter) counter).
|
||||
collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,13 +28,7 @@
|
|||
package mage.game;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import mage.MageItem;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -50,11 +44,7 @@ import mage.cards.Cards;
|
|||
import mage.cards.MeldCard;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.choices.Choice;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.PlayerAction;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.counters.Counters;
|
||||
import mage.game.combat.Combat;
|
||||
import mage.game.command.Commander;
|
||||
|
|
@ -128,7 +118,7 @@ public interface Game extends MageItem, Serializable {
|
|||
|
||||
Card getCard(UUID cardId);
|
||||
|
||||
Ability getAbility(UUID abilityId, UUID sourceId);
|
||||
Optional<Ability> getAbility(UUID abilityId, UUID sourceId);
|
||||
|
||||
void setZone(UUID objectId, Zone zone);
|
||||
|
||||
|
|
@ -402,7 +392,7 @@ public interface Game extends MageItem, Serializable {
|
|||
|
||||
void playPriority(UUID activePlayerId, boolean resuming);
|
||||
|
||||
boolean endTurn();
|
||||
boolean endTurn(Ability source);
|
||||
|
||||
int doAction(MageAction action);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@
|
|||
*/
|
||||
package mage.game;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import mage.MageException;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.*;
|
||||
|
|
@ -92,11 +96,6 @@ import mage.watchers.Watchers;
|
|||
import mage.watchers.common.*;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public abstract class GameImpl implements Game, Serializable {
|
||||
|
||||
private static final int ROLLBACK_TURNS_MAX = 4;
|
||||
|
|
@ -503,12 +502,12 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Ability getAbility(UUID abilityId, UUID sourceId) {
|
||||
public Optional<Ability> getAbility(UUID abilityId, UUID sourceId) {
|
||||
MageObject object = getObject(sourceId);
|
||||
if (object != null) {
|
||||
return object.getAbilities().get(abilityId);
|
||||
}
|
||||
return null;
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// @Override
|
||||
|
|
@ -2336,10 +2335,10 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
Iterator it = gameCards.entrySet().iterator();
|
||||
Iterator<Entry<UUID, Card>> it = gameCards.entrySet().iterator();
|
||||
|
||||
while (it.hasNext()) {
|
||||
Entry<UUID, Card> entry = (Entry<UUID, Card>) it.next();
|
||||
Entry<UUID, Card> entry = it.next();
|
||||
Card card = entry.getValue();
|
||||
if (card.getOwnerId().equals(playerId)) {
|
||||
it.remove();
|
||||
|
|
@ -2672,8 +2671,8 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean endTurn() {
|
||||
getTurn().endTurn(this, getActivePlayerId());
|
||||
public boolean endTurn(Ability source) {
|
||||
getTurn().endTurn(this, getActivePlayerId(), source);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@
|
|||
*/
|
||||
package mage.game;
|
||||
|
||||
import java.io.Serializable;
|
||||
import mage.players.Player;
|
||||
import mage.players.PlayerType;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -37,18 +39,18 @@ import mage.players.Player;
|
|||
public class Seat implements Serializable {
|
||||
|
||||
// private static final Logger logger = Logger.getLogger(Seat.class);
|
||||
private String playerType;
|
||||
private PlayerType playerType;
|
||||
private Player player;
|
||||
|
||||
public Seat(String playerType) {
|
||||
public Seat(PlayerType playerType) {
|
||||
this.playerType = playerType;
|
||||
}
|
||||
|
||||
public String getPlayerType() {
|
||||
public PlayerType getPlayerType() {
|
||||
return playerType;
|
||||
}
|
||||
|
||||
public void setPlayerType(String playerType) {
|
||||
public void setPlayerType(PlayerType playerType) {
|
||||
this.playerType = playerType;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,13 +27,6 @@
|
|||
*/
|
||||
package mage.game;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.cards.decks.DeckValidator;
|
||||
import mage.constants.TableState;
|
||||
import mage.game.events.Listener;
|
||||
|
|
@ -43,9 +36,12 @@ import mage.game.match.Match;
|
|||
import mage.game.result.ResultProtos.TableProto;
|
||||
import mage.game.tournament.Tournament;
|
||||
import mage.players.Player;
|
||||
import mage.players.PlayerType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class Table implements Serializable {
|
||||
|
|
@ -74,21 +70,21 @@ public class Table implements Serializable {
|
|||
|
||||
protected TableEventSource tableEventSource = new TableEventSource();
|
||||
|
||||
public Table(UUID roomId, String gameType, String name, String controllerName, DeckValidator validator, List<String> playerTypes, TableRecorder recorder, Tournament tournament, Set<String> bannedUsernames) {
|
||||
public Table(UUID roomId, String gameType, String name, String controllerName, DeckValidator validator, List<PlayerType> playerTypes, TableRecorder recorder, Tournament tournament, Set<String> bannedUsernames) {
|
||||
this(roomId, gameType, name, controllerName, validator, playerTypes, recorder, bannedUsernames);
|
||||
this.tournament = tournament;
|
||||
this.isTournament = true;
|
||||
setState(TableState.WAITING);
|
||||
}
|
||||
|
||||
public Table(UUID roomId, String gameType, String name, String controllerName, DeckValidator validator, List<String> playerTypes, TableRecorder recorder, Match match, Set<String> bannedUsernames) {
|
||||
public Table(UUID roomId, String gameType, String name, String controllerName, DeckValidator validator, List<PlayerType> playerTypes, TableRecorder recorder, Match match, Set<String> bannedUsernames) {
|
||||
this(roomId, gameType, name, controllerName, validator, playerTypes, recorder, bannedUsernames);
|
||||
this.match = match;
|
||||
this.isTournament = false;
|
||||
setState(TableState.WAITING);
|
||||
}
|
||||
|
||||
protected Table(UUID roomId, String gameType, String name, String controllerName, DeckValidator validator, List<String> playerTypes, TableRecorder recorder, Set<String> bannedUsernames) {
|
||||
protected Table(UUID roomId, String gameType, String name, String controllerName, DeckValidator validator, List<PlayerType> playerTypes, TableRecorder recorder, Set<String> bannedUsernames) {
|
||||
tableId = UUID.randomUUID();
|
||||
this.roomId = roomId;
|
||||
this.numSeats = playerTypes.size();
|
||||
|
|
@ -102,10 +98,10 @@ public class Table implements Serializable {
|
|||
this.bannedUsernames = new HashSet<>(bannedUsernames);
|
||||
}
|
||||
|
||||
private void createSeats(List<String> playerTypes) {
|
||||
private void createSeats(List<PlayerType> playerTypes) {
|
||||
int i = 0;
|
||||
seats = new Seat[numSeats];
|
||||
for (String playerType : playerTypes) {
|
||||
for (PlayerType playerType : playerTypes) {
|
||||
seats[i] = new Seat(playerType);
|
||||
i++;
|
||||
}
|
||||
|
|
@ -145,7 +141,6 @@ public class Table implements Serializable {
|
|||
/**
|
||||
* All activities of the table end (only replay of games (if active) and
|
||||
* display tournament results)
|
||||
*
|
||||
*/
|
||||
public void closeTable() {
|
||||
if (getState() != TableState.WAITING && getState() != TableState.READY_TO_START) {
|
||||
|
|
@ -156,7 +151,6 @@ public class Table implements Serializable {
|
|||
|
||||
/**
|
||||
* Complete remove of the table, release all objects
|
||||
*
|
||||
*/
|
||||
public void cleanUp() {
|
||||
if (match != null) {
|
||||
|
|
@ -211,9 +205,9 @@ public class Table implements Serializable {
|
|||
return numSeats;
|
||||
}
|
||||
|
||||
public Seat getNextAvailableSeat(String playerType) {
|
||||
public Seat getNextAvailableSeat(PlayerType playerType) {
|
||||
for (int i = 0; i < numSeats; i++) {
|
||||
if (seats[i].getPlayer() == null && seats[i].getPlayerType().equals(playerType)) {
|
||||
if (seats[i].getPlayer() == null && seats[i].getPlayerType() == (playerType)) {
|
||||
return seats[i];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,6 @@
|
|||
*/
|
||||
package mage.game.command;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Abilities;
|
||||
|
|
@ -48,18 +44,22 @@ import mage.game.Game;
|
|||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.util.GameLog;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Commander implements CommandObject {
|
||||
|
||||
private final Card sourceObject;
|
||||
private final Abilities<Ability> abilites = new AbilitiesImpl<>();
|
||||
private final Abilities<Ability> abilities = new AbilitiesImpl<>();
|
||||
|
||||
public Commander(Card card) {
|
||||
this.sourceObject = card;
|
||||
abilites.add(new CastCommanderAbility(card));
|
||||
abilities.add(new CastCommanderAbility(card));
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
if (!(ability instanceof SpellAbility)) {
|
||||
Ability newAbility = ability.copy();
|
||||
abilites.add(newAbility);
|
||||
abilities.add(newAbility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -134,7 +134,7 @@ public class Commander implements CommandObject {
|
|||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities() {
|
||||
return abilites;
|
||||
return abilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@
|
|||
*/
|
||||
package mage.game.command;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.ObjectColor;
|
||||
|
|
@ -46,6 +44,11 @@ import mage.game.Game;
|
|||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.util.GameLog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author nantuko
|
||||
*/
|
||||
|
|
@ -92,7 +95,7 @@ public class Emblem implements CommandObject {
|
|||
this.sourceObject = sourceObject;
|
||||
if (sourceObject instanceof Card) {
|
||||
if (name.isEmpty()) {
|
||||
name = ((Card) sourceObject).getSubtype(null).toString();
|
||||
name = sourceObject.getSubtype(null).toString();
|
||||
}
|
||||
if (expansionSetCodeForImage.isEmpty()) {
|
||||
expansionSetCodeForImage = ((Card) sourceObject).getExpansionSetCode();
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ public class GameEvent implements Serializable {
|
|||
mana the mana added
|
||||
*/
|
||||
MANA_ADDED,
|
||||
/* MANA_PAYED
|
||||
/* MANA_PAID
|
||||
targetId id if the ability the mana was paid for (not the sourceId)
|
||||
sourceId sourceId of the mana source
|
||||
playerId controller of the ability the mana was paid for
|
||||
|
|
@ -174,7 +174,7 @@ public class GameEvent implements Serializable {
|
|||
flag indicates a special condition
|
||||
data originalId of the mana producing ability
|
||||
*/
|
||||
MANA_PAYED,
|
||||
MANA_PAID,
|
||||
LOSES, LOST, WINS,
|
||||
TARGET, TARGETED,
|
||||
/* TARGETS_VALID
|
||||
|
|
@ -451,12 +451,19 @@ public class GameEvent implements Serializable {
|
|||
return type == EventType.CUSTOM_EVENT && this.customEventType.equals(customEventType);
|
||||
}
|
||||
|
||||
public void setAppliedEffects(ArrayList<UUID> appliedEffects) {
|
||||
if (this.appliedEffects == null) {
|
||||
this.appliedEffects = new ArrayList<>();
|
||||
}
|
||||
public void addAppliedEffects(ArrayList<UUID> appliedEffects) {
|
||||
if (appliedEffects != null) {
|
||||
this.appliedEffects.addAll(appliedEffects);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAppliedEffects(ArrayList<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
|
||||
} else {
|
||||
this.appliedEffects.addAll(appliedEffects);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,16 +28,18 @@
|
|||
|
||||
package mage.game.match;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import mage.constants.MatchTimeLimit;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.SkillLevel;
|
||||
import mage.game.result.ResultProtos;
|
||||
import mage.players.PlayerType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -53,7 +55,7 @@ public class MatchOptions implements Serializable {
|
|||
protected String gameType;
|
||||
protected String deckType;
|
||||
protected boolean limited;
|
||||
protected List<String> playerTypes = new ArrayList<>();
|
||||
protected List<PlayerType> playerTypes = new ArrayList<>();
|
||||
protected boolean multiPlayer;
|
||||
protected int numSeats;
|
||||
protected String password;
|
||||
|
|
@ -154,7 +156,7 @@ public class MatchOptions implements Serializable {
|
|||
this.deckType = deckType;
|
||||
}
|
||||
|
||||
public List<String> getPlayerTypes() {
|
||||
public List<PlayerType> getPlayerTypes() {
|
||||
return playerTypes;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,22 +103,20 @@ public class Battlefield implements Serializable {
|
|||
* @return count
|
||||
*/
|
||||
public int count(FilterPermanent filter, UUID sourceId, UUID sourcePlayerId, Game game) {
|
||||
int count;
|
||||
if (game.getRangeOfInfluence() == RangeOfInfluence.ALL) {
|
||||
count = (int) field.values()
|
||||
return (int) field.values()
|
||||
.stream()
|
||||
.filter(permanent -> filter.match(permanent, sourceId, sourcePlayerId, game)
|
||||
&& permanent.isPhasedIn())
|
||||
.count();
|
||||
} else {
|
||||
Set<UUID> range = game.getPlayer(sourcePlayerId).getInRange();
|
||||
count = (int) field.values()
|
||||
return (int) field.values()
|
||||
.stream()
|
||||
.filter(permanent -> range.contains(permanent.getControllerId())
|
||||
&& filter.match(permanent, sourceId, sourcePlayerId, game)
|
||||
&& permanent.isPhasedIn()).count();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -319,20 +317,18 @@ public class Battlefield implements Serializable {
|
|||
* @see Permanent
|
||||
*/
|
||||
public List<Permanent> getActivePermanents(FilterPermanent filter, UUID sourcePlayerId, UUID sourceId, Game game) {
|
||||
List<Permanent> active = new ArrayList<>();
|
||||
if (game.getRangeOfInfluence() == RangeOfInfluence.ALL) {
|
||||
active = field.values()
|
||||
return field.values()
|
||||
.stream()
|
||||
.filter(perm -> perm.isPhasedIn() && filter.match(perm, sourceId, sourcePlayerId, game))
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
Set<UUID> range = game.getPlayer(sourcePlayerId).getInRange();
|
||||
active = field.values()
|
||||
return field.values()
|
||||
.stream()
|
||||
.filter(perm -> perm.isPhasedIn() && range.contains(perm.getControllerId())
|
||||
&& filter.match(perm, sourceId, sourcePlayerId, game)).collect(Collectors.toList());
|
||||
}
|
||||
return active;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ public class AngelToken extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("AVR", "C14", "CFX", "GTC", "ISD", "M14", "ORI", "SOI", "ZEN", "C15"));
|
||||
tokenImageSets.addAll(Arrays.asList("AVR", "C14", "CFX", "GTC", "ISD", "M14", "ORI", "SOI", "ZEN", "C15", "MM3"));
|
||||
}
|
||||
|
||||
public AngelToken() {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public class BeastToken extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("C14", "LRW", "M15", "M14", "DDL", "M13", "M12", "DD3GVL", "NPH", "M11", "M10", "EVE"));
|
||||
tokenImageSets.addAll(Arrays.asList("C14", "LRW", "M15", "M14", "DDL", "M13", "M12", "DD3GVL", "NPH", "M11", "M10", "EVE", "MM3"));
|
||||
}
|
||||
|
||||
public BeastToken() {
|
||||
|
|
@ -71,7 +71,7 @@ public class BeastToken extends Token {
|
|||
if (getOriginalExpansionSetCode().equals("M15")) {
|
||||
this.setTokenType(2);
|
||||
}
|
||||
if (getOriginalExpansionSetCode().equals("DD3GVL") || getOriginalExpansionSetCode().equals("C14") || getOriginalExpansionSetCode().equals("DDD")) {
|
||||
if (getOriginalExpansionSetCode().equals("DD3GVL") || getOriginalExpansionSetCode().equals("C14") || getOriginalExpansionSetCode().equals("DDD") || getOriginalExpansionSetCode().equals("MM3")) {
|
||||
this.setTokenType(1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public class BeastToken2 extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("ZEN", "C14", "DDD", "C15", "DD3GVL"));
|
||||
tokenImageSets.addAll(Arrays.asList("ZEN", "C14", "DDD", "C15", "DD3GVL", "MM3"));
|
||||
}
|
||||
|
||||
public BeastToken2() {
|
||||
|
|
@ -76,7 +76,7 @@ public class BeastToken2 extends Token {
|
|||
@Override
|
||||
public void setExpansionSetCodeForImage(String code) {
|
||||
super.setExpansionSetCodeForImage(code);
|
||||
if (getOriginalExpansionSetCode().equals("C14") || getOriginalExpansionSetCode().equals("DDD") || getOriginalExpansionSetCode().equals("DD3GVL")) {
|
||||
if (getOriginalExpansionSetCode().equals("C14") || getOriginalExpansionSetCode().equals("DDD") || getOriginalExpansionSetCode().equals("DD3GVL") || getOriginalExpansionSetCode().equals("MM3")) {
|
||||
this.setTokenType(2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public class BirdToken extends Token {
|
|||
power = new MageInt(1);
|
||||
toughness = new MageInt(1);
|
||||
addAbility(FlyingAbility.getInstance());
|
||||
availableImageSetCodes.addAll(Arrays.asList("BNG", "RTR", "ZEN", "C16"));
|
||||
availableImageSetCodes.addAll(Arrays.asList("BNG", "RTR", "ZEN", "C16", "MM3", "DGM"));
|
||||
}
|
||||
|
||||
public BirdToken(final BirdToken token) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import mage.constants.CardType;
|
||||
import mage.MageInt;
|
||||
import mage.util.RandomUtil;
|
||||
|
|
@ -38,6 +41,12 @@ import mage.util.RandomUtil;
|
|||
*/
|
||||
public class CentaurToken extends Token {
|
||||
|
||||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("RTR", "MM3"));
|
||||
}
|
||||
|
||||
public CentaurToken() {
|
||||
super("Centaur", "3/3 green Centaur creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
|
|
@ -46,7 +55,6 @@ public class CentaurToken extends Token {
|
|||
subtype.add("Centaur");
|
||||
power = new MageInt(3);
|
||||
toughness = new MageInt(3);
|
||||
setOriginalExpansionSetCode("RTR");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public class DragonToken extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("DTK", "MMA", "ALA"));
|
||||
tokenImageSets.addAll(Arrays.asList("DTK", "MMA", "ALA", "MM3"));
|
||||
}
|
||||
|
||||
public DragonToken() {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ public class ElephantToken extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("C14", "CNS", "DDD", "MM2", "WWK", "OGW", "C15", "DD3GVL"));
|
||||
tokenImageSets.addAll(Arrays.asList("C14", "CNS", "DDD", "MM2", "WWK", "OGW", "C15", "DD3GVL", "MM3"));
|
||||
}
|
||||
|
||||
public ElephantToken() {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ public class GoblinToken extends Token {
|
|||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("10E", "ALA", "SOM", "M10", "NPH", "M13", "RTR",
|
||||
"MMA", "M15", "C14", "KTK", "EVG", "DTK", "ORI", "DDG", "DDN", "DD3EVG", "MM2"));
|
||||
"MMA", "M15", "C14", "KTK", "EVG", "DTK", "ORI", "DDG", "DDN", "DD3EVG", "MM2", "MM3", "EMA", "C16"));
|
||||
}
|
||||
|
||||
public GoblinToken() {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ public class GolemToken extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("MM2", "NPH", "SOM"));
|
||||
tokenImageSets.addAll(Arrays.asList("MM2", "NPH", "SOM", "MM3"));
|
||||
}
|
||||
|
||||
public GolemToken() {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public class SaprolingToken extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("10E", "ALA", "DDE", "DDH", "DDJ", "M12", "M13", "M14", "MM2", "MMA", "RTR", "C15"));
|
||||
tokenImageSets.addAll(Arrays.asList("10E", "ALA", "DDE", "DDH", "DDJ", "M12", "M13", "M14", "MM2", "MMA", "RTR", "C15", "MM3", "C16"));
|
||||
}
|
||||
|
||||
public SaprolingToken() {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public class SoldierToken extends Token {
|
|||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("10E", "M15", "C14", "ORI", "ALA", "DDF", "THS", "M12", "M13", "MM2", "MMA", "RTR",
|
||||
"SOM", "DDO", "M10", "ORI", "EMN", "EMA", "CN2", "C16"));
|
||||
"SOM", "DDO", "M10", "ORI", "EMN", "EMA", "CN2", "C16", "MM3"));
|
||||
}
|
||||
|
||||
public SoldierToken() {
|
||||
|
|
@ -65,7 +65,7 @@ public class SoldierToken extends Token {
|
|||
if (getOriginalExpansionSetCode() != null && getOriginalExpansionSetCode().equals("THS")) {
|
||||
this.setTokenType(RandomUtil.nextInt(2) + 1);
|
||||
}
|
||||
if (getOriginalExpansionSetCode() != null && getOriginalExpansionSetCode().equals("CN2")) {
|
||||
if (getOriginalExpansionSetCode() != null && getOriginalExpansionSetCode().equals("CN2") || getOriginalExpansionSetCode().equals("MM3")) {
|
||||
setTokenType(1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import mage.constants.CardType;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
|
|
@ -38,6 +41,12 @@ import mage.abilities.keyword.HasteAbility;
|
|||
*/
|
||||
public class SoldierTokenWithHaste extends Token {
|
||||
|
||||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("GTC", "MM3"));
|
||||
}
|
||||
|
||||
public SoldierTokenWithHaste() {
|
||||
super("Soldier", "1/1 red and white Soldier creature token with haste");
|
||||
cardType.add(CardType.CREATURE);
|
||||
|
|
@ -47,6 +56,23 @@ public class SoldierTokenWithHaste extends Token {
|
|||
power = new MageInt(1);
|
||||
toughness = new MageInt(1);
|
||||
addAbility(HasteAbility.getInstance());
|
||||
setOriginalExpansionSetCode("GTC");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setExpansionSetCodeForImage(String code) {
|
||||
super.setExpansionSetCodeForImage(code);
|
||||
if (getOriginalExpansionSetCode() != null && getOriginalExpansionSetCode().equals("MM3")) {
|
||||
setTokenType(2);
|
||||
}
|
||||
}
|
||||
|
||||
public SoldierTokenWithHaste(final SoldierTokenWithHaste token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoldierTokenWithHaste copy() {
|
||||
return new SoldierTokenWithHaste(this); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public class SpiritWhiteToken extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("AVR", "C14", "CNS", "DDC", "DDK", "FRF", "ISD", "KTK", "M15", "MM2", "SHM", "SOI", "EMA", "C16"));
|
||||
tokenImageSets.addAll(Arrays.asList("AVR", "C14", "CNS", "DDC", "DDK", "FRF", "ISD", "KTK", "M15", "MM2", "SHM", "SOI", "EMA", "C16", "MM3"));
|
||||
}
|
||||
|
||||
public SpiritWhiteToken() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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.permanent.token;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.constants.CardType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
*/
|
||||
public class WarriorVigilantToken extends Token {
|
||||
|
||||
public WarriorVigilantToken() {
|
||||
super("Warrior", "1/1 white Warrior creature token with vigilance");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setWhite(true);
|
||||
subtype.add("Warrior");
|
||||
power = new MageInt(1);
|
||||
toughness = new MageInt(1);
|
||||
addAbility(VigilanceAbility.getInstance());
|
||||
availableImageSetCodes.addAll(Arrays.asList("AKH"));
|
||||
}
|
||||
|
||||
public WarriorVigilantToken(final WarriorVigilantToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WarriorVigilantToken copy() {
|
||||
return new WarriorVigilantToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import mage.constants.CardType;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
|
|
@ -38,6 +41,12 @@ import mage.abilities.keyword.TrampleAbility;
|
|||
*/
|
||||
public class WurmToken2 extends Token {
|
||||
|
||||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("RTR", "MM3"));
|
||||
}
|
||||
|
||||
public WurmToken2() {
|
||||
super("Wurm", "5/5 green Wurm creature token with trample");
|
||||
cardType.add(CardType.CREATURE);
|
||||
|
|
@ -46,6 +55,5 @@ public class WurmToken2 extends Token {
|
|||
power = new MageInt(5);
|
||||
toughness = new MageInt(5);
|
||||
addAbility(TrampleAbility.getInstance());
|
||||
setOriginalExpansionSetCode("RTR");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ public class ZombieToken extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("10E", "M10", "M11", "M12", "M13", "M14", "M15", "MBS", "ALA", "ISD", "C14", "C15", "CNS",
|
||||
"MMA", "BNG", "KTK", "DTK", "ORI", "OGW", "SOI", "EMN", "EMA"));
|
||||
tokenImageSets.addAll(Arrays.asList("10E", "M10", "M11", "M12", "M13", "M14", "M15", "MBS", "ALA", "ISD", "C14", "C15", "C16", "CNS",
|
||||
"MMA", "BNG", "KTK", "DTK", "ORI", "OGW", "SOI", "EMN", "EMA", "MM3"));
|
||||
}
|
||||
|
||||
public ZombieToken() {
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@
|
|||
*/
|
||||
package mage.game.stack;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
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;
|
||||
|
|
@ -331,8 +333,8 @@ public class Spell extends StackObjImpl implements Card {
|
|||
* determine whether card was kicked or not. E.g. Desolation Angel
|
||||
*/
|
||||
private void updateOptionalCosts(int index) {
|
||||
Ability abilityOrig = spellCards.get(index).getAbilities().get(spellAbilities.get(index).getId());
|
||||
if (abilityOrig != null) {
|
||||
spellCards.get(index).getAbilities().get(spellAbilities.get(index).getId()).ifPresent(abilityOrig
|
||||
-> {
|
||||
for (Object object : spellAbilities.get(index).getOptionalCosts()) {
|
||||
Cost cost = (Cost) object;
|
||||
for (Cost costOrig : abilityOrig.getOptionalCosts()) {
|
||||
|
|
@ -346,7 +348,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -746,24 +748,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this.getId(), sourceId, this.getOwnerId(), Zone.STACK, Zone.EXILED, appliedEffects);
|
||||
if (!game.replaceEvent(event)) {
|
||||
game.getStack().remove(this);
|
||||
game.rememberLKI(this.getId(), event.getFromZone(), this);
|
||||
|
||||
if (!this.isCopiedSpell()) {
|
||||
if (exileId == null) {
|
||||
game.getExile().getPermanentExile().add(this.card);
|
||||
} else {
|
||||
game.getExile().createZone(exileId, name).add(this.card);
|
||||
}
|
||||
|
||||
game.setZone(this.card.getId(), event.getToZone());
|
||||
}
|
||||
game.fireEvent(event);
|
||||
return event.getToZone() == Zone.EXILED;
|
||||
}
|
||||
return false;
|
||||
return this.card.moveToExile(exileId, name, sourceId, game, appliedEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -27,10 +27,6 @@
|
|||
*/
|
||||
package mage.game.tournament;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.game.draft.Draft;
|
||||
|
|
@ -39,6 +35,12 @@ import mage.game.events.PlayerQueryEvent;
|
|||
import mage.game.events.TableEvent;
|
||||
import mage.game.result.ResultProtos.TourneyProto;
|
||||
import mage.players.Player;
|
||||
import mage.players.PlayerType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -48,7 +50,7 @@ public interface Tournament {
|
|||
|
||||
UUID getId();
|
||||
|
||||
void addPlayer(Player player, String playerType);
|
||||
void addPlayer(Player player, PlayerType playerType);
|
||||
|
||||
void removePlayer(UUID playerId);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import mage.game.match.Match;
|
|||
import mage.game.match.MatchPlayer;
|
||||
import mage.game.result.ResultProtos.*;
|
||||
import mage.players.Player;
|
||||
import mage.players.PlayerType;
|
||||
import mage.util.RandomUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
|
@ -82,7 +83,7 @@ public abstract class TournamentImpl implements Tournament {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addPlayer(Player player, String playerType) {
|
||||
public void addPlayer(Player player, PlayerType playerType) {
|
||||
players.put(player.getId(), new TournamentPlayer(player, playerType));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,10 +27,12 @@
|
|||
*/
|
||||
package mage.game.tournament;
|
||||
|
||||
import mage.game.match.MatchOptions;
|
||||
import mage.players.PlayerType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import mage.game.match.MatchOptions;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -40,7 +42,7 @@ public class TournamentOptions implements Serializable {
|
|||
|
||||
protected String name;
|
||||
protected String tournamentType;
|
||||
protected List<String> playerTypes = new ArrayList<>();
|
||||
protected List<PlayerType> playerTypes = new ArrayList<>();
|
||||
protected MatchOptions matchOptions;
|
||||
protected LimitedOptions limitedOptions;
|
||||
protected boolean watchingAllowed = true;
|
||||
|
|
@ -65,7 +67,7 @@ public class TournamentOptions implements Serializable {
|
|||
this.tournamentType = tournamentType;
|
||||
}
|
||||
|
||||
public List<String> getPlayerTypes() {
|
||||
public List<PlayerType> getPlayerTypes() {
|
||||
return playerTypes;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,14 +28,16 @@
|
|||
|
||||
package mage.game.tournament;
|
||||
|
||||
import java.util.Set;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.constants.TournamentPlayerState;
|
||||
import mage.game.result.ResultProtos.TourneyPlayerProto;
|
||||
import mage.game.result.ResultProtos.TourneyQuitStatus;
|
||||
import mage.players.Player;
|
||||
import mage.players.PlayerType;
|
||||
import mage.util.TournamentUtil;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -43,7 +45,7 @@ import mage.util.TournamentUtil;
|
|||
public class TournamentPlayer {
|
||||
|
||||
protected int points;
|
||||
protected String playerType;
|
||||
protected PlayerType playerType;
|
||||
protected TournamentPlayerState state;
|
||||
protected String stateInfo;
|
||||
protected String disconnectInfo;
|
||||
|
|
@ -57,7 +59,7 @@ public class TournamentPlayer {
|
|||
protected TourneyQuitStatus quitStatus = TourneyQuitStatus.NO_TOURNEY_QUIT;
|
||||
protected TournamentPlayer replacedTournamentPlayer;
|
||||
|
||||
public TournamentPlayer(Player player, String playerType) {
|
||||
public TournamentPlayer(Player player, PlayerType playerType) {
|
||||
this.player = player;
|
||||
this.playerType = playerType;
|
||||
this.state = TournamentPlayerState.JOINED;
|
||||
|
|
@ -70,7 +72,7 @@ public class TournamentPlayer {
|
|||
return player;
|
||||
}
|
||||
|
||||
public String getPlayerType() {
|
||||
public PlayerType getPlayerType() {
|
||||
return playerType;
|
||||
}
|
||||
|
||||
|
|
@ -232,7 +234,7 @@ public class TournamentPlayer {
|
|||
public TourneyPlayerProto toProto() {
|
||||
return TourneyPlayerProto.newBuilder()
|
||||
.setName(this.player.getName())
|
||||
.setPlayerType(this.playerType)
|
||||
.setPlayerType(this.playerType.toString())
|
||||
.setQuit(this.quitStatus)
|
||||
.build();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import java.util.ArrayList;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.TurnPhase;
|
||||
import mage.counters.CounterType;
|
||||
|
|
@ -268,8 +269,9 @@ public class Turn implements Serializable {
|
|||
*
|
||||
* @param game
|
||||
* @param activePlayerId
|
||||
* @param source
|
||||
*/
|
||||
public void endTurn(Game game, UUID activePlayerId) {
|
||||
public void endTurn(Game game, UUID activePlayerId, Ability source) {
|
||||
// Ending the turn this way (Time Stop) means the following things happen in order:
|
||||
|
||||
setEndTurnRequested(true);
|
||||
|
|
@ -277,9 +279,9 @@ public class Turn implements Serializable {
|
|||
// 1) All spells and abilities on the stack are exiled. This includes Time Stop, though it will continue to resolve.
|
||||
// It also includes spells and abilities that can't be countered.
|
||||
while (!game.getStack().isEmpty()) {
|
||||
StackObject stackObject = game.getStack().removeLast();
|
||||
StackObject stackObject = game.getStack().peekFirst();
|
||||
if (stackObject instanceof Spell) {
|
||||
((Spell) stackObject).moveToExile(null, "", null, game);
|
||||
((Spell) stackObject).moveToExile(null, "", source.getSourceId(), game);
|
||||
}
|
||||
}
|
||||
// 2) All attacking and blocking creatures are removed from combat.
|
||||
|
|
|
|||
|
|
@ -27,26 +27,16 @@
|
|||
*/
|
||||
package mage.players;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
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.cards.Card;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.util.RandomUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
|
@ -182,11 +172,7 @@ public class Library implements Serializable {
|
|||
}
|
||||
|
||||
public List<Card> getCards(Game game) {
|
||||
List<Card> cards = new ArrayList<>();
|
||||
for (UUID cardId : library) {
|
||||
cards.add(game.getCard(cardId));
|
||||
}
|
||||
return cards;
|
||||
return library.stream().map(game::getCard).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Set<Card> getTopCards(Game game, int amount) {
|
||||
|
|
@ -214,13 +200,7 @@ public class Library implements Serializable {
|
|||
}
|
||||
|
||||
public int count(FilterCard filter, Game game) {
|
||||
int result = 0;
|
||||
for (UUID card : library) {
|
||||
if (filter.match(game.getCard(card), game)) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return (int) library.stream().filter(cardId -> filter.match(game.getCard(cardId), game)).count();
|
||||
}
|
||||
|
||||
public boolean isEmptyDraw() {
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ public class ManaPool implements Serializable {
|
|||
return false;
|
||||
}
|
||||
if (autoPayment && autoPaymentRestricted && !wasManaAddedBeyondStock() && manaType != unlockedManaType) {
|
||||
// if automatic restricted payment and there is laready mana in the pool
|
||||
// if automatic restricted payment and there is already mana in the pool
|
||||
// and the needed mana type was not unlocked, nothing will be paid
|
||||
return false;
|
||||
}
|
||||
|
|
@ -146,7 +146,7 @@ public class ManaPool implements Serializable {
|
|||
continue;
|
||||
}
|
||||
if (mana.get(usableManaType) > 0) {
|
||||
GameEvent event = new GameEvent(GameEvent.EventType.MANA_PAYED, ability.getId(), mana.getSourceId(), ability.getControllerId(), 0, mana.getFlag());
|
||||
GameEvent event = new GameEvent(GameEvent.EventType.MANA_PAID, ability.getId(), mana.getSourceId(), ability.getControllerId(), 0, mana.getFlag());
|
||||
event.setData(mana.getOriginalId().toString());
|
||||
game.fireEvent(event);
|
||||
mana.remove(usableManaType);
|
||||
|
|
@ -205,6 +205,10 @@ public class ManaPool implements Serializable {
|
|||
doNotEmptyManaTypes.add(manaType);
|
||||
}
|
||||
|
||||
public void init() {
|
||||
manaItems.clear();
|
||||
}
|
||||
|
||||
public int emptyPool(Game game) {
|
||||
int total = 0;
|
||||
Iterator<ManaPoolItem> it = manaItems.iterator();
|
||||
|
|
@ -424,7 +428,7 @@ public class ManaPool implements Serializable {
|
|||
for (ConditionalMana mana : getConditionalMana()) {
|
||||
if (mana.get(manaType) > 0 && mana.apply(ability, game, mana.getManaProducerId(), costToPay)) {
|
||||
mana.set(manaType, mana.get(manaType) - 1);
|
||||
GameEvent event = new GameEvent(GameEvent.EventType.MANA_PAYED, ability.getId(), mana.getManaProducerId(), ability.getControllerId(), 0, mana.getFlag());
|
||||
GameEvent event = new GameEvent(GameEvent.EventType.MANA_PAID, ability.getId(), mana.getManaProducerId(), ability.getControllerId(), 0, mana.getFlag());
|
||||
event.setData(mana.getManaProducerOriginalId().toString());
|
||||
game.fireEvent(event);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -422,6 +422,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
this.castSourceIdWithAlternateMana = null;
|
||||
this.castSourceIdManaCosts = null;
|
||||
this.castSourceIdCosts = null;
|
||||
this.getManaPool().init(); // needed to remove mana that not empties on step change from previous game if left
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
32
Mage/src/main/java/mage/players/PlayerType.java
Normal file
32
Mage/src/main/java/mage/players/PlayerType.java
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package mage.players;
|
||||
|
||||
/**
|
||||
* Created by IGOUDT on 2-4-2017.
|
||||
*/
|
||||
public enum PlayerType {
|
||||
HUMAN("Human"),
|
||||
COMPUTER_DRAFT_BOT("Computer - draftbot"),
|
||||
COMPUTER_MINIMAX_HYBRID("Computer - minimax hybrid"),
|
||||
COMPUTER_MONTE_CARLO("Computer - monte carlo"),
|
||||
COMPUTER_MAD("Computer - mad");
|
||||
|
||||
String description;
|
||||
|
||||
PlayerType(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public static PlayerType getByDescription(String description) {
|
||||
for (PlayerType type : values()) {
|
||||
if (type.description.equals(description)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException(String.format("PlayerType (%s) is not configured", description));
|
||||
}
|
||||
}
|
||||
|
|
@ -34,6 +34,7 @@ import mage.abilities.dynamicvalue.common.StaticValue;
|
|||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -142,12 +143,7 @@ public abstract class TargetAmount extends TargetImpl {
|
|||
t.addTarget(targetId, n, source, game, true);
|
||||
if (t.remainingAmount > 0) {
|
||||
if (targets.size() > 1) {
|
||||
Set<UUID> newTargets = new HashSet<>();
|
||||
for (UUID newTarget: targets) {
|
||||
if (!newTarget.equals(targetId)) {
|
||||
newTargets.add(newTarget);
|
||||
}
|
||||
}
|
||||
Set<UUID> newTargets = targets.stream().filter(newTarget -> !newTarget.equals(targetId)).collect(Collectors.toSet());
|
||||
addTargets(t, newTargets, options, source, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,7 @@
|
|||
*/
|
||||
package mage.target;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageItem;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.Cards;
|
||||
import mage.constants.Zone;
|
||||
|
|
@ -38,6 +36,11 @@ import mage.game.Game;
|
|||
import mage.game.events.GameEvent;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -200,11 +203,7 @@ public class TargetCard extends TargetObject {
|
|||
}
|
||||
|
||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Cards cards, Game game) {
|
||||
Set<UUID> possibleTargets = new HashSet<>();
|
||||
for (Card card : cards.getCards(filter, game)) {
|
||||
possibleTargets.add(card.getId());
|
||||
}
|
||||
return possibleTargets;
|
||||
return cards.getCards(filter,game).stream().map(MageItem::getId).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -27,15 +27,16 @@
|
|||
*/
|
||||
package mage.target;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.filter.FilterPlayer;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -158,12 +159,7 @@ public class TargetPlayer extends TargetImpl {
|
|||
if (getNumberOfTargets() == 0 && targets.isEmpty()) {
|
||||
return true; // 0 targets selected is valid
|
||||
}
|
||||
for (UUID playerId : targets.keySet()) {
|
||||
if (canTarget(playerId, source, game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return targets.keySet().stream().anyMatch(playerId -> canTarget(playerId, source, game));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -27,9 +27,6 @@
|
|||
*/
|
||||
package mage.target;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterSpell;
|
||||
|
|
@ -37,6 +34,11 @@ import mage.game.Game;
|
|||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackObject;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -112,13 +114,10 @@ public class TargetSpell extends TargetObject {
|
|||
|
||||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
Set<UUID> possibleTargets = new HashSet<>();
|
||||
for (StackObject stackObject : game.getStack()) {
|
||||
if (canBeChosen(stackObject, sourceId, sourceControllerId, game)) {
|
||||
possibleTargets.add(stackObject.getId());
|
||||
}
|
||||
}
|
||||
return possibleTargets;
|
||||
return game.getStack().stream()
|
||||
.filter(stackObject -> canBeChosen(stackObject, sourceId, sourceControllerId, game))
|
||||
.map(StackObject::getId)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -27,14 +27,16 @@
|
|||
*/
|
||||
package mage.target;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -51,13 +53,7 @@ public class Targets extends ArrayList<Target> {
|
|||
}
|
||||
|
||||
public List<Target> getUnchosen() {
|
||||
List<Target> unchosen = new ArrayList<>();
|
||||
for (Target target : this) {
|
||||
if (!target.isChosen()) {
|
||||
unchosen.add(target);
|
||||
}
|
||||
}
|
||||
return unchosen;
|
||||
return stream().filter(target -> !target.isChosen()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public void clearChosen() {
|
||||
|
|
@ -67,12 +63,7 @@ public class Targets extends ArrayList<Target> {
|
|||
}
|
||||
|
||||
public boolean isChosen() {
|
||||
for (Target target : this) {
|
||||
if (!target.isChosen()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return stream().allMatch(Target::isChosen);
|
||||
}
|
||||
|
||||
public boolean choose(Outcome outcome, UUID playerId, UUID sourceId, Game game) {
|
||||
|
|
@ -122,12 +113,8 @@ public class Targets extends ArrayList<Target> {
|
|||
public boolean stillLegal(Ability source, Game game) {
|
||||
// 608.2
|
||||
// The spell or ability is countered if all its targets, for every instance of the word "target," are now illegal
|
||||
int illegalCount = 0;
|
||||
for (Target target : this) {
|
||||
if (!target.isLegal(source, game)) {
|
||||
illegalCount++;
|
||||
}
|
||||
}
|
||||
int illegalCount = (int) stream().filter(target -> !target.isLegal(source, game)).count();
|
||||
|
||||
// it is legal when either there is no target or not all targets are illegal
|
||||
return this.isEmpty() || this.size() != illegalCount;
|
||||
}
|
||||
|
|
@ -142,12 +129,7 @@ public class Targets extends ArrayList<Target> {
|
|||
* @return - true if enough valid targets exist
|
||||
*/
|
||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
for (Target target : this) {
|
||||
if (!target.canChoose(sourceId, sourceControllerId, game)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return stream().allMatch(target -> target.canChoose(sourceId, sourceControllerId, game));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -160,12 +142,7 @@ public class Targets extends ArrayList<Target> {
|
|||
* @return - true if enough valid objects exist
|
||||
*/
|
||||
public boolean canChoose(UUID sourceControllerId, Game game) {
|
||||
for (Target target : this) {
|
||||
if (!target.canChoose(sourceControllerId, game)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return stream().allMatch(target -> target.canChoose(sourceControllerId, game));
|
||||
}
|
||||
|
||||
public UUID getFirstTarget() {
|
||||
|
|
@ -174,7 +151,6 @@ public class Targets extends ArrayList<Target> {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Targets copy() {
|
||||
return new Targets(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,27 +28,27 @@
|
|||
|
||||
package mage.target.common;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.constants.Zone;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterAbility;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.target.TargetObject;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
|
||||
public class TargetActivatedOrTriggeredAbility extends TargetObject {
|
||||
|
||||
public TargetActivatedOrTriggeredAbility() {
|
||||
public TargetActivatedOrTriggeredAbility() {
|
||||
this.minNumberOfTargets = 1;
|
||||
this.maxNumberOfTargets = 1;
|
||||
this.zone = Zone.STACK;
|
||||
|
|
@ -78,12 +78,9 @@ public class TargetActivatedOrTriggeredAbility extends TargetObject {
|
|||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceControllerId, Game game) {
|
||||
for (StackObject stackObject : game.getStack()) {
|
||||
if (isActivatedOrTriggeredAbility(stackObject)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return game.getStack()
|
||||
.stream()
|
||||
.anyMatch(TargetActivatedOrTriggeredAbility::isActivatedOrTriggeredAbility);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -93,13 +90,10 @@ public class TargetActivatedOrTriggeredAbility extends TargetObject {
|
|||
|
||||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
|
||||
Set<UUID> possibleTargets = new HashSet<>();
|
||||
for (StackObject stackObject : game.getStack()) {
|
||||
if (isActivatedOrTriggeredAbility(stackObject)) {
|
||||
possibleTargets.add(stackObject.getStackAbility().getId());
|
||||
}
|
||||
}
|
||||
return possibleTargets;
|
||||
return game.getStack().stream()
|
||||
.filter(TargetActivatedOrTriggeredAbility::isActivatedOrTriggeredAbility)
|
||||
.map(stackObject -> stackObject.getStackAbility().getId())
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -117,9 +111,9 @@ public class TargetActivatedOrTriggeredAbility extends TargetObject {
|
|||
return false;
|
||||
}
|
||||
if (stackObject instanceof Ability) {
|
||||
Ability ability = (Ability)stackObject;
|
||||
Ability ability = (Ability) stackObject;
|
||||
return ability.getAbilityType() == AbilityType.TRIGGERED
|
||||
|| ability.getAbilityType() == AbilityType.ACTIVATED;
|
||||
|| ability.getAbilityType() == AbilityType.ACTIVATED;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@
|
|||
*/
|
||||
package mage.target.common;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.cards.Card;
|
||||
|
|
@ -39,8 +37,10 @@ import mage.game.Game;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetCard;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class TargetCardInGraveyardOrBattlefield extends TargetCard {
|
||||
|
|
@ -82,8 +82,7 @@ public class TargetCardInGraveyardOrBattlefield extends TargetCard {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID id, Ability source, Game game
|
||||
) {
|
||||
public boolean canTarget(UUID id, Ability source, Game game) {
|
||||
Permanent permanent = game.getPermanent(id);
|
||||
if (permanent != null) {
|
||||
return filter.match(permanent, game);
|
||||
|
|
@ -93,8 +92,7 @@ public class TargetCardInGraveyardOrBattlefield extends TargetCard {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game
|
||||
) {
|
||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
|
||||
//return super.possibleTargets(sourceControllerId, game); //To change body of generated methods, choose Tools | Templates.
|
||||
Set<UUID> possibleTargets = super.possibleTargets(sourceControllerId, game);
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterPermanent(), sourceControllerId, game)) {
|
||||
|
|
@ -106,8 +104,7 @@ public class TargetCardInGraveyardOrBattlefield extends TargetCard {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game
|
||||
) {
|
||||
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
Set<UUID> possibleTargets = super.possibleTargets(sourceId, sourceControllerId, game);
|
||||
MageObject targetSource = game.getObject(sourceId);
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterPermanent(), sourceControllerId, game)) {
|
||||
|
|
|
|||
|
|
@ -27,12 +27,12 @@
|
|||
*/
|
||||
package mage.target.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -62,7 +62,7 @@ public class TargetCreaturePermanentWithDifferentTypes extends TargetCreaturePer
|
|||
UUID targetId = (UUID) object;
|
||||
Permanent selectedCreature = game.getPermanent(targetId);
|
||||
if (!creature.getId().equals(selectedCreature.getId())) {
|
||||
if (CardUtil.shareSubtypes(creature, selectedCreature, game)) {
|
||||
if (creature.shareSubtypes(selectedCreature, game)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,10 +35,8 @@ import mage.abilities.ActivatedAbility;
|
|||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.costs.VariableCost;
|
||||
import mage.abilities.costs.mana.*;
|
||||
import mage.abilities.keyword.ChangelingAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.FilterMana;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
|
@ -84,57 +82,9 @@ public final class CardUtil {
|
|||
"Trap", "Arcane"};
|
||||
public static final Set<String> NON_CREATURE_SUBTYPES = new HashSet<>(Arrays.asList(NON_CHANGELING_SUBTYPES_VALUES));
|
||||
|
||||
/**
|
||||
* Checks whether two cards share card types.
|
||||
*
|
||||
* @param card1
|
||||
* @param card2
|
||||
* @return
|
||||
*/
|
||||
public static boolean shareTypes(Card card1, Card card2) {
|
||||
|
||||
if (card1 == null || card2 == null) {
|
||||
throw new IllegalArgumentException("Params can't be null");
|
||||
}
|
||||
|
||||
for (CardType type : card1.getCardType()) {
|
||||
if (card2.getCardType().contains(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether two cards share card subtypes.
|
||||
*
|
||||
* @param card1
|
||||
* @param card2
|
||||
* @return
|
||||
*/
|
||||
public static boolean shareSubtypes(Card card1, Card card2, Game game) {
|
||||
|
||||
if (card1 == null || card2 == null) {
|
||||
throw new IllegalArgumentException("Params can't be null");
|
||||
}
|
||||
|
||||
if (card1.isCreature() && card2.isCreature()) {
|
||||
if (card1.getAbilities().contains(ChangelingAbility.getInstance())
|
||||
|| card1.getSubtype(game).contains(ChangelingAbility.ALL_CREATURE_TYPE)
|
||||
|| card2.getAbilities().contains(ChangelingAbility.getInstance())
|
||||
|| card2.getSubtype(game).contains(ChangelingAbility.ALL_CREATURE_TYPE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (String subtype : card1.getSubtype(game)) {
|
||||
if (card2.getSubtype(game).contains(subtype)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase spell or ability cost to be paid.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue