Merge branch 'master' of github.com:rsypen/mage into fix_tests_not_passing

This commit is contained in:
Radoslaw Sypen 2018-01-12 10:42:50 +01:00
commit 29a889b236
58 changed files with 2327 additions and 150 deletions

View file

@ -27,11 +27,12 @@
*/
package mage.abilities.common;
import mage.constants.Zone;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
@ -51,7 +52,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
/**
* optional = false<br>
* opponentController = false
*
*
* @param effect
*/
public CreatureEntersBattlefieldTriggeredAbility(Effect effect) {
@ -60,7 +61,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
/**
* opponentController = false
*
*
* @param effect
* @param optional
*/
@ -69,7 +70,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
}
/**
*
*
* @param effect
* @param optional
* @param opponentController
@ -78,7 +79,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
this(Zone.BATTLEFIELD, effect, optional, opponentController);
}
/**
* @param zone
* @param effect
@ -104,7 +105,6 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
}
}
public CreatureEntersBattlefieldTriggeredAbility(CreatureEntersBattlefieldTriggeredAbility ability) {
super(ability);
this.opponentController = ability.opponentController;
@ -118,7 +118,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanent(event.getTargetId());
Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget();
if (filter.match(permanent, sourceId, controllerId, game)
&& (permanent.getControllerId().equals(this.controllerId) ^ opponentController)) {
if (!this.getTargets().isEmpty()) {
@ -137,7 +137,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
@Override
public String getRule() {
return "Whenever a " + filter.getMessage() +" enters the battlefield under "
return "Whenever a " + filter.getMessage() + " enters the battlefield under "
+ (opponentController ? "an opponent's control, " : "your control, ")
+ super.getRule();
}

View file

@ -36,7 +36,9 @@ public class DoIfCostPaid extends OneShotEffect {
public DoIfCostPaid(Effect effect, Cost cost, String chooseUseText, boolean optional) {
super(Outcome.Benefit);
this.executingEffects.add(effect);
if (effect != null) {
this.executingEffects.add(effect);
}
this.cost = cost;
this.chooseUseText = chooseUseText;
this.optional = optional;
@ -74,10 +76,9 @@ public class DoIfCostPaid extends OneShotEffect {
message = CardUtil.replaceSourceName(message, mageObject.getLogName());
boolean result = true;
if (cost.canPay(source, source.getSourceId(), player.getId(), game)
&& (!optional || player.chooseUse(executingEffects.get(0).getOutcome(), message, source, game))) {
&& executingEffects.size() > 0 && (!optional || player.chooseUse(executingEffects.get(0).getOutcome(), message, source, game))) {
cost.clearPaid();
if (cost.pay(source, game, source.getSourceId(), player.getId(), false)) {
game.applyEffects(); // To end effects e.g. of sacrificed permanents
for (Effect effect : executingEffects) {
effect.setTargetPointer(this.targetPointer);
if (effect instanceof OneShotEffect) {
@ -87,7 +88,8 @@ public class DoIfCostPaid extends OneShotEffect {
}
}
player.resetStoredBookmark(game); // otherwise you can e.g. undo card drawn with Mentor of the Meek
} else if (!otherwiseEffects.isEmpty()) {
}
else if (!otherwiseEffects.isEmpty()) {
for (Effect effect : otherwiseEffects) {
effect.setTargetPointer(this.targetPointer);
if (effect instanceof OneShotEffect) {
@ -97,7 +99,8 @@ public class DoIfCostPaid extends OneShotEffect {
}
}
}
} else if (!otherwiseEffects.isEmpty()) {
}
else if (!otherwiseEffects.isEmpty()) {
for (Effect effect : otherwiseEffects) {
effect.setTargetPointer(this.targetPointer);
if (effect instanceof OneShotEffect) {

View file

@ -58,7 +58,7 @@ public enum CardRepository {
// raise this if db structure was changed
private static final long CARD_DB_VERSION = 51;
// raise this if new cards were added to the server
private static final long CARD_CONTENT_VERSION = 99;
private static final long CARD_CONTENT_VERSION = 100;
private Dao<CardInfo, Object> cardDao;
private Set<String> classNames;

View file

@ -85,12 +85,14 @@ public enum SubType {
CENTAUR("Centaur", SubTypeSet.CreatureType),
CEREAN("Cerean", SubTypeSet.CreatureType, true), // Star Wars
CEPHALID("Cephalid", SubTypeSet.CreatureType),
CHICKEN("Chicken", SubTypeSet.CreatureType, true), // Unglued
CHIMERA("Chimera", SubTypeSet.CreatureType),
CHISS("Chiss", SubTypeSet.CreatureType, true),
CITIZEN("Citizen", SubTypeSet.CreatureType),
CLERIC("Cleric", SubTypeSet.CreatureType),
COCKATRICE("Cockatrice", SubTypeSet.CreatureType),
CONSTRUCT("Construct", SubTypeSet.CreatureType),
COW("Cow", SubTypeSet.CreatureType, true), // Unglued
COWARD("Coward", SubTypeSet.CreatureType),
CRAB("Crab", SubTypeSet.CreatureType),
CROCODILE("Crocodile", SubTypeSet.CreatureType),
@ -114,6 +116,7 @@ public enum SubType {
DWARF("Dwarf", SubTypeSet.CreatureType),
// E
EFREET("Efreet", SubTypeSet.CreatureType),
EGG("Egg", SubTypeSet.CreatureType),
ELDER("Elder", SubTypeSet.CreatureType),
ELDRAZI("Eldrazi", SubTypeSet.CreatureType),
ELEMENTAL("Elemental", SubTypeSet.CreatureType),
@ -131,6 +134,7 @@ public enum SubType {
FROG("Frog", SubTypeSet.CreatureType),
FUNGUS("Fungus", SubTypeSet.CreatureType),
// G
GAMER("Gamer", SubTypeSet.CreatureType, true), // Un-sets
GAMORREAN("Gamorrean", SubTypeSet.CreatureType, true), // Star Wars
GAND("Gand", SubTypeSet.CreatureType, true), // Star Wars
GARGOYLE("Gargoyle", SubTypeSet.CreatureType),
@ -194,6 +198,7 @@ public enum SubType {
LHURGOYF("Lhurgoyf", SubTypeSet.CreatureType),
LICID("Licid", SubTypeSet.CreatureType),
LIZARD("Lizard", SubTypeSet.CreatureType),
LOBSTER("Lobster", SubTypeSet.CreatureType, true), // Unglued
// M
MANTELLIAN("Mantellian", SubTypeSet.CreatureType, true), // Star Wars
MANTICORE("Manticore", SubTypeSet.CreatureType),

View file

@ -0,0 +1,51 @@
/*
* 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.filter.predicate.permanent;
import java.util.List;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author L_J
*/
public class PermanentInListPredicate implements Predicate<Permanent> {
private final List<Permanent> permanents;
public PermanentInListPredicate(List<Permanent> permanents) {
this.permanents = permanents;
}
@Override
public boolean apply(Permanent input, Game game) {
return permanents.contains(input);
}
}

View file

@ -38,7 +38,6 @@ import mage.abilities.keyword.special.JohanVigilanceAbility;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreatureForCombatBlock;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
@ -655,7 +654,7 @@ public class Combat implements Serializable, Copyable<Combat> {
Map<UUID, Set<UUID>> mustBeBlockedByAtLeastOne = new HashMap<>();
// check mustBlock requirements of creatures from opponents of attacking player
for (Permanent creature : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), player.getId(), game)) {
for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED, player.getId(), game)) {
// creature is controlled by an opponent of the attacker
if (opponents.contains(creature.getControllerId())) {
@ -1180,6 +1179,7 @@ public class Combat implements Serializable, Copyable<Combat> {
//TODO: handle banding
blockingGroups.get(blockerId).attackers.add(attackerId);
}
// "blocker.setBlocking(blocker.getBlocking() + 1)" is handled by the attacking combat group
}
}
@ -1392,6 +1392,7 @@ public class Combat implements Serializable, Copyable<Combat> {
}
public void removeBlockerGromGroup(UUID blockerId, CombatGroup groupToUnblock, Game game) {
// Manual player action for undoing one declared blocker (used for multi-blocker creatures)
Permanent creature = game.getPermanent(blockerId);
if (creature != null) {
for (CombatGroup group : groups) {
@ -1404,7 +1405,26 @@ public class Combat implements Serializable, Copyable<Combat> {
if (creature.getBlocking() > 0) {
creature.setBlocking(creature.getBlocking() - 1);
} else {
throw new UnsupportedOperationException("Tryinging creature to unblock, but blocking number value of creature < 1");
throw new UnsupportedOperationException("Trying to unblock creature, but blocking number value of creature < 1");
}
boolean canRemove = false;
for (CombatGroup blockGroup : getBlockingGroups()) {
if (blockGroup.blockers.contains(blockerId)) {
for (UUID attackerId : group.getAttackers()) {
blockGroup.attackers.remove(attackerId);
blockGroup.attackerOrder.remove(attackerId);
}
if (creature.getBlocking() == 0) {
blockGroup.blockers.remove(blockerId);
blockGroup.attackerOrder.clear();
}
}
if (blockGroup.blockers.isEmpty()) {
canRemove = true;
}
}
if (canRemove) {
blockingGroups.remove(blockerId);
}
}
}
@ -1412,6 +1432,7 @@ public class Combat implements Serializable, Copyable<Combat> {
}
public void removeBlocker(UUID blockerId, Game game) {
// Manual player action for undoing all declared blockers (used for single-blocker creatures and multi-blockers exceeding blocking limit)
for (CombatGroup group : groups) {
if (group.blockers.contains(blockerId)) {
group.blockers.remove(blockerId);

View file

@ -60,12 +60,15 @@ import mage.target.TargetCard;
import mage.util.CardUtil;
import mage.util.GameLog;
import mage.util.ThreadLocalStringBuilder;
import org.apache.log4j.Logger;
/**
* @author BetaSteward_at_googlemail.com
*/
public abstract class PermanentImpl extends CardImpl implements Permanent {
private static final Logger logger = Logger.getLogger(PermanentImpl.class);
public class MarkedDamageInfo {
public MarkedDamageInfo(Counter counter, MageObject sourceObject) {
@ -699,6 +702,10 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
}
}
}
if (getSpellAbility() == null) {
logger.info("FATAL : no spell ability for attach to permanent: " + getName());
return;
}
if (!getSpellAbility().getTargets().isEmpty() && (getSpellAbility().getTargets().get(0) instanceof TargetCard)) {
Card attachedToCard = game.getCard(this.getAttachedTo());
if (attachedToCard != null) {

View file

@ -0,0 +1,50 @@
/*
* 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 mage.MageInt;
import mage.constants.CardType;
import mage.constants.SubType;
/**
*
* @author ciaccona007
*/
public class GiantChickenToken extends Token {
public GiantChickenToken() {
super("Giant Chicken", "4/4 red Giant Chicken creature token");
cardType.add(CardType.CREATURE);
color.setRed(true);
subtype.add(SubType.GIANT);
subtype.add(SubType.CHICKEN);
power = new MageInt(4);
toughness = new MageInt(4);
}
}