Replaced some replacement effects with restriction effects. Added new method to restriction effect. Improved canAttack methods (not finished yet).

This commit is contained in:
LevelX2 2014-08-01 15:59:59 +02:00
parent d3dadc41aa
commit cbb6117b8e
17 changed files with 101 additions and 110 deletions

View file

@ -28,6 +28,7 @@
package mage.abilities.effects;
import java.util.UUID;
import mage.abilities.Ability;
import mage.constants.Duration;
import mage.constants.EffectType;
@ -64,6 +65,10 @@ public abstract class RestrictionEffect extends ContinuousEffectImpl {
public boolean canAttack(Game game) {
return true;
}
public boolean canAttack(UUID defenderId, Ability source, Game game) {
return true;
}
public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) {
return true;

View file

@ -29,25 +29,22 @@
package mage.abilities.effects.common.combat;
import mage.abilities.Ability;
import mage.abilities.MageSingleton;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.constants.AttachmentType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
/**
*
* @author LevelX2
*/
public class CanBlockOnlyFlyingAttachedEffect extends ReplacementEffectImpl implements MageSingleton {
public class CanBlockOnlyFlyingAttachedEffect extends RestrictionEffect {
public CanBlockOnlyFlyingAttachedEffect(AttachmentType attachmentType) {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
super(Duration.WhileOnBattlefield);
if (attachmentType.equals(AttachmentType.AURA)) {
this.staticText = "Enchanted creature can block only creatures with flying";
} else {
@ -59,34 +56,19 @@ public class CanBlockOnlyFlyingAttachedEffect extends ReplacementEffectImpl impl
super(effect);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return permanent.getAttachments().contains(source.getSourceId());
}
@Override
public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) {
return attacker.getAbilities().contains(FlyingAbility.getInstance());
}
@Override
public CanBlockOnlyFlyingAttachedEffect copy() {
return new CanBlockOnlyFlyingAttachedEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
return true;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == EventType.DECLARE_BLOCKER) {
Permanent attachment = game.getPermanent(source.getSourceId());
if (attachment != null && attachment.getAttachedTo() != null
&& event.getSourceId().equals(attachment.getAttachedTo())) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null && !permanent.getAbilities().containsKey(FlyingAbility.getInstance().getId())) {
return true;
}
}
}
return false;
}
}

View file

@ -28,82 +28,53 @@
package mage.abilities.effects.common.combat;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.MageSingleton;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.RestrictionEffect;
import mage.constants.AttachmentType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author LevelX2
*/
public class CantAttackControllerAttachedEffect extends ReplacementEffectImpl implements MageSingleton {
/**
* The creature this permanent is attached to can't attack the controller
* of the attachment nor it's plainswalkers
*
* @param attachmentType
*/
public class CantAttackControllerAttachedEffect extends RestrictionEffect {
public CantAttackControllerAttachedEffect(AttachmentType attachmentType) {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
super(Duration.WhileOnBattlefield);
if (attachmentType.equals(AttachmentType.AURA)) {
this.staticText = "Enchanted creature can't attack you or a planeswalker you control";
} else {
this.staticText = "Equiped creature can't attack you or a planeswalker you control";
}
}
}
public CantAttackControllerAttachedEffect(final CantAttackControllerAttachedEffect effect) {
super(effect);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return permanent.getAttachments().contains(source.getSourceId());
}
@Override
public boolean canAttack(UUID defenderId, Ability source, Game game) {
if (defenderId.equals(source.getControllerId())) {
return false;
}
Permanent plainswalker = game.getPermanent(defenderId);
return plainswalker == null || !plainswalker.getControllerId().equals(source.getSourceId());
}
@Override
public CantAttackControllerAttachedEffect copy() {
return new CantAttackControllerAttachedEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
Player attackingPlayer = game.getPlayer(event.getPlayerId());
if (attackingPlayer != null && sourcePermanent != null) {
game.informPlayer(attackingPlayer,
new StringBuilder("You can't attack this player or his or her planeswalker, because the attacking creature is enchanted by ")
.append(sourcePermanent.getName()).append(".").toString());
}
return true;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == EventType.DECLARE_ATTACKER) {
Permanent attachment = game.getPermanent(source.getSourceId());
if (attachment != null && attachment.getAttachedTo() != null
&& event.getSourceId().equals(attachment.getAttachedTo())) {
if (event.getTargetId().equals(source.getControllerId())) {
return true;
}
Permanent plainswalker = game.getPermanent(event.getTargetId());
if (plainswalker != null && plainswalker.getControllerId().equals(source.getSourceId())) {
return true;
}
}
}
return false;
}
}

View file

@ -50,10 +50,7 @@ public class CantAttackTargetEffect extends RestrictionEffect {
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
if (permanent.getId().equals(targetPointer.getFirst(game, source))) {
return true;
}
return false;
return permanent.getId().equals(targetPointer.getFirst(game, source));
}
@Override

View file

@ -150,6 +150,14 @@ public interface Permanent extends Card, Controllable {
void setMaxBlockedBy(int maxBlockedBy);
boolean canAttack(Game game);
/**
*
* @param defenderId id of planeswalker or player to attack
* @param game
* @return
*/
boolean canAttack(UUID defenderId, Game game);
boolean canBlock(UUID attackerId, Game game);
boolean canBlockAny(Game game);

View file

@ -857,8 +857,15 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
return game.replaceEvent(GameEvent.getEvent(eventType, this.objectId, ownerId));
}
@Override
public boolean canAttack(Game game) {
return canAttack(null, game);
}
@Override
public boolean canAttack(UUID defenderId, Game game) {
if (tapped) {
return false;
}
@ -866,15 +873,22 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
return false;
}
//20101001 - 508.1c
for (RestrictionEffect effect: game.getContinuousEffects().getApplicableRestrictionEffects(this, game).keySet()) {
if (!effect.canAttack(game)) {
for (Map.Entry<RestrictionEffect, HashSet<Ability>> effectEntry: game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
if (!effectEntry.getKey().canAttack(game)) {
return false;
}
if (defenderId != null) {
for (Ability ability :effectEntry.getValue()) {
if (!effectEntry.getKey().canAttack(defenderId, ability, game)) {
return false;
}
}
}
}
return !abilities.containsKey(DefenderAbility.getInstance().getId())
|| game.getContinuousEffects().asThough(this.objectId, AsThoughEffectType.ATTACK, this.getControllerId(), game);
}
@Override
public boolean canBlock(UUID attackerId, Game game) {
if (tapped && !game.getState().getContinuousEffects().asThough(this.getId(), AsThoughEffectType.BLOCK_TAPPED, this.getControllerId(), game)) {

View file

@ -321,6 +321,7 @@ public interface Player extends MageItem, Copyable<Player> {
void declareAttacker(UUID attackerId, UUID defenderId, Game game, boolean allowUndo);
void declareBlocker(UUID defenderId, UUID blockerId, UUID attackerId, Game game);
List<Permanent> getAvailableAttackers(Game game);
List<Permanent> getAvailableAttackers(UUID defenderId, Game game);
List<Permanent> getAvailableBlockers(Game game);
void beginTurn(Game game);

View file

@ -1673,7 +1673,7 @@ public abstract class PlayerImpl implements Player, Serializable {
setStoredBookmark(game.bookmarkState()); // makes it possible to UNDO a declared attacker with costs from e.g. Propaganda
}
Permanent attacker = game.getPermanent(attackerId);
if (attacker != null && attacker.canAttack(game) && attacker.getControllerId().equals(playerId)) {
if (attacker != null && attacker.canAttack(defenderId, game) && attacker.getControllerId().equals(playerId)) {
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_ATTACKER, defenderId, attackerId, playerId))) {
game.getCombat().declareAttacker(attackerId, defenderId, game);
}
@ -1767,13 +1767,19 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override
public List<Permanent> getAvailableAttackers(Game game) {
// TODO: get available opponents and their planeswalkers, check for each if permanent can attack one
return getAvailableAttackers(null, game);
}
@Override
public List<Permanent> getAvailableAttackers(UUID defenderId, Game game) {
FilterCreatureForCombat filter = new FilterCreatureForCombat();
List<Permanent> attackers = game.getBattlefield().getAllActivePermanents(filter, playerId, game);
for (Iterator<Permanent> i = attackers.iterator(); i.hasNext();) {
Permanent entry = i.next();
if (!entry.canAttack(game)) {
if (!entry.canAttack(defenderId, game)) {
i.remove();
}
}
}
return attackers;
}