Ejemplo n.º 1
0
 @Override
 public boolean replaceEvent(GameEvent event, Ability source, Game game) {
   boolean retValue = false;
   GameEvent preventEvent =
       new GameEvent(
           GameEvent.EventType.PREVENT_DAMAGE,
           source.getFirstTarget(),
           source.getId(),
           source.getControllerId(),
           event.getAmount(),
           false);
   int damage = event.getAmount();
   if (!game.replaceEvent(preventEvent)) {
     event.setAmount(0);
     game.fireEvent(
         GameEvent.getEvent(
             GameEvent.EventType.PREVENTED_DAMAGE,
             source.getFirstTarget(),
             source.getId(),
             source.getControllerId(),
             damage));
     retValue = true;
   }
   Permanent permanent = game.getPermanent(source.getSourceId());
   if (permanent != null) {
     permanent.removeCounters(CounterType.P1P1.createInstance(damage), game);
   }
   return retValue;
 }
Ejemplo n.º 2
0
 @Override
 public boolean replaceEvent(GameEvent event, Ability source, Game game) {
   GameEvent preventEvent =
       new GameEvent(
           GameEvent.EventType.PREVENT_DAMAGE,
           source.getControllerId(),
           source.getId(),
           source.getControllerId(),
           event.getAmount(),
           false);
   if (!game.replaceEvent(preventEvent)) {
     int damage = event.getAmount();
     if (damage > 0) {
       event.setAmount(damage - 1);
       this.used = true;
       game.fireEvent(
           GameEvent.getEvent(
               GameEvent.EventType.PREVENTED_DAMAGE,
               source.getControllerId(),
               source.getId(),
               source.getControllerId(),
               1));
     }
   }
   return false;
 }
Ejemplo n.º 3
0
 @Override
 public boolean replaceEvent(GameEvent event, Ability source, Game game) {
   GameEvent preventEvent =
       new GameEvent(
           GameEvent.EventType.PREVENT_DAMAGE,
           source.getFirstTarget(),
           source.getId(),
           source.getControllerId(),
           event.getAmount(),
           false);
   if (!game.replaceEvent(preventEvent)) {
     int damage = event.getAmount();
     Permanent permanent = game.getPermanent(event.getSourceId());
     StringBuilder message = new StringBuilder();
     if (permanent != null) {
       message.append(" from ").append(permanent.getName());
     }
     message.insert(0, "Damage").append(" has been prevented: ").append(damage);
     event.setAmount(0);
     game.informPlayers(message.toString());
     game.fireEvent(
         GameEvent.getEvent(
             GameEvent.EventType.PREVENTED_DAMAGE,
             source.getFirstTarget(),
             source.getId(),
             source.getControllerId(),
             damage));
   }
   return false;
 }
Ejemplo n.º 4
0
  Cards ProteanHulkSearch(Game game, Ability source) {
    Cards cardsPicked = new CardsImpl(Zone.PICK);
    Player player = game.getPlayer(source.getControllerId());
    if (player != null) {
      GameEvent event =
          GameEvent.getEvent(
              GameEvent.EventType.SEARCH_LIBRARY,
              source.getControllerId(),
              source.getControllerId(),
              source.getControllerId(),
              Integer.MAX_VALUE);
      if (!game.replaceEvent(event)) {
        int manaCostLeftToFetch = 6;
        int librarySearchLimit = event.getAmount();

        FilterCard filter =
            new FilterCreatureCard(
                "number of creature cards with total converted mana cost 6 or less (6 CMC left)");
        filter.add(
            new ConvertedManaCostPredicate(ComparisonType.LessThan, manaCostLeftToFetch + 1));
        TargetCardInLibrary target = new TargetCardInLibrary(0, 1, filter);
        target.setCardLimit(librarySearchLimit);

        while (target.canChoose(source.getSourceId(), source.getControllerId(), game)) {
          target.choose(
              Outcome.PutCreatureInPlay, source.getControllerId(), source.getControllerId(), game);
          Card card = player.getLibrary().remove(target.getFirstTarget(), game);
          if (card == null) {
            break;
          }
          cardsPicked.add(card);
          game.setZone(card.getId(), Zone.PICK);
          game.getState().getLookedAt(source.getControllerId()).add("Protean Hulk", cardsPicked);

          librarySearchLimit--;
          if (librarySearchLimit == 0) {
            break;
          }
          manaCostLeftToFetch -= card.getManaCost().convertedManaCost();
          filter =
              new FilterCreatureCard(
                  "number of creature cards with total converted mana cost 6 or less ("
                      + manaCostLeftToFetch
                      + " CMC left)");
          filter.add(
              new ConvertedManaCostPredicate(ComparisonType.LessThan, manaCostLeftToFetch + 1));
          target = new TargetCardInLibrary(0, 1, filter);
          target.setCardLimit(librarySearchLimit);
        }
        game.fireEvent(
            GameEvent.getEvent(
                GameEvent.EventType.LIBRARY_SEARCHED,
                source.getControllerId(),
                source.getControllerId()));
      }
    }
    return cardsPicked;
  }
Ejemplo n.º 5
0
 public void addBlocker(UUID blockerId, UUID playerId, Game game) {
   for (UUID attackerId : attackers) {
     if (game.replaceEvent(
         GameEvent.getEvent(
             GameEvent.EventType.DECLARE_BLOCKER, attackerId, blockerId, playerId))) {
       return;
     }
   }
   Permanent blocker = game.getPermanent(blockerId);
   if (blockerId != null && blocker != null) {
     blocker.setBlocking(blocker.getBlocking() + 1);
     blockers.add(blockerId);
     blockerOrder.add(blockerId);
     this.blocked = true;
     this.players.put(blockerId, playerId);
   }
 }
Ejemplo n.º 6
0
 public boolean putOntoBattlefield(int amount, Game game, UUID sourceId, UUID controllerId) {
   Card source = game.getCard(sourceId);
   String setCode = source != null ? source.getExpansionSetCode() : null;
   GameEvent event =
       GameEvent.getEvent(EventType.CREATE_TOKEN, null, sourceId, controllerId, amount);
   if (!game.replaceEvent(event)) {
     amount = event.getAmount();
     for (int i = 0; i < amount; i++) {
       PermanentToken permanent = new PermanentToken(this, controllerId, setCode, game);
       game.getState().addCard(permanent);
       game.addPermanent(permanent);
       this.lastAddedTokenId = permanent.getId();
       permanent.entersBattlefield(sourceId, game);
       game.applyEffects();
       game.fireEvent(
           new ZoneChangeEvent(permanent, controllerId, Zone.OUTSIDE, Zone.BATTLEFIELD));
     }
     return true;
   }
   return false;
 }
Ejemplo n.º 7
0
  @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 (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;
  }
Ejemplo n.º 8
0
Archivo: Token.java Proyecto: royk/mage
  public boolean putOntoBattlefield(
      int amount,
      Game game,
      UUID sourceId,
      UUID controllerId,
      boolean tapped,
      boolean attacking,
      UUID attackedPlayer) {
    Player controller = game.getPlayer(controllerId);
    if (controller == null) {
      return false;
    }
    lastAddedTokenIds.clear();

    // moved here from CreateTokenEffect because not all cards that create tokens use
    // CreateTokenEffect
    // they use putOntoBattlefield directly
    // TODO: Check this setCode handling because it makes no sense if token put into play with e.g.
    // "Feldon of the third Path"
    String setCode = null;
    if (this.getOriginalExpansionSetCode() != null
        && !this.getOriginalExpansionSetCode().isEmpty()) {
      setCode = this.getOriginalExpansionSetCode();
    } else {
      Card source = game.getCard(sourceId);
      if (source != null) {
        setCode = source.getExpansionSetCode();
      } else {
        MageObject object = game.getObject(sourceId);
        if (object instanceof PermanentToken) {
          setCode = ((PermanentToken) object).getExpansionSetCode();
        }
      }
    }
    if (!expansionSetCodeChecked) {
      expansionSetCodeChecked = this.updateExpansionSetCode(setCode);
    }

    GameEvent event =
        new GameEvent(
            EventType.CREATE_TOKEN,
            null,
            sourceId,
            controllerId,
            amount,
            this.getCardType().contains(CardType.CREATURE));
    if (!game.replaceEvent(event)) {
      amount = event.getAmount();

      List<Permanent> permanents = new ArrayList<>();
      List<Permanent> permanentsEntered = new ArrayList<>();

      for (int i = 0; i < amount; i++) {
        PermanentToken newToken =
            new PermanentToken(
                this,
                event.getPlayerId(),
                setCode,
                game); // use event.getPlayerId() because it can be replaced by replacement effect
        game.getState().addCard(newToken);
        permanents.add(newToken);
        game.getPermanentsEntering().put(newToken.getId(), newToken);
        newToken.setTapped(tapped);
      }
      game.setScopeRelevant(true);
      for (Permanent permanent : permanents) {
        if (permanent.entersBattlefield(sourceId, game, Zone.OUTSIDE, true)) {
          permanentsEntered.add(permanent);
        } else {
          game.getPermanentsEntering().remove(permanent.getId());
        }
      }
      game.setScopeRelevant(false);
      for (Permanent permanent : permanentsEntered) {
        game.addPermanent(permanent);
        permanent.setZone(Zone.BATTLEFIELD, game);
        game.getPermanentsEntering().remove(permanent.getId());

        this.lastAddedTokenIds.add(permanent.getId());
        this.lastAddedTokenId = permanent.getId();
        game.addSimultaneousEvent(
            new ZoneChangeEvent(
                permanent, permanent.getControllerId(), Zone.OUTSIDE, Zone.BATTLEFIELD));
        if (attacking && game.getCombat() != null) {
          game.getCombat().addAttackingCreature(permanent.getId(), game, attackedPlayer);
        }
        if (!game.isSimulation()) {
          game.informPlayers(
              controller.getLogName()
                  + " puts a "
                  + permanent.getLogName()
                  + " token onto the battlefield");
        }
      }
      return true;
    }
    return false;
  }
Ejemplo n.º 9
0
 protected int simulateCombat(
     Game game, SimulationNode2 node, int depth, int alpha, int beta, boolean counter) {
   Integer val = null;
   if (ALLOW_INTERRUPT && Thread.interrupted()) {
     Thread.currentThread().interrupt();
     logger.debug("interrupted");
     return GameStateEvaluator2.evaluate(playerId, game);
   }
   if (game.getTurn().getStepType() != PhaseStep.DECLARE_BLOCKERS) {
     game.getTurn().setPhase(new CombatPhase());
     if (game.getPhase().beginPhase(game, game.getActivePlayerId())) {
       simulateStep(game, new BeginCombatStep());
       game.getPhase().setStep(new DeclareAttackersStep());
       if (!game.getStep().skipStep(game, game.getActivePlayerId())) {
         game.fireEvent(
             new GameEvent(
                 GameEvent.EventType.DECLARE_ATTACKERS_STEP_PRE,
                 null,
                 null,
                 game.getActivePlayerId()));
         if (!game.replaceEvent(
             GameEvent.getEvent(
                 GameEvent.EventType.DECLARING_ATTACKERS,
                 game.getActivePlayerId(),
                 game.getActivePlayerId()))) {
           val =
               simulateAttackers(
                   game, node, game.getActivePlayerId(), depth, alpha, beta, counter);
         }
       } else if (!counter) {
         simulateToEnd(game);
         val = simulatePostCombatMain(game, node, depth, alpha, beta);
       }
     }
   } else {
     if (!game.getStep().skipStep(game, game.getActivePlayerId())) {
       game.fireEvent(
           new GameEvent(
               GameEvent.EventType.DECLARE_BLOCKERS_STEP_PRE,
               null,
               null,
               game.getActivePlayerId()));
       if (!game.replaceEvent(
           GameEvent.getEvent(
               GameEvent.EventType.DECLARING_BLOCKERS,
               game.getActivePlayerId(),
               game.getActivePlayerId()))) {
         // only suitable for two player games - only simulates blocks for 1st defender
         val =
             simulateBlockers(
                 game,
                 node,
                 game.getCombat().getDefenders().iterator().next(),
                 depth,
                 alpha,
                 beta,
                 counter);
       }
     } else if (!counter) {
       finishCombat(game);
       /// val = simulateCounterAttack(game, node, depth, alpha, beta);
     }
   }
   if (val == null) {
     val = GameStateEvaluator2.evaluate(playerId, game);
   }
   if (logger.isDebugEnabled()) {
     logger.debug(
         "returning -- combat score: "
             + val
             + " depth:"
             + depth
             + " for player:"
             + game.getPlayer(node.getPlayerId()).getName());
   }
   return val;
 }
Ejemplo n.º 10
0
  @Override
  public boolean activate(Game game, boolean noMana) {
    Player controller = game.getPlayer(this.getControllerId());
    if (controller == null) {
      return false;
    }
    game.applyEffects();

    /* 20130201 - 601.2b
     * If the spell is modal the player announces the mode choice (see rule 700.2).
     */
    if (!getModes().choose(game, this)) {
      return false;
    }
    if (controller.isTestMode()) {
      if (!controller.addTargets(this, game)) {
        return false;
      }
    }

    getSourceObject(game);

    /* 20130201 - 601.2b
     * If the player wishes to splice any cards onto the spell (see rule 702.45), he
     * or she reveals those cards in his or her hand.
     */
    if (this.abilityType.equals(AbilityType.SPELL)) {
      game.getContinuousEffects().applySpliceEffects(this, game);
    }

    // if ability can be cast for no mana, clear the mana costs now, because additional mana costs
    // must be paid.
    // For Flashback ability can be set X before, so the X costs have to be restored for the
    // flashbacked ability
    if (noMana) {
      if (this.getManaCostsToPay().getVariableCosts().size() > 0) {
        int xValue = this.getManaCostsToPay().getX();
        this.getManaCostsToPay().clear();
        VariableManaCost xCosts = new VariableManaCost();
        xCosts.setAmount(xValue);
        this.getManaCostsToPay().add(xCosts);
      } else {
        this.getManaCostsToPay().clear();
      }
    }
    // 20130201 - 601.2b
    // If the spell has alternative or additional costs that will be paid as it's being cast such
    // as buyback, kicker, or convoke costs (see rules 117.8 and 117.9), the player announces his
    // or her intentions to pay any or all of those costs (see rule 601.2e).
    // A player can't apply two alternative methods of casting or two alternative costs to a single
    // spell.
    if (!activateAlternateOrAdditionalCosts(sourceObject, noMana, controller, game)) {
      if (getAbilityType().equals(AbilityType.SPELL)
          && ((SpellAbility) this)
              .getSpellAbilityType()
              .equals(SpellAbilityType.FACE_DOWN_CREATURE)) {
        return false;
      }
    }

    // 20121001 - 601.2b
    // If the spell has a variable cost that will be paid as it's being cast (such as an {X} in
    // its mana cost; see rule 107.3), the player announces the value of that variable.
    VariableManaCost variableManaCost = handleManaXCosts(game, noMana, controller);
    String announceString = handleOtherXCosts(game, controller);
    // For effects from cards like Void Winnower x costs have to be set
    if (this.getAbilityType().equals(AbilityType.SPELL)
        && game.replaceEvent(
            GameEvent.getEvent(
                GameEvent.EventType.CAST_SPELL_LATE, getId(), getSourceId(), getControllerId()),
            this)) {
      return false;
    }
    for (Mode mode : this.getModes().getSelectedModes()) {
      this.getModes().setActiveMode(mode);
      // 20121001 - 601.2c
      // 601.2c The player announces his or her choice of an appropriate player, object, or zone for
      // each target the spell requires. A spell may require some targets only if an alternative or
      // additional cost (such as a buyback or kicker cost), or a particular mode, was chosen for
      // it;
      // otherwise, the spell is cast as though it did not require those targets. If the spell has a
      // variable number of targets, the player announces how many targets he or she will choose
      // before
      // he or she announces those targets. The same target can't be chosen multiple times for any
      // one
      // instance of the word "target" on the spell. However, if the spell uses the word "target" in
      // multiple places, the same object, player, or zone can be chosen once for each instance of
      // the
      // word "target" (as long as it fits the targeting criteria). If any effects say that an
      // object
      // or player must be chosen as a target, the player chooses targets so that he or she obeys
      // the
      // maximum possible number of such effects without violating any rules or effects that say
      // that
      // an object or player can't be chosen as a target. The chosen players, objects, and/or zones
      // each become a target of that spell. (Any abilities that trigger when those players,
      // objects,
      // and/or zones become the target of a spell trigger at this point; they'll wait to be put on
      // the stack until the spell has finished being cast.)

      if (sourceObject != null
          && !this.getAbilityType()
              .equals(AbilityType.TRIGGERED)) { // triggered abilities check this already in
        // playerImpl.triggerAbility
        sourceObject.adjustTargets(this, game);
      }
      if (mode.getTargets().size() > 0
          && mode.getTargets()
                  .chooseTargets(
                      getEffects().get(0).getOutcome(), this.controllerId, this, noMana, game)
              == false) {
        if ((variableManaCost != null || announceString != null) && !game.isSimulation()) {
          game.informPlayer(
              controller,
              (sourceObject != null ? sourceObject.getIdName() : "")
                  + ": no valid targets with this value of X");
        }
        return false; // when activation of ability is canceled during target selection
      }
    } // end modes

    // TODO: Handle optionalCosts at the same time as already OptionalAdditionalSourceCosts are
    // handled.
    for (Cost cost : optionalCosts) {
      if (cost instanceof ManaCost) {
        cost.clearPaid();
        if (controller.chooseUse(
            Outcome.Benefit, "Pay optional cost " + cost.getText() + "?", this, game)) {
          manaCostsToPay.add((ManaCost) cost);
        }
      }
    }
    // 20100716 - 601.2e
    if (sourceObject != null) {
      sourceObject.adjustCosts(this, game);
      if (sourceObject instanceof Card) {
        for (Ability ability : ((Card) sourceObject).getAbilities(game)) {
          if (ability instanceof AdjustingSourceCosts) {
            ((AdjustingSourceCosts) ability).adjustCosts(this, game);
          }
        }
      } else {
        for (Ability ability : sourceObject.getAbilities()) {
          if (ability instanceof AdjustingSourceCosts) {
            ((AdjustingSourceCosts) ability).adjustCosts(this, game);
          }
        }
      }
    }

    // this is a hack to prevent mana abilities with mana costs from causing endless loops - pay
    // other costs first
    if (this instanceof ManaAbility
        && !costs.pay(this, game, sourceId, controllerId, noMana, null)) {
      logger.debug("activate mana ability failed - non mana costs");
      return false;
    }

    // 20101001 - 601.2e
    if (costModificationActive) {
      game.getContinuousEffects().costModification(this, game);
    } else {
      costModificationActive = true;
    }

    UUID activatorId = controllerId;
    if ((this instanceof ActivatedAbilityImpl)
        && ((ActivatedAbilityImpl) this).getActivatorId() != null) {
      activatorId = ((ActivatedAbilityImpl) this).getActivatorId();
    }

    // 20100716 - 601.2f  (noMana is not used here, because mana costs were cleared for this ability
    // before adding additional costs and applying cost modification effects)
    if (!manaCostsToPay.pay(this, game, sourceId, activatorId, false, null)) {
      return false; // cancel during mana payment
    }

    // 20100716 - 601.2g
    if (!costs.pay(this, game, sourceId, activatorId, noMana, null)) {
      logger.debug("activate failed - non mana costs");
      return false;
    }
    if (!game.isSimulation()) {
      // inform about x costs now, so canceled announcements are not shown in the log
      if (announceString != null) {
        game.informPlayers(announceString);
      }
      if (variableManaCost != null) {
        int xValue = getManaCostsToPay().getX();
        game.informPlayers(
            controller.getLogName()
                + " announces a value of "
                + xValue
                + " for "
                + variableManaCost.getText());
      }
    }
    activated = true;
    // fire if tapped for mana (may only fire now because else costs of ability itself can be payed
    // with mana of abilities that trigger for that event
    if (this.getAbilityType().equals(AbilityType.MANA)) {
      for (Cost cost : costs) {
        if (cost instanceof TapSourceCost) {
          Mana mana = null;
          Effect effect = getEffects().get(0);
          if (effect instanceof DynamicManaEffect) {
            mana = ((DynamicManaEffect) effect).getMana(game, this);
          } else if (effect instanceof BasicManaEffect) {
            mana = ((BasicManaEffect) effect).getMana(game, this);
          }
          if (mana != null
              && mana.getAny()
                  == 0) { // if mana == null or Any > 0 the event has to be fired in the mana effect
            // to know which mana was produced
            ManaEvent event =
                new ManaEvent(
                    GameEvent.EventType.TAPPED_FOR_MANA, sourceId, sourceId, controllerId, mana);
            if (!game.replaceEvent(event)) {
              game.fireEvent(event);
            }
          }
          break;
        }
      }
    }
    return true;
  }