* Until your next turn effects - fixed that continuous effects of lost/leaved players can be discarded by combat or some cards before next turn starts;

This commit is contained in:
Oleg Agafonov 2019-12-26 07:28:37 +04:00
parent a2e4e55811
commit 2460408da8
14 changed files with 147 additions and 93 deletions

View file

@ -1,4 +1,3 @@
package mage.cards.a;
import mage.abilities.Ability;
@ -21,13 +20,12 @@ import java.util.List;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class Aetherspouts extends CardImpl {
public Aetherspouts(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{U}{U}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}{U}");
// For each attacking creature, its owner puts it on the top or bottom of their library.
@ -73,14 +71,14 @@ class AetherspoutsEffect extends OneShotEffect {
game.getPlayerList();
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
PlayerList playerList = game.getPlayerList();
PlayerList playerList = game.getPlayerList().copy();
playerList.setCurrent(game.getActivePlayerId());
Player player = game.getPlayer(game.getActivePlayerId());
Player activePlayer = player;
do {
List<Permanent> permanentsToTop = new ArrayList<>();
List<Permanent> permanentsToBottom = new ArrayList<>();
for (Permanent permanent:game.getState().getBattlefield().getActivePermanents(new FilterAttackingCreature(), player.getId(), source.getSourceId(), game)) {
for (Permanent permanent : game.getState().getBattlefield().getActivePermanents(new FilterAttackingCreature(), player.getId(), source.getSourceId(), game)) {
if (permanent.isOwnedBy(player.getId())) {
if (player.chooseUse(outcome, "Put " + permanent.getLogName() + " to the top? (else it goes to bottom)", source, game)) {
permanentsToTop.add(permanent);
@ -94,7 +92,7 @@ class AetherspoutsEffect extends OneShotEffect {
// cards to top
Cards cards = new CardsImpl();
List<Permanent> toLibrary = new ArrayList<>();
for (Permanent permanent: permanentsToTop) {
for (Permanent permanent : permanentsToTop) {
if (permanent instanceof PermanentToken) {
toLibrary.add(permanent);
} else {
@ -128,13 +126,13 @@ class AetherspoutsEffect extends OneShotEffect {
}
}
// move all permanents to lib at the same time
for(Permanent permanent: toLibrary) {
for (Permanent permanent : toLibrary) {
player.moveCardToLibraryWithInfo(permanent, source.getSourceId(), game, Zone.BATTLEFIELD, true, false);
}
// cards to bottom
cards.clear();
toLibrary.clear();
for (Permanent permanent: permanentsToBottom) {
for (Permanent permanent : permanentsToBottom) {
if (permanent instanceof PermanentToken) {
toLibrary.add(permanent);
} else {
@ -161,15 +159,15 @@ class AetherspoutsEffect extends OneShotEffect {
if (cards.size() == 1) {
Card card = cards.get(cards.iterator().next(), game);
Permanent permanent = game.getPermanent(card.getId());
if (permanent != null) {
if (permanent != null) {
toLibrary.add(permanent);
}
}
// move all permanents to lib at the same time
for(Permanent permanent: toLibrary) {
for (Permanent permanent : toLibrary) {
player.moveCardToLibraryWithInfo(permanent, source.getSourceId(), game, Zone.BATTLEFIELD, false, false);
}
player = playerList.getNext(game);
player = playerList.getNext(game, false);
} while (player != null && !player.getId().equals(game.getActivePlayerId()) && activePlayer.canRespond());
return true;
}

View file

@ -1,9 +1,5 @@
package mage.cards.e;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@ -27,21 +23,26 @@ import mage.players.PlayerList;
import mage.target.Target;
import mage.target.common.TargetNonlandPermanent;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class EyeOfDoom extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("permanent with a doom counter on it");
static {
filter.add(new CounterPredicate(CounterType.DOOM));
}
public EyeOfDoom(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// When Eye of Doom enters the battlefield, each player chooses a nonland permanent and puts a doom counter on it.
this.addAbility(new EntersBattlefieldTriggeredAbility(new EyeOfDoomEffect(),false));
this.addAbility(new EntersBattlefieldTriggeredAbility(new EyeOfDoomEffect(), false));
// {2}, {tap}, Sacrifice Eye of Doom: Destroy each permanent with a doom counter on it.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyAllEffect(filter), new GenericManaCost(2));
@ -93,10 +94,10 @@ class EyeOfDoomEffect extends OneShotEffect {
game.informPlayers(player.getLogName() + " chooses " + permanent.getName());
}
}
player = playerList.getNext(game);
player = playerList.getNext(game, false);
} while (!player.getId().equals(game.getActivePlayerId()));
for (Permanent permanent: permanents) {
for (Permanent permanent : permanents) {
permanent.addCounters(CounterType.DOOM.createInstance(), source, game);
}

View file

@ -1,10 +1,6 @@
package mage.cards.i;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.abilities.keyword.DoubleStrikeAbility;
@ -21,8 +17,12 @@ import mage.players.Player;
import mage.players.PlayerList;
import mage.target.common.TargetCreaturePermanent;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
/**
*
* @author Quercitron
*/
public final class IllicitAuction extends CardImpl {
@ -66,18 +66,17 @@ class IllicitAuctionEffect extends GainControlTargetEffect {
public void init(Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
Permanent targetCreature = game.getPermanent(source.getFirstTarget());
if (controller != null
&& targetCreature != null) {
PlayerList playerList = game.getPlayerList().copy();
playerList.setCurrent(game.getActivePlayerId());
Player winner = game.getPlayer(game.getActivePlayerId());
if (controller != null && targetCreature != null) {
PlayerList playerList = game.getState().getPlayersInRange(controller.getId(), game);
Player winner = game.getPlayer(controller.getId());
int highBid = 0;
game.informPlayers(winner.getLogName() + " has bet 0 lifes");
Player currentPlayer = playerList.getNextInRange(controller, game);
while (!Objects.equals(currentPlayer, winner)) {
Player currentPlayer = playerList.getNext(game, false);
while (currentPlayer != null && !Objects.equals(currentPlayer, winner)) {
String text = winner.getLogName() + " has bet " + highBid + " life" + (highBid > 1 ? "s" : "") + ". Top the bid?";
if (currentPlayer.chooseUse(Outcome.GainControl, text, source, game)) {
if (currentPlayer.canRespond()
&& currentPlayer.chooseUse(Outcome.GainControl, text, source, game)) {
int newBid = 0;
if (!currentPlayer.isHuman()) {//AI will evaluate the creature and bid
CreatureEvaluator eval = new CreatureEvaluator();
@ -85,7 +84,9 @@ class IllicitAuctionEffect extends GainControlTargetEffect {
int creatureValue = eval.evaluate(targetCreature, game);
newBid = Math.max(creatureValue % 2, computerLife - 100);
} else {
newBid = currentPlayer.getAmount(highBid + 1, Integer.MAX_VALUE, "Choose bid", game);
if (currentPlayer.canRespond()) {
newBid = currentPlayer.getAmount(highBid + 1, Integer.MAX_VALUE, "Choose bid", game);
}
}
if (newBid > highBid) {
highBid = newBid;
@ -93,7 +94,12 @@ class IllicitAuctionEffect extends GainControlTargetEffect {
game.informPlayers(currentPlayer.getLogName() + " bet " + newBid + " life" + (newBid > 1 ? "s" : ""));
}
}
currentPlayer = playerList.getNextInRange(controller, game);
currentPlayer = playerList.getNext(game, false);
// stops loop on all players quite
if (game.getState().getPlayersInRange(controller.getId(), game).isEmpty()) {
break;
}
}
game.informPlayers(winner.getLogName() + " won the auction with a bid of " + highBid + " life" + (highBid > 1 ? "s" : ""));

View file

@ -1,7 +1,5 @@
package mage.cards.k;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
@ -16,8 +14,9 @@ import mage.players.Player;
import mage.players.PlayerList;
import mage.target.common.TargetAnyTarget;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class Kindle extends CardImpl {
@ -29,7 +28,7 @@ public final class Kindle extends CardImpl {
}
public Kindle(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}");
// Kindle deals X damage to any target, where X is 2 plus the number of cards named Kindle in all graveyards.
@ -64,7 +63,7 @@ class KindleCardsInAllGraveyardsCount implements DynamicValue {
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
int amount = 0;
PlayerList playerList = game.getPlayerList();
PlayerList playerList = game.getPlayerList().copy();
for (UUID playerUUID : playerList) {
Player player = game.getPlayer(playerUUID);
if (player != null) {

View file

@ -1,9 +1,5 @@
package mage.cards.t;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCosts;
@ -24,14 +20,17 @@ import mage.players.Player;
import mage.players.PlayerList;
import mage.target.TargetCard;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
*
* @author Quercitron
*/
public final class Tariff extends CardImpl {
public Tariff(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{W}");
// Each player sacrifices the creature they control with the highest converted mana cost unless they pay that creature's mana cost. If two or more creatures a player controls are tied for highest cost, that player chooses one.
@ -49,12 +48,12 @@ public final class Tariff extends CardImpl {
}
class TariffEffect extends OneShotEffect {
public TariffEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "Each player sacrifices the creature they control with the highest converted mana cost unless they pay that creature's mana cost. If two or more creatures a player controls are tied for highest cost, that player chooses one.";
}
public TariffEffect(final TariffEffect effect) {
super(effect);
}
@ -63,21 +62,20 @@ class TariffEffect extends OneShotEffect {
public TariffEffect copy() {
return new TariffEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
PlayerList playerList = game.getPlayerList().copy();
playerList.setCurrent(game.getActivePlayerId());
Player player = game.getPlayer(game.getActivePlayerId());
do {
processPlayer(game, source, player);
player = playerList.getNext(game);
player = playerList.getNext(game, false);
} while (!player.getId().equals(game.getActivePlayerId()));
return true;
}
private void processPlayer(Game game, Ability source, Player player) {
MageObject sourceObject = game.getObject(source.getSourceId());
@ -100,7 +98,7 @@ class TariffEffect extends OneShotEffect {
creatureToPayFor.sacrifice(source.getSourceId(), game);
}
}
private List<Permanent> getPermanentsWithTheHighestCMC(Game game, UUID playerId, FilterPermanent filter) {
List<Permanent> permanents = game.getBattlefield().getAllActivePermanents(filter, playerId, game);
int highestCMC = -1;
@ -135,5 +133,5 @@ class TariffEffect extends OneShotEffect {
}
return permanent;
}
}

View file

@ -1,9 +1,5 @@
package mage.cards.t;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
@ -18,8 +14,11 @@ import mage.players.Player;
import mage.players.PlayerList;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class TemptWithReflections extends CardImpl {
@ -81,7 +80,7 @@ class TemptWithReflectionsEffect extends OneShotEffect {
}
game.informPlayers((player.getLogName() + decision + permanent.getName()));
}
player = playerList.getNext(game);
player = playerList.getNext(game, false);
} while (!player.getId().equals(game.getActivePlayerId()));
for (UUID playerId : playersSaidYes) {

View file

@ -1,14 +1,8 @@
package mage.cards.t;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
@ -24,14 +18,15 @@ import mage.target.TargetCard;
import mage.target.common.TargetCardInExile;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author emerald000
*/
public final class ThievesAuction extends CardImpl {
public ThievesAuction(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{R}{R}{R}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}{R}{R}");
// Exile all nontoken permanents. Starting with you, each player chooses one of the exiled cards and puts it onto the battlefield tapped under their control. Repeat this process until all cards exiled this way have been chosen.
this.getSpellAbility().addEffect(new ThievesAuctionEffect());
@ -98,7 +93,7 @@ class ThievesAuctionEffect extends OneShotEffect {
}
}
// Repeat this process until all cards exiled this way have been chosen.
player = playerList.getNext(game);
player = playerList.getNext(game, false);
}
return true;
}

View file

@ -153,4 +153,58 @@ public class EndOfTurnMultiOpponentsTest extends CardTestMultiPlayerBaseWithRang
assertAllCommandsUsed();
}
// leaved players
// 800.4i When a player leaves the game, any continuous effects with durations that last until that player's next turn
// or until a specific point in that turn will last until that turn would have begun.
// They neither expire immediately nor last indefinitely.
@Test
public void test_UntilYourNextTurnMulti_Leaved() {
// Player order: A -> D -> C -> B
addCustomCardWithAbility("boost1", playerA, new SimpleStaticAbility(Zone.ALL, new BoostAllEffect(1, 1, Duration.UntilYourNextTurn)));
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilYourNextTurn effect", 1, playerA, true, PhaseStep.END_TURN);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilYourNextTurn effect", 2, playerD, true, PhaseStep.END_TURN);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilYourNextTurn effect", 3, playerC, true, PhaseStep.END_TURN);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilYourNextTurn effect", 4, playerB, true, PhaseStep.END_TURN);
EndOfTurnOneOpponentTest.prepareStepChecks(this, "Duration.UntilYourNextTurn effect", 5, playerD, true, null);
addCard(Zone.BATTLEFIELD, playerA, cardBear2, 1);
addCard(Zone.BATTLEFIELD, playerB, cardBear2, 1);
addCard(Zone.BATTLEFIELD, playerC, cardBear2, 1);
addCard(Zone.BATTLEFIELD, playerD, cardBear2, 1);
//
// When Eye of Doom enters the battlefield, each player chooses a nonland permanent and puts a doom counter on it.
addCard(Zone.HAND, playerC, "Eye of Doom", 1);
addCard(Zone.BATTLEFIELD, playerC, "Forest", 4);
checkPlayerInGame("A must plays in 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerA, true);
attack(1, playerA, cardBear2);
checkPlayerInGame("A must plays in 2", 2, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, true);
attack(2, playerD, cardBear2);
checkPlayerInGame("A must plays in 3 before", 3, PhaseStep.PRECOMBAT_MAIN, playerC, playerA, true);
attack(3, playerC, cardBear2);
concede(3, PhaseStep.PRECOMBAT_MAIN, playerA);
checkPlayerInGame("A must leaved in 3 after", 3, PhaseStep.POSTCOMBAT_MAIN, playerC, playerA, false);
// test PlayerList.getNext processing
// play Eye of Doom, ask all players to put doom counter
castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerC, "Eye of Doom");
addTarget(playerC, cardBear2);
addTarget(playerB, cardBear2);
//addTarget(playerA, cardBear2); // leaved
addTarget(playerD, cardBear2);
checkPlayerInGame("A must leaved in 4", 4, PhaseStep.POSTCOMBAT_MAIN, playerB, playerA, false);
attack(4, playerB, cardBear2);
checkPlayerInGame("A must leaved in 5", 5, PhaseStep.POSTCOMBAT_MAIN, playerD, playerA, false);
attack(5, playerD, cardBear2);
setStopAt(5, PhaseStep.CLEANUP);
setStrictChooseMode(true);
execute();
assertAllCommandsUsed();
}
}

View file

@ -217,7 +217,7 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
boolean canDelete = false;
Player player = game.getPlayer(startingControllerId);
// discard on start of turn for leave player
// discard on start of turn for leaved player
// 800.4i When a player leaves the game, any continuous effects with durations that last until that player's next turn
// or until a specific point in that turn will last until that turn would have begun.
// They neither expire immediately nor last indefinitely.

View file

@ -1,7 +1,5 @@
package mage.abilities.effects.common;
import java.io.ObjectStreamException;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.MageSingleton;
@ -20,6 +18,8 @@ import mage.players.PlayerList;
import mage.target.Target;
import mage.target.common.TargetOpponent;
import java.io.ObjectStreamException;
/**
* 1. The controller of the spell or ability chooses an opponent. (This doesn't
* target the opponent.) 2. Each player involved in the clash reveals the top
@ -36,7 +36,7 @@ import mage.target.common.TargetOpponent;
* 7. The clash spell or ability finishes resolving. That usually involves a
* bonus gained by the controller of the clash spell or ability if they won
* the clash. 8. Abilities that triggered during the clash are put on the stack.
*
* <p>
* There are no draws or losses in a clash. Either you win it or you don't. Each
* spell or ability with clash says what happens if you (the controller of that
* spell or ability) win the clash. Typically, if you don't win the clash,
@ -148,7 +148,7 @@ public class ClashEffect extends OneShotEffect implements MageSingleton {
if (cardOpponent != null && current.getId().equals(opponent.getId())) {
topOpponent = current.chooseUse(Outcome.Detriment, "Put " + cardOpponent.getLogName() + " back on top of your library? (otherwise it goes to bottom)", source, game);
}
nextPlayer = playerList.getNext(game);
nextPlayer = playerList.getNext(game, false);
} while (nextPlayer != null && !nextPlayer.getId().equals(game.getActivePlayerId()));
// put the cards back to library
if (cardController != null) {

View file

@ -766,7 +766,7 @@ public abstract class GameImpl implements Game, Serializable {
state.getTurn().resumePlay(this, wasPaused);
if (!isPaused() && !checkIfGameIsOver()) {
endOfTurn();
player = playerList.getNext(this);
player = playerList.getNext(this, true);
state.setTurnNum(state.getTurnNum() + 1);
}
}
@ -791,7 +791,7 @@ public abstract class GameImpl implements Game, Serializable {
if (!playExtraTurns()) {
break;
}
playerByOrder = playerList.getNext(this);
playerByOrder = playerList.getNext(this, true);
state.setPlayerByOrderId(playerByOrder.getId());
}
}
@ -2494,7 +2494,6 @@ public abstract class GameImpl implements Game, Serializable {
perm.removeFromCombat(this, true);
}
toOutside.add(perm);
// it.remove();
} else if (perm.isControlledBy(player.getId())) {
// and any effects which give that player control of any objects or players end
Effects:
@ -2591,7 +2590,7 @@ public abstract class GameImpl implements Game, Serializable {
if (!isActivePlayer(playerId)) {
setMonarchId(null, getActivePlayerId());
} else {
Player nextPlayer = getPlayerList().getNext(this);
Player nextPlayer = getPlayerList().getNext(this, true);
if (nextPlayer != null) {
setMonarchId(null, nextPlayer.getId());
}

View file

@ -1236,7 +1236,7 @@ public class Combat implements Serializable, Copyable<Combat> {
case LEFT:
players = game.getState().getPlayerList(attackingPlayerId);
while (attackingPlayer.isInGame()) {
Player opponent = players.getNext(game);
Player opponent = players.getNext(game, false);
if (attackingPlayer.hasOpponent(opponent.getId(), game)) {
attackablePlayers.add(opponent.getId());
break;

View file

@ -487,10 +487,10 @@ public abstract class PlayerImpl implements Player, Serializable {
inRange.add(playerId);
PlayerList players = game.getState().getPlayerList(playerId);
for (int i = 0; i < range.getRange(); i++) {
Player player = players.getNext(game);
Player player = players.getNext(game, false);
if (player != null) {
while (player.hasLeft()) {
player = players.getNext(game);
player = players.getNext(game, false);
}
inRange.add(player.getId());
}

View file

@ -1,12 +1,11 @@
package mage.players;
import java.util.UUID;
import mage.game.Game;
import mage.util.CircularList;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class PlayerList extends CircularList<UUID> {
@ -23,7 +22,7 @@ public class PlayerList extends CircularList<UUID> {
}
public Player getNextInRange(Player basePlayer, Game game) {
UUID currentPlayerBefore = get();
UUID currentPlayerBefore = this.get();
UUID nextPlayerId = super.getNext();
do {
if (basePlayer.getInRange().contains(nextPlayerId)) {
@ -34,7 +33,10 @@ public class PlayerList extends CircularList<UUID> {
return null;
}
public Player getNext(Game game) {
/**
* checkNextTurnReached - use it turns/priority code only to mark leaved player as "reached next turn end" (need for some continous effects)
*/
public Player getNext(Game game, boolean checkNextTurnReached) {
UUID start = this.get();
if (start == null) {
return null;
@ -42,11 +44,14 @@ public class PlayerList extends CircularList<UUID> {
Player player;
while (true) {
player = game.getPlayer(super.getNext());
if (!player.hasLeft() && !player.hasLost()) {
if (player.isInGame()) {
break;
}
if (!player.hasReachedNextTurnAfterLeaving()) {
player.setReachedNextTurnAfterLeaving(true);
if (checkNextTurnReached) {
if (!player.hasReachedNextTurnAfterLeaving()) {
player.setReachedNextTurnAfterLeaving(true);
}
}
if (player.getId().equals(start)) {
return null;
@ -60,7 +65,7 @@ public class PlayerList extends CircularList<UUID> {
UUID start = this.get();
while (true) {
player = game.getPlayer(super.getPrevious());
if (!player.hasLeft() && !player.hasLost()) {
if (player.isInGame()) {
break;
}
if (player.getId().equals(start)) {