Controlling other players turns (only effect, replacing message is not implemented yet). ControlTargetPlayerNextTurnEffect.

This commit is contained in:
magenoxx 2011-08-04 21:50:24 +04:00
parent 25b78736c6
commit 752569874d
9 changed files with 327 additions and 12 deletions

View file

@ -0,0 +1,71 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.common.delayed;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.game.Game;
import mage.game.events.GameEvent;
/**
* @author nantuko
*/
public class AtTheEndOfTurnDelayedTriggeredAbility extends DelayedTriggeredAbility<AtTheEndOfTurnDelayedTriggeredAbility> {
public AtTheEndOfTurnDelayedTriggeredAbility(Effect effect) {
super(effect);
}
public AtTheEndOfTurnDelayedTriggeredAbility(Effect effect, boolean usesStack) {
super(effect);
this.usesStack = usesStack;
}
public AtTheEndOfTurnDelayedTriggeredAbility(AtTheEndOfTurnDelayedTriggeredAbility ability) {
super(ability);
}
@Override
public AtTheEndOfTurnDelayedTriggeredAbility copy() {
return new AtTheEndOfTurnDelayedTriggeredAbility(this);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.COMBAT_PHASE_POST) {
return true;
}
return false;
}
@Override
public String getRule() {
return "At end of turn " + modes.getText();
}
}

View file

@ -0,0 +1,66 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common;
import mage.Constants.Outcome;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author nantuko
*/
public class LoseControlOnOtherPlayersControllerEffect extends OneShotEffect<LoseControlOnOtherPlayersControllerEffect> {
public LoseControlOnOtherPlayersControllerEffect() {
super(Outcome.Detriment);
}
public LoseControlOnOtherPlayersControllerEffect(final LoseControlOnOtherPlayersControllerEffect effect) {
super(effect);
}
@Override
public LoseControlOnOtherPlayersControllerEffect copy() {
return new LoseControlOnOtherPlayersControllerEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.resetOtherTurnsControlled();
return true;
}
return false;
}
}

View file

@ -0,0 +1,67 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common.turn;
import mage.Constants;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.game.Game;
import mage.game.turn.TurnMod;
import java.util.UUID;
/**
* @author nantuko
*/
public class ControlTargetPlayerNextTurnEffect extends OneShotEffect<ControlTargetPlayerNextTurnEffect> {
public ControlTargetPlayerNextTurnEffect() {
super(Constants.Outcome.Benefit);
staticText = "You control target player during that player's next turn. (You see all cards that player could see and make all decisions for the player.)";
}
public ControlTargetPlayerNextTurnEffect(ControlTargetPlayerNextTurnEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
UUID targetId = source.getFirstTarget();
UUID controllerId = source.getControllerId();
if (targetId != null && controllerId != null && !targetId.equals(controllerId)) {
game.getState().getTurnMods().add(new TurnMod(targetId, controllerId));
return true;
}
return false;
}
@Override
public ControlTargetPlayerNextTurnEffect copy() {
return new ControlTargetPlayerNextTurnEffect();
}
}

View file

@ -56,8 +56,10 @@ public class CleanupStep extends Step<CleanupStep> {
super.beginStep(game, activePlayerId);
Player activePlayer = game.getPlayer(activePlayerId);
//20091005 - 514.1
if (!activePlayer.hasLeft() && !activePlayer.hasLost())
if (!activePlayer.hasLeft() && !activePlayer.hasLost()) {
activePlayer.discardToMax(game);
activePlayer.setGameUnderYourControl(true);
}
//20100423 - 514.2
game.getBattlefield().endOfTurn(activePlayerId, game);
game.getState().removeEotEffects(game);

View file

@ -106,6 +106,8 @@ public class Turn implements Serializable {
if (game.getState().getTurnMods().skipTurn(activePlayerId))
return;
checkTurnIsControlledByOtherPlayer(game, activePlayerId);
this.activePlayerId = activePlayerId;
resetCounts();
game.getPlayer(activePlayerId).beginTurn(game);
@ -127,6 +129,13 @@ public class Turn implements Serializable {
playExtraTurns(game);
}
private void checkTurnIsControlledByOtherPlayer(Game game, UUID activePlayerId) {
UUID newControllerId = game.getState().getTurnMods().controlsTurn(activePlayerId);
if (newControllerId != null && !newControllerId.equals(activePlayerId)) {
game.getPlayer(newControllerId).controlPlayersTurn(game, activePlayerId);
}
}
private void resetCounts() {
for (Phase phase: phases) {
phase.resetCount();

View file

@ -41,6 +41,7 @@ import mage.Constants.TurnPhase;
public class TurnMod implements Serializable {
private UUID playerId;
private UUID newControllerId;
private boolean extraTurn;
private boolean skipTurn;
private TurnPhase extraPhase;
@ -58,8 +59,14 @@ public class TurnMod implements Serializable {
this.extraTurn = true;
}
public TurnMod(UUID playerId, UUID newControllerId) {
this.playerId = playerId;
this.newControllerId = newControllerId;
}
public TurnMod(final TurnMod mod) {
this.playerId = mod.playerId;
this.newControllerId = mod.newControllerId;
this.extraTurn = mod.extraTurn;
this.skipTurn = mod.skipTurn;
this.extraPhase = mod.extraPhase;
@ -74,7 +81,7 @@ public class TurnMod implements Serializable {
/**
*
* @param playerId
* @param extraPhase
* @param phase
* @param afterPhase - set to null if extraPhase is after the next phase
*/
public TurnMod(UUID playerId, TurnPhase phase, TurnPhase afterPhase, boolean skip) {
@ -89,7 +96,7 @@ public class TurnMod implements Serializable {
/**
*
* @param playerId
* @param extraStep
* @param step
* @param afterStep - set to null if extraStep is after the next step
*/
public TurnMod(UUID playerId, Step step, PhaseStep afterStep) {
@ -139,6 +146,10 @@ public class TurnMod implements Serializable {
return afterStep;
}
public UUID getNewControllerId() {
return newControllerId;
}
public TurnMod copy() {
return new TurnMod(this);
}

View file

@ -72,6 +72,27 @@ public class TurnMods extends ArrayList<TurnMod> {
return false;
}
public UUID controlsTurn(UUID playerId) {
ListIterator<TurnMod> it = this.listIterator(this.size());
UUID newControllerId = null;
while (it.hasPrevious()) {
TurnMod turnMod = it.previous();
if (turnMod.getNewControllerId() != null && turnMod.getPlayerId().equals(playerId)) {
newControllerId = turnMod.getNewControllerId();
it.remove();
}
}
// now delete all other - control next turn effect is not cumulative
it = this.listIterator(this.size());
while (it.hasPrevious()) {
TurnMod turnMod = it.previous();
if (turnMod.getNewControllerId() != null && turnMod.getPlayerId().equals(playerId)) {
it.remove();
}
}
return newControllerId;
}
public Step extraStep(UUID playerId, PhaseStep afterStep) {
ListIterator<TurnMod> it = this.listIterator(this.size());
while (it.hasPrevious()) {

View file

@ -102,6 +102,43 @@ public interface Player extends MageItem, Copyable<Player> {
public ManaPool getManaPool();
public Set<UUID> getInRange();
/**
* Returns a set of players which turns under you control.
* Doesn't include yourself.
*
* @return
*/
public Set<UUID> getPlayersUnderYourControl();
/**
* Defines player whose turn you control at the moment.
* @param playerId
*/
public void controlPlayersTurn(Game game, UUID playerId);
/**
* Resets players whose turns you control at the moment.
*/
public void resetOtherTurnsControlled();
/**
* Returns false in case you don't control the game.
*
* Note: For effects like "You control target player during that player's next turn".
*
* @return
*/
public boolean isGameUnderYourControl();
/**
* Returns false in case you don't control the game.
*
* Note: For effects like "You control target player during that player's next turn".
*
* @param value
*/
public void setGameUnderYourControl(boolean value);
public boolean isTestMode();
public void setTestMode(boolean value);

View file

@ -42,17 +42,11 @@ import mage.Constants.RangeOfInfluence;
import mage.Constants.Zone;
import mage.MageObject;
import mage.Mana;
import mage.abilities.Abilities;
import mage.abilities.AbilitiesImpl;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.Mode;
import mage.abilities.PlayLandAbility;
import mage.abilities.SpecialAction;
import mage.abilities.SpellAbility;
import mage.abilities.TriggeredAbility;
import mage.abilities.*;
import mage.abilities.common.PassAbility;
import mage.abilities.common.delayed.AtTheEndOfTurnDelayedTriggeredAbility;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.effects.common.LoseControlOnOtherPlayersControllerEffect;
import mage.abilities.keyword.*;
import mage.abilities.mana.ManaAbility;
import mage.abilities.mana.ManaOptions;
@ -100,6 +94,8 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
protected Set<UUID> inRange = new HashSet<UUID>();
protected boolean isTestMode = false;
protected boolean lifeTotalCanChange = true;
protected boolean isGameUnderYourControl = true;
protected Set<UUID> playersUnderYourControl = new HashSet<UUID>();
@Override
public abstract T copy();
@ -234,6 +230,41 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
return inRange;
}
@Override
public Set<UUID> getPlayersUnderYourControl() {
return this.playersUnderYourControl;
}
@Override
public void controlPlayersTurn(Game game, UUID playerId) {
if (!playerId.equals(getId())) {
this.playersUnderYourControl.add(playerId);
Player player = game.getPlayer(playerId);
if (!player.hasLeft() && !player.hasLost()) {
player.setGameUnderYourControl(false);
}
DelayedTriggeredAbility ability = new AtTheEndOfTurnDelayedTriggeredAbility(new LoseControlOnOtherPlayersControllerEffect());
ability.setSourceId(getId());
ability.setControllerId(getId());
game.addDelayedTriggeredAbility(ability);
}
}
@Override
public void resetOtherTurnsControlled() {
playersUnderYourControl.clear();
}
@Override
public boolean isGameUnderYourControl() {
return isGameUnderYourControl;
}
@Override
public void setGameUnderYourControl(boolean value) {
this.isGameUnderYourControl = value;
}
@Override
public void endOfTurn(Game game) {
this.passedTurn = false;