refactor: deduplicate combat damage steps (#11566)

This commit is contained in:
xenohedron 2023-12-21 22:44:01 -05:00 committed by GitHub
parent 0862461d6b
commit eec5c5b2e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 22 additions and 95 deletions

View file

@ -9,7 +9,6 @@ import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.turn.CombatDamageStep; import mage.game.turn.CombatDamageStep;
import mage.game.turn.EndOfCombatStep; import mage.game.turn.EndOfCombatStep;
import mage.game.turn.FirstCombatDamageStep;
import mage.game.turn.Step; import mage.game.turn.Step;
import mage.players.Player; import mage.players.Player;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -220,8 +219,8 @@ public final class CombatUtil {
} }
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId())); sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId()));
simulateStep(sim, new FirstCombatDamageStep()); simulateStep(sim, new CombatDamageStep(true));
simulateStep(sim, new CombatDamageStep()); simulateStep(sim, new CombatDamageStep(false));
simulateStep(sim, new EndOfCombatStep()); simulateStep(sim, new EndOfCombatStep());
// The following commented out call produces random freezes. // The following commented out call produces random freezes.
//sim.checkStateAndTriggered(); //sim.checkStateAndTriggered();
@ -253,8 +252,8 @@ public final class CombatUtil {
} }
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId())); sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId()));
simulateStep(sim, new FirstCombatDamageStep()); simulateStep(sim, new CombatDamageStep(true));
simulateStep(sim, new CombatDamageStep()); simulateStep(sim, new CombatDamageStep(false));
simulateStep(sim, new EndOfCombatStep()); simulateStep(sim, new EndOfCombatStep());
// The following commented out call produces random freezes. // The following commented out call produces random freezes.
//sim.checkStateAndTriggered(); //sim.checkStateAndTriggered();

View file

@ -1,4 +1,3 @@
package mage.game.turn; package mage.game.turn;
import java.util.UUID; import java.util.UUID;
@ -14,15 +13,22 @@ import mage.game.events.GameEvent.EventType;
*/ */
public class CombatDamageStep extends Step { public class CombatDamageStep extends Step {
public CombatDamageStep() { private final boolean first;
super(PhaseStep.COMBAT_DAMAGE, true);
/**
* @param first if true, then it is the FirstCombatDamageStep
*/
public CombatDamageStep(boolean first) {
super(first ? PhaseStep.FIRST_COMBAT_DAMAGE : PhaseStep.COMBAT_DAMAGE, true);
this.stepEvent = EventType.COMBAT_DAMAGE_STEP; this.stepEvent = EventType.COMBAT_DAMAGE_STEP;
this.preStepEvent = EventType.COMBAT_DAMAGE_STEP_PRE; this.preStepEvent = EventType.COMBAT_DAMAGE_STEP_PRE;
this.postStepEvent = EventType.COMBAT_DAMAGE_STEP_POST; this.postStepEvent = EventType.COMBAT_DAMAGE_STEP_POST;
this.first = first;
} }
protected CombatDamageStep(final CombatDamageStep step) { protected CombatDamageStep(final CombatDamageStep step) {
super(step); super(step);
this.first = step.first;
} }
@Override @Override
@ -33,9 +39,14 @@ public class CombatDamageStep extends Step {
@Override @Override
public boolean skipStep(Game game, UUID activePlayerId) { public boolean skipStep(Game game, UUID activePlayerId) {
// 508.8
if (game.getCombat().noAttackers()) { if (game.getCombat().noAttackers()) {
return true; return true;
} }
// 510.4
if (first && !game.getCombat().hasFirstOrDoubleStrike(game)) {
return true;
}
return super.skipStep(game, activePlayerId); return super.skipStep(game, activePlayerId);
} }
@ -43,16 +54,14 @@ public class CombatDamageStep extends Step {
public void beginStep(Game game, UUID activePlayerId) { public void beginStep(Game game, UUID activePlayerId) {
super.beginStep(game, activePlayerId); super.beginStep(game, activePlayerId);
for (CombatGroup group : game.getCombat().getGroups()) { for (CombatGroup group : game.getCombat().getGroups()) {
group.assignDamageToBlockers(false, game); group.assignDamageToBlockers(first, game);
} }
for (CombatGroup group : game.getCombat().getBlockingGroups()) { for (CombatGroup group : game.getCombat().getBlockingGroups()) {
group.assignDamageToAttackers(false, game); group.assignDamageToAttackers(first, game);
} }
for (CombatGroup group : game.getCombat().getGroups()) { for (CombatGroup group : game.getCombat().getGroups()) {
group.applyDamage(game); group.applyDamage(game);
} }
for (CombatGroup group : game.getCombat().getBlockingGroups()) { for (CombatGroup group : game.getCombat().getBlockingGroups()) {
group.applyDamage(game); group.applyDamage(game);
} }
@ -60,10 +69,6 @@ public class CombatDamageStep extends Step {
game.getState().handleSimultaneousEvent(game); game.getState().handleSimultaneousEvent(game);
} }
public boolean getFirst() {
return false;
}
@Override @Override
public CombatDamageStep copy() { public CombatDamageStep copy() {
return new CombatDamageStep(this); return new CombatDamageStep(this);

View file

@ -1,5 +1,3 @@
package mage.game.turn; package mage.game.turn;
import mage.constants.TurnPhase; import mage.constants.TurnPhase;
@ -18,8 +16,8 @@ public class CombatPhase extends Phase {
this.steps.add(new BeginCombatStep()); this.steps.add(new BeginCombatStep());
this.steps.add(new DeclareAttackersStep()); this.steps.add(new DeclareAttackersStep());
this.steps.add(new DeclareBlockersStep()); this.steps.add(new DeclareBlockersStep());
this.steps.add(new FirstCombatDamageStep()); this.steps.add(new CombatDamageStep(true));
this.steps.add(new CombatDamageStep()); this.steps.add(new CombatDamageStep(false));
this.steps.add(new EndOfCombatStep()); this.steps.add(new EndOfCombatStep());
} }

View file

@ -1,75 +0,0 @@
package mage.game.turn;
import java.util.UUID;
import mage.constants.PhaseStep;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
/**
* @author BetaSteward_at_googlemail.com
*/
public class FirstCombatDamageStep extends Step {
public FirstCombatDamageStep() {
super(PhaseStep.FIRST_COMBAT_DAMAGE, true);
this.stepEvent = EventType.COMBAT_DAMAGE_STEP;
this.preStepEvent = EventType.COMBAT_DAMAGE_STEP_PRE;
this.postStepEvent = EventType.COMBAT_DAMAGE_STEP_POST;
}
protected FirstCombatDamageStep(final FirstCombatDamageStep step) {
super(step);
}
@Override
public void priority(Game game, UUID activePlayerId, boolean resuming) {
game.fireEvent(new GameEvent(GameEvent.EventType.COMBAT_DAMAGE_STEP_PRIORITY, null, null, activePlayerId));
super.priority(game, activePlayerId, resuming);
}
@Override
public boolean skipStep(Game game, UUID activePlayerId) {
if (game.getCombat().noAttackers()) {
return true;
}
if (!game.getCombat().hasFirstOrDoubleStrike(game)) {
return true;
}
return super.skipStep(game, activePlayerId);
}
@Override
public void beginStep(Game game, UUID activePlayerId) {
super.beginStep(game, activePlayerId);
for (CombatGroup group : game.getCombat().getGroups()) {
group.assignDamageToBlockers(true, game);
}
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
group.assignDamageToAttackers(true, game);
}
for (CombatGroup group : game.getCombat().getGroups()) {
group.applyDamage(game);
}
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
group.applyDamage(game);
}
// Must fire damage batch events now, before SBA (https://github.com/magefree/mage/issues/9129)
game.getState().handleSimultaneousEvent(game);
}
public boolean getFirst() {
return true;
}
@Override
public FirstCombatDamageStep copy() {
return new FirstCombatDamageStep(this);
}
}