Search in sources :

Example 26 with CombatGroup

use of mage.game.combat.CombatGroup in project mage by magefree.

the class TideOfWarEffect method apply.

@Override
public boolean apply(Game game, Ability source) {
    Player controller = game.getPlayer(source.getControllerId());
    if (controller != null) {
        Set<UUID> toSacrifice = new HashSet<>();
        if (controller.flipCoin(source, game, true)) {
            // each blocking creature is sacrificed by its controller
            for (CombatGroup combatGroup : game.getCombat().getGroups()) {
                for (UUID blockerId : combatGroup.getBlockers()) {
                    toSacrifice.add(blockerId);
                }
            }
        } else {
            // each blocked creature is sacrificed by its controller
            for (CombatGroup combatGroup : game.getCombat().getGroups()) {
                if (!combatGroup.getBlockers().isEmpty()) {
                    for (UUID attackerId : combatGroup.getAttackers()) {
                        toSacrifice.add(attackerId);
                    }
                }
            }
        }
        for (UUID creatureId : toSacrifice) {
            Permanent creature = game.getPermanent(creatureId);
            if (creature != null) {
                creature.sacrifice(source, game);
                Player player = game.getPlayer(creature.getControllerId());
                if (player != null) {
                    game.informPlayers(player.getLogName() + " sacrifices " + creature.getName());
                }
            }
        }
        return true;
    }
    return false;
}
Also used : Player(mage.players.Player) Permanent(mage.game.permanent.Permanent) UUID(java.util.UUID) CombatGroup(mage.game.combat.CombatGroup) HashSet(java.util.HashSet)

Example 27 with CombatGroup

use of mage.game.combat.CombatGroup in project mage by magefree.

the class GameState method getValue.

public String getValue(Game game, UUID playerId) {
    StringBuilder sb = threadLocalBuilder.get();
    sb.append(turn.getValue(turnNum));
    sb.append(activePlayerId).append(priorityPlayerId).append(playerByOrderId);
    for (Player player : players.values()) {
        sb.append("player").append(player.isPassed()).append(player.getLife()).append("hand");
        if (Objects.equals(playerId, player.getId())) {
            sb.append(player.getHand().getValue(game));
        } else {
            sb.append(player.getHand().size());
        }
        sb.append("library").append(player.getLibrary().size());
        sb.append("graveyard");
        sb.append(player.getGraveyard().getValue(game));
    }
    sb.append("permanents");
    List<String> perms = new ArrayList<>();
    for (Permanent permanent : battlefield.getAllPermanents()) {
        perms.add(permanent.getValue(this));
    }
    Collections.sort(perms);
    sb.append(perms);
    sb.append("spells");
    for (StackObject spell : stack) {
        sb.append(spell.getControllerId()).append(spell.getName());
        sb.append(spell.getStackAbility().toString());
        for (UUID modeId : spell.getStackAbility().getModes().getSelectedModes()) {
            Mode mode = spell.getStackAbility().getModes().get(modeId);
            if (!mode.getTargets().isEmpty()) {
                sb.append("targets");
                for (Target target : mode.getTargets()) {
                    sb.append(target.getTargets());
                }
            }
        }
    }
    for (ExileZone zone : exile.getExileZones()) {
        sb.append("exile").append(zone.getName()).append(zone.getValue(game));
    }
    sb.append("combat");
    for (CombatGroup group : combat.getGroups()) {
        sb.append(group.getDefenderId()).append(group.getAttackers()).append(group.getBlockers());
    }
    return sb.toString();
}
Also used : Player(mage.players.Player) Target(mage.target.Target) ThreadLocalStringBuilder(mage.util.ThreadLocalStringBuilder) FilterCreaturePermanent(mage.filter.common.FilterCreaturePermanent) Permanent(mage.game.permanent.Permanent) StackObject(mage.game.stack.StackObject) CombatGroup(mage.game.combat.CombatGroup)

Example 28 with CombatGroup

use of mage.game.combat.CombatGroup in project mage by magefree.

the class TraceUtil method traceCombatIfNeeded.

/**
 * This method is intended to catch various bugs with combat.
 *
 * One of them (possibly the most annoying) is when creature without flying or reach blocks creature with flying.
 * No test managed to reproduce it, but it happens in the games time to time and was reported by different players.
 *
 * The idea: is to catch such cases manually and print out as much information from game state that may help as possible.
 * @param game
 * @param combat
 */
public static void traceCombatIfNeeded(Game game, Combat combat) {
    // trace non-flying vs flying
    for (CombatGroup group : combat.getGroups()) {
        for (UUID attackerId : group.getAttackers()) {
            Permanent attacker = game.getPermanent(attackerId);
            if (attacker != null) {
                if (hasFlying(attacker)) {
                    // traceCombat(game, attacker, null);
                    for (UUID blockerId : group.getBlockers()) {
                        Permanent blocker = game.getPermanent(blockerId);
                        if (blocker != null && !hasFlying(blocker) && !hasReach(blocker)) {
                            log.warn("Found non-flying non-reach creature blocking creature with flying");
                            traceCombat(game, attacker, blocker);
                        }
                    }
                }
                if (hasIntimidate(attacker)) {
                    for (UUID blockerId : group.getBlockers()) {
                        Permanent blocker = game.getPermanent(blockerId);
                        if (blocker != null && !blocker.isArtifact(game) && !attacker.getColor(game).shares(blocker.getColor(game))) {
                            log.warn("Found creature with intimidate blocked by non artifact not sharing color creature");
                            traceCombat(game, attacker, blocker);
                        }
                    }
                }
                if (cantBeBlocked(attacker)) {
                    if (!group.getBlockers().isEmpty()) {
                        Permanent blocker = game.getPermanent(group.getBlockers().get(0));
                        if (blocker != null) {
                            log.warn("Found creature that can't be blocked by some other creature");
                            traceCombat(game, attacker, blocker);
                        }
                    }
                }
            }
        }
    }
}
Also used : Permanent(mage.game.permanent.Permanent) CombatGroup(mage.game.combat.CombatGroup)

Example 29 with CombatGroup

use of mage.game.combat.CombatGroup in project mage by magefree.

the class GodsendRuleModifyingEffect method checkTrigger.

@Override
public boolean checkTrigger(GameEvent event, Game game) {
    Permanent equipment = game.getPermanentOrLKIBattlefield((this.getSourceId()));
    if (equipment != null && equipment.getAttachedTo() != null) {
        Permanent equippedPermanent = game.getPermanentOrLKIBattlefield((equipment.getAttachedTo()));
        if (equippedPermanent != null) {
            possibleTargets.clear();
            String targetName = "";
            if (equippedPermanent.isAttacking()) {
                for (CombatGroup group : game.getCombat().getGroups()) {
                    if (group.getAttackers().contains(equippedPermanent.getId())) {
                        possibleTargets.addAll(group.getBlockers());
                    }
                }
                targetName = "a creature blocking attacker ";
            } else if (equippedPermanent.getBlocking() > 0) {
                for (CombatGroup group : game.getCombat().getGroups()) {
                    if (group.getBlockers().contains(equippedPermanent.getId())) {
                        possibleTargets.addAll(group.getAttackers());
                    }
                }
                targetName = "a creature blocked by creature ";
            }
            if (!possibleTargets.isEmpty()) {
                this.getTargets().clear();
                if (possibleTargets.size() == 1) {
                    this.getEffects().get(0).setTargetPointer(new FixedTarget(possibleTargets.iterator().next(), game));
                } else {
                    this.getEffects().get(0).setTargetPointer(new FirstTargetPointer());
                    targetName = targetName + " equipped by " + equipment.getName();
                    FilterCreaturePermanent filter = new FilterCreaturePermanent(targetName);
                    List<PermanentIdPredicate> uuidPredicates = new ArrayList<>();
                    for (UUID creatureId : possibleTargets) {
                        uuidPredicates.add(new PermanentIdPredicate(creatureId));
                    }
                    filter.add(Predicates.or(uuidPredicates));
                    this.getTargets().add(new TargetCreaturePermanent(filter));
                }
                return true;
            }
        }
    }
    return false;
}
Also used : FixedTarget(mage.target.targetpointer.FixedTarget) PermanentIdPredicate(mage.filter.predicate.permanent.PermanentIdPredicate) TargetCreaturePermanent(mage.target.common.TargetCreaturePermanent) FilterCreaturePermanent(mage.filter.common.FilterCreaturePermanent) FilterCreaturePermanent(mage.filter.common.FilterCreaturePermanent) Permanent(mage.game.permanent.Permanent) TargetCreaturePermanent(mage.target.common.TargetCreaturePermanent) FirstTargetPointer(mage.target.targetpointer.FirstTargetPointer) CombatGroup(mage.game.combat.CombatGroup)

Example 30 with CombatGroup

use of mage.game.combat.CombatGroup in project mage by magefree.

the class SorrowsPathSwitchBlockersEffect method apply.

@Override
public boolean apply(Game game, Ability source) {
    Player controller = game.getPlayer(source.getControllerId());
    List<UUID> targets = source.getTargets().get(0).getTargets();
    if (controller != null && targets != null) {
        Permanent blocker1 = game.getPermanent(targets.get(0));
        Permanent blocker2 = game.getPermanent(targets.get(1));
        if (blocker1 != null && blocker2 != null) {
            Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
            // 10/1/2009: When determining whether a creature could block all creatures the other is blocking, take into account evasion abilities (like flying), protection
            // abilities, and other blocking restrictions, as well as abilities that allow a creature to block multiple creatures or block as though a certain condition were true.
            // Take into account whether those creatures are tapped, but not whether they have costs to block (since those apply only as blockers are declared).
            CombatGroup chosenGroup1 = findBlockingGroup(blocker1, game);
            CombatGroup chosenGroup2 = findBlockingGroup(blocker2, game);
            Set<Permanent> attackers1 = new HashSet<>();
            Set<Permanent> attackers2 = new HashSet<>();
            boolean blockPossible = false;
            if (chosenGroup1 != null && chosenGroup2 != null) {
                blockPossible = getRestrictions(chosenGroup1, blocker2, attackers1, sourcePermanent, controller, game) && getRestrictions(chosenGroup2, blocker1, attackers2, sourcePermanent, controller, game);
            }
            if (!blockPossible) {
                return true;
            }
            // 10/1/2009: When the first ability resolves, if all the creatures that one of the targeted creatures was blocking have left combat, then the other targeted creature
            // is considered to be able to block all creatures the first creature is blocking. If the ability has its full effect, the second creature will be removed from combat
            // but not returned to combat; it doesn't block anything.
            game.getCombat().removeFromCombat(blocker1.getId(), game, false);
            game.getCombat().removeFromCombat(blocker2.getId(), game, false);
            blocker1.setRemovedFromCombat(attackers2.isEmpty());
            blocker2.setRemovedFromCombat(attackers1.isEmpty());
            // 10/1/2009: Abilities that trigger whenever one of the targeted creatures blocks will trigger when the first ability resolves, because those creatures will change from
            // not blocking (since they're removed from combat) to blocking. It doesn't matter if those abilities triggered when those creatures blocked the first time. Abilities
            // that trigger whenever one of the attacking creatures becomes blocked will not trigger again, because they never stopped being blocked creatures. Abilities that
            // trigger whenever a creature blocks one of the attacking creatures will trigger again, though; those kinds of abilities trigger once for each creature that blocks.
            reassignBlocker(blocker1, attackers2, game);
            reassignBlocker(blocker2, attackers1, game);
            Set<MageObjectReference> morSet = new HashSet<>();
            attackers1.stream().map(permanent -> new MageObjectReference(permanent, game)).forEach(morSet::add);
            attackers2.stream().map(permanent -> new MageObjectReference(permanent, game)).forEach(morSet::add);
            String key = UUID.randomUUID().toString();
            game.getState().setValue("becameBlocked_" + key, morSet);
            game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BATCH_BLOCK_NONCOMBAT, source.getSourceId(), source, source.getControllerId(), key, 0));
            return true;
        }
    }
    return false;
}
Also used : MageObjectReference(mage.MageObjectReference) Player(mage.players.Player) HashSet(java.util.HashSet) TapSourceCost(mage.abilities.costs.common.TapSourceCost) BecomesTappedSourceTriggeredAbility(mage.abilities.common.BecomesTappedSourceTriggeredAbility) CardType(mage.constants.CardType) CombatGroup(mage.game.combat.CombatGroup) BlockerDeclaredEvent(mage.game.events.BlockerDeclaredEvent) DamageControllerEffect(mage.abilities.effects.common.DamageControllerEffect) SimpleActivatedAbility(mage.abilities.common.SimpleActivatedAbility) StaticFilters(mage.filter.StaticFilters) DamageAllEffect(mage.abilities.effects.common.DamageAllEffect) Outcome(mage.constants.Outcome) BlockingPredicate(mage.filter.predicate.permanent.BlockingPredicate) Set(java.util.Set) OneShotEffect(mage.abilities.effects.OneShotEffect) UUID(java.util.UUID) TargetCreaturePermanentSameController(mage.target.common.TargetCreaturePermanentSameController) CardSetInfo(mage.cards.CardSetInfo) Game(mage.game.Game) List(java.util.List) GameEvent(mage.game.events.GameEvent) CardImpl(mage.cards.CardImpl) Permanent(mage.game.permanent.Permanent) FilterOpponentsCreaturePermanent(mage.filter.common.FilterOpponentsCreaturePermanent) Ability(mage.abilities.Ability) Player(mage.players.Player) Permanent(mage.game.permanent.Permanent) FilterOpponentsCreaturePermanent(mage.filter.common.FilterOpponentsCreaturePermanent) UUID(java.util.UUID) CombatGroup(mage.game.combat.CombatGroup) MageObjectReference(mage.MageObjectReference) HashSet(java.util.HashSet)

Aggregations

CombatGroup (mage.game.combat.CombatGroup)44 Permanent (mage.game.permanent.Permanent)39 UUID (java.util.UUID)25 Player (mage.players.Player)23 FilterCreaturePermanent (mage.filter.common.FilterCreaturePermanent)9 FixedTarget (mage.target.targetpointer.FixedTarget)9 TargetPermanent (mage.target.TargetPermanent)8 TargetCreaturePermanent (mage.target.common.TargetCreaturePermanent)8 HashSet (java.util.HashSet)7 OneShotEffect (mage.abilities.effects.OneShotEffect)6 Game (mage.game.Game)6 ArrayList (java.util.ArrayList)5 List (java.util.List)5 Combat (mage.game.combat.Combat)5 BlockerDeclaredEvent (mage.game.events.BlockerDeclaredEvent)5 Target (mage.target.Target)5 MageObjectReference (mage.MageObjectReference)4 Ability (mage.abilities.Ability)4 PermanentInListPredicate (mage.filter.predicate.permanent.PermanentInListPredicate)4 BlockedByOnlyOneCreatureThisCombatWatcher (mage.watchers.common.BlockedByOnlyOneCreatureThisCombatWatcher)4