Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing "Start your engines!" mechanic #13259

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Mage.Sets/src/mage/sets/Aetherdrift.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,5 @@ private Aetherdrift() {
cards.add(new SetCardInfo("Wild Roads", 269, Rarity.UNCOMMON, mage.cards.w.WildRoads.class));
cards.add(new SetCardInfo("Willowrush Verge", 270, Rarity.RARE, mage.cards.w.WillowrushVerge.class));
cards.add(new SetCardInfo("Wind-Scarred Crag", 271, Rarity.COMMON, mage.cards.w.WindScarredCrag.class));

cards.removeIf(setCardInfo -> unfinished.contains(setCardInfo.getName()));
}
}
15 changes: 15 additions & 0 deletions Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -3977,6 +3977,21 @@ public boolean isDrawsOnOpponentsTurn() {
return computerPlayer.isDrawsOnOpponentsTurn();
}

@Override
public int getSpeed() {
return computerPlayer.getSpeed();
}

@Override
public void initSpeed(Game game) {
computerPlayer.initSpeed(game);
}

@Override
public void increaseSpeed(Game game) {
computerPlayer.increaseSpeed(game);
}

@Override
public void setPayManaMode(boolean payManaMode) {
computerPlayer.setPayManaMode(payManaMode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.game.Game;
import mage.players.Player;

import java.util.Optional;

/**
* @author TheElk801
Expand All @@ -13,8 +16,10 @@ public enum ControllerSpeedCount implements DynamicValue {

@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
// TODO: Implement this
return 0;
return Optional
.ofNullable(game.getPlayer(sourceAbility.getControllerId()))
.map(Player::getSpeed)
.orElse(0);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public MaxSpeedGainAbilityEffect(Effect effect) {

public MaxSpeedGainAbilityEffect(Ability ability) {
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
ability.setRuleVisible(false);
this.ability = ability;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
package mage.abilities.keyword;

import mage.abilities.Ability;
import mage.abilities.StaticAbility;
import mage.constants.Zone;
import mage.abilities.dynamicvalue.common.ControllerSpeedCount;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.constants.*;
import mage.game.Game;

import java.util.Optional;

/**
* TODO: Implement this
*
* @author TheElk801
*/
public class StartYourEnginesAbility extends StaticAbility {

private static final Hint hint = new ValueHint("Your current speed", ControllerSpeedCount.instance);

public StartYourEnginesAbility() {
super(Zone.BATTLEFIELD, null);
super(Zone.BATTLEFIELD, new StartYourEnginesEffect());
this.addHint(hint);
}

private StartYourEnginesAbility(final StartYourEnginesAbility ability) {
Expand All @@ -25,6 +34,30 @@ public StartYourEnginesAbility copy() {

@Override
public String getRule() {
return "Start your engines!";
return "start your engines!";
}
}

class StartYourEnginesEffect extends ContinuousEffectImpl {

StartYourEnginesEffect() {
super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit);
}

private StartYourEnginesEffect(final StartYourEnginesEffect effect) {
super(effect);
}

@Override
public StartYourEnginesEffect copy() {
return new StartYourEnginesEffect(this);
}

@Override
public boolean apply(Game game, Ability source) {
Optional.ofNullable(source.getControllerId())
.map(game::getPlayer)
.ifPresent(player -> player.initSpeed(game));
return true;
}
}
5 changes: 2 additions & 3 deletions Mage/src/main/java/mage/designations/DesignationType.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
public enum DesignationType {
THE_MONARCH("The Monarch"), // global
CITYS_BLESSING("City's Blessing"), // per player
THE_INITIATIVE("The Initiative"); // global

THE_INITIATIVE("The Initiative"), // global
SPEED("Speed"); // per player
private final String text;

DesignationType(String text) {
Expand All @@ -18,5 +18,4 @@ public enum DesignationType {
public String toString() {
return text;
}

}
108 changes: 108 additions & 0 deletions Mage/src/main/java/mage/designations/Speed.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package mage.designations;

import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;

import java.util.Optional;

/**
* @author TheElk801
*/
public class Speed extends Designation {

public Speed() {
super(DesignationType.SPEED);
addAbility(new SpeedTriggeredAbility());
}

private Speed(final Speed card) {
super(card);
}

@Override
public Speed copy() {
return new Speed(this);
}
}

class SpeedTriggeredAbility extends TriggeredAbilityImpl {

SpeedTriggeredAbility() {
super(Zone.ALL, new SpeedEffect());
setTriggersLimitEachTurn(1);
}

private SpeedTriggeredAbility(final SpeedTriggeredAbility ability) {
super(ability);
}

@Override
public SpeedTriggeredAbility copy() {
return new SpeedTriggeredAbility(this);
}

@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.LOST_LIFE_BATCH_FOR_ONE_PLAYER;
}

@Override
public boolean checkTrigger(GameEvent event, Game game) {
return game.isActivePlayer(getControllerId())
&& game
.getOpponents(getControllerId())
.contains(event.getTargetId());
}

@Override
public boolean checkInterveningIfClause(Game game) {
return Optional
.ofNullable(getControllerId())
.map(game::getPlayer)
.map(Player::getSpeed)
.map(x -> x < 4)
.orElse(false);
}

@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return true;
}

@Override
public String getRule() {
return "Whenever one or more opponents lose life during your turn, if your speed is less than 4, " +
"increase your speed by 1. This ability triggers only once each turn.";
}
}

class SpeedEffect extends OneShotEffect {

SpeedEffect() {
super(Outcome.Benefit);
}

private SpeedEffect(final SpeedEffect effect) {
super(effect);
}

@Override
public SpeedEffect copy() {
return new SpeedEffect(this);
}

@Override
public boolean apply(Game game, Ability source) {
Optional.ofNullable(source.getControllerId())
.map(game::getPlayer)
.ifPresent(player -> player.increaseSpeed(game));
return true;
}
}
6 changes: 6 additions & 0 deletions Mage/src/main/java/mage/players/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,12 @@ default boolean isComputer() {

boolean isDrawsOnOpponentsTurn();

int getSpeed();

void initSpeed(Game game);

void increaseSpeed(Game game);

/**
* Returns alternative casting costs a player can cast spells for
*
Expand Down
28 changes: 28 additions & 0 deletions Mage/src/main/java/mage/players/PlayerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import mage.counters.Counters;
import mage.designations.Designation;
import mage.designations.DesignationType;
import mage.designations.Speed;
import mage.filter.FilterCard;
import mage.filter.FilterMana;
import mage.filter.FilterPermanent;
Expand Down Expand Up @@ -153,6 +154,7 @@ public abstract class PlayerImpl implements Player, Serializable {
protected boolean canPlotFromTopOfLibrary = false;
protected boolean drawsFromBottom = false;
protected boolean drawsOnOpponentsTurn = false;
protected int speed = 0;

protected FilterPermanent sacrificeCostFilter;
protected List<AlternativeSourceCosts> alternativeSourceCosts = new ArrayList<>();
Expand Down Expand Up @@ -252,6 +254,7 @@ protected PlayerImpl(final PlayerImpl player) {
this.canPlotFromTopOfLibrary = player.canPlotFromTopOfLibrary;
this.drawsFromBottom = player.drawsFromBottom;
this.drawsOnOpponentsTurn = player.drawsOnOpponentsTurn;
this.speed = player.speed;

this.attachments.addAll(player.attachments);

Expand Down Expand Up @@ -367,6 +370,7 @@ public void restore(Player player) {
this.drawsFromBottom = player.isDrawsFromBottom();
this.drawsOnOpponentsTurn = player.isDrawsOnOpponentsTurn();
this.alternativeSourceCosts = CardUtil.deepCopyObject(((PlayerImpl) player).alternativeSourceCosts);
this.speed = player.getSpeed();

this.topCardRevealed = player.isTopCardRevealed();

Expand Down Expand Up @@ -480,6 +484,7 @@ public void init(Game game) {
this.canPlotFromTopOfLibrary = false;
this.drawsFromBottom = false;
this.drawsOnOpponentsTurn = false;
this.speed = 0;

this.sacrificeCostFilter = null;
this.alternativeSourceCosts.clear();
Expand Down Expand Up @@ -4674,6 +4679,29 @@ public boolean isDrawsOnOpponentsTurn() {
return drawsOnOpponentsTurn;
}

@Override
public int getSpeed() {
return speed;
}

@Override
public void initSpeed(Game game) {
if (speed > 0) {
return;
}
speed = 1;
game.getState().addDesignation(new Speed(), game, getId());
game.informPlayers(this.getLogName() + "'s speed is now 1.");
}

@Override
public void increaseSpeed(Game game) {
if (speed < 4) {
speed++;
game.informPlayers(this.getLogName() + "'s speed has increased to " + speed);
}
}

@Override
public boolean autoLoseGame() {
return false;
Expand Down
Loading