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;
}
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();
}
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);
}
}
}
}
}
}
}
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;
}
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;
}
Aggregations