Added a quit match option. FFA game gets no more killed if host left mage or quitted match.

This commit is contained in:
LevelX2 2013-07-02 22:15:49 +02:00
parent ec9bb538ed
commit 7b260c960b
15 changed files with 178 additions and 54 deletions

View file

@ -417,7 +417,7 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
player.won(this);
}
}
state.endGame();
end();
endTime = new Date();
return true;
}
@ -736,9 +736,11 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
@Override
public void end() {
state.endGame();
for (Player player: state.getPlayers().values()) {
player.abort();
if (!state.isGameOver()) {
state.endGame();
for (Player player: state.getPlayers().values()) {
player.abort();
}
}
}
@ -797,8 +799,8 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
public synchronized void quit(UUID playerId) {
Player player = state.getPlayer(playerId);
if (player != null) {
leave(playerId);
fireInformEvent(player.getName() + " has left the game.");
player.quit(this);
fireInformEvent(player.getName() + " has quitted the match.");
}
}
@ -1580,9 +1582,12 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
@Override
public synchronized void leave(UUID playerId) {
Player player = getPlayer(playerId);
if (player.hasLeft()) {
return;
}
player.leave();
if (this.isGameOver()) {
// no need to remove objects if only one player is left
// no need to remove objects if only one player is left so the game is over
return;
}
//20100423 - 800.4a

View file

@ -398,7 +398,7 @@ public class GameState implements Serializable, Copyable<GameState> {
public PlayerList getPlayerList(UUID playerId) {
PlayerList newPlayerList = new PlayerList();
for (Player player: players.values()) {
if (!player.hasLeft() && !player.hasLost()) {
if (!player.hasLeft()&& !player.hasLost()) {
newPlayerList.add(player.getId());
}
}

View file

@ -117,12 +117,20 @@ public abstract class MatchImpl implements Match {
@Override
public boolean isMatchOver() {
int activePlayers = 0;
for (MatchPlayer player: players) {
if (!player.hasQuitted()) {
activePlayers++;
}
if (player.getWins() >= options.getWinsNeeded()) {
endTime = new Date();
return true;
}
}
if (activePlayers < 2) {
endTime = new Date();
return true;
}
return false;
}
@ -157,10 +165,12 @@ public abstract class MatchImpl implements Match {
protected void initGame(Game game) throws GameException {
shufflePlayers();
for (MatchPlayer matchPlayer: this.players) {
matchPlayer.getPlayer().init(game);
game.loadCards(matchPlayer.getDeck().getCards(), matchPlayer.getPlayer().getId());
game.loadCards(matchPlayer.getDeck().getSideboard(), matchPlayer.getPlayer().getId());
game.addPlayer(matchPlayer.getPlayer(), matchPlayer.getDeck());
if (!matchPlayer.hasQuitted()) {
matchPlayer.getPlayer().init(game);
game.loadCards(matchPlayer.getDeck().getCards(), matchPlayer.getPlayer().getId());
game.loadCards(matchPlayer.getDeck().getSideboard(), matchPlayer.getPlayer().getId());
game.addPlayer(matchPlayer.getPlayer(), matchPlayer.getDeck());
}
}
game.setPriorityTime(options.getPriorityTime());
}
@ -175,6 +185,9 @@ public abstract class MatchImpl implements Match {
for (MatchPlayer player: this.players) {
Player p = game.getPlayer(player.getPlayer().getId());
if (p != null) {
if (p.hasQuitted()) {
player.setQuitted(true);
}
if (p.hasWon()) {
player.addWin();
}
@ -191,7 +204,7 @@ public abstract class MatchImpl implements Match {
Game game = getGame();
for (MatchPlayer player: this.players) {
Player p = game.getPlayer(player.getPlayer().getId());
if (p != null && p.hasLost()) {
if (p != null && p.hasLost() && !p.hasQuitted()) {
loserId = p.getId();
}
}
@ -206,8 +219,10 @@ public abstract class MatchImpl implements Match {
@Override
public void sideboard() {
for (MatchPlayer player: this.players) {
player.setSideboarding();
player.getPlayer().sideboard(this, player.getDeck());
if (!player.hasQuitted()) {
player.setSideboarding();
player.getPlayer().sideboard(this, player.getDeck());
}
}
synchronized(this) {
while (!isDoneSideboarding()) {
@ -221,7 +236,7 @@ public abstract class MatchImpl implements Match {
@Override
public boolean isDoneSideboarding() {
for (MatchPlayer player: this.players) {
if (!player.isDoneSideboarding()) {
if (!player.hasQuitted() && !player.isDoneSideboarding()) {
return false;
}
}
@ -261,7 +276,11 @@ public abstract class MatchImpl implements Match {
for (MatchPlayer mp :this.getPlayers()) {
sb.append("- ").append(mp.getPlayer().getName());
sb.append(" (").append(mp.getWins()).append(mp.getWins()==1?" win / ":" wins / ");
sb.append(mp.getLoses()).append(mp.getLoses()==1?" loss)\n":" losses)\n");
sb.append(mp.getLoses()).append(mp.getLoses()==1?" loss)":" losses)");
if (mp.hasQuitted()) {
sb.append(" QUITTED");
}
sb.append("\n");
}
sb.append("\n").append(this.getWinsNeeded()).append(this.getWinsNeeded() == 1 ? " win":" wins").append(" needed to win the match\n");
sb.append("\nGame has started\n");

View file

@ -40,7 +40,9 @@ public class MatchPlayer {
private int wins;
private int loses;
private Deck deck;
private Player player;
private boolean quitted;
private boolean doneSideboarding;
public MatchPlayer(Player player, Deck deck) {
@ -49,6 +51,7 @@ public class MatchPlayer {
this.wins = 0;
this.loses = 0;
this.doneSideboarding = true;
this.quitted = false;
}
public int getWins() {
@ -102,4 +105,11 @@ public class MatchPlayer {
return this.doneSideboarding;
}
public boolean hasQuitted() {
return quitted;
}
public void setQuitted(boolean quitted) {
this.quitted = quitted;
}
}

View file

@ -99,6 +99,8 @@ public interface Player extends MageItem, Copyable<Player> {
boolean hasLost();
boolean hasWon();
boolean hasQuitted();
void quit(Game game);
boolean hasLeft();
/**
* Player is still active in game (has not left, lost or won the game).

View file

@ -28,16 +28,41 @@
package mage.players;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.Mana;
import mage.abilities.*;
import mage.abilities.Abilities;
import mage.abilities.AbilitiesImpl;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.Mode;
import mage.abilities.PlayLandAbility;
import mage.abilities.SpecialAction;
import mage.abilities.SpellAbility;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.PassAbility;
import mage.abilities.common.delayed.AtTheEndOfTurnStepPostDelayedTriggeredAbility;
import mage.abilities.costs.AdjustingSourceCosts;
import mage.abilities.costs.AlternativeCost;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.effects.common.LoseControlOnOtherPlayersControllerEffect;
import mage.abilities.keyword.*;
import mage.abilities.keyword.FlashbackAbility;
import mage.abilities.keyword.HexproofAbility;
import mage.abilities.keyword.InfectAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.abilities.keyword.ProtectionAbility;
import mage.abilities.keyword.ShroudAbility;
import mage.abilities.mana.ManaAbility;
import mage.abilities.mana.ManaOptions;
import mage.actions.MageDrawAction;
@ -46,7 +71,13 @@ import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.SplitCard;
import mage.cards.decks.Deck;
import mage.constants.*;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.RangeOfInfluence;
import mage.constants.SpellAbilityType;
import mage.constants.TimingRule;
import mage.constants.Zone;
import mage.counters.Counter;
import mage.counters.CounterType;
import mage.counters.Counters;
@ -72,9 +103,6 @@ import mage.target.common.TargetDiscard;
import mage.watchers.common.BloodthirstWatcher;
import org.apache.log4j.Logger;
import java.io.Serializable;
import java.util.*;
public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Serializable {
@ -84,6 +112,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
/**
* Means what exactly?
* No more actions?
*/
protected boolean abort;
protected final UUID playerId;
@ -113,7 +142,12 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
* Note! This differs from passedTurn as it doesn't care about spells and abilities in the stack and will pass them as well.
*/
protected boolean passedAllTurns;
// conceded or connection lost game
protected boolean left;
// quitted match
protected boolean quitted;
protected RangeOfInfluence range;
protected Set<UUID> inRange = new HashSet<UUID>();
protected boolean isTestMode = false;
@ -174,6 +208,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
this.turns = player.turns;
this.left = player.left;
this.quitted = player.quitted;
this.range = player.range;
this.canGainLife = player.canGainLife;
this.canLoseLife = player.canLoseLife;
@ -220,8 +255,8 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
this.manaPool = player.getManaPool().copy();
this.turns = player.getTurns();
this.left = player.hasLeft();
this.quitted = player.hasQuitted();
this.range = player.getRange();
this.canGainLife = player.isCanGainLife();
this.canLoseLife = player.isCanLoseLife();
@ -274,6 +309,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
this.wins = false;
this.loses = false;
this.left = false;
// quittet won't be reset because the player stays quit
this.passed = false;
this.passedTurn = false;
this.passedAllTurns = false;
@ -367,7 +403,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
if (!playerId.equals(this.getId())) {
this.playersUnderYourControl.add(playerId);
Player player = game.getPlayer(playerId);
if (!player.hasLeft() && !player.hasLost()) {
if (!player.hasLeft()&& !player.hasLost()) {
player.setGameUnderYourControl(false);
player.setTurnControlledBy(this.getId());
}
@ -1217,7 +1253,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
@Override
public void resetPassed() {
if (!this.loses && !this.left) {
if (!this.loses && !this.hasLeft()) {
this.passed = false;
}
else {
@ -1225,10 +1261,14 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
}
}
@Override
public void quit(Game game) {
quitted = true;
this.concede(game);
}
@Override
public void concede(Game game) {
this.loses = true;
this.abort();
game.leave(playerId);
}
@ -1265,7 +1305,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
this.graveyard.clear();
this.library.clear();
}
@Override
public boolean hasLeft() {
return this.left;
@ -1279,7 +1319,9 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
if (!this.wins) {
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LOST, null, null, playerId));
}
game.leave(playerId);
if (!hasLeft()) {
game.leave(playerId);
}
}
}
@ -1802,4 +1844,10 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
public int getPriorityTimeLeft() {
return priorityTimeLeft;
}
@Override
public boolean hasQuitted() {
return quitted;
}
}