예제 #1
0
  public List<ContinuousEffect> getLayeredEffects(Game game) {
    List<ContinuousEffect> layerEffects = new ArrayList<>();
    for (ContinuousEffect effect : layeredEffects) {
      switch (effect.getDuration()) {
        case WhileOnBattlefield:
        case WhileOnStack:
        case WhileInGraveyard:
          HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
          for (Ability ability : abilities) {
            // If e.g. triggerd abilities (non static) created the effect, the ability must not be
            // in usable zone (e.g. Unearth giving Haste effect)
            if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) {
              layerEffects.add(effect);
              break;
            }
          }
          break;
        default:
          layerEffects.add(effect);
      }
    }

    updateTimestamps(layerEffects);

    Collections.sort(layerEffects, sorter);
    return layerEffects;
  }
예제 #2
0
 public void addEffect(ContinuousEffect effect, Ability source) {
   if (effect == null) {
     logger.error("Effect is null: " + source.toString());
     return;
   } else if (source == null) {
     logger.warn("Adding effect without ability : " + effect.toString());
   }
   switch (effect.getEffectType()) {
     case REPLACEMENT:
     case REDIRECTION:
       ReplacementEffect newReplacementEffect = (ReplacementEffect) effect;
       replacementEffects.addEffect(newReplacementEffect, source);
       break;
     case PREVENTION:
       PreventionEffect newPreventionEffect = (PreventionEffect) effect;
       preventionEffects.addEffect(newPreventionEffect, source);
       break;
     case RESTRICTION:
       RestrictionEffect newRestrictionEffect = (RestrictionEffect) effect;
       restrictionEffects.addEffect(newRestrictionEffect, source);
       break;
     case RESTRICTION_UNTAP_NOT_MORE_THAN:
       RestrictionUntapNotMoreThanEffect newRestrictionUntapNotMoreThanEffect =
           (RestrictionUntapNotMoreThanEffect) effect;
       restrictionUntapNotMoreThanEffects.addEffect(newRestrictionUntapNotMoreThanEffect, source);
       break;
     case REQUIREMENT:
       RequirementEffect newRequirementEffect = (RequirementEffect) effect;
       requirementEffects.addEffect(newRequirementEffect, source);
       break;
     case ASTHOUGH:
       AsThoughEffect newAsThoughEffect = (AsThoughEffect) effect;
       if (!asThoughEffectsMap.containsKey(newAsThoughEffect.getAsThoughEffectType())) {
         ContinuousEffectsList<AsThoughEffect> list = new ContinuousEffectsList<>();
         allEffectsLists.add(list);
         asThoughEffectsMap.put(newAsThoughEffect.getAsThoughEffectType(), list);
       }
       asThoughEffectsMap
           .get(newAsThoughEffect.getAsThoughEffectType())
           .addEffect(newAsThoughEffect, source);
       break;
     case COSTMODIFICATION:
       CostModificationEffect newCostModificationEffect = (CostModificationEffect) effect;
       costModificationEffects.addEffect(newCostModificationEffect, source);
       break;
     case SPLICE:
       SpliceCardEffect newSpliceCardEffect = (SpliceCardEffect) effect;
       spliceCardEffects.addEffect(newSpliceCardEffect, source);
       break;
     case CONTINUOUS_RULE_MODIFICATION:
       ContinuousRuleModifyingEffect newContinuousRuleModifiyingEffect =
           (ContinuousRuleModifyingEffect) effect;
       continuousRuleModifyingEffects.addEffect(newContinuousRuleModifiyingEffect, source);
       break;
     default:
       layeredEffects.addEffect(effect, source);
       break;
   }
 }
예제 #3
0
 private List<ContinuousEffect> filterLayeredEffects(List<ContinuousEffect> effects, Layer layer) {
   List<ContinuousEffect> layerEffects = new ArrayList<>();
   for (ContinuousEffect effect : effects) {
     if (effect.hasLayer(layer)) {
       layerEffects.add(effect);
     }
   }
   return layerEffects;
 }
예제 #4
0
 private boolean checkAbilityStillExists(
     Ability ability, ContinuousEffect effect, GameEvent event, Game game) {
   switch (effect
       .getDuration()) { // effects with fixed duration don't need an object with the source
                         // ability (e.g. a silence cast with isochronic Scepter has no more a card
                         // object
     case EndOfCombat:
     case EndOfGame:
     case EndOfStep:
     case EndOfTurn:
     case OneUse:
     case Custom: // custom duration means the effect ends itself if needed
       return true;
   }
   if (ability.getSourceId() == null) { // commander replacement effect
     return true;
   }
   MageObject object;
   if (event.getType().equals(EventType.ZONE_CHANGE)
       && ((ZoneChangeEvent) event).getFromZone().equals(Zone.BATTLEFIELD)
       && event.getTargetId().equals(ability.getSourceId())) {
     object = ((ZoneChangeEvent) event).getTarget();
   } else {
     object = game.getObject(ability.getSourceId());
   }
   if (object == null) {
     return false;
   }
   boolean exists = true;
   if (!object.getAbilities().contains(ability)) {
     exists = false;
     if (object instanceof PermanentCard) {
       PermanentCard permanent = (PermanentCard) object;
       if (permanent.canTransform() && event.getType() == GameEvent.EventType.TRANSFORMED) {
         exists = permanent.getCard().getAbilities().contains(ability);
       }
     }
   } else {
     if (object instanceof PermanentCard) {
       PermanentCard permanent = (PermanentCard) object;
       if (permanent.isFaceDown(game) && !ability.getWorksFaceDown()) {
         return false;
       }
     } else if (object instanceof Spell) {
       Spell spell = (Spell) object;
       if (spell.isFaceDown(game) && !ability.getWorksFaceDown()) {
         return false;
       }
     }
   }
   return exists;
 }
예제 #5
0
  /**
   * Adds a continuous ability with a reference to a sourceId. It's used for effects that cease to
   * exist again So this effects were removed again before each applyEffecs
   *
   * @param effect
   * @param sourceId
   * @param source
   */
  public void addEffect(ContinuousEffect effect, UUID sourceId, Ability source) {
    if (!(source
        instanceof
        MageSingleton)) { // because MageSingletons may never be removed by removing the temporary
                          // effecs they are not added to the temporaryEffects to prevent this
      effect.setTemporary(true);
      Set abilities = temporaryEffects.get(effect);
      if (abilities == null) {
        abilities = new HashSet<>();
        temporaryEffects.put(effect, abilities);
      } else {
        if (abilities.contains(source)) {
          // this ability (for the continuous effect) is already added
          return;
        }
      }
      abilities.add(source);

      // add the effect itself
    }
    addEffect(effect, source);
  }
예제 #6
0
  // 20091005 - 613
  public void apply(Game game) {
    removeInactiveEffects(game);
    List<ContinuousEffect> layerEffects = getLayeredEffects(game);
    List<ContinuousEffect> layer = filterLayeredEffects(layerEffects, Layer.CopyEffects_1);
    for (ContinuousEffect effect : layer) {
      HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
      for (Ability ability : abilities) {
        effect.apply(Layer.CopyEffects_1, SubLayer.NA, ability, game);
      }
    }
    // Reload layerEffect if copy effects were applied
    if (layer.size() > 0) {
      layerEffects = getLayeredEffects(game);
    }

    layer = filterLayeredEffects(layerEffects, Layer.ControlChangingEffects_2);
    // apply control changing effects multiple times if it's needed
    // for cases when control over permanents with change control abilities is changed
    // e.g. Mind Control is controlled by Steal Enchantment
    while (true) {
      for (ContinuousEffect effect : layer) {
        HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
        for (Ability ability : abilities) {
          effect.apply(Layer.ControlChangingEffects_2, SubLayer.NA, ability, game);
        }
      }
      // if control over all permanent has not changed, we can no longer reapply control changing
      // effects
      if (!game.getBattlefield().fireControlChangeEvents(game)) {
        break;
      }
      // reset control before reapplying control changing effects
      game.getBattlefield().resetPermanentsControl();
    }
    layer = filterLayeredEffects(layerEffects, Layer.TextChangingEffects_3);
    for (ContinuousEffect effect : layer) {
      HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
      for (Ability ability : abilities) {
        effect.apply(Layer.TextChangingEffects_3, SubLayer.NA, ability, game);
      }
    }
    layer = filterLayeredEffects(layerEffects, Layer.TypeChangingEffects_4);
    for (ContinuousEffect effect : layer) {
      HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
      for (Ability ability : abilities) {
        effect.apply(Layer.TypeChangingEffects_4, SubLayer.NA, ability, game);
      }
    }
    layer = filterLayeredEffects(layerEffects, Layer.ColorChangingEffects_5);
    for (ContinuousEffect effect : layer) {
      HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
      for (Ability ability : abilities) {
        effect.apply(Layer.ColorChangingEffects_5, SubLayer.NA, ability, game);
      }
    }

    Map<ContinuousEffect, List<Ability>> appliedEffects = new HashMap<>();
    boolean done = false;
    while (!done) { // loop needed if a added effect adds again an effect (e.g. Level 5- of Joraga
                    // Treespeaker)
      done = true;
      layer = filterLayeredEffects(layerEffects, Layer.AbilityAddingRemovingEffects_6);
      for (ContinuousEffect effect : layer) {
        if (layerEffects.contains(effect)) {
          List<Ability> appliedAbilities = appliedEffects.get(effect);
          HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
          for (Ability ability : abilities) {
            if (appliedAbilities == null || !appliedAbilities.contains(ability)) {
              if (appliedAbilities == null) {
                appliedAbilities = new ArrayList<>();
                appliedEffects.put(effect, appliedAbilities);
              }
              appliedAbilities.add(ability);
              effect.apply(Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, ability, game);
              done = false;
              // list must be updated after each applied effect (eg. if "Turn to Frog" removes
              // abilities)
              layerEffects = getLayeredEffects(game);
            }
          }
        }
      }
    }

    layer = filterLayeredEffects(layerEffects, Layer.PTChangingEffects_7);
    for (ContinuousEffect effect : layer) {
      HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
      for (Ability ability : abilities) {
        effect.apply(Layer.PTChangingEffects_7, SubLayer.SetPT_7b, ability, game);
      }
    }
    for (ContinuousEffect effect : layer) {
      HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
      for (Ability ability : abilities) {
        effect.apply(Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, ability, game);
      }
    }

    applyCounters.apply(Layer.PTChangingEffects_7, SubLayer.Counters_7d, null, game);

    for (ContinuousEffect effect : layer) {
      HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
      for (Ability ability : abilities) {
        effect.apply(Layer.PTChangingEffects_7, SubLayer.SwitchPT_e, ability, game);
      }
    }
    layer = filterLayeredEffects(layerEffects, Layer.PlayerEffects);
    for (ContinuousEffect effect : layer) {
      HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
      for (Ability ability : abilities) {
        effect.apply(Layer.PlayerEffects, SubLayer.NA, ability, game);
      }
    }
    layer = filterLayeredEffects(layerEffects, Layer.RulesEffects);
    for (ContinuousEffect effect : layer) {
      HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
      for (Ability ability : abilities) {
        effect.apply(Layer.RulesEffects, SubLayer.NA, ability, game);
      }
    }
  }
예제 #7
0
 public void setOrder(ContinuousEffect effect) {
   effect.setOrder(order++);
 }
예제 #8
0
 @Override
 public int compare(ContinuousEffect one, ContinuousEffect two) {
   return Long.compare(one.getOrder(), two.getOrder());
 }